Completed
Push — master ( 14d2bd...06e609 )
by mw
81:37 queued 59:24
created

includes/dataitems/SMW_DI_Container.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @ingroup SMWDataItems
4
 */
5
6
use SMW\DataItemException;
7
8
/**
9
 * Subclass of SMWSemanticData that is used to store the data in SMWDIContainer
10
 * objects. It is special since the subject that the stored property-value pairs
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
 *
17
 * Besides this change, the subclass mainly is needed to restroe the disabled
18
 * serialization of SMWSemanticData.
19
 *
20
 * See also the documentation of SMWDIContainer.
21
 *
22
 * @since 1.6
23
 *
24
 * @author Markus Krötzsch
25
 * @ingroup SMWDataItems
26
 */
27
class SMWContainerSemanticData extends SMWSemanticData {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
28
29
	/**
30
	 * @var boolean
31
	 */
32
	private $skipAnonymousCheck = false;
33
34
	/**
35
	 * Construct a data container that refers to an anonymous subject. See
36
	 * the documentation of the class for details.
37
	 *
38
	 * @since 1.7
39
	 *
40
	 * @param boolean $noDuplicates stating if duplicate data should be avoided
41
	 */
42 3
	public static function makeAnonymousContainer( $noDuplicates = true, $skipAnonymousCheck = false ) {
43 3
		$subject = new SMWDIWikiPage( 'SMWInternalObject', NS_SPECIAL, '', 'int' );
44 3
		$containerSemanticData = new SMWContainerSemanticData( $subject, $noDuplicates );
45
46 3
		if ( $skipAnonymousCheck ) {
47
			$containerSemanticData->skipAnonymousCheck();
48
		}
49
50 3
		return $containerSemanticData;
51
	}
52
53
	/**
54
	 * Restore complete serialization which is disabled in SMWSemanticData.
55
	 */
56
	public function __sleep() {
57
		return array( 'mSubject', 'mProperties', 'mPropVals',
58
			'mHasVisibleProps', 'mHasVisibleSpecs', 'mNoDuplicates', 'skipAnonymousCheck' );
59
	}
60
61
	/**
62
	 * @since 2.4
63
	 */
64 3
	public function skipAnonymousCheck() {
65 3
		$this->skipAnonymousCheck = true;
66 3
	}
67
68
	/**
69
	 * Check if the subject of this container is an anonymous object.
70
	 * See the documenation of the class for details.
71
	 *
72
	 * @return boolean
73
	 */
74 118
	public function hasAnonymousSubject() {
75 118
		if ( $this->mSubject->getNamespace() == NS_SPECIAL &&
76 118
		     $this->mSubject->getDBkey() == 'SMWInternalObject' &&
77 118
		     $this->mSubject->getInterwiki() === '' &&
78 118
		     $this->mSubject->getSubobjectName() === 'int' ) {
79
			return true;
80
		} else {
81 118
			return false;
82
		}
83
	}
84
85
	/**
86
	 * Return subject to which the stored semantic annotation refer to, or
87
	 * throw an exception if the subject is anonymous (if the data has not
88
	 * been contextualized with setMasterPage() yet).
89
	 *
90
	 * @return SMWDIWikiPage subject
91
	 */
92 118
	public function getSubject() {
93
94 118
		if ( !$this->skipAnonymousCheck && $this->hasAnonymousSubject() ) {
95
			throw new DataItemException("This container has been classified as anonymous and by trying to access its subject (that has not been given any) an exception is raised to inform about the incorrect usage. An anonymous container can only be used for a search pattern match.");
96
		}
97
98 118
		return $this->mSubject;
99
	}
100
101
	/**
102
	 * Change the object to become an exact copy of the given
103
	 * SMWSemanticData object. This is used to make other types of
104
	 * SMWSemanticData into an SMWContainerSemanticData. To copy objects of
105
	 * the same type, PHP clone() should be used.
106
	 *
107
	 * @since 1.7
108
	 *
109
	 * @param $semanticData SMWSemanticData object to copy from
110
	 */
111 8
	public function copyDataFrom( SMWSemanticData $semanticData ) {
112 8
		$this->mSubject = $semanticData->getSubject();
113 8
		$this->mProperties = $semanticData->getProperties();
114 8
		$this->mPropVals = array();
115 8
		foreach ( $this->mProperties as $property ) {
116 8
			$this->mPropVals[$property->getKey()] = $semanticData->getPropertyValues( $property );
117
		}
118 8
		$this->mHasVisibleProps = $semanticData->hasVisibleProperties();
119 8
		$this->mHasVisibleSpecs = $semanticData->hasVisibleSpecialProperties();
120 8
		$this->mNoDuplicates = $semanticData->mNoDuplicates;
121 8
	}
122
123
}
124
125
/**
126
 * This class implements container data items that can store SMWSemanticData
127
 * objects. Containers are not dataitems in the proper sense: they do not
128
 * represent a single, opaque value that can be assigned to a property. Rather,
129
 * a container represents a "subobject" with a number of property-value
130
 * assignments. When a container is stored, these individual data assignments
131
 * are stored -- the data managed by SMW never contains any "container", just
132
 * individual property assignments for the subobject. Likewise, when a container
133
 * is used in search, it is interpreted as a patterns of possible property
134
 * assignments, and this pattern is searched for.
135
 *
136
 * The data encapsulated in a container data item is essentially an
137
 * SMWSemanticData object of class SMWContainerSemanticData. This class allows
138
 * the subject to be kept anonymous if not known (if no context page is
139
 * available for finding a suitable subobject name). See the repsective
140
 * documentation for details.
141
 *
142
 * Being a mere placeholder/template for other data, an SMWDIContainer is not
143
 * immutable as the other basic data items. New property-value pairs can always
144
 * be added to the internal SMWContainerSemanticData.
145
 *
146
 * @since 1.6
147
 *
148
 * @author Markus Krötzsch
149
 * @ingroup SMWDataItems
150
 */
