r101266 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r101265‎ | r101266 | r101267 >
Date:14:55, 29 October 2011
Author:mkroetzsch
Status:deferred
Tags:
Comment:
* Add an optional page context to be used when parsing datavalues
* Use this to parse user inputs like "#section" and to name auxiliary subobjects
* Modify container handling to use/expect named subjects
* Allow subobject data to be managed in SMWSemanticData
* Use this in new #subobject parser function to create named subobjects
* Clean up various deprecated functions
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_CompatibilityHelpers.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DataValueFactory.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_Factbox.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_ParseData.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_SemanticData.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DataValue.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/parserhooks/SMW_Subobject.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStore.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SqlStubSemanticData.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/SMW_ParseData.php
@@ -106,15 +106,20 @@
107107 $propertyDv = SMWPropertyValue::makeUserProperty( $propertyName );
108108 if ( !$propertyDv->isValid() ) return $propertyDv;
109109 $propertyDi = $propertyDv->getDataItem();
110 - $result = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $value, $caption );
111110
 111+ $semandticData = self::getSMWData( $parser );
 112+
 113+ $result = SMWDataValueFactory::newPropertyObjectValue( $propertyDi,
 114+ $value, $caption, $semandticData->getSubject() );
 115+
112116 if ( $propertyDi->isInverse() ) {
113117 $result->addError( wfMsgForContent( 'smw_noinvannot' ) );
114118 } elseif ( $storeAnnotation && ( self::getSMWData( $parser ) !== null ) ) {
115 - self::getSMWData( $parser )->addPropertyObjectValue( $propertyDi, $result->getDataItem() );
 119+ $semandticData->addPropertyObjectValue( $propertyDi, $result->getDataItem() );
116120 // Take note of the error for storage (do this here and not in storage, thus avoiding duplicates).
117121 if ( !$result->isValid() ) {
118 - self::getSMWData( $parser )->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() );
 122+ $semandticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ),
 123+ $propertyDi->getDiWikiPage() );
119124 }
120125 }
121126
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DataValue.php
@@ -61,12 +61,25 @@
6262 protected $m_dataitem;
6363
6464 /**
65 - * The text label of the respective property or false if none given.
 65+ * The property for which this value is constructed or null if none
 66+ * given. Property pages are used to make settings that affect parsing
 67+ * and display, hence it is sometimes needed to know them.
 68+ *
6669 * @var SMWDIProperty
6770 */
6871 protected $m_property = null;
6972
7073 /**
 74+ * Wiki page in the context of which the value is to be interpreted, or
 75+ * null if not given (or not on a page). This information is used to
 76+ * parse user values such as "#subsection" which only make sense when
 77+ * used on a certain page.
 78+ *
 79+ * @var SMWDIWikiPage
 80+ */
 81+ protected $m_contextPage = null;
 82+
 83+ /**
7184 * The text label to be used for output or false if none given.
7285 * @var string
7386 */
@@ -151,7 +164,7 @@
152165 // e.g. math. In general, we are not prepared to handle such content properly, and we
153166 // also have no means of obtaining the user input at this point. Hence the assignement
154167 // just fails.
155 - // Note: \x07 was used in MediaWiki 1.11.0, \x7f is used now
 168+ // Note: \x07 was used in MediaWiki 1.11.0, \x7f is used now (backwards compatiblity, b/c)
