Index: trunk/extensions/SemanticMediaWiki/specials/SearchTriple/SMW_SpecialSearchByProperty.php |
— | — | @@ -205,7 +205,7 @@ |
206 | 206 | $html .= '<li>' . $result[0]->getLongHTMLText( smwfGetLinker() ); |
207 | 207 | |
208 | 208 | if ( $result[0]->getTypeID() == '_wpg' ) { |
209 | | - $html .= '  ' . SMWInfolink::newBrowsingLink( '+', $result[0]->getShortHTMLText() )->getHTML( smwfGetLinker() ); |
| 209 | + $html .= '  ' . SMWInfolink::newBrowsingLink( '+', $result[0]->getLongWikiText() )->getHTML( smwfGetLinker() ); |
210 | 210 | } |
211 | 211 | |
212 | 212 | if ( is_object( $result[1] ) && ( ( $this->value != $result[1] ) || $highlight ) ) { |
Index: trunk/extensions/SemanticMediaWiki/includes/export/SMW_ExportController.php |
— | — | @@ -11,34 +11,6 @@ |
12 | 12 | */ |
13 | 13 | |
14 | 14 | /** |
15 | | - * Small data object that specifies one wiki page to be serialised. |
16 | | - * SMWSmallTitle objects are used to queue pages for serialisation, hence it |
17 | | - * should be small to save memory. |
18 | | - * |
19 | | - * @ingroup SMW |
20 | | - */ |
21 | | -class SMWSmallTitle { |
22 | | - /// DB key version of the title. |
23 | | - public $dbkey; |
24 | | - /// MediaWiki namespace constant. |
25 | | - public $namespace; |
26 | | - /** |
27 | | - * Recursion depth for serialising this object. Depth of 1 or above means |
28 | | - * the object is serialised with all property values, and referenced |
29 | | - * objects are serialised with depth reduced by 1. Depth 0 means that only |
30 | | - * minimal declarations are serialised, so no dependencies are added. A |
31 | | - * depth of -1 encodes "infinite" depth, i.e. a complete recursive |
32 | | - * serialisation without limit. |
33 | | - * @var integer |
34 | | - */ |
35 | | - public $recdepth = 1; |
36 | | - |
37 | | - public function getHash() { |
38 | | - return $this->dbkey . ' ' . $this->namespace; |
39 | | - } |
40 | | -} |
41 | | - |
42 | | -/** |
43 | 15 | * Class for controlling the export of SMW page data, supporting high-level |
44 | 16 | * features such as recursive export and backlink inclusion. The class controls |
45 | 17 | * export independent of the serialisation syntax that is used. |
— | — | @@ -135,18 +107,20 @@ |
136 | 108 | * level of pages, i.e. it serialises parts of SMW content and implements |
137 | 109 | * features like recursive export or backlinks that are available for this |
138 | 110 | * type of data. |
| 111 | + * |
| 112 | + * The recursion depth means the following. Depth of 1 or above means |
| 113 | + * the object is serialised with all property values, and referenced |
| 114 | + * objects are serialised with depth reduced by 1. Depth 0 means that only |
| 115 | + * minimal declarations are serialised, so no dependencies are added. A |
| 116 | + * depth of -1 encodes "infinite" depth, i.e. a complete recursive |
| 117 | + * serialisation without limit. |
139 | 118 | * |
140 | 119 | * @param SMWDIWikiPage $diWikiPage specifying the page to be exported |
141 | | - * @param integer $recursiondepth specifying the depth of recursion, see |
142 | | - * SMWSmallTitle::$recdepth |
| 120 | + * @param integer $recursiondepth specifying the depth of recursion |
143 | 121 | */ |
144 | 122 | protected function serializePage( SMWDIWikiPage $diWikiPage, $recursiondepth = 1 ) { |
145 | | - $st = new SMWSmallTitle(); |
146 | | - $st->dbkey = $diWikiPage->getDBKey(); |
147 | | - $st->namespace = $diWikiPage->getNamespace(); |
148 | | - $st->recdepth = $recursiondepth; |
149 | | - if ( $this->isDone( $st ) ) return; // do not export twice |
150 | | - $this->markAsDone( $st ); |
| 123 | + if ( $this->isPageDone( $diWikiPage, $recursiondepth ) ) return; // do not export twice |
| 124 | + $this->markPageAsDone( $diWikiPage, $recursiondepth ); |
151 | 125 | $data = SMWExporter::makeExportData( $this->getSemanticData( $diWikiPage, ( $recursiondepth == 0 ) ) ); |
152 | 126 | $this->serializer->serializeExpData( $data, $recursiondepth ); |
153 | 127 | |
— | — | @@ -195,11 +169,7 @@ |
196 | 170 | } |
197 | 171 | $inSubs = smwfGetStore()->getPropertySubjects( $inprop, $diWikiPage ); |
198 | 172 | foreach ( $inSubs as $inSub ) { |
199 | | - $stb = new SMWSmallTitle(); |
200 | | - $stb->dbkey = $inSub->getDBkey(); |
201 | | - $stb->namespace = $inSub->getNamespace(); |
202 | | - $stb->recdepth = $subrecdepth; |
203 | | - if ( !$this->isDone($stb) ) { |
| 173 | + if ( !$this->isPageDone( $inSub, $subrecdepth ) ) { |
204 | 174 | $semdata = $this->getSemanticData( $inSub, true ); |
205 | 175 | $semdata->addPropertyObjectValue( $inprop, $diWikiPage ); |
206 | 176 | $data = SMWExporter::makeExportData( $semdata ); |
— | — | @@ -215,11 +185,7 @@ |
216 | 186 | $pinst = new SMWDIProperty( '_INST' ); |
217 | 187 | |
218 | 188 | foreach ( $instances as $instance ) { |
219 | | - $stb = new SMWSmallTitle(); |
220 | | - $stb->dbkey = $instance->getDBkey(); |
221 | | - $stb->namespace = $instance->getNamespace(); |
222 | | - |
223 | | - if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) { |
| 189 | + if ( !array_key_exists( $instance->getHash(), $this->element_done ) ) { |
224 | 190 | $semdata = $this->getSemanticData( $instance, true ); |
225 | 191 | $semdata->addPropertyObjectValue( $pinst, $diWikiPage ); |
226 | 192 | $data = SMWExporter::makeExportData( $semdata ); |
— | — | @@ -238,12 +204,8 @@ |
239 | 205 | |
240 | 206 | while ( $resarray !== false ) { |
241 | 207 | $instance = end( $resarray )->getNextDataValue(); |
242 | | - |
243 | | - $stb = new SMWSmallTitle(); |
244 | | - $stb->dbkey = $instance->getDBkey(); |
245 | | - $stb->namespace = $instance->getNamespace(); |
246 | | - |
247 | | - if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) { |
| 208 | + |
| 209 | + if ( !array_key_exists( $instance->getHash(), $this->element_done ) ) { |
248 | 210 | $semdata = $this->getSemanticData( $instance, true ); |
249 | 211 | $semdata->addPropertyObjectValue( $pinst, $diWikiPage ); |
250 | 212 | $data = SMWExporter::makeExportData( $semdata ); |
— | — | @@ -259,57 +221,57 @@ |
260 | 222 | } |
261 | 223 | |
262 | 224 | /** |
263 | | - * Serialize data associated to a specific page. |
264 | | - * |
265 | | - * @param SMWSmallTitle $st specifying the page to be exported |
266 | | - */ |
267 | | - protected function serializeSmallTitle( SMWSmallTitle $st ) { |
268 | | - if ( $this->isDone( $st ) ) return; // do not export twice |
269 | | - $diWikiPage = new SMWDIWikiPage( $st->dbkey, $st->namespace, '' ); |
270 | | - $this->serializePage( $diWikiPage, $st->recdepth ); |
271 | | - } |
272 | | - |
273 | | - /** |
274 | 225 | * Add a given SMWDIWikiPage to the export queue if needed. |
275 | 226 | */ |
276 | 227 | protected function queuePage( SMWDIWikiPage $diWikiPage, $recursiondepth ) { |
277 | | - $spt = new SMWSmallTitle(); |
278 | | - $spt->dbkey = $diWikiPage->getDBkey(); |
279 | | - $spt->namespace = $diWikiPage->getNamespace(); |
280 | | - $spt->recdepth = $recursiondepth; |
281 | | - if ( !$this->isDone( $spt ) ) { |
282 | | - $this->element_queue[$spt->getHash()] = $spt; |
| 228 | + if ( !$this->isPageDone( $diWikiPage, $recursiondepth ) ) { |
| 229 | + $diWikiPage->recdepth = $recursiondepth; // add a field |
| 230 | + $this->element_queue[$diWikiPage->getHash()] = $diWikiPage; |
283 | 231 | } |
284 | 232 | } |
285 | 233 | |
286 | 234 | /** |
287 | 235 | * Mark an article as done while making sure that the cache used for this |
288 | | - * stays reasonably small. Input is given as an SMWSmallTitle object. |
| 236 | + * stays reasonably small. Input is given as an SMWDIWikiPage object. |
289 | 237 | */ |
290 | | - protected function markAsDone( $st ) { |
| 238 | + protected function markPageAsDone( SMWDIWikiPage $di, $recdepth ) { |
| 239 | + $this->markHashAsDone( $di->getHash(), $recdepth ); |
| 240 | + } |
| 241 | + |
| 242 | + /** |
| 243 | + * Mark a task as done while making sure that the cache used for this |
| 244 | + * stays reasonably small. |
| 245 | + */ |
| 246 | + protected function markHashAsDone( $hash, $recdepth ) { |
291 | 247 | if ( count( $this->element_done ) >= self::MAX_CACHE_SIZE ) { |
292 | 248 | $this->element_done = array_slice( $this->element_done, |
293 | | - self::CACHE_BACKJUMP, |
294 | | - self::MAX_CACHE_SIZE - self::CACHE_BACKJUMP, |
295 | | - true ); |
| 249 | + self::CACHE_BACKJUMP, |
| 250 | + self::MAX_CACHE_SIZE - self::CACHE_BACKJUMP, |
| 251 | + true ); |
296 | 252 | } |
297 | | - $hash = $st->getHash(); |
298 | | - if ( !$this->isDone( $st ) ) { |
299 | | - $this->element_done[$hash] = $st->recdepth; // mark title as done, with given recursion |
| 253 | + if ( !$this->isHashDone( $hash, $recdepth ) ) { |
| 254 | + $this->element_done[$hash] = $recdepth; // mark title as done, with given recursion |
300 | 255 | } |
301 | 256 | unset( $this->element_queue[$hash] ); // make sure it is not in the queue |
302 | 257 | } |
303 | | - |
| 258 | + |
304 | 259 | /** |
305 | 260 | * Check if the given object has already been serialised at sufficient |
306 | 261 | * recursion depth. |
307 | | - * @param SMWSmallTitle $st specifying the object to check |
| 262 | + * @param SMWDIWikiPage $st specifying the object to check |
308 | 263 | */ |
309 | | - protected function isDone( SMWSmallTitle $st ) { |
310 | | - $hash = $st->getHash(); |
| 264 | + protected function isPageDone( SMWDIWikiPage $di, $recdepth ) { |
| 265 | + return $this->isHashDone( $di->getHash(), $recdepth ); |
| 266 | + } |
| 267 | + |
| 268 | + /** |
| 269 | + * Check if the given task has already been completed at sufficient |
| 270 | + * recursion depth. |
| 271 | + */ |
| 272 | + protected function isHashDone( $hash, $recdepth ) { |
311 | 273 | return ( ( array_key_exists( $hash, $this->element_done ) ) && |
312 | 274 | ( ( $this->element_done[$hash] == -1 ) || |
313 | | - ( ( $st->recdepth != -1 ) && ( $this->element_done[$hash] >= $st->recdepth ) ) ) ); |
| 275 | + ( ( $recdepth != -1 ) && ( $this->element_done[$hash] >= $recdepth ) ) ) ); |
314 | 276 | } |
315 | 277 | |
316 | 278 | /** |
— | — | @@ -386,11 +348,9 @@ |
387 | 349 | $rev = Revision::getTimeStampFromID( $title, $title->getLatestRevID() ); |
388 | 350 | if ( $rev < $revisiondate ) continue; |
389 | 351 | } |
390 | | - $st = new SMWSmallTitle(); |
391 | | - $st->dbkey = $title->getDBkey(); |
392 | | - $st->namespace = $title->getNamespace(); |
393 | | - $st->recdepth = $recursion==1 ? -1 : 1; |
394 | | - $this->element_queue[$st->getHash()] = $st; |
| 352 | + |
| 353 | + $diPage = SMWDIWikiPage::newFromTitle( $title ); |
| 354 | + $this->queuePage( $diPage, ( $recursion==1 ? -1 : 1 ) ); |
395 | 355 | } |
396 | 356 | |
397 | 357 | $this->serializer->startSerialization(); |
— | — | @@ -403,7 +363,8 @@ |
404 | 364 | $this->serializer->serializeExpData( SMWExporter::getOntologyExpData( $ontologyuri ) ); |
405 | 365 | |
406 | 366 | while ( count( $this->element_queue ) > 0 ) { |
407 | | - $this->serializeSmallTitle( reset( $this->element_queue ) ); |
| 367 | + $diPage = reset( $this->element_queue ); |
| 368 | + $this->serializePage( $diPage, $diPage->recdepth ); |
408 | 369 | $this->flush(); |
409 | 370 | $linkCache->clear(); // avoid potential memory leak |
410 | 371 | } |
— | — | @@ -444,18 +405,16 @@ |
445 | 406 | if ( !SMWExportController::fitsNsRestriction( $ns_restriction, $title->getNamespace() ) ) continue; |
446 | 407 | $a_count += 1; // DEBUG |
447 | 408 | |
448 | | - $st = new SMWSmallTitle(); |
449 | | - $st->dbkey = $title->getDBkey(); |
450 | | - $st->namespace = $title->getNamespace(); |
451 | | - $st->recdepth = 1; |
452 | | - $this->element_queue[$st->getHash()] = $st; |
| 409 | + $diPage = SMWDIWikiPage::newFromTitle( $title ); |
| 410 | + $this->queuePage( $diPage, 1 ); |
453 | 411 | |
454 | 412 | while ( count( $this->element_queue ) > 0 ) { |
455 | | - $this->serializeSmallTitle( reset( $this->element_queue ) ); |
| 413 | + $diPage = reset( $this->element_queue ); |
| 414 | + $this->serializePage( $diPage, $diPage->recdepth ); |
456 | 415 | // resolve dependencies that will otherwise not be printed |
457 | | - foreach ( $this->element_queue as $key => $staux ) { |
458 | | - if ( !smwfIsSemanticsProcessed( $staux->namespace ) || |
459 | | - !SMWExportController::fitsNsRestriction( $ns_restriction, $staux->namespace ) ) { |
| 416 | + foreach ( $this->element_queue as $key => $diaux ) { |
| 417 | + if ( !smwfIsSemanticsProcessed( $diaux->getNamespace() ) || |
| 418 | + !SMWExportController::fitsNsRestriction( $ns_restriction, $diaux->getNamespace() ) ) { |
460 | 419 | // Note: we do not need to check the cache to guess if an element was already |
461 | 420 | // printed. If so, it would not be included in the queue in the first place. |
462 | 421 | $d_count += 1; // DEBUG |
— | — | @@ -512,14 +471,16 @@ |
513 | 472 | |
514 | 473 | foreach ( $res as $row ) { |
515 | 474 | $foundpages = true; |
516 | | - $st = new SMWSmallTitle(); |
517 | | - $st->dbkey = $row->page_title; |
518 | | - $st->namespace = $row->page_namespace; |
519 | | - $st->recdepth = 0; |
520 | | - $this->serializeSmallTitle( $st ); |
521 | | - $this->flush(); |
522 | | - $linkCache->clear(); |
| 475 | + try { |
| 476 | + $diPage = new SMWDIWikiPage( $row->page_title, $row->page_namespace, '' ); |
| 477 | + $this->serializePage( $diPage, 0 ); |
| 478 | + $this->flush(); |
| 479 | + $linkCache->clear(); |
| 480 | + } catch ( SMWDataItemException $e ) { |
| 481 | + // strange data, who knows, not our DB table, keep calm and carry on |
| 482 | + } |
523 | 483 | } |
| 484 | + |
524 | 485 | if ( $foundpages ) { // add link to next result page |
525 | 486 | if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL |
526 | 487 | $nexturl = SMWExporter::expandURI( '&export;?offset=' ) . ( $offset + $limit ); |
Index: trunk/extensions/SemanticMediaWiki/includes/export/SMW_Exporter.php |
— | — | @@ -45,14 +45,11 @@ |
46 | 46 | * Create exportable data from a given semantic data record. |
47 | 47 | * |
48 | 48 | * @param $semdata SMWSemanticData |
49 | | - * @param $subject mixed SMWDIWikiPage to use as subject, or null to use the one from $semdata |
50 | 49 | * @return SMWExpData |
51 | 50 | */ |
52 | | - static public function makeExportData( SMWSemanticData $semdata, $subject = null ) { |
| 51 | + static public function makeExportData( SMWSemanticData $semdata ) { |
53 | 52 | self::initBaseURIs(); |
54 | | - if ( is_null( $subject ) ) { |
55 | | - $subject = $semdata->getSubject(); |
56 | | - } |
| 53 | + $subject = $semdata->getSubject(); |
57 | 54 | if ( $subject->getNamespace() == SMW_NS_PROPERTY ) { |
58 | 55 | $types = $semdata->getPropertyValues( new SMWDIProperty( '_TYPE' ) ); |
59 | 56 | } else { |
— | — | @@ -81,13 +78,13 @@ |
82 | 79 | */ |
83 | 80 | static public function makeExportDataForSubject( SMWDIWikiPage $diWikiPage, $typesvalueforproperty = null, $addStubData = false ) { |
84 | 81 | global $wgContLang; |
85 | | - $wikiPageExpElement = self::getDataItemExpElement( $diWikiPage, $diWikiPage ); |
| 82 | + $wikiPageExpElement = self::getDataItemExpElement( $diWikiPage ); |
86 | 83 | $result = new SMWExpData( $wikiPageExpElement ); |
87 | 84 | |
88 | 85 | if ( $diWikiPage->getSubobjectName() != '' ) { |
89 | 86 | $result->addPropertyObjectValue( self::getSpecialNsResource( 'rdf', 'type' ), self::getSpecialNsResource( 'swivt', 'Subject' ) ); |
90 | 87 | $masterPage = new SMWDIWikiPage( $diWikiPage->getDBkey(), $diWikiPage->getNamespace(), $diWikiPage->getInterwiki() ); |
91 | | - $masterExpElement = self::getDataItemExpElement( $masterPage, $masterPage ); |
| 88 | + $masterExpElement = self::getDataItemExpElement( $masterPage ); |
92 | 89 | $result->addPropertyObjectValue( self::getSpecialNsResource( 'swivt', 'masterPage' ), $masterExpElement ); |
93 | 90 | } else { |
94 | 91 | $pageTitle = str_replace( '_', ' ', $diWikiPage->getDBkey() ); |
— | — | @@ -145,14 +142,13 @@ |
146 | 143 | * @param $property SMWDIProperty |
147 | 144 | * @param $dataItems array of SMWDataItem objects for the given property |
148 | 145 | * @param $data SMWExpData to add the data to |
149 | | - * @param $masterPage SMWDIWikiPage to which the data belongs; needed for internal object URIs |
150 | 146 | */ |
151 | | - static public function addPropertyValues( SMWDIProperty $property, array $dataItems, SMWExpData &$expData, SMWDIWikiPage $masterPage ) { |
| 147 | + static public function addPropertyValues( SMWDIProperty $property, array $dataItems, SMWExpData &$expData ) { |
152 | 148 | if ( $property->isUserDefined() ) { |
153 | 149 | $pe = self::getResourceElementForProperty( $property ); |
154 | 150 | $peHelper = self::getResourceElementForProperty( $property, true ); |
155 | 151 | foreach ( $dataItems as $dataItem ) { |
156 | | - $ed = self::getDataItemExpElement( $dataItem, $masterPage ); |
| 152 | + $ed = self::getDataItemExpElement( $dataItem ); |
157 | 153 | if ( $ed !== null ) { |
158 | 154 | $expData->addPropertyObjectValue( $pe, $ed ); |
159 | 155 | } |
— | — | @@ -186,7 +182,7 @@ |
187 | 183 | ( $dataItem->getNamespace() != $diSubject->getNamespace() ) ) ) { |
188 | 184 | continue; |
189 | 185 | } |
190 | | - $ed = self::getDataItemExpElement( $dataItem, $masterPage ); |
| 186 | + $ed = self::getDataItemExpElement( $dataItem ); |
191 | 187 | if ( $ed !== null ) { |
192 | 188 | if ( ( $property->getKey() == '_CONC' ) && ( $ed->getSubject()->getUri() == '' ) ) { |
193 | 189 | // equivalent to anonymous class -> simplify description |
— | — | @@ -273,9 +269,6 @@ |
274 | 270 | $namespace = $importValue->getNS(); |
275 | 271 | $namespaceId = $importValue->getNSID(); |
276 | 272 | $localName = $importValue->getLocalName(); |
277 | | - } elseif ( self::isInternalObjectDiPage( $diWikiPage ) ) { // blank node |
278 | | - $localName = $namespace = $namespaceId = ''; |
279 | | - $diWikiPage = null; // do not associate any wiki page with blank nodes |
280 | 273 | } else { |
281 | 274 | $localName = ''; |
282 | 275 | if ( $diWikiPage->getNamespace() == SMW_NS_PROPERTY ) { |
— | — | @@ -537,10 +530,9 @@ |
538 | 531 | * SMWExporter::getSpecialPropertyResource(). |
539 | 532 | * |
540 | 533 | * @param $dataItem SMWDataItem |
541 | | - * @param $masterPage mixed SMWDIWikiPage to which the data belongs (needed for internal object URIs); or NULL if deemed irrelevant |
542 | 534 | * @return SMWExpElement |
543 | 535 | */ |
544 | | - static public function getDataItemExpElement( SMWDataItem $dataItem, $masterPage ) { |
| 536 | + static public function getDataItemExpElement( SMWDataItem $dataItem ) { |
545 | 537 | switch ( $dataItem->getDIType() ) { |
546 | 538 | case SMWDataItem::TYPE_NUMBER: |
547 | 539 | $lit = new SMWExpLiteral( $dataItem->getNumber(), 'http://www.w3.org/2001/XMLSchema#double', $dataItem ); |
— | — | @@ -585,7 +577,7 @@ |
586 | 578 | /// TODO |
587 | 579 | return null; |
588 | 580 | case SMWDataItem::TYPE_CONTAINER: |
589 | | - return self::makeExportData( $dataItem->getSemanticData(), $dataItem->getSubjectPage( $masterPage ) ); |
| 581 | + return self::makeExportData( $dataItem->getSemanticData() ); |
590 | 582 | case SMWDataItem::TYPE_WIKIPAGE: |
591 | 583 | return self::getResourceElementForWikiPage( $dataItem ); |
592 | 584 | case SMWDataItem::TYPE_CONCEPT: |
— | — | @@ -643,35 +635,4 @@ |
644 | 636 | return ( $dataItemType == SMWDataItem::TYPE_TIME ); |
645 | 637 | } |
646 | 638 | |
647 | | - /** |
648 | | - * Create a dataitem of a wikipage that is used to represent internal |
649 | | - * objects. These objects are used as anonymous placeholders that are |
650 | | - * only defined by their context. In particular, no two distinct |
651 | | - * dataitems for this wiki page should be assumed to represent the same |
652 | | - * object. |
653 | | - * |
654 | | - * @return SMWDIWikiPage |
655 | | - */ |
656 | | - static public function getInternalObjectDiPage() { |
657 | | - return new SMWDIWikiPage( 'SMWInternalObject', NS_SPECIAL, '' ); |
658 | | - } |
659 | | - |
660 | | - /** |
661 | | - * Check if the given wiki page represents an internal object. See |
662 | | - * SMWExporter::getInternalObjectDiPage() for details. |
663 | | - * |
664 | | - * @see SMWExporter::getInternalObjectDiPage() |
665 | | - * @param $diWikiPage SMWDIWikiPage |
666 | | - * @return boolean |
667 | | - */ |
668 | | - static public function isInternalObjectDiPage( SMWDIWikiPage $diWikiPage ) { |
669 | | - if ( $diWikiPage->getNamespace() == NS_SPECIAL && |
670 | | - $diWikiPage->getDBkey() == 'SMWInternalObject' && |
671 | | - $diWikiPage->getInterwiki() == '' ) { |
672 | | - return true; |
673 | | - } else { |
674 | | - return false; |
675 | | - } |
676 | | - } |
677 | | - |
678 | 639 | } |
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php |
— | — | @@ -117,12 +117,18 @@ |
118 | 118 | * @return boolean |
119 | 119 | */ |
120 | 120 | protected function loadDataItem( SMWDataItem $dataItem ) { |
| 121 | + if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) { |
| 122 | + // might throw an exception, we just pass it through |
| 123 | + $dataItem = $dataItem->getSemanticData()->getSubject(); |
| 124 | + } |
| 125 | + |
121 | 126 | if ( $dataItem->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { |
122 | 127 | $this->m_dataitem = $dataItem; |
123 | 128 | $this->m_textform = str_replace( '_', ' ', $dataItem->getDBkey() ); |
124 | 129 | $this->m_id = -1; |
125 | 130 | $this->m_title = null; |
126 | | - $this->m_fragment = $this->m_prefixedtext = ''; |
| 131 | + $this->m_fragment = $dataItem->getSubobjectName(); |
| 132 | + $this->m_prefixedtext = ''; |
127 | 133 | $this->m_caption = false; |
128 | 134 | if ( ( $this->m_fixNamespace != NS_MAIN ) && ( $this->m_fixNamespace != $dataItem->getNamespace() ) ) { |
129 | 135 | smwfLoadExtensionMessages( 'SemanticMediaWiki' ); |
— | — | @@ -138,8 +144,7 @@ |
139 | 145 | if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( !$this->isValid() ) || ( $this->m_caption === '' ) ) { |
140 | 146 | return $this->getCaption(); |
141 | 147 | } else { |
142 | | - return '[[:' . str_replace( "'", ''', $this->getPrefixedText() ) . |
143 | | - ( $this->m_fragment ? "#{$this->m_fragment}" : '' ) . '|' . $this->getCaption() . ']]'; |
| 148 | + return '[[:' . $this->getWikiLinkTarget() . '|' . $this->getCaption() . ']]'; |
144 | 149 | } |
145 | 150 | } |
146 | 151 | |
— | — | @@ -164,14 +169,16 @@ |
165 | 170 | return $this->getErrorText(); |
166 | 171 | } |
167 | 172 | if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) ) { |
168 | | - return $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText(); |
| 173 | + return ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . |
| 174 | + ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
169 | 175 | } elseif ( $this->m_dataitem->getNamespace() == NS_FILE ) { |
170 | 176 | // For images and other files, embed them and display |
171 | 177 | // their name, instead of just displaying their name |
| 178 | + // TODO? We forget about subobjecs/fragments here. |
172 | 179 | $fileName = str_replace( "'", ''', $this->getPrefixedText() ); |
173 | 180 | return '[[' . $fileName . '|' . $this->m_textform . '|frameless|border|text-top]]' . "<br />\n" . '[[:' . $fileName . '|' . $this->m_textform . ']]'; |
174 | 181 | } else { |
175 | | - return '[[:' . str_replace( "'", ''', $this->getPrefixedText() ) . '|' . $this->m_textform . ']]'; |
| 182 | + return '[[' . $this->getWikiLinkTarget() . '|' . $this->m_textform . ']]'; |
176 | 183 | } |
177 | 184 | } |
178 | 185 | |
— | — | @@ -191,13 +198,15 @@ |
192 | 199 | |
193 | 200 | public function getWikiValue() { |
194 | 201 | if ( $this->m_fixNamespace != NS_MAIN ) { // no explicit namespace needed! |
195 | | - return $this->getText(); |
| 202 | + $result = $this->getText(); |
196 | 203 | } elseif ( $this->m_dataitem->getNamespace() == NS_CATEGORY ) { |
197 | 204 | // escape to enable use in links; todo: not generally required/suitable :-/ |
198 | | - return ':' . $this->getPrefixedText(); |
| 205 | + $result = ':' . $this->getPrefixedText(); |
199 | 206 | } else { |
200 | | - return $this->getPrefixedText(); |
| 207 | + $result = $this->getPrefixedText(); |
201 | 208 | } |
| 209 | + |
| 210 | + return $result . ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
202 | 211 | } |
203 | 212 | |
204 | 213 | public function getHash() { |
— | — | @@ -309,10 +318,22 @@ |
310 | 319 | */ |
311 | 320 | protected function getCaption() { |
312 | 321 | return $this->m_caption !== false ? $this->m_caption : |
313 | | - ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ); |
| 322 | + ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . |
| 323 | + ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
314 | 324 | } |
315 | 325 | |
316 | 326 | /** |
| 327 | + * Compute a text that can be used in wiki text to link to this |
| 328 | + * datavalue. Processing includes some escaping and adding the |
| 329 | + * fragment. |
| 330 | + */ |
| 331 | + protected function getWikiLinkTarget() { |
| 332 | + return ':' . |
| 333 | + str_replace( "'", ''', $this->getPrefixedText() ) . |
| 334 | + ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
| 335 | + } |
| 336 | + |
| 337 | + /** |
317 | 338 | * Find the sortkey for this object. |
318 | 339 | * |
319 | 340 | * @deprecated Use SMWStore::getWikiPageSortKey(). |
Index: trunk/extensions/SemanticMediaWiki/includes/parserhooks/SMW_Subobject.php |
— | — | @@ -0,0 +1,72 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Class for the 'subobject' parser functions. |
| 6 | + * |
| 7 | + * |
| 8 | + * @since 1.6.3 |
| 9 | + * |
| 10 | + * @file SMW_Subobject.php |
| 11 | + * @ingroup SMW |
| 12 | + * @ingroup ParserHooks |
| 13 | + * |
| 14 | + * @author Markus Krötzsch |
| 15 | + */ |
| 16 | +class SMWSubobject { |
| 17 | + |
| 18 | + /** |
| 19 | + * Method for handling the subobject parser function. |
| 20 | + * |
| 21 | + * @since 1.6.3 |
| 22 | + * |
| 23 | + * @param Parser $parser |
| 24 | + */ |
| 25 | + public static function render( Parser &$parser ) { |
| 26 | + $params = func_get_args(); |
| 27 | + array_shift( $params ); // We already know the $parser ... |
| 28 | + |
| 29 | + $semanticData = new SMWContainerSemanticData(); |
| 30 | + $propertyName = null; |
| 31 | + foreach ( $params as $param ) { |
| 32 | + if ( is_null( $propertyName ) ) { |
| 33 | + $propertyName = trim( $param ); |
| 34 | + } else { |
| 35 | + $parts = explode( '=', trim( $param ), 2 ); |
| 36 | + |
| 37 | + // Only add the property when there is both a name and a value. |
| 38 | + if ( count( $parts ) == 2 ) { |
| 39 | + self::addPropertyValueToSemanticData( $parts[0], $parts[1], $semanticData ); |
| 40 | + } |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + $propertyDv = SMWPropertyValue::makeUserProperty( $propertyName ); |
| 45 | + $propertyDi = $propertyDv->getDataItem(); |
| 46 | + |
| 47 | + if ( !$propertyDi->isInverse() ) { |
| 48 | + try { |
| 49 | + $subObjectDi = new SMWDIContainer( $semanticData ); |
| 50 | + SMWParseData::getSMWData( $parser )->addPropertyObjectValue( $propertyDi, $subObjectDi ); |
| 51 | + } catch ( SMWDataItemException $e ) { |
| 52 | + SMWParseData::getSMWData( $parser )->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() ); |
| 53 | + } |
| 54 | + } // else: error reporting for this parser function unclear |
| 55 | + |
| 56 | + return ''; |
| 57 | + } |
| 58 | + |
| 59 | + protected static function addPropertyValueToSemanticData( $propertyName, $valueString, $semanticData ) { |
| 60 | + $propertyDv = SMWPropertyValue::makeUserProperty( $propertyName ); |
| 61 | + $propertyDi = $propertyDv->getDataItem(); |
| 62 | + |
| 63 | + if ( !$propertyDi->isInverse() ) { |
| 64 | + $valueDv = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $valueString ); |
| 65 | + $semanticData->addPropertyObjectValue( $propertyDi, $valueDv->getDataItem() ); |
| 66 | + // Take note of the error for storage (do this here and not in storage, thus avoiding duplicates). |
| 67 | + if ( !$valueDv->isValid() ) { |
| 68 | + $semanticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() ); |
| 69 | + } |
| 70 | + } // else: error reporting for this parser function unclear |
| 71 | + } |
| 72 | + |
| 73 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/SemanticMediaWiki/includes/parserhooks/SMW_Subobject.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 74 | + native |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Factbox.php |
— | — | @@ -82,7 +82,7 @@ |
83 | 83 | |
84 | 84 | foreach ( $propvalues as $dataItem ) { |
85 | 85 | $dataValue = SMWDataValueFactory::newDataItemValue( $dataItem, $propertyDi ); |
86 | | - |
| 86 | + |
87 | 87 | if ( $dataValue->isValid() ) { |
88 | 88 | $valuesHtml[] = $dataValue->getLongWikiText( true ) . $dataValue->getInfolinkText( SMW_OUTPUT_WIKI ); |
89 | 89 | } |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStoreQueryEngine.php |
— | — | @@ -812,7 +812,7 @@ |
813 | 813 | } elseif ( $comparator == '=' ) { |
814 | 814 | $expElement = SMWExporter::getDataItemHelperExpElement( $dataItem ); |
815 | 815 | if ( $expElement === null ) { |
816 | | - $expElement = SMWExporter::getDataItemExpElement( $dataItem, null ); |
| 816 | + $expElement = SMWExporter::getDataItemExpElement( $dataItem ); |
817 | 817 | } |
818 | 818 | $result = new SMWSparqlSingletonCondition( $expElement ); |
819 | 819 | $this->addOrderByDataForProperty( $result, $joinVariable, $orderByProperty, $dataItem->getDIType() ); |
— | — | @@ -832,11 +832,11 @@ |
833 | 833 | $orderByVariable = $result->orderByVariable; |
834 | 834 | |
835 | 835 | if ( $dataItem instanceof SMWDIWikiPage ) { |
836 | | - $expElement = SMWExporter::getDataItemExpElement( $dataItem->getSortKeyDataItem(), null ); |
| 836 | + $expElement = SMWExporter::getDataItemExpElement( $dataItem->getSortKeyDataItem() ); |
837 | 837 | } else { |
838 | 838 | $expElement = SMWExporter::getDataItemHelperExpElement( $dataItem ); |
839 | 839 | if ( $expElement === null ) { |
840 | | - $expElement = SMWExporter::getDataItemExpElement( $dataItem, null ); |
| 840 | + $expElement = SMWExporter::getDataItemExpElement( $dataItem ); |
841 | 841 | } |
842 | 842 | } |
843 | 843 | |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php |
— | — | @@ -471,7 +471,8 @@ |
472 | 472 | $db = wfGetDB( DB_SLAVE ); |
473 | 473 | |
474 | 474 | if ( $value instanceof SMWDIContainer ) { // recursive handling of containers |
475 | | - $joinfield = "t$tableindex." . reset( array_keys( $proptable->objectfields ) ); // this must be a type 'p' object |
| 475 | + $keys = array_keys( $proptable->objectfields ); |
| 476 | + $joinfield = "t$tableindex." . reset( $keys ); // this must be a type 'p' object |
476 | 477 | $proptables = self::getPropertyTables(); |
477 | 478 | $semanticData = $value->getSemanticData(); |
478 | 479 | |
— | — | @@ -832,7 +833,7 @@ |
833 | 834 | } |
834 | 835 | |
835 | 836 | if ( $di instanceof SMWDIContainer ) { // process subobjects recursively |
836 | | - $subObject = $di->getSubjectPage( $subject ); |
| 837 | + $subObject = $di->getSemanticData()->getSubject(); |
837 | 838 | $subObjectId = $this->prepareDBUpdates( $updates, $di->getSemanticData(), 0, $subObject ); |
838 | 839 | // Note: tables for container objects MUST have objectfields == array(<somename> => 'p') |
839 | 840 | reset( $proptable->objectfields ); |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStore.php |
— | — | @@ -24,7 +24,7 @@ |
25 | 25 | |
26 | 26 | public function deleteSubject( Title $subject ) { |
27 | 27 | $dataItem = SMWDIWikiPage::newFromTitle( $subject ); |
28 | | - $expResource = SMWExporter::getDataItemExpElement( $dataItem, $dataItem ); |
| 28 | + $expResource = SMWExporter::getDataItemExpElement( $dataItem ); |
29 | 29 | $this->deleteSparqlData( $expResource ); |
30 | 30 | parent::deleteSubject( $subject ); |
31 | 31 | } |
— | — | @@ -32,8 +32,8 @@ |
33 | 33 | public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) { |
34 | 34 | $oldWikiPage = SMWDIWikiPage::newFromTitle( $oldtitle ); |
35 | 35 | $newWikiPage = SMWDIWikiPage::newFromTitle( $newtitle ); |
36 | | - $oldExpResource = SMWExporter::getDataItemExpElement( $oldWikiPage, $oldWikiPage ); |
37 | | - $newExpResource = SMWExporter::getDataItemExpElement( $newWikiPage, $newWikiPage ); |
| 36 | + $oldExpResource = SMWExporter::getDataItemExpElement( $oldWikiPage ); |
| 37 | + $newExpResource = SMWExporter::getDataItemExpElement( $newWikiPage ); |
38 | 38 | $namespaces = array( $oldExpResource->getNamespaceId() => $oldExpResource->getNamespace() ); |
39 | 39 | $namespaces[$newExpResource->getNamespaceId()] = $newExpResource->getNamespace(); |
40 | 40 | $oldUri = SMWTurtleSerializer::getTurtleNameForExpElement( $oldExpResource ); |
— | — | @@ -62,7 +62,7 @@ |
63 | 63 | $expDataArray = $this->prepareUpdateExpData( $data ); |
64 | 64 | |
65 | 65 | if ( count( $expDataArray ) > 0 ) { |
66 | | - $subjectResource = SMWExporter::getDataItemExpElement( $data->getSubject(), $data->getSubject() ); |
| 66 | + $subjectResource = SMWExporter::getDataItemExpElement( $data->getSubject() ); |
67 | 67 | $this->deleteSparqlData( $subjectResource ); |
68 | 68 | |
69 | 69 | $turtleSerializer = new SMWTurtleSerializer( true ); |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_SemanticData.php |
— | — | @@ -181,8 +181,8 @@ |
182 | 182 | foreach ( $this->getProperties() as $property ) { |
183 | 183 | hash_update( $ctx, '_#_' . $property->getKey() . '##' ); |
184 | 184 | |
185 | | - foreach ( $this->getPropertyValues( $property ) as $dv ) { |
186 | | - hash_update( $ctx, '_#_' . $dv->getSerialization() ); |
| 185 | + foreach ( $this->getPropertyValues( $property ) as $di ) { |
| 186 | + hash_update( $ctx, '_#_' . $di->getSerialization() ); |
187 | 187 | } |
188 | 188 | } |
189 | 189 | |
— | — | @@ -218,6 +218,8 @@ |
219 | 219 | |
220 | 220 | /** |
221 | 221 | * Store a value for a property identified by its SMWDataItem object. |
| 222 | + * For container "pseudo" dataitems, this function also sets the master |
| 223 | + * page. |
222 | 224 | * |
223 | 225 | * @note There is no check whether the type of the given data item |
224 | 226 | * agrees with the type of the property. Since property types can |
— | — | @@ -243,6 +245,10 @@ |
244 | 246 | $this->mPropVals[$property->getKey()][] = $dataItem; |
245 | 247 | } |
246 | 248 | |
| 249 | + if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) { |
| 250 | + $dataItem->getSemanticData()->setMasterPage( $this->mSubject ); |
| 251 | + } |
| 252 | + |
247 | 253 | if ( !$property->isUserDefined() ) { |
248 | 254 | if ( $property->isShown() ) { |
249 | 255 | $this->mHasVisibleSpecs = true; |
Index: trunk/extensions/SemanticMediaWiki/includes/dataitems/SMW_DI_WikiPage.php |
— | — | @@ -95,8 +95,8 @@ |
96 | 96 | */ |
97 | 97 | public function getTitle() { |
98 | 98 | if ( $this->m_interwiki == '' ) { |
99 | | - return Title::makeTitleSafe( $this->m_namespace, $this->m_dbkey, '' ); |
100 | | - } else { |
| 99 | + return Title::makeTitleSafe( $this->m_namespace, $this->m_dbkey, $this->m_subobjectname ); |
| 100 | + } else { // TODO inefficient; incomplete for fragments (see above commment) |
101 | 101 | $datavalue = new SMWWikiPageValue( '_wpg' ); |
102 | 102 | $datavalue->setDataItem( $this ); |
103 | 103 | return Title::newFromText( $datavalue->getPrefixedText() ); |
— | — | @@ -134,7 +134,8 @@ |
135 | 135 | * @return SMWDIWikiPage |
136 | 136 | */ |
137 | 137 | public static function newFromTitle( Title $title ) { |
138 | | - return new SMWDIWikiPage( $title->getDBkey(), $title->getNamespace(), $title->getInterwiki() ); |
| 138 | + return new SMWDIWikiPage( $title->getDBkey(), $title->getNamespace(), |
| 139 | + $title->getInterwiki(), str_replace( ' ', '_', $title->getFragment() ) ); |
139 | 140 | } |
140 | 141 | |
141 | 142 | } |
Index: trunk/extensions/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php |
— | — | @@ -16,23 +16,25 @@ |
17 | 17 | * contain only immutable objects and values of basic types. Arrays are copied |
18 | 18 | * (lazily) when cloning in PHP, so later changes in the cloce will not affect |
19 | 19 | * the original. |
| 20 | + * |
| 21 | + * In contrast to normal SMWSemanticData objects, SMWContainerSemanticData can |
| 22 | + * be created without specifying a subject. In this case, the subject is some |
| 23 | + * "anonymous" object that is left unspecified (for search) or generated later |
| 24 | + * (for storage). The method hasAnonymousSubject() should be used to check for |
| 25 | + * this case (as the method getSubject() will always return a valid subject). |
| 26 | + * See the documentation of SMWDIContainer for further details. |
20 | 27 | */ |
21 | 28 | class SMWContainerSemanticData extends SMWSemanticData { |
22 | 29 | |
23 | 30 | /** |
24 | | - * If true, the object will not allow further changes. |
25 | | - * @var boolean |
26 | | - */ |
27 | | - protected $m_immutable = false; |
28 | | - |
29 | | - /** |
30 | | - * Constructor. |
| 31 | + * Construct a data container that refers to an anonymous subject. See |
| 32 | + * the documenation of the class for details. |
31 | 33 | * |
32 | 34 | * @param boolean $noDuplicates stating if duplicate data should be avoided |
33 | 35 | */ |
34 | 36 | public function __construct( $noDuplicates = true ) { |
35 | | - $subject = SMWExporter::getInternalObjectDiPage(); |
36 | | - parent::__construct( $subject, $noDuplicates ); |
| 37 | + $subject = new SMWDIWikiPage( 'SMWInternalObject', NS_SPECIAL, '' ); |
| 38 | + return parent::__construct( $subject, $noDuplicates ); |
37 | 39 | } |
38 | 40 | |
39 | 41 | /** |
— | — | @@ -43,22 +45,37 @@ |
44 | 46 | } |
45 | 47 | |
46 | 48 | /** |
47 | | - * Clone handler. Make any clone mutable again. |
| 49 | + * Change the subject of this semantic data container so that it is used |
| 50 | + * as a subobject of the given master page. |
| 51 | + * |
| 52 | + * This "contextualizes" the data to belong to a given (master) wiki |
| 53 | + * page. It happens automatically when adding the object as part of a |
| 54 | + * property value to another SMWSemanticData object. |
| 55 | + * |
| 56 | + * @note This method could be extended to allow custom subobject names |
| 57 | + * to be set instead of using the hash. Note, however, that the length |
| 58 | + * of the subobject name in the database is limited in SQLStore2. To |
| 59 | + * make subobjects for sections of a page, this limit would have to be |
| 60 | + * extended. |
| 61 | + * |
| 62 | + * @param SMWDIWikiPage $masterPage |
48 | 63 | */ |
49 | | - public function __clone() { |
50 | | - $this->m_immutable = false; |
| 64 | + public function setMasterPage( SMWDIWikiPage $masterPage ) { |
| 65 | + $subobject = $this->getHash(); // 32 chars: current max length of subobject name in store |
| 66 | + $subobject{0} = '_'; // mark as anonymous subobject; hash is still good |
| 67 | + $this->mSubject = new SMWDIWikiPage( $masterPage->getDBkey(), |
| 68 | + $masterPage->getNamespace(), $masterPage->getInterwiki(), |
| 69 | + $subobject ); |
| 70 | + foreach ( $this->getProperties() as $property ) { |
| 71 | + foreach ( $this->getPropertyValues( $property ) as $di ) { |
| 72 | + if ( $di->getDIType() == SMWDataItem::TYPE_CONTAINER ) { |
| 73 | + $di->getSemanticData()->setMasterPage( $this->mSubject ); |
| 74 | + } |
| 75 | + } |
| 76 | + } |
51 | 77 | } |
52 | 78 | |
53 | 79 | /** |
54 | | - * Freeze the object: no more change operations allowed after calling |
55 | | - * this. Normally this is only called when passing the object to an |
56 | | - * SMWDIContainer. Other code should not need this. |
57 | | - */ |
58 | | - public function makeImmutable() { |
59 | | - $this->m_immutable = true; |
60 | | - } |
61 | | - |
62 | | - /** |
63 | 80 | * Change the object to become an exact copy of the given |
64 | 81 | * SMWSemanticData object. Useful to convert arbitrary such |
65 | 82 | * objects into SMWContainerSemanticData objects. |
— | — | @@ -66,7 +83,6 @@ |
67 | 84 | * @param $semanticData SMWSemanticData |
68 | 85 | */ |
69 | 86 | public function copyDataFrom( SMWSemanticData $semanticData ) { |
70 | | - $this->throwImmutableException(); |
71 | 87 | $this->mSubject = $semanticData->getSubject(); |
72 | 88 | $this->mProperties = $semanticData->getProperties(); |
73 | 89 | $this->mPropVals = array(); |
— | — | @@ -79,42 +95,61 @@ |
80 | 96 | } |
81 | 97 | |
82 | 98 | /** |
83 | | - * Store a value for a property identified by its SMWDataItem object, |
84 | | - * if the object was not set to immutable. |
85 | | - * |
86 | | - * @param $property SMWDIProperty |
87 | | - * @param $dataItem SMWDataItem |
| 99 | + * Check if the subject of this container is an anonymous object. |
| 100 | + * See the documenation of the class for details. |
| 101 | + * @return boolean |
88 | 102 | */ |
89 | | - public function addPropertyObjectValue( SMWDIProperty $property, SMWDataItem $dataItem ) { |
90 | | - $this->throwImmutableException(); |
91 | | - parent::addPropertyObjectValue( $property, $dataItem ); |
| 103 | + public function hasAnonymousSubject() { |
| 104 | + if ( $this->mSubject->getNamespace() == NS_SPECIAL && |
| 105 | + $this->mSubject->getDBkey() == 'SMWInternalObject' && |
| 106 | + $this->mSubject->getInterwiki() == '' ) { |
| 107 | + return true; |
| 108 | + } else { |
| 109 | + return false; |
| 110 | + } |
92 | 111 | } |
93 | 112 | |
94 | 113 | /** |
95 | | - * Delete all data other than the subject, if the object was not set to |
96 | | - * immutable. |
| 114 | + * Return subject to which the stored semantic annotation refer to, or |
| 115 | + * throw an exception if the subject is anonymous (if the data has not |
| 116 | + * been contextualized with setMasterPage() yet). |
| 117 | + * |
| 118 | + * @return SMWDIWikiPage subject |
97 | 119 | */ |
98 | | - public function clear() { |
99 | | - $this->throwImmutableException(); |
100 | | - parent::clear(); |
| 120 | + public function getSubject() { |
| 121 | + if ( $this->hasAnonymousSubject() ) { |
| 122 | + throw new SMWDataItemException("Trying to get the subject of a container data item that has not been given any. The method hasAnonymousSubject() can be called to detect this situation."); |
| 123 | + } else { |
| 124 | + return $this->mSubject; |
| 125 | + } |
101 | 126 | } |
102 | 127 | |
103 | | - /** |
104 | | - * Throw an exception if the object is immutable. |
105 | | - */ |
106 | | - protected function throwImmutableException() { |
107 | | - if ( $this->m_immutable ) { |
108 | | - throw new SMWDataItemException( 'Changing the SMWSemanticData object that belongs to a data item of type SMWDIContainer is not allowed. Data items are immutable.' ); |
109 | | - } |
110 | | - } |
111 | 128 | } |
112 | 129 | |
113 | 130 | /** |
114 | 131 | * This class implements container data items that can store SMWSemanticData |
115 | | - * objects. In this sense, data items of this type are a kind of "internal |
116 | | - * object" that can contain the data that is otherwise associated with a wiki |
117 | | - * page. |
| 132 | + * objects. Containers are not dataitems in the proper sense: they do not |
| 133 | + * represent a single, opaque value that can be assigned to a property. Rather, |
| 134 | + * a container represents a collection of individual property-value assignments. |
| 135 | + * When a container is stored, these individual data assignments are stored -- |
| 136 | + * the data managed by SMW never contains any "container", just individual |
| 137 | + * property assignments. Likewise, when a container is used in search, it is |
| 138 | + * interpreted as a patterns of possible property assignments, and this pattern |
| 139 | + * is searched for. |
118 | 140 | * |
| 141 | + * The data encapsulated in a container data item is essentially an |
| 142 | + * SMWSemanticData object. The data represented by the container consists of |
| 143 | + * the data stored in this SMWSemanticData object. As a special case, it is |
| 144 | + * possible that the subject of this data is left unspecified. The name of the |
| 145 | + * subject in this case is not part of the data: when storing such containers, a |
| 146 | + * new name will be invented; when searching for such containers, only the |
| 147 | + * property-value pairs are considered relevant in the search. If the subject is |
| 148 | + * given (i.e. not anonymous), and the container DI is used as a property value |
| 149 | + * for a wikipage Foo, then the subject of the container must be a subobject of |
| 150 | + * Foo, for example Foo#section. In this case "Foo" is called the master page of |
| 151 | + * the container. To get a suitable subject for a given master page, the method |
| 152 | + * getSubjectPage() can be used. |
| 153 | + * |
119 | 154 | * @since 1.6 |
120 | 155 | * |
121 | 156 | * @author Markus Krötzsch |
— | — | @@ -137,7 +172,6 @@ |
138 | 173 | */ |
139 | 174 | public function __construct( SMWContainerSemanticData $semanticData ) { |
140 | 175 | $this->m_semanticData = $semanticData; |
141 | | - $this->m_semanticData->makeImmutable(); |
142 | 176 | } |
143 | 177 | |
144 | 178 | public function getDIType() { |
— | — | @@ -166,20 +200,6 @@ |
167 | 201 | } |
168 | 202 | |
169 | 203 | /** |
170 | | - * Get an internal object that can be used as a subject for this data. |
171 | | - * This subject is not part of the data itself but makes the connection |
172 | | - * to the wiki page for which this data will be stored. This allows to |
173 | | - * encode a kind of provenance information when storing container data, |
174 | | - * useful to find the source of the data, and to retrieve more data when |
175 | | - * a structural (helper) node is found in a query etc. |
176 | | - * |
177 | | - * @return SMWDIWikiPage |
178 | | - */ |
179 | | - public function getSubjectPage( SMWDIWikiPage $masterPage ) { |
180 | | - return new SMWDIWikiPage( $masterPage->getDBkey(), $masterPage->getNamespace(), $masterPage->getInterwiki(), '_' . $this->getHash() ); |
181 | | - } |
182 | | - |
183 | | - /** |
184 | 204 | * Create a data item from the provided serialization string and type |
185 | 205 | * ID. |
186 | 206 | * @return SMWDIContainer |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Setup.php |
— | — | @@ -270,6 +270,7 @@ |
271 | 271 | $wgAutoloadClasses['SMWAsk'] = $phDir . 'SMW_Ask.php'; |
272 | 272 | $wgAutoloadClasses['SMWShow'] = $phDir . 'SMW_Show.php'; |
273 | 273 | $wgAutoloadClasses['SMWInfo'] = $phDir . 'SMW_Info.php'; |
| 274 | + $wgAutoloadClasses['SMWSubobject'] = $phDir . 'SMW_Subobject.php'; |
274 | 275 | $wgAutoloadClasses['SMWConcept'] = $phDir . 'SMW_Concept.php'; |
275 | 276 | $wgAutoloadClasses['SMWSet'] = $phDir . 'SMW_Set.php'; |
276 | 277 | $wgAutoloadClasses['SMWSetRecurringEvent'] = $phDir . 'SMW_SetRecurringEvent.php'; |
— | — | @@ -621,6 +622,7 @@ |
622 | 623 | $magicWords['ask'] = array( 0, 'ask' ); |
623 | 624 | $magicWords['show'] = array( 0, 'show' ); |
624 | 625 | $magicWords['info'] = array( 0, 'info' ); |
| 626 | + $magicWords['setobject'] = array( 0, 'setobject' ); |
625 | 627 | $magicWords['concept'] = array( 0, 'concept' ); |
626 | 628 | $magicWords['set'] = array( 0, 'set' ); |
627 | 629 | $magicWords['set_recurring_event'] = array( 0, 'set_recurring_event' ); |
— | — | @@ -673,6 +675,7 @@ |
674 | 676 | $parser->setFunctionHook( 'ask', array( 'SMWAsk', 'render' ) ); |
675 | 677 | $parser->setFunctionHook( 'show', array( 'SMWShow', 'render' ) ); |
676 | 678 | $parser->setFunctionHook( 'info', array( 'SMWInfo', 'render' ) ); |
| 679 | + $parser->setFunctionHook( 'setobject', array( 'SMWSubobject', 'render' ) ); |
677 | 680 | $parser->setFunctionHook( 'concept', array( 'SMWConcept', 'render' ) ); |
678 | 681 | $parser->setFunctionHook( 'set', array( 'SMWSet', 'render' ) ); |
679 | 682 | $parser->setFunctionHook( 'set_recurring_event', array( 'SMWSetRecurringEvent', 'render' ) ); |