Index: trunk/extensions/SemanticMediaWiki/includes/SMW_ParseData.php |
— | — | @@ -106,15 +106,20 @@ |
107 | 107 | $propertyDv = SMWPropertyValue::makeUserProperty( $propertyName ); |
108 | 108 | if ( !$propertyDv->isValid() ) return $propertyDv; |
109 | 109 | $propertyDi = $propertyDv->getDataItem(); |
110 | | - $result = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $value, $caption ); |
111 | 110 | |
| 111 | + $semandticData = self::getSMWData( $parser ); |
| 112 | + |
| 113 | + $result = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, |
| 114 | + $value, $caption, $semandticData->getSubject() ); |
| 115 | + |
112 | 116 | if ( $propertyDi->isInverse() ) { |
113 | 117 | $result->addError( wfMsgForContent( 'smw_noinvannot' ) ); |
114 | 118 | } elseif ( $storeAnnotation && ( self::getSMWData( $parser ) !== null ) ) { |
115 | | - self::getSMWData( $parser )->addPropertyObjectValue( $propertyDi, $result->getDataItem() ); |
| 119 | + $semandticData->addPropertyObjectValue( $propertyDi, $result->getDataItem() ); |
116 | 120 | // Take note of the error for storage (do this here and not in storage, thus avoiding duplicates). |
117 | 121 | if ( !$result->isValid() ) { |
118 | | - self::getSMWData( $parser )->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() ); |
| 122 | + $semandticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), |
| 123 | + $propertyDi->getDiWikiPage() ); |
119 | 124 | } |
120 | 125 | } |
121 | 126 | |
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DataValue.php |
— | — | @@ -61,12 +61,25 @@ |
62 | 62 | protected $m_dataitem; |
63 | 63 | |
64 | 64 | /** |
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 | + * |
66 | 69 | * @var SMWDIProperty |
67 | 70 | */ |
68 | 71 | protected $m_property = null; |
69 | 72 | |
70 | 73 | /** |
| 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 | + /** |
71 | 84 | * The text label to be used for output or false if none given. |
72 | 85 | * @var string |
73 | 86 | */ |
— | — | @@ -151,7 +164,7 @@ |
152 | 165 | // e.g. math. In general, we are not prepared to handle such content properly, and we |
153 | 166 | // also have no means of obtaining the user input at this point. Hence the assignement |
154 | 167 | // 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) |
156 | 169 | if ( ( strpos( $value, "\x7f" ) === false ) && ( strpos( $value, "\x07" ) === false ) ) { |
157 | 170 | $this->parseUserValue( $value ); // may set caption if not set yet, depending on datavalue |
158 | 171 | } else { |
— | — | @@ -190,8 +203,9 @@ |
191 | 204 | } |
192 | 205 | |
193 | 206 | /** |
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. |
196 | 210 | * |
197 | 211 | * @param SMWDIProperty $property |
198 | 212 | */ |
— | — | @@ -200,6 +214,19 @@ |
201 | 215 | } |
202 | 216 | |
203 | 217 | /** |
| 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 | + /** |
204 | 231 | * Change the caption (the text used for displaying this datavalue). The given |
205 | 232 | * value must be a string. |
206 | 233 | * |
— | — | @@ -219,21 +246,22 @@ |
220 | 247 | } |
221 | 248 | |
222 | 249 | /** |
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 |
227 | 255 | * particular datatype in mind. |
228 | 256 | */ |
229 | 257 | public function addServiceLinks() { |
230 | 258 | if ( $this->mHasServiceLinks ) { |
231 | 259 | return; |
232 | 260 | } |
233 | | - if ( $this->m_property !== null ) { |
| 261 | + if ( !is_null( $this->m_property ) ) { |
234 | 262 | $propertyDiWikiPage = $this->m_property->getDiWikiPage(); |
235 | 263 | } |
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 |
238 | 266 | } |
239 | 267 | |
240 | 268 | $args = $this->getServiceLinkParams(); |
— | — | @@ -566,9 +594,10 @@ |
567 | 595 | abstract public function getWikiValue(); |
568 | 596 | |
569 | 597 | /** |
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). |
573 | 602 | */ |
574 | 603 | public function getTypeID() { |
575 | 604 | return $this->m_typeid; |
— | — | @@ -576,15 +605,16 @@ |
577 | 606 | |
578 | 607 | /** |
579 | 608 | * 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. |
583 | 612 | */ |
584 | 613 | public function getInfolinks() { |
585 | | - if ( $this->isValid() && ( $this->m_property !== null ) ) { |
| 614 | + if ( $this->isValid() && !is_null( $this->m_property ) ) { |
586 | 615 | if ( !$this->mHasSearchLink ) { // add default search link |
587 | 616 | $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() ); |
589 | 619 | } |
590 | 620 | |
591 | 621 | if ( !$this->mHasServiceLinks ) { // add further service links |
— | — | @@ -607,8 +637,8 @@ |
608 | 638 | /** |
609 | 639 | * Return a string that identifies the value of the object, and that can |
610 | 640 | * 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) |
613 | 643 | * |
614 | 644 | * @return string |
615 | 645 | */ |
— | — | @@ -631,31 +661,12 @@ |
632 | 662 | } |
633 | 663 | |
634 | 664 | /** |
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, |
654 | 666 | * and false if parsing errors occured or no value was given. |
655 | 667 | * |
656 | 668 | * @return boolean |
657 | 669 | */ |
658 | 670 | public function isValid() { |
659 | | - $this->unstub(); |
660 | 671 | return !$this->mHasErrors && isset( $this->m_dataitem ); |
661 | 672 | } |
662 | 673 | |
— | — | @@ -684,11 +695,12 @@ |
685 | 696 | * Creates an error if the value is illegal. |
686 | 697 | */ |
687 | 698 | protected function checkAllowedValues() { |
688 | | - if ( $this->m_property !== null ) { |
| 699 | + if ( !is_null( $this->m_property ) ) { |
689 | 700 | $propertyDiWikiPage = $this->m_property->getDiWikiPage(); |
690 | 701 | } |
691 | 702 | |
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 ) ) { |
693 | 705 | return; // no property known, or no data to check |
694 | 706 | } |
695 | 707 | |
— | — | @@ -728,35 +740,4 @@ |
729 | 741 | } |
730 | 742 | } |
731 | 743 | |
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 | | - |
763 | 744 | } |
\ No newline at end of file |
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php |
— | — | @@ -26,7 +26,7 @@ |
27 | 27 | protected function parseUserValueOrQuery( $value, $queryMode ) { |
28 | 28 | if ( $value == '' ) { |
29 | 29 | $this->addError( wfMsg( 'smw_novalues' ) ); |
30 | | - |
| 30 | + |
31 | 31 | if ( $queryMode ) { |
32 | 32 | return new SMWThingDescription(); |
33 | 33 | } else { |
— | — | @@ -36,8 +36,14 @@ |
37 | 37 | |
38 | 38 | if ( $queryMode ) { |
39 | 39 | $subdescriptions = array(); |
| 40 | + } elseif ( is_null( $this->m_contextPage ) ) { |
| 41 | + $semanticData = SMWContainerSemanticData::makeAnonymousContainer(); |
40 | 42 | } 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 ); |
42 | 48 | } |
43 | 49 | |
44 | 50 | $values = preg_split( '/[\s]*;[\s]*/u', trim( $value ) ); |
— | — | @@ -77,7 +83,7 @@ |
78 | 84 | } |
79 | 85 | |
80 | 86 | $this->addError( $dataValue->getErrors() ); |
81 | | - $valueIndex++; |
| 87 | + ++$valueIndex; |
82 | 88 | } |
83 | 89 | } |
84 | 90 | ++$propertyIndex; |
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php |
— | — | @@ -83,15 +83,31 @@ |
84 | 84 | |
85 | 85 | protected function parseUserValue( $value ) { |
86 | 86 | 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 | + |
88 | 92 | if ( $this->m_caption === false ) { |
89 | 93 | $this->m_caption = $value; |
90 | 94 | } |
91 | 95 | |
92 | 96 | 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 | + |
94 | 110 | ///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 ) ) { |
96 | 112 | $this->addError( wfMsgForContent( 'smw_notitle', $value ) ); |
97 | 113 | } elseif ( ( $this->m_fixNamespace != NS_MAIN ) && |
98 | 114 | ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) { |
Index: trunk/extensions/SemanticMediaWiki/includes/parserhooks/SMW_Subobject.php |
— | — | @@ -17,9 +17,9 @@ |
18 | 18 | |
19 | 19 | /** |
20 | 20 | * Method for handling the subobject parser function. |
21 | | - * |
| 21 | + * |
22 | 22 | * @since 1.7 |
23 | | - * |
| 23 | + * |
24 | 24 | * @param Parser $parser |
25 | 25 | */ |
26 | 26 | public static function render( Parser &$parser ) { |
— | — | @@ -27,37 +27,19 @@ |
28 | 28 | |
29 | 29 | $params = func_get_args(); |
30 | 30 | array_shift( $params ); // We already know the $parser ... |
| 31 | + $subobjectName = trim( array_shift( $params ) ); |
31 | 32 | |
32 | | - $semanticData = new SMWContainerSemanticData(); |
33 | | - $propertyName = null; |
34 | | - |
| 33 | + $semanticData = SMWParseData::getSMWData( $parser )->getChild( $subobjectName ); |
| 34 | + |
35 | 35 | 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 ); |
40 | 37 | |
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 ); |
45 | 41 | } |
46 | 42 | } |
47 | 43 | |
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 | | - |
62 | 44 | return smwfEncodeMessages( self::$m_errors ); |
63 | 45 | } |
64 | 46 | |
— | — | @@ -66,12 +48,14 @@ |
67 | 49 | $propertyDi = $propertyDv->getDataItem(); |
68 | 50 | |
69 | 51 | if ( !$propertyDi->isInverse() ) { |
70 | | - $valueDv = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $valueString ); |
| 52 | + $valueDv = SMWDataValueFactory::newPropertyObjectValue( $propertyDi, $valueString, |
| 53 | + false, $semanticData->getSubject() ); |
71 | 54 | $semanticData->addPropertyObjectValue( $propertyDi, $valueDv->getDataItem() ); |
72 | 55 | |
73 | 56 | // Take note of the error for storage (do this here and not in storage, thus avoiding duplicates). |
74 | 57 | if ( !$valueDv->isValid() ) { |
75 | | - $semanticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), $propertyDi->getDiWikiPage() ); |
| 58 | + $semanticData->addPropertyObjectValue( new SMWDIProperty( '_ERRP' ), |
| 59 | + $propertyDi->getDiWikiPage() ); |
76 | 60 | self::$m_errors = array_merge( self::$m_errors, $valueDv->getErrors() ); |
77 | 61 | } |
78 | 62 | } else { |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Factbox.php |
— | — | @@ -57,10 +57,11 @@ |
58 | 58 | 'swmfactboxheadbrowse' |
59 | 59 | ); |
60 | 60 | $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 | + |
65 | 66 | foreach ( $semdata->getProperties() as $propertyDi ) { |
66 | 67 | $propertyDv = SMWDataValueFactory::newDataItemValue( $propertyDi, null ); |
67 | 68 | if ( !$propertyDi->isShown() ) { // showing this is not desired, hide |
— | — | @@ -76,24 +77,32 @@ |
77 | 78 | } |
78 | 79 | |
79 | 80 | $propvalues = $semdata->getPropertyValues( $propertyDi ); |
80 | | - |
| 81 | + |
81 | 82 | $valuesHtml = array(); |
82 | | - |
| 83 | + |
83 | 84 | foreach ( $propvalues as $dataItem ) { |
84 | 85 | $dataValue = SMWDataValueFactory::newDataItemValue( $dataItem, $propertyDi ); |
85 | 86 | |
86 | 87 | if ( $dataValue->isValid() ) { |
87 | | - $valuesHtml[] = $dataValue->getLongWikiText( true ) . $dataValue->getInfolinkText( SMW_OUTPUT_WIKI ); |
| 88 | + $valuesHtml[] = $dataValue->getLongWikiText( true ) . |
| 89 | + $dataValue->getInfolinkText( SMW_OUTPUT_WIKI ); |
88 | 90 | } |
89 | 91 | } |
90 | | - |
| 92 | + |
91 | 93 | $text .= $GLOBALS['wgLang']->listToText( $valuesHtml ); |
92 | | - |
| 94 | + |
93 | 95 | $text .= '</td></tr>'; |
94 | 96 | } |
95 | | - |
| 97 | + |
96 | 98 | $text .= '</table></div>'; |
97 | 99 | } |
| 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 | + |
98 | 107 | wfProfileOut( 'SMWFactbox::printFactbox (SMW)' ); |
99 | 108 | return $text; |
100 | 109 | } |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SqlStubSemanticData.php |
— | — | @@ -90,7 +90,7 @@ |
91 | 91 | try { |
92 | 92 | if ( $propertyDiId == SMWDataItem::TYPE_CONTAINER ) { |
93 | 93 | $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys ); |
94 | | - $semanticData = new SMWContainerSemanticData(); |
| 94 | + $semanticData = new SMWContainerSemanticData( $diSubWikiPage ); |
95 | 95 | $semanticData->copyDataFrom( smwfGetStore()->getSemanticData( $diSubWikiPage ) ); |
96 | 96 | |
97 | 97 | $di = new SMWDIContainer( $semanticData ); |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php |
— | — | @@ -216,7 +216,7 @@ |
217 | 217 | foreach ( $data as $dbkeys ) { |
218 | 218 | try { |
219 | 219 | $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys ); |
220 | | - $semanticData = new SMWContainerSemanticData(); |
| 220 | + $semanticData = new SMWContainerSemanticData( $diSubWikiPage ); |
221 | 221 | $semanticData->copyDataFrom( $this->getSemanticData( $diSubWikiPage ) ); |
222 | 222 | $result[] = new SMWDIContainer( $semanticData ); |
223 | 223 | } catch ( SMWDataItemException $e ) { |
— | — | @@ -735,6 +735,9 @@ |
736 | 736 | $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, $sortkey ); |
737 | 737 | $updates = array(); // collect data for bulk updates; format: tableid => updatearray |
738 | 738 | $this->prepareDBUpdates( $updates, $data, $sid, $subject ); |
| 739 | + foreach ( $data->getAllChildren() as $childData ) { |
| 740 | + $this->prepareDBUpdates( $updates, $childData, 0, $childData->getSubject() ); |
| 741 | + } |
739 | 742 | |
740 | 743 | $db = wfGetDB( DB_MASTER ); |
741 | 744 | foreach ( $updates as $tablename => $uvals ) { |
— | — | @@ -1285,7 +1288,7 @@ |
1286 | 1289 | 'smw_namespace' => $dbtypes['n'] . ' NOT NULL', |
1287 | 1290 | 'smw_title' => $dbtypes['t'] . ' NOT NULL', |
1288 | 1291 | 'smw_iw' => $dbtypes['w'] . ' NOT NULL', |
1289 | | - 'smw_subobject' => $dbtypes['w'] . ' NOT NULL', |
| 1292 | + 'smw_subobject' => $dbtypes['t'] . ' NOT NULL', |
1290 | 1293 | 'smw_sortkey' => $dbtypes['t'] . ' NOT NULL' |
1291 | 1294 | ), |
1292 | 1295 | $db, |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStore.php |
— | — | @@ -60,6 +60,10 @@ |
61 | 61 | parent::doDataUpdate( $data ); |
62 | 62 | |
63 | 63 | $expDataArray = $this->prepareUpdateExpData( $data ); |
| 64 | + foreach ( $data->getAllChildren() as $childData ) { |
| 65 | + $subExpDataArray = $this->prepareUpdateExpData( $childData ); |
| 66 | + $expDataArray = $expDataArray + $subExpDataArray; |
| 67 | + } |
64 | 68 | |
65 | 69 | if ( count( $expDataArray ) > 0 ) { |
66 | 70 | $subjectResource = SMWExporter::getDataItemExpElement( $data->getSubject() ); |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_CompatibilityHelpers.php |
— | — | @@ -75,7 +75,10 @@ |
76 | 76 | case SMWDataItem::TYPE_GEO: |
77 | 77 | return new SMWDIGeoCoord( array( 'lat' => (float)$dbkeys[0], 'lon' => (float)$dbkeys[1] ) ); |
78 | 78 | 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(); |
80 | 83 | foreach ( reset( $dbkeys ) as $value ) { |
81 | 84 | if ( is_array( $value ) && ( count( $value ) == 2 ) ) { |
82 | 85 | $diP = new SMWDIProperty( reset( $value ), false ); |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_SemanticData.php |
— | — | @@ -55,7 +55,31 @@ |
56 | 56 | */ |
57 | 57 | protected $mProperties = array(); |
58 | 58 | |
| 59 | + |
59 | 60 | /** |
| 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 | + /** |
60 | 84 | * States whether the container holds any normal properties. |
61 | 85 | * |
62 | 86 | * @var boolean |
— | — | @@ -87,14 +111,26 @@ |
88 | 112 | |
89 | 113 | /** |
90 | 114 | * 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). |
93 | 117 | * |
94 | 118 | * @var SMWDIWikiPage |
95 | 119 | */ |
96 | 120 | protected $mSubject; |
97 | 121 | |
98 | 122 | /** |
| 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 | + /** |
99 | 135 | * Constructor. |
100 | 136 | * |
101 | 137 | * @param SMWDIWikiPage $subject to which this data refers |
— | — | @@ -117,9 +153,6 @@ |
118 | 154 | * output, then the Semdata container will at least look as if properly |
119 | 155 | * initialised (though empty). |
120 | 156 | * |
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 | | - * |
124 | 157 | * @return array |
125 | 158 | */ |
126 | 159 | public function __sleep() { |
— | — | @@ -127,7 +160,7 @@ |
128 | 161 | } |
129 | 162 | |
130 | 163 | /** |
131 | | - * Return subject to which the stored semantic annotation refer to. |
| 164 | + * Return subject to which the stored semantic annotations refer to. |
132 | 165 | * |
133 | 166 | * @return SMWDIWikiPage subject |
134 | 167 | */ |
— | — | @@ -136,6 +169,68 @@ |
137 | 170 | } |
138 | 171 | |
139 | 172 | /** |
| 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 | + /** |
140 | 235 | * Get the array of all properties that have stored values. |
141 | 236 | * |
142 | 237 | * @return array of SMWDIProperty objects |
— | — | @@ -174,9 +269,8 @@ |
175 | 270 | public function getHash() { |
176 | 271 | $ctx = hash_init( 'md5' ); |
177 | 272 | |
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() ); |
181 | 275 | |
182 | 276 | foreach ( $this->getProperties() as $property ) { |
183 | 277 | hash_update( $ctx, '_#_' . $property->getKey() . '##' ); |
— | — | @@ -186,6 +280,10 @@ |
187 | 281 | } |
188 | 282 | } |
189 | 283 | |
| 284 | + foreach ( $this->mChildren as $child ) { |
| 285 | + hash_update( $ctx, '_#_' . $child->getHash() . '##' ); |
| 286 | + } |
| 287 | + |
190 | 288 | return hash_final( $ctx ); |
191 | 289 | } |
192 | 290 | |
— | — | @@ -218,8 +316,6 @@ |
219 | 317 | |
220 | 318 | /** |
221 | 319 | * Store a value for a property identified by its SMWDataItem object. |
222 | | - * For container "pseudo" dataitems, this function also sets the master |
223 | | - * page. |
224 | 320 | * |
225 | 321 | * @note There is no check whether the type of the given data item |
226 | 322 | * agrees with the type of the property. Since property types can |
— | — | @@ -245,10 +341,6 @@ |
246 | 342 | $this->mPropVals[$property->getKey()][] = $dataItem; |
247 | 343 | } |
248 | 344 | |
249 | | - if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) { |
250 | | - $dataItem->getSemanticData()->setMasterPage( $this->mSubject ); |
251 | | - } |
252 | | - |
253 | 345 | if ( !$property->isUserDefined() ) { |
254 | 346 | if ( $property->isShown() ) { |
255 | 347 | $this->mHasVisibleSpecs = true; |
— | — | @@ -298,6 +390,60 @@ |
299 | 391 | $this->mHasVisibleProps = false; |
300 | 392 | $this->mHasVisibleSpecs = false; |
301 | 393 | $this->stubObject = false; |
| 394 | + $mParentSemanticData = null; |
| 395 | + $this->mChildren = array(); |
302 | 396 | } |
303 | 397 | |
| 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 | + |
304 | 450 | } |
\ No newline at end of file |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DataValueFactory.php |
— | — | @@ -13,7 +13,7 @@ |
14 | 14 | * Factory class for creating SMWDataValue objects for supplied types or |
15 | 15 | * properties and data values. |
16 | 16 | * |
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 |
18 | 18 | * datavalue object, possibly with preset user values, captions and |
19 | 19 | * property names. To create suitable datavalues for a given property, the |
20 | 20 | * method newPropertyObjectValue() can be used. |
— | — | @@ -40,7 +40,8 @@ |
41 | 41 | static private $mTypeAliases; |
42 | 42 | |
43 | 43 | /** |
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. |
45 | 46 | * |
46 | 47 | * @var array of string |
47 | 48 | */ |
— | — | @@ -76,32 +77,42 @@ |
77 | 78 | ); |
78 | 79 | |
79 | 80 | /** |
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. |
82 | 83 | * |
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 |
85 | 86 | * @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 |
87 | 89 | * |
88 | 90 | * @return SMWDataValue |
89 | 91 | */ |
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 | + |
91 | 95 | self::initDatatypes(); |
92 | 96 | |
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 ); |
95 | 99 | } 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 ); |
97 | 103 | } |
98 | 104 | |
99 | | - if ( $property !== null ) { |
| 105 | + if ( !is_null( $property ) ) { |
100 | 106 | $result->setProperty( $property ); |
101 | 107 | } |
102 | | - if ( $value !== false ) { |
103 | | - $result->setUserValue( $value, $caption ); |
| 108 | + |
| 109 | + if ( !is_null( $contextPage ) ) { |
| 110 | + $result->setContextPage( $contextPage ); |
104 | 111 | } |
105 | 112 | |
| 113 | + if ( $valueString !== false ) { |
| 114 | + $result->setUserValue( $valueString, $caption ); |
| 115 | + } |
| 116 | + |
106 | 117 | return $result; |
107 | 118 | } |
108 | 119 | |
— | — | @@ -116,12 +127,12 @@ |
117 | 128 | */ |
118 | 129 | static public function newDataItemValue( SMWDataItem $dataItem, $property, $caption = false ) { |
119 | 130 | if ( $property !== null ) { |
120 | | - $typeid = $property->findPropertyTypeID(); |
| 131 | + $typeId = $property->findPropertyTypeID(); |
121 | 132 | } else { |
122 | | - $typeid = self::$mDefaultDataItemTypeIds[$dataItem->getDiType()]; |
| 133 | + $typeId = self::$mDefaultDataItemTypeIds[$dataItem->getDiType()]; |
123 | 134 | } |
124 | 135 | |
125 | | - $result = self::newTypeIdValue( $typeid, false, $caption, $property ); |
| 136 | + $result = self::newTypeIdValue( $typeId, false, $caption, $property ); |
126 | 137 | $result->setDataItem( $dataItem ); |
127 | 138 | if ( $caption !== false ) { |
128 | 139 | $result->setCaption( $caption ); |
— | — | @@ -135,13 +146,13 @@ |
136 | 147 | * appropriate data item class for processing data of this type. See |
137 | 148 | * SMWDataItem for possible values. |
138 | 149 | * |
139 | | - * @param $typeid string id string for the given type |
| 150 | + * @param $typeId string id string for the given type |
140 | 151 | * @return integer data item ID |
141 | 152 | */ |
142 | | - static public function getDataItemId( $typeid ) { |
| 153 | + static public function getDataItemId( $typeId ) { |
143 | 154 | 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]; |
146 | 157 | } else { |
147 | 158 | return SMWDataItem::TYPE_NOTYPE; |
148 | 159 | } |
— | — | @@ -149,26 +160,27 @@ |
150 | 161 | |
151 | 162 | /** |
152 | 163 | * 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. |
155 | 166 | * |
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 |
159 | 171 | * |
160 | 172 | * @return SMWDataValue |
161 | 173 | */ |
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 ); |
168 | 179 | } |
169 | 180 | |
170 | 181 | /** |
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. |
173 | 185 | */ |
174 | 186 | static protected function initDatatypes() { |
175 | 187 | global $smwgContLang; |
— | — | @@ -348,28 +360,4 @@ |
349 | 361 | return self::$mTypeLabels; |
350 | 362 | } |
351 | 363 | |
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 | | - |
376 | 364 | } |
\ No newline at end of file |
Index: trunk/extensions/SemanticMediaWiki/includes/dataitems/SMW_DI_Container.php |
— | — | @@ -7,20 +7,14 @@ |
8 | 8 | /** |
9 | 9 | * Subclass of SMWSemanticData that is used to store the data in SMWDIContainer |
10 | 10 | * 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. |
16 | 16 | * |
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. |
25 | 19 | * |
26 | 20 | * See also the documentation of SMWDIContainer. |
27 | 21 | * |
— | — | @@ -33,75 +27,29 @@ |
34 | 28 | |
35 | 29 | /** |
36 | 30 | * 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. |
38 | 32 | * |
| 33 | + * @since 1.7 |
| 34 | + * |
39 | 35 | * @param boolean $noDuplicates stating if duplicate data should be avoided |
40 | 36 | */ |
41 | | - public function __construct( $noDuplicates = true ) { |
| 37 | + public static function makeAnonymousContainer( $noDuplicates = true ) { |
42 | 38 | $subject = new SMWDIWikiPage( 'SMWInternalObject', NS_SPECIAL, '' ); |
43 | | - return parent::__construct( $subject, $noDuplicates ); |
| 39 | + return new SMWContainerSemanticData( $subject, $noDuplicates ); |
44 | 40 | } |
45 | 41 | |
46 | 42 | /** |
47 | 43 | * Restore complete serialization which is disabled in SMWSemanticData. |
48 | 44 | */ |
49 | 45 | public function __sleep() { |
50 | | - return array( 'mSubject', 'mProperties', 'mPropVals', 'mHasVisibleProps', 'mHasVisibleSpecs', 'mNoDuplicates' ); |
| 46 | + return array( 'mSubject', 'mProperties', 'mPropVals', |
| 47 | + 'mHasVisibleProps', 'mHasVisibleSpecs', 'mNoDuplicates' ); |
51 | 48 | } |
52 | 49 | |
53 | 50 | /** |
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 | | - /** |
104 | 51 | * Check if the subject of this container is an anonymous object. |
105 | 52 | * See the documenation of the class for details. |
| 53 | + * |
106 | 54 | * @return boolean |
107 | 55 | */ |
108 | 56 | public function hasAnonymousSubject() { |
— | — | @@ -123,12 +71,36 @@ |
124 | 72 | */ |
125 | 73 | public function getSubject() { |
126 | 74 | 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."); |
128 | 76 | } else { |
129 | 77 | return $this->mSubject; |
130 | 78 | } |
131 | 79 | } |
132 | 80 | |
| 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 | + |
133 | 105 | } |
134 | 106 | |
135 | 107 | /** |
— | — | @@ -143,20 +115,15 @@ |
144 | 116 | * assignments, and this pattern is searched for. |
145 | 117 | * |
146 | 118 | * 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 | + * |
151 | 124 | * Being a mere placeholder/template for other data, an SMWDIContainer is not |
152 | 125 | * 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. |
159 | 127 | * |
160 | | - * |
161 | 128 | * @since 1.6 |
162 | 129 | * |
163 | 130 | * @author Markus Krötzsch |
— | — | @@ -166,6 +133,7 @@ |
167 | 134 | |
168 | 135 | /** |
169 | 136 | * Internal value. |
| 137 | + * |
170 | 138 | * @var SMWSemanticData |
171 | 139 | */ |
172 | 140 | protected $m_semanticData; |
— | — | @@ -209,6 +177,7 @@ |
210 | 178 | /** |
211 | 179 | * Create a data item from the provided serialization string and type |
212 | 180 | * ID. |
| 181 | + * |
213 | 182 | * @return SMWDIContainer |
214 | 183 | */ |
215 | 184 | public static function doUnserialize( $serialization ) { |