156169 if ( ( strpos( $value, "\x7f" ) === false ) && ( strpos( $value, "\x07" ) === false ) ) {
157170 $this->parseUserValue( $value ); // may set caption if not set yet, depending on datavalue
158171 } else {
@@ -190,8 +203,9 @@
191204 }
192205
193206 /**
194 - * Specify the property to which this value refers. Used to generate search links and
195 - * to find custom settings that relate to the property.
 207+ * Specify the property to which this value refers. Property pages are
 208+ * used to make settings that affect parsing and display, hence it is
 209+ * sometimes needed to know them.
196210 *
197211 * @param SMWDIProperty $property
198212 */
@@ -200,6 +214,19 @@
201215 }
202216
203217 /**
 218+ * Specify the wiki page to which this value refers. This information is
 219+ * used to parse user values such as "#subsection" which only make sense
 220+ * when used on a certain page.
 221+ *
 222+ * @since 1.7
 223+ *
 224+ * @param SMWDIWikiPage $contextPage
 225+ */
 226+ public function setContextPage( SMWDIWikiPage $contextPage ) {
 227+ $this->m_contextPage = $contextPage;
 228+ }
 229+
 230+ /**
204231 * Change the caption (the text used for displaying this datavalue). The given
205232 * value must be a string.
206233 *
@@ -219,21 +246,22 @@
220247 }
221248
222249 /**
223 - * Servicelinks are special kinds of infolinks that are created from current parameters
224 - * and in-wiki specification of URL templates. This method adds the current property's
225 - * servicelinks found in the messages. The number and content of the parameters is
226 - * depending on the datatype, and the service link message is usually crafted with a
 250+ * Servicelinks are special kinds of infolinks that are created from
 251+ * current parameters and in-wiki specification of URL templates. This
 252+ * method adds the current property's servicelinks found in the
 253+ * messages. The number and content of the parameters is depending on
 254+ * the datatype, and the service link message is usually crafted with a
227255 * particular datatype in mind.
228256 */
229257 public function addServiceLinks() {
230258 if ( $this->mHasServiceLinks ) {
231259 return;
232260 }
233 - if ( $this->m_property !== null ) {
 261+ if ( !is_null( $this->m_property ) ) {
234262 $propertyDiWikiPage = $this->m_property->getDiWikiPage();
235263 }
236 - if ( ( $this->m_property === null ) || ( $propertyDiWikiPage === null ) ) {
237 - return; // no property known
 264+ if ( is_null( $this->m_property ) || is_null( $propertyDiWikiPage ) ) {
 265+ return; // no property known, or not associated with a page
238266 }
239267
240268 $args = $this->getServiceLinkParams();
@@ -566,9 +594,10 @@
567595 abstract public function getWikiValue();
568596
569597 /**
570 - * Return a short string that unambiguously specify the type of this value.
571 - * This value will globally be used to identify the type of a value (in spite
572 - * of the class it actually belongs to, which can still implement various types).
 598+ * Return a short string that unambiguously specify the type of this
 599+ * value. This value will globally be used to identify the type of a
 600+ * value (in spite of the class it actually belongs to, which can still
 601+ * implement various types).
573602 */
574603 public function getTypeID() {
575604 return $this->m_typeid;
@@ -576,15 +605,16 @@
577606
578607 /**
579608 * Return an array of SMWLink objects that provide additional resources
580 - * for the given value.
581 - * Captions can contain some HTML markup which is admissible for wiki
582 - * text, but no more. Result might have no entries but is always an array.
 609+ * for the given value. Captions can contain some HTML markup which is
 610+ * admissible for wiki text, but no more. Result might have no entries
 611+ * but is always an array.
583612 */
584613 public function getInfolinks() {
585 - if ( $this->isValid() && ( $this->m_property !== null ) ) {
 614+ if ( $this->isValid() && !is_null( $this->m_property ) ) {
586615 if ( !$this->mHasSearchLink ) { // add default search link
587616 $this->mHasSearchLink = true;
588 - $this->m_infolinks[] = SMWInfolink::newPropertySearchLink( '+', $this->m_property->getLabel(), $this->getWikiValue() );
 617+ $this->m_infolinks[] = SMWInfolink::newPropertySearchLink( '+',
 618+ $this->m_property->getLabel(), $this->getWikiValue() );
589619 }
590620
591621 if ( !$this->mHasServiceLinks ) { // add further service links
@@ -607,8 +637,8 @@
608638 /**
609639 * Return a string that identifies the value of the object, and that can
610640 * be used to compare different value objects.
611 - * Possibly overwritten by subclasses (e.g. to ensure that returned value is
612 - * normalised first)
 641+ * Possibly overwritten by subclasses (e.g. to ensure that returned
 642+ * value is normalized first)
613643 *
614644 * @return string
615645 */
@@ -631,31 +661,12 @@
632662 }
633663
634664 /**
635 - * Convenience method that returns the DB key that holds the value that is
636 - * to be used for sorting data of this kind. If this datatype does not
637 - * support sorting, then null is returned here.
638 - *
639 - * @deprecated since SMW 1.6, use getDataItem()->get...() instead. Will vanish before SMW 1.7.
640 - */
641 - public function getValueKey() {
642 - $dbkeys = $this->getDBkeys();
643 - $validx = $this->getValueIndex();
644 -
645 - if ( array_key_exists( $validx, $dbkeys ) ) {
646 - return $dbkeys[$validx];
647 - } else {
648 - return null;
649 - }
650 - }
651 -
652 - /**
653 - * Return TRUE if a value was defined and understood by the given type,
 665+ * Return true if a value was defined and understood by the given type,
654666 * and false if parsing errors occured or no value was given.
655667 *
656668 * @return boolean
657669 */
658670 public function isValid() {
659 - $this->unstub();
660671 return !$this->mHasErrors && isset( $this->m_dataitem );
661672 }
662673
@@ -684,11 +695,12 @@
685696 * Creates an error if the value is illegal.
686697 */
687698 protected function checkAllowedValues() {
688 - if ( $this->m_property !== null ) {
 699+ if ( !is_null( $this->m_property ) ) {
689700 $propertyDiWikiPage = $this->m_property->getDiWikiPage();
690701 }
691702
692 - if ( ( $this->m_property === null ) || ( $propertyDiWikiPage === null ) || ( !isset( $this->m_dataitem ) ) ) {
 703+ if ( is_null( $this->m_property ) || is_null( $propertyDiWikiPage ) ||
 704+ !isset( $this->m_dataitem ) ) {
693705 return; // no property known, or no data to check
694706 }
695707
@@ -728,35 +740,4 @@
729741 }
730742 }
731743
732 - /**
733 - * @deprecated Use SMWDataItem::setDataItem() and SMWCompatibilityHelpers::dataItemFromDBKeys(). Will vanish before SMW 1.7.
734 - */
735 - private function setDBkeys( array $args ) {}
736 - /**
737 - * @deprecated This function is no longer used and should not be implemented in subclasses.
738 - */
739 - protected function parseDBkeys( $args ) {}
740 - /**
741 - * @deprecated Use SMWCompatibilityHelpers::getDBkeysFromDataItem(). Will vanish before SMW 1.7.
742 - */
743 - public function getDBkeys() {}
744 - /**
745 - * @deprecated Use SMWCompatibilityHelpers::getSignatureFromDataItemId(). Will vanish before SMW 1.7.
746 - */
747 - public function getSignature() {}
748 - /**
749 - * @deprecated Use SMWCompatibilityHelpers::getIndexFromDataItemId(). Will vanish before SMW 1.7.
750 - */
751 - public function getValueIndex() {}
752 - /**
753 - * @deprecated Use SMWCompatibilityHelpers::getIndexFromDataItemId(). Will vanish before SMW 1.7.
754 - */
755 - public function getLabelIndex() {}
756 - /**
757 - * @deprecated There is no more unstubbing now. Data is kept in lean
758 - * data items. If any other fields need costy initialization,
759 - * subclasses can create their own mechanism.
760 - */
761 - public function unstub() {}
762 -
763744 }
\ No newline at end of file
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php
@@ -26,7 +26,7 @@
2727 protected function parseUserValueOrQuery( $value, $queryMode ) {
2828 if ( $value == '' ) {
2929 $this->addError( wfMsg( 'smw_novalues' ) );
30 -
 30+
3131 if ( $queryMode ) {
3232 return new SMWThingDescription();
3333 } else {
@@ -36,8 +36,14 @@
3737
3838 if ( $queryMode ) {
3939 $subdescriptions = array();
 40+ } elseif ( is_null( $this->m_contextPage ) ) {
 41+ $semanticData = SMWContainerSemanticData::makeAnonymousContainer();
4042 } else {
41 - $semanticData = new SMWContainerSemanticData();
 43+ $subobjectName = hash( 'md4', $value, false); // md4 is probably fastest of PHP's hashes
 44+ $subject = new SMWDIWikiPage( $this->m_contextPage->getDBkey(),
 45+ $this->m_contextPage->getNamespace(), $this->m_contextPage->getInterwiki(),
 46+ $subobjectName );
 47+ $semanticData = new SMWContainerSemanticData( $subject );
4248 }
4349
4450 $values = preg_split( '/[\s]*;[\s]*/u', trim( $value ) );
@@ -77,7 +83,7 @@
7884 }
7985
8086 $this->addError( $dataValue->getErrors() );
81 - $valueIndex++;
 87+ ++$valueIndex;
8288 }
8389 }
8490 ++$propertyIndex;
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php
@@ -83,15 +83,31 @@
8484
8585 protected function parseUserValue( $value ) {
8686 global $wgContLang;
87 - $value = ltrim( rtrim( $value, ' ]' ), ' [' ); // support inputs like " [[Test]] "
 87+
 88+ // support inputs like " [[Test]] ";
 89+ // note that this only works in pages if $smwgLinksInValues is set to true
 90+ $value = ltrim( rtrim( $value, ' ]' ), ' [' );
 91+
8892 if ( $this->m_caption === false ) {
8993 $this->m_caption = $value;
9094 }
9195
9296 if ( $value != '' ) {
93 - $this->m_title = Title::newFromText( $value, $this->m_fixNamespace );
 97+ if ( $value{0} == '#' ) {
 98+ if ( is_null( $this->m_contextPage ) ) {
 99+ $this->addError( wfMsgForContent( 'smw_notitle', $value ) );
 100+ return;
 101+ } else {
 102+ $this->m_title = Title::makeTitle( $this->m_contextPage->getNamespace(),
 103+ $this->m_contextPage->getDBkey(), substr( $value, 1 ),
 104+ $this->m_contextPage->getInterwiki() );
 105+ }
 106+ } else {
 107+ $this->m_title = Title::newFromText( $value, $this->m_fixNamespace );
 108+ }
 109+
94110 ///TODO: Escape the text so users can see punctuation problems (bug 11666).
95 - if ( $this->m_title === null ) {
 111+ if ( is_null( $this->m_title ) ) {
96112 $this->addError( wfMsgForContent( 'smw_notitle', $value ) );
97113 } elseif ( ( $this->m_fixNamespace != NS_MAIN ) &&
98114 ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) {
Index: trunk/extensions/SemanticMediaWiki/includes/parserhooks/SMW_Subobject.php
@@ -17,9 +17,9 @@
1818
1919 /**
2020 * Method for handling the subobject parser function.
21 - *
 21+ *
2222 * @since 1.7
23 - *
 23+ *
2424 * @param Parser $parser
2525 */
2626 public static function render( Parser &$parser ) {
@@ -27,37 +27,19 @@
2828
2929 $params = func_get_args();
3030 array_shift( $params ); // We already know the $parser ...
 31+ $subobjectName = trim( array_shift( $params ) );
3132
32 - $semanticData = new SMWContainerSemanticData();
33 - $propertyName = null;
34 -
 33+ $semanticData = SMWParseData::getSMWData( $parser )->getChild( $subobjectName );
 34+
3535 foreach ( $params as $param ) {
36 - if ( is_null( $propertyName ) ) {
37 - $propertyName = trim( $param );
38 - } else {
39 - $parts = explode( '=', trim( $param ), 2 );
 36+ $parts = explode( '=', trim( $param ), 2 );
4037
41 - // Only add the property when there is both a name and a value.
42 - if ( count( $parts ) == 2 ) {
43 - self::addPropertyValueToSemanticData( $parts[0], $parts[1], $semanticData );
44 - }
 38+ // Only add the property when there is both a name and a value.
 39+ if ( count( $parts ) == 2 ) {
 40+ self::addPropertyValueToSemanticData( $parts[0], $parts[1], $semanticData );
4541 }
4642 }
4743
48 - $propertyDv = SMWPropertyValue::makeUserProperty( $propertyName );
49 - $propertyDi = $propertyDv->getDataItem();
50 -
51 - if ( !$propertyDi->isInverse() ) {
52 - try {
53 - $subObjectDi = new SMWDIContainer( $semanticData );
54 - SMWParseData::getSMWData( $parser )->addPropertyObjectValue( $propertyDi, $subObjectDi );
55 - } catch ( SMWDataItemException $e ) {
56 - SMWParseData::getSMWData( $parser )->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() );
57 - }
58 - } else {
59 - self::$m_errors[] = wfMsgForContent( 'smw_noinvannot' );
60 - }
61 -
6244 return smwfEncodeMessages( self::$m_errors );
6345 }
6446
@@ -66,12 +48,14 @@
6749 $propertyDi = $propertyDv->getDataItem();
6850
6951 if ( !$propertyDi->isInverse() ) {
70 - $valueDv = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $valueString );
 52+ $valueDv = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $valueString,
 53+ false, $semanticData->getSubject() );
7154 $semanticData->addPropertyObjectValue( $propertyDi, $valueDv->getDataItem() );
7255
7356 // Take note of the error for storage (do this here and not in storage, thus avoiding duplicates).
7457 if ( !$valueDv->isValid() ) {
75 - $semanticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() );
 58+ $semanticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ),
 59+ $propertyDi->getDiWikiPage() );
7660 self::$m_errors = array_merge( self::$m_errors, $valueDv->getErrors() );
7761 }
7862 } else {
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Factbox.php
@@ -57,10 +57,11 @@
5858 'swmfactboxheadbrowse'
5959 );
6060 $text .= '<div class="smwfact">' .
61 - '<span class="smwfactboxhead">' . wfMsgForContent( 'smw_factbox_head', $browselink->getWikiText() ) . '</span>' .
62 - '<span class="smwrdflink">' . $rdflink->getWikiText() . '</span>' .
63 - '<table class="smwfacttable">' . "\n";
64 -
 61+ '<span class="smwfactboxhead">' .
 62+ wfMsgForContent( 'smw_factbox_head', $browselink->getWikiText() ) . '</span>' .
 63+ '<span class="smwrdflink">' . $rdflink->getWikiText() . '</span>' .
 64+ '<table class="smwfacttable">' . "\n";
 65+
6566 foreach ( $semdata->getProperties() as $propertyDi ) {
6667 $propertyDv = SMWDataValueFactory::newDataItemValue( $propertyDi, null );
6768 if ( !$propertyDi->isShown() ) { // showing this is not desired, hide
@@ -76,24 +77,32 @@
7778 }
7879
7980 $propvalues = $semdata->getPropertyValues( $propertyDi );
80 -
 81+
8182 $valuesHtml = array();
82 -
 83+
8384 foreach ( $propvalues as $dataItem ) {
8485 $dataValue = SMWDataValueFactory::newDataItemValue( $dataItem, $propertyDi );
8586
8687 if ( $dataValue->isValid() ) {
87 - $valuesHtml[] = $dataValue->getLongWikiText( true ) . $dataValue->getInfolinkText( SMW_OUTPUT_WIKI );
 88+ $valuesHtml[] = $dataValue->getLongWikiText( true ) .
 89+ $dataValue->getInfolinkText( SMW_OUTPUT_WIKI );
8890 }
8991 }
90 -
 92+
9193 $text .= $GLOBALS['wgLang']->listToText( $valuesHtml );
92 -
 94+
9395 $text .= '</td></tr>';
9496 }
95 -
 97+
9698 $text .= '</table></div>';
9799 }
 100+
 101+ // Debugging: show all child objects
 102+ // (does not play too well with Records, hence disabled by default)
 103+// foreach ( $semdata->getAllChildren() as $childSemanticData ) {
 104+// $text .= SMWFactbox::getFactboxText( $childSemanticData, $showfactbox );
 105+// }
 106+
98107 wfProfileOut( 'SMWFactbox::printFactbox (SMW)' );
99108 return $text;
100109 }
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SqlStubSemanticData.php
@@ -90,7 +90,7 @@
9191 try {
9292 if ( $propertyDiId == SMWDataItem::TYPE_CONTAINER ) {
9393 $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys );
94 - $semanticData = new SMWContainerSemanticData();
 94+ $semanticData = new SMWContainerSemanticData( $diSubWikiPage );
9595 $semanticData->copyDataFrom( smwfGetStore()->getSemanticData( $diSubWikiPage ) );
9696
9797 $di = new SMWDIContainer( $semanticData );
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php
@@ -216,7 +216,7 @@
217217 foreach ( $data as $dbkeys ) {
218218 try {
219219 $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys );
220 - $semanticData = new SMWContainerSemanticData();
 220+ $semanticData = new SMWContainerSemanticData( $diSubWikiPage );
221221 $semanticData->copyDataFrom( $this->getSemanticData( $diSubWikiPage ) );
222222 $result[] = new SMWDIContainer( $semanticData );
223223 } catch ( SMWDataItemException $e ) {
@@ -735,6 +735,9 @@
736736 $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, $sortkey );
737737 $updates = array(); // collect data for bulk updates; format: tableid => updatearray
738738 $this->prepareDBUpdates( $updates, $data, $sid, $subject );
 739+ foreach ( $data->getAllChildren() as $childData ) {
 740+ $this->prepareDBUpdates( $updates, $childData, 0, $childData->getSubject() );
 741+ }
739742
740743 $db = wfGetDB( DB_MASTER );
741744 foreach ( $updates as $tablename => $uvals ) {
@@ -1285,7 +1288,7 @@
12861289 'smw_namespace' => $dbtypes['n'] . ' NOT NULL',
12871290 'smw_title' => $dbtypes['t'] . ' NOT NULL',
12881291 'smw_iw' => $dbtypes['w'] . ' NOT NULL',
1289 - 'smw_subobject' => $dbtypes['w'] . ' NOT NULL',
 1292+ 'smw_subobject' => $dbtypes['t'] . ' NOT NULL',
12901293 'smw_sortkey' => $dbtypes['t'] . ' NOT NULL'
12911294 ),
12921295 $db,
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStore.php
@@ -60,6 +60,10 @@
6161 parent::doDataUpdate( $data );
6262
6363 $expDataArray = $this->prepareUpdateExpData( $data );
 64+ foreach ( $data->getAllChildren() as $childData ) {
 65+ $subExpDataArray = $this->prepareUpdateExpData( $childData );
 66+ $expDataArray = $expDataArray + $subExpDataArray;
 67+ }
6468
6569 if ( count( $expDataArray ) > 0 ) {
6670 $subjectResource = SMWExporter::getDataItemExpElement( $data->getSubject() );
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_CompatibilityHelpers.php
@@ -75,7 +75,10 @@
7676 case SMWDataItem::TYPE_GEO:
7777 return new SMWDIGeoCoord( array( 'lat' => (float)$dbkeys[0], 'lon' => (float)$dbkeys[1] ) );
7878 case SMWDataItem::TYPE_CONTAINER:
79 - $semanticData = new SMWContainerSemanticData();
 79+ // provided for backwards compatibility only;
 80+ // today containers are read from the store as substructures,
 81+ // not retrieved as single complex values
 82+ $semanticData = SMWContainerSemanticData::makeAnonymousContainer();
8083 foreach ( reset( $dbkeys ) as $value ) {
8184 if ( is_array( $value ) && ( count( $value ) == 2 ) ) {
8285 $diP = new SMWDIProperty( reset( $value ), false );
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_SemanticData.php
@@ -55,7 +55,31 @@
5656 */
5757 protected $mProperties = array();
5858
 59+
5960 /**
 61+ * Array of SMWSemanticData objects that refer to subobjects of this
 62+ * object and for which this object is the parent. Elements in this
 63+ * array are created (only) by calling the method getChild().
 64+ * Existing data from other SMWSemanticData objects can be imported
 65+ * into such children by calling the child's importDataFrom()
 66+ * method.
 67+ *
 68+ * The array is indexed by the subobject name of the children's
 69+ * subjects.
 70+ *
 71+ * @note The subject SMWDIWikiPage of a child is always a subobject of
 72+ * the subject of its parent. Nevertheless, it is perfectly possible to
 73+ * create an SMWSemanticData for a subject that is a subobject without
 74+ * this SMWSemanticData being a child of anything.
 75+ *
 76+ * @since 1.7
 77+ * @see SMWSemanticData::getChild()
 78+ *
 79+ * @var array of string => SMWSemanticData
 80+ */
 81+ protected $mChildren = array();
 82+
 83+ /**
6084 * States whether the container holds any normal properties.
6185 *
6286 * @var boolean
@@ -87,14 +111,26 @@
88112
89113 /**
90114 * SMWDIWikiPage object that is the subject of this container.
91 - * Subjects that are null are used to represent "internal objects"
92 - * only.
 115+ * Subjects can never be null (and this is ensured in all methods setting
 116+ * them in this class).
93117 *
94118 * @var SMWDIWikiPage
95119 */
96120 protected $mSubject;
97121
98122 /**
 123+ * If the data describes a subobject, this field refers to its parent
 124+ * object. To associate a semantic data with its parent, the method
 125+ * getChild() can be used (see documentation there for details).
 126+ *
 127+ * @since 1.7
 128+ * @see SMWSemanticData::getChild()
 129+ *
 130+ * @var SMWSemanticData or null
 131+ */
 132+ protected $mParentSemanticData = null;
 133+
 134+ /**
99135 * Constructor.
100136 *
101137 * @param SMWDIWikiPage $subject to which this data refers
@@ -117,9 +153,6 @@
118154 * output, then the Semdata container will at least look as if properly
119155 * initialised (though empty).
120156 *
121 - * @note It might be even better to have other members with stub object
122 - * data that is used for serializing, thus using much less data.
123 - *
124157 * @return array
125158 */
126159 public function __sleep() {
@@ -127,7 +160,7 @@
128161 }
129162
130163 /**
131 - * Return subject to which the stored semantic annotation refer to.
 164+ * Return subject to which the stored semantic annotations refer to.
132165 *
133166 * @return SMWDIWikiPage subject
134167 */
@@ -136,6 +169,68 @@
137170 }
138171
139172 /**
 173+ * Return a semantic data object to store data of the subobject with
 174+ * the given name. If no data container exists for this purpose yet,
 175+ * a new one will be created. Globally, child data has the same meaning
 176+ * as if it was used in a separate SMWSemanticData (with the same
 177+ * subobject as subject but which is not a child). The child-parent
 178+ * association is merely used to attach extra data to an SMWSemanticData
 179+ * so that a single object can carry information about all related
 180+ * subobjects.
 181+ *
 182+ * Contrary to biological intuition, children are always managed by the
 183+ * (unique) parent: when calling getChild() on a child SMWSemanticData,
 184+ * the new child will be attached to the old child's parent. So there is
 185+ * no hierarchy of children and all existing children can be accessed
 186+ * through the parent. In the rare case that the given subobject name for
 187+ * the child is the same as the subobject name of the subject of $this,
 188+ * the method wil return $this instead of creating a new child.
 189+ *
 190+ * Overall, this management ensures that there will be at most one
 191+ * SMWSemanticData object for any subobjectName. Note that the relation
 192+ * parent-child is not the same as the relation page-subobject. A parent
 193+ * SMWSemanticData can still refer to a subject with an empty subobject
 194+ * name, while a child's subobject name might be empty.
 195+ *
 196+ * @see SMWSemanticData::importDataFrom()
 197+ * @see SMWSemanticData::mChildren
 198+ *
 199+ * @since 1.7
 200+ *
 201+ * @param String $subobjectName must be non-empty
 202+ * @return SMWSemanticData
 203+ */
 204+ public function getChild( $subobjectName ) {
 205+ if ( $subobjectName == $this->mSubject->getSubobjectName() ) {
 206+ return $this;
 207+ } elseif ( !is_null( $this->mParentSemanticData ) ) {
 208+ return $this->mParentSemanticData->getChild( $subobjectName );
 209+ } elseif ( array_key_exists( $subobjectName, $this->mChildren ) ) {
 210+ return $this->mChildren[$subobjectName];
 211+ } else {
 212+ $diSubWikiPage = new SMWDIWikiPage( $this->mSubject->getDBkey(),
 213+ $this->mSubject->getNamespace(), $this->mSubject->getInterwiki(),
 214+ $subobjectName );
 215+ $result = new SMWSemanticData( $diSubWikiPage );
 216+ $result->mParentSemanticData = $this;
 217+ $this->mChildren[$subobjectName] = $result;
 218+ return $result;
 219+ }
 220+ }
 221+
 222+ /**
 223+ * Return an array of SMWSemanticData objects for all children of this
 224+ * object, indexed by the subobject name that they are using.
 225+ *
 226+ * @since 1.7
 227+ *
 228+ * @return array of SMWSemanticData
 229+ */
 230+ public function getAllChildren() {
 231+ return $this->mChildren;
 232+ }
 233+
 234+ /**
140235 * Get the array of all properties that have stored values.
141236 *
142237 * @return array of SMWDIProperty objects
@@ -174,9 +269,8 @@
175270 public function getHash() {
176271 $ctx = hash_init( 'md5' );
177272
178 - if ( $this->mSubject !== null ) { // here and below, use "_#_" to separate values; really not much care needed here
179 - hash_update( $ctx, '_#_' . $this->mSubject->getSerialization() );
180 - }
 273+ // here and below, use "_#_" to separate values; really not much care needed here
 274+ hash_update( $ctx, '_#_' . $this->mSubject->getSerialization() );
181275
182276 foreach ( $this->getProperties() as $property ) {
183277 hash_update( $ctx, '_#_' . $property->getKey() . '##' );
@@ -186,6 +280,10 @@
187281 }
188282 }
189283
 284+ foreach ( $this->mChildren as $child ) {
 285+ hash_update( $ctx, '_#_' . $child->getHash() . '##' );
 286+ }
 287+
190288 return hash_final( $ctx );
191289 }
192290
@@ -218,8 +316,6 @@
219317
220318 /**
221319 * Store a value for a property identified by its SMWDataItem object.
222 - * For container "pseudo" dataitems, this function also sets the master
223 - * page.
224320 *
225321 * @note There is no check whether the type of the given data item
226322 * agrees with the type of the property. Since property types can
@@ -245,10 +341,6 @@
246342 $this->mPropVals[$property->getKey()][] = $dataItem;
247343 }
248344
249 - if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) {
250 - $dataItem->getSemanticData()->setMasterPage( $this->mSubject );
251 - }
252 -
253345 if ( !$property->isUserDefined() ) {
254346 if ( $property->isShown() ) {
255347 $this->mHasVisibleSpecs = true;
@@ -298,6 +390,60 @@
299391 $this->mHasVisibleProps = false;
300392 $this->mHasVisibleSpecs = false;
301393 $this->stubObject = false;
 394+ $mParentSemanticData = null;
 395+ $this->mChildren = array();
302396 }
303397
 398+ /**
 399+ * Add all data from the given SMWSemanticData. Children will be added
 400+ * recursively and might be moved to the parent of $this object (if it
 401+ * is a child of something else).
 402+ *
 403+ * @note The subject of the SMWSemanticData that is imported is not
 404+ * relevant to the result of this operation, but the subobject names of
 405+ * its children (if any) will be used. Therefore, if one of the children
 406+ * has the same subobject name as the subject of the SMWSemanticData
 407+ * into which the data is imported, then the data of imported parent
 408+ * and the eponymous child will be combined into a single object.
 409+ * Example: we have data about "Foo#Bar" (no children) and we import
 410+ * data about "Baz" with a child "Baz#Bar". Then the result will be
 411+ * about "Foo#Bar" and have no children but all data from the three
 412+ * sources. The original data from "Foo#Bar" is kept, the data from
 413+ * "Baz" is imported (ignoring the name "Baz"), and the data of the
 414+ * child "Baz#Bar" is merged into "Foo#Bar" (using only the subobject
 415+ * name). While slightly subtle, this should make sense in most cases.
 416+ * Typically, if "Baz" != "Foo" then "Baz" is just some internal page
 417+ * name that is used as a placeholder. Children can never hold data
 418+ * about other pages, so mergnig all data is most likely desired.
 419+ *
 420+ * @since 1.7
 421+ * @see SMWSemanticData::getChild()
 422+ *
 423+ * @param $semanticData SMWSemanticData object to copy from
 424+ */
 425+ public function importDataFrom( SMWSemanticData $semanticData ) {
 426+ // Shortcut when copying into empty objects that don't ask for more duplicate elimination:
 427+ if ( count( $this->mProperties ) == 0 &&
 428+ ( $semanticData->mNoDuplicates >= $this->mNoDuplicates ) ) {
 429+ $this->mProperties = $semanticData->getProperties();
 430+ $this->mPropVals = array();
 431+ foreach ( $this->mProperties as $property ) {
 432+ $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues( $property );
 433+ }
 434+ $this->mHasVisibleProps = $semanticData->hasVisibleProperties();
 435+ $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties();
 436+ } else {
 437+ foreach ( $semanticData->getProperties() as $property ) {
 438+ $values = $semanticData->getPropertyValues( $property );
 439+ foreach ( $values as $dataItem ) {
 440+ $this->addPropertyObjectValue( $property, $dataItem);
 441+ }
 442+ }
 443+ }
 444+
 445+ foreach ( $semanticData->getAllChildren() as $subobjectName => $child ) {
 446+ $this->getChild( $subobjectName )->importDataFrom( $child );
 447+ }
 448+ }
 449+
304450 }
\ No newline at end of file
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DataValueFactory.php
@@ -13,7 +13,7 @@
1414 * Factory class for creating SMWDataValue objects for supplied types or
1515 * properties and data values.
1616 *
17 - * The class has the main entry point newTypeIDValue(), which creates a new
 17+ * The class has the main entry point newTypeIdValue(), which creates a new
1818 * datavalue object, possibly with preset user values, captions and
1919 * property names. To create suitable datavalues for a given property, the
2020 * method newPropertyObjectValue() can be used.
@@ -40,7 +40,8 @@
4141 static private $mTypeAliases;
4242
4343 /**
44 - * Array of class names for creating new SMWDataValue, indexed by type id.
 44+ * Array of class names for creating new SMWDataValue, indexed by type
 45+ * id.
4546 *
4647 * @var array of string
4748 */
@@ -76,32 +77,42 @@
7778 );
7879
7980 /**
80 - * Create a value from a type id. If no $value is given, an empty container
81 - * is created, the value of which can be set later on.
 81+ * Create a value from a type id. If no $value is given, an empty
 82+ * container is created, the value of which can be set later on.
8283 *
83 - * @param $typeid string id string for the given type
84 - * @param $value mixed user value string, or false if unknown
 84+ * @param $typeId string id string for the given type
 85+ * @param $valueString mixed user value string, or false if unknown
8586 * @param $caption mixed user-defined caption, or false if none given
86 - * @param $property SMWDIProperty property object for which this value is made, or NULL
 87+ * @param $property SMWDIProperty property object for which this value is made, or null
 88+ * @param $contextPage SMWDIWikiPage that provides a context for parsing the value string, or null
8789 *
8890 * @return SMWDataValue
8991 */
90 - static public function newTypeIdValue( $typeid, $value = false, $caption = false, $property = null ) {
 92+ static public function newTypeIdValue( $typeId, $valueString = false, $caption = false,
 93+ $property = null, $contextPage = null ) {
 94+
9195 self::initDatatypes();
9296
93 - if ( array_key_exists( $typeid, self::$mTypeClasses ) ) {
94 - $result = new self::$mTypeClasses[$typeid]( $typeid );
 97+ if ( array_key_exists( $typeId, self::$mTypeClasses ) ) {
 98+ $result = new self::$mTypeClasses[$typeId]( $typeId );
9599 } else {
96 - return new SMWErrorValue( $typeid, wfMsgForContent( 'smw_unknowntype', $typeid ), $value, $caption );
 100+ return new SMWErrorValue( $typeId,
 101+ wfMsgForContent( 'smw_unknowntype', $typeId ),
 102+ $valueString, $caption );
97103 }
98104
99 - if ( $property !== null ) {
 105+ if ( !is_null( $property ) ) {
100106 $result->setProperty( $property );
101107 }
102 - if ( $value !== false ) {
103 - $result->setUserValue( $value, $caption );
 108+
 109+ if ( !is_null( $contextPage ) ) {
 110+ $result->setContextPage( $contextPage );
104111 }
105112
 113+ if ( $valueString !== false ) {
 114+ $result->setUserValue( $valueString, $caption );
 115+ }
 116+
106117 return $result;
107118 }
108119
@@ -116,12 +127,12 @@
117128 */
118129 static public function newDataItemValue( SMWDataItem $dataItem, $property, $caption = false ) {
119130 if ( $property !== null ) {
120 - $typeid = $property->findPropertyTypeID();
 131+ $typeId = $property->findPropertyTypeID();
121132 } else {
122 - $typeid = self::$mDefaultDataItemTypeIds[$dataItem->getDiType()];
 133+ $typeId = self::$mDefaultDataItemTypeIds[$dataItem->getDiType()];
123134 }
124135
125 - $result = self::newTypeIdValue( $typeid, false, $caption, $property );
 136+ $result = self::newTypeIdValue( $typeId, false, $caption, $property );
126137 $result->setDataItem( $dataItem );
127138 if ( $caption !== false ) {
128139 $result->setCaption( $caption );
@@ -135,13 +146,13 @@
136147 * appropriate data item class for processing data of this type. See
137148 * SMWDataItem for possible values.
138149 *
139 - * @param $typeid string id string for the given type
 150+ * @param $typeId string id string for the given type
140151 * @return integer data item ID
141152 */
142 - static public function getDataItemId( $typeid ) {
 153+ static public function getDataItemId( $typeId ) {
143154 self::initDatatypes();
144 - if ( array_key_exists( $typeid, self::$mTypeDataItemIds ) ) {
145 - return self::$mTypeDataItemIds[$typeid];
 155+ if ( array_key_exists( $typeId, self::$mTypeDataItemIds ) ) {
 156+ return self::$mTypeDataItemIds[$typeId];
146157 } else {
147158 return SMWDataItem::TYPE_NOTYPE;
148159 }
@@ -149,26 +160,27 @@
150161
151162 /**
152163 * Create a value for the given property, provided as an SMWDIProperty
153 - * object. If no value is given, an empty container is created, the value
154 - * of which can be set later on.
 164+ * object. If no value is given, an empty container is created, the
 165+ * value of which can be set later on.
155166 *
156 - * @param $property SMWDIProperty
157 - * @param $value mixed
158 - * @param $caption mixed
 167+ * @param $property SMWDIProperty property object for which this value is made
 168+ * @param $valueString mixed user value string, or false if unknown
 169+ * @param $caption mixed user-defined caption, or false if none given
 170+ * @param $contextPage SMWDIWikiPage that provides a context for parsing the value string, or null
159171 *
160172 * @return SMWDataValue
161173 */
162 - static public function newPropertyObjectValue( SMWDIProperty $property, $value = false, $caption = false ) {
163 - if ( $property->isInverse() ) {
164 - return self::newTypeIdValue( '_wpg', $value, $caption, $property );
165 - } else {
166 - return self::newTypeIdValue( $property->findPropertyTypeID(), $value, $caption, $property );
167 - }
 174+ static public function newPropertyObjectValue( SMWDIProperty $property, $valueString = false,
 175+ $caption = false, $contextPage = null ) {
 176+
 177+ $typeId = $property->isInverse() ? '_wpg' : $property->findPropertyTypeID();
 178+ return self::newTypeIdValue( $typeId, $valueString, $caption, $property, $contextPage );
168179 }
169180
170181 /**
171 - * Gather all available datatypes and label<=>id<=>datatype associations.
172 - * This method is called before most methods of this factory.
 182+ * Gather all available datatypes and label<=>id<=>datatype
 183+ * associations. This method is called before most methods of this
 184+ * factory.
173185 */
174186 static protected function initDatatypes() {
175187 global $smwgContLang;
@@ -348,28 +360,4 @@
349361 return self::$mTypeLabels;
350362 }
351363
352 - /**
353 - * Create an SMWDataValue object that can hold values for the type that the
354 - * given SMWTypesValue object specifies. If no $value is given, an empty
355 - * container is created, the value of which can be set later on.
356 - *
357 - * @param $typevalue SMWTypesValue Represents the type of the object
358 - * @param $value mixed user value string, or false if unknown
359 - * @param $caption mixed user-defined caption or false if none given
360 - * @param $property SMWDIProperty property object for which this value was made, or null
361 - *
362 - * @deprecated Like all datavalues, SMWTypesValue objects should only be
363 - * used for parsing type inputs, or for producing formatted outputs.
364 - * Internal functions like datavalue creation should avoid them.
365 - * Use newTypeIdValue() instead. This function will vanish before SMW 1.7.
366 - */
367 - static public function newTypeObjectValue( SMWTypesValue $typeValue, $value = false, $caption = false, $property = null ) {
368 - if ( !$typeValue->isValid() ) { // just return the error, pass it through
369 - $result = self::newTypeIDValue( '__err' );
370 - $result->addError( $typeValue->getErrors() );
371 - return $result;
372 - }
373 - return self::newTypeIDValue( $typeValue->getDBkey(), $value, $caption, $property );
374 - }
375 -
376364 }
\ No newline at end of file
Index: trunk/extensions/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php
@@ -7,20 +7,14 @@
88 /**
99 * Subclass of SMWSemanticData that is used to store the data in SMWDIContainer
1010 * objects. It is special since the subject that the stored property-value pairs
11 - * refer to is not specified explicitly. Instead, the subject used in container
12 - * data items is determined by the stored data together with the page that the
13 - * data item is assigned to (the "master page" of this data). Maintaining the
14 - * relation to the master page is important for data management since the
15 - * subjects of container data items must be deleted when deleting the value.
 11+ * refer may or may not be specified explicitly. This can be tested with
 12+ * hasAnonymousSubject(). When trying to access the subject in anonymous state,
 13+ * an Exception will be thrown. Anonymous container data items are used when no
 14+ * page context is available, e.g. when specifying such a value in a search form
 15+ * where the parent page is not known.
1616 *
17 - * Therefore, this container data provides a method setMasterPage() that is used
18 - * to define the master page. SMWSemanticData will always call this method when
19 - * it is given a container data item to store. Until this is done, the subject
20 - * of the container is "anonymous" -- it has no usable name. This can be tested
21 - * with hasAnonymousSubject(). When trying to access the subject in this state,
22 - * an Exception will be thrown. Note that container data items that are not
23 - * related to any master page are necessary, e.g. when specifying such a value
24 - * in a search form where the master page is not known.
 17+ * Besides this change, the subclass mainly is needed to restroe the disabled
 18+ * serialization of SMWSemanticData.
2519 *
2620 * See also the documentation of SMWDIContainer.
2721 *
@@ -33,75 +27,29 @@
3428
3529 /**
3630 * Construct a data container that refers to an anonymous subject. See
37 - * the documenation of the class for details.
 31+ * the documentation of the class for details.
3832 *
 33+ * @since 1.7
 34+ *
3935 * @param boolean $noDuplicates stating if duplicate data should be avoided
4036 */
41 - public function __construct( $noDuplicates = true ) {
 37+ public static function makeAnonymousContainer( $noDuplicates = true ) {
4238 $subject = new SMWDIWikiPage( 'SMWInternalObject', NS_SPECIAL, '' );
43 - return parent::__construct( $subject, $noDuplicates );
 39+ return new SMWContainerSemanticData( $subject, $noDuplicates );
4440 }
4541
4642 /**
4743 * Restore complete serialization which is disabled in SMWSemanticData.
4844 */
4945 public function __sleep() {
50 - return array( 'mSubject', 'mProperties', 'mPropVals', 'mHasVisibleProps', 'mHasVisibleSpecs', 'mNoDuplicates' );
 46+ return array( 'mSubject', 'mProperties', 'mPropVals',
 47+ 'mHasVisibleProps', 'mHasVisibleSpecs', 'mNoDuplicates' );
5148 }
5249
5350 /**
54 - * Change the subject of this semantic data container so that it is used
55 - * as a subobject of the given master page.
56 - *
57 - * This "contextualizes" the data to belong to a given (master) wiki
58 - * page. It happens automatically when adding the object as part of a
59 - * property value to another SMWSemanticData object.
60 - *
61 - * @note This method could be extended to allow custom subobject names
62 - * to be set instead of using the hash. Note, however, that the length
63 - * of the subobject name in the database is limited in SQLStore2. To
64 - * make subobjects for sections of a page, this limit would have to be
65 - * extended.
66 - *
67 - * @param SMWDIWikiPage $masterPage
68 - */
69 - public function setMasterPage( SMWDIWikiPage $masterPage ) {
70 - $subobject = $this->getHash(); // 32 chars: current max length of subobject name in store
71 - $subobject{0} = '_'; // mark as anonymous subobject; hash is still good
72 - $this->mSubject = new SMWDIWikiPage( $masterPage->getDBkey(),
73 - $masterPage->getNamespace(), $masterPage->getInterwiki(),
74 - $subobject );
75 - foreach ( $this->getProperties() as $property ) {
76 - foreach ( $this->getPropertyValues( $property ) as $di ) {
77 - if ( $di->getDIType() == SMWDataItem::TYPE_CONTAINER ) {
78 - $di->getSemanticData()->setMasterPage( $this->mSubject );
79 - }
80 - }
81 - }
82 - }
83 -
84 - /**
85 - * Change the object to become an exact copy of the given
86 - * SMWSemanticData object. Useful to convert arbitrary such
87 - * objects into SMWContainerSemanticData objects.
88 - *
89 - * @param $semanticData SMWSemanticData
90 - */
91 - public function copyDataFrom( SMWSemanticData $semanticData ) {
92 - $this->mSubject = $semanticData->getSubject();
93 - $this->mProperties = $semanticData->getProperties();
94 - $this->mPropVals = array();
95 - foreach ( $this->mProperties as $property ) {
96 - $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues( $property );
97 - }
98 - $this->mHasVisibleProps = $semanticData->hasVisibleProperties();
99 - $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties();
100 - $this->mNoDuplicates = $semanticData->mNoDuplicates;
101 - }
102 -
103 - /**
10451 * Check if the subject of this container is an anonymous object.
10552 * See the documenation of the class for details.
 53+ *
10654 * @return boolean
10755 */
10856 public function hasAnonymousSubject() {
@@ -123,12 +71,36 @@
12472 */
12573 public function getSubject() {
12674 if ( $this->hasAnonymousSubject() ) {
127 - 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.");
 75+ throw new SMWDataItemException("Trying to get the subject of a container data item that has not been given any. This container can only be used as a search pattern.");
12876 } else {
12977 return $this->mSubject;
13078 }
13179 }
13280
 81+ /**
 82+ * Change the object to become an exact copy of the given
 83+ * SMWSemanticData object. This is used to make other types of
 84+ * SMWSemanticData into an SMWContainerSemanticData. To copy objects of
 85+ * the same type, PHP clone() should be used.
 86+ *
 87+ * @since 1.7
 88+ *
 89+ * @param $semanticData SMWSemanticData object to copy from
 90+ */
 91+ public function copyDataFrom( SMWSemanticData $semanticData ) {
 92+ $this->mSubject = $semanticData->getSubject();
 93+ $this->mProperties = $semanticData->getProperties();
 94+ $this->mPropVals = array();
 95+ foreach ( $this->mProperties as $property ) {
 96+ $this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues( $property );
 97+ }
 98+ $this->mHasVisibleProps = $semanticData->hasVisibleProperties();
 99+ $this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties();
 100+ $this->mNoDuplicates = $semanticData->mNoDuplicates;
 101+ $this->mChildren = $semanticData->mChildren;
 102+ $this->mParentSemanticData = $semanticData->mParentSemanticData;
 103+ }
 104+
133105 }
134106
135107 /**
@@ -143,20 +115,15 @@
144116 * assignments, and this pattern is searched for.
145117 *
146118 * The data encapsulated in a container data item is essentially an
147 - * SMWSemanticData object of class SMWContainerSemanticData. This class has a
148 - * special handling for the subject of the stored annotations (i.e. the
149 - * subobject). See the repsective documentation for details.
150 - *
 119+ * SMWSemanticData object of class SMWContainerSemanticData. This class allows
 120+ * the subject to be kept anonymous if not known (if no context page is
 121+ * available for finding a suitable subobject name). See the repsective
 122+ * documentation for details.
 123+ *
151124 * Being a mere placeholder/template for other data, an SMWDIContainer is not
152125 * immutable as the other basic data items. New property-value pairs can always
153 - * be added to the internal SMWContainerSemanticData. Moreover, the subobject
154 - * that the container refers to is set only after it has been created, when the
155 - * data item is added as a property value to some existing SMWSemanticData.
156 - * Only after this has happened is the subobject fully defined. Any attempt to
157 - * obtain the subobject from the internal SMWContainerSemanticData before it
158 - * has been defined will result in an SMWDataItemException.
 126+ * be added to the internal SMWContainerSemanticData.
159127 *
160 - *
161128 * @since 1.6
162129 *
163130 * @author Markus Krötzsch
@@ -166,6 +133,7 @@
167134
168135 /**
169136 * Internal value.
 137+ *
170138 * @var SMWSemanticData
171139 */
172140 protected $m_semanticData;
@@ -209,6 +177,7 @@
210178 /**
211179 * Create a data item from the provided serialization string and type
212180 * ID.
 181+ *
213182 * @return SMWDIContainer
214183 */
215184 public static function doUnserialize( $serialization ) {