151
class SMWDIContainer extends SMWDataItem {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
152
153
	/**
154
	 * Internal value.
155
	 *
156
	 * @var SMWSemanticData
157
	 */
158
	protected $m_semanticData;
159
160
	/**
161
	 * Constructor. The given SMWContainerSemanticData object will be owned
162
	 * by the constructed object afterwards, and in particular will not
163
	 * allow further changes.
164
	 *
165
	 * @param $semanticData SMWContainerSemanticData
166
	 */
167 118
	public function __construct( SMWContainerSemanticData $semanticData ) {
168 118
		$this->m_semanticData = $semanticData;
169 118
	}
170
171 3
	public function getDIType() {
172 3
		return SMWDataItem::TYPE_CONTAINER;
173
	}
174
175 118
	public function getSemanticData() {
176 118
		return $this->m_semanticData;
177
	}
178
179 3
	public function getSortKey() {
180 3
		return '';
181
	}
182
183
	public function getSerialization() {
184
		return serialize( $this->m_semanticData );
185
	}
186
187
	/**
188
	 * Get a hash string for this data item.
189
	 *
190
	 * @return string
191
	 */
192 1
	public function getHash() {
193
194 1
		$hash = $this->getValueHash( $this->m_semanticData );
195 1
		sort( $hash );
196
197 1
		return md5( implode( '#', $hash ) );
198
199
		// We want a value hash, not an entity hash!!
200
		// return $this->m_semanticData->getHash();
201
	}
202
203 1
	private function getValueHash( $semanticData ) {
204
205 1
		$hash = array();
206
207 1
		foreach ( $semanticData->getProperties() as $property ) {
208 1
			$hash[] = $property->getKey();
209
210 1
			foreach ( $semanticData->getPropertyValues( $property ) as $di ) {
211 1
				$hash[] = $di->getHash();
212
			}
213
		}
214
215 1
		foreach ( $semanticData->getSubSemanticData() as $data ) {
216
			$hash[] = $this->getValueHash( $data );
217
		}
218
219 1
		return $hash;
220
	}
221
222
	/**
223
	 * Create a data item from the provided serialization string and type
224
	 * ID.
225
	 *
226
	 * @return SMWDIContainer
227
	 */
228
	public static function doUnserialize( $serialization ) {
229
		/// TODO May issue an E_NOTICE when problems occur; catch this
230
		$data = unserialize( $serialization );
231
		if ( !( $data instanceof SMWContainerSemanticData ) ) {
232
			throw new DataItemException( "Could not unserialize SMWDIContainer from the given string." );
233
		}
234
		return new SMWDIContainer( $data );
235
	}
236
237
	public function equals( SMWDataItem $di ) {
238
		if ( $di->getDIType() !== SMWDataItem::TYPE_CONTAINER ) {
239
			return false;
240
		}
241
242
		return $di->getSerialization() === $this->getSerialization();
243
	}
244
}
245