Completed
Push — master ( 9eae06...a41cb5 )
by mw
16s
created

includes/datavalues/SMW_DV_Record.php (1 issue)

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
use SMW\DataValueFactory;
4
5
/**
6
 * SMWDataValue implements the handling of small sets of property-value pairs.
7
 * The declaration of Records in SMW uses the order of values to encode the
8
 * property that should be used, so the user only needs to enter a list of
9
 * values. Internally, however, the property-value assignments are not stored
10
 * with a particular order; they will only be ordered for display, following
11
 * the declaration. This is why it is not supported to have Records using the
12
 * same property for more than one value.
13
 *
14
 * The class uses SMWDIContainer objects to return its inner state. See the
15
 * documentation for SMWDIContainer for details on how this "pseudo" data
16
 * encapsulated many property assignments. Such data is stored internally
17
 * like a page with various property-value assignments. Indeed, record values
18
 * can be created from SMWDIWikiPage objects (the missing information will
19
 * be fetched from the store).
20
 *
21
 * @todo Enforce limitation of maximal number of values.
22
 * @todo Enforce uniqueness of properties in declaration.
23
 * @todo Complete internationalisation.
24
 *
25
 * @author Markus Krötzsch
26
 * @ingroup SMWDataValues
27
 */
28
class SMWRecordValue extends SMWDataValue {
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...
29
30
	/// cache for properties for the fields of this data value
31
	protected $m_diProperties = null;
32
33
	/**
34
	 * @since 2.3
35
	 *
36
	 * @return DIProperty[]|null
37
	 */
38 1
	public function getProperties() {
39 1
		return $this->m_diProperties;
40
	}
41
42
	/**
43
	 * @since 2.3
44
	 *
45
	 * @param string $value
46
	 *
47
	 * @return array
48
	 */
49 23
	public function getValuesFromString( $value ) {
50
		// #664 / T17732
51 23
		$value = str_replace( "\;", "-3B", $value );
52
53
		// Bug 21926 / T23926
54
		// Values that use html entities are encoded with a semicolon
55 23
		$value = htmlspecialchars_decode( $value, ENT_QUOTES );
56
57 23
		return preg_split( '/[\s]*;[\s]*/u', trim( $value ) );
58
	}
59
60 19
	protected function parseUserValue( $value ) {
61
62 19
		if ( $value === '' ) {
63
			$this->addErrorMsg( array( 'smw_novalues' ) );
64
			return;
65
		}
66
67 19
		if ( is_null( $this->m_contextPage ) ) {
68 7
			$semanticData = SMWContainerSemanticData::makeAnonymousContainer();
69 7
			$semanticData->skipAnonymousCheck();
70
		} else {
71 15
			$subobjectName = '_' . hash( 'md4', $value, false ); // md4 is probably fastest of PHP's hashes
72 15
			$subject = new SMWDIWikiPage( $this->m_contextPage->getDBkey(),
73 15
				$this->m_contextPage->getNamespace(), $this->m_contextPage->getInterwiki(),
74
				$subobjectName );
75 15
			$semanticData = new SMWContainerSemanticData( $subject );
76
		}
77
78 19
		$values = $this->getValuesFromString( $value );
79 19
		$valueIndex = 0; // index in value array
80 19
		$propertyIndex = 0; // index in property list
81 19
		$empty = true;
82
83 19
		foreach ( $this->getPropertyDataItems() as $diProperty ) {
84
85 19
			if ( !array_key_exists( $valueIndex, $values ) || $this->getErrors() !== array() ) {
86 1
				break; // stop if there are no values left
87
			}
88
89 19
			$values[$valueIndex] = str_replace( "-3B", ";", $values[$valueIndex] );
90
91
			// generating the DVs:
92 19
			if ( ( $values[$valueIndex] === '' ) || ( $values[$valueIndex] == '?' ) ) { // explicit omission
93 1
				$valueIndex++;
94
			} else {
95 19
				$dataValue = DataValueFactory::getInstance()->newDataValueByProperty(
96
					$diProperty,
97 19
					$values[$valueIndex],
98 19
					false,
99 19
					$this->getContextPage()
100
				);
101
102 19
				if ( $dataValue->isValid() ) { // valid DV: keep
103 19
					$semanticData->addPropertyObjectValue( $diProperty, $dataValue->getDataItem() );
104
105 19
					$valueIndex++;
106 19
					$empty = false;
107
				} elseif ( ( count( $values ) - $valueIndex ) == ( count( $this->m_diProperties ) - $propertyIndex ) ) {
108
					$semanticData->addPropertyObjectValue( $diProperty, $dataValue->getDataItem() );
109
					$this->addError( $dataValue->getErrors() );
110
					++$valueIndex;
111
				}
112
			}
113 19
			++$propertyIndex;
114
		}
115
116 19
		if ( $empty && $this->getErrors() === array()  ) {
117
			$this->addErrorMsg( array( 'smw_novalues' ) );
118
		}
119
120 19
		$this->m_dataitem = new SMWDIContainer( $semanticData );
121 19
	}
122
123
	/**
124
	 * @see SMWDataValue::loadDataItem()
125
	 * @param $dataitem SMWDataItem
126
	 * @return boolean
127
	 */
128 5
	protected function loadDataItem( SMWDataItem $dataItem ) {
129 5
		if ( $dataItem->getDIType() == SMWDataItem::TYPE_CONTAINER ) {
130
			$this->m_dataitem = $dataItem;
131
			return true;
132 5
		} elseif ( $dataItem->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) {
133 5
			$semanticData = new SMWContainerSemanticData( $dataItem );
134 5
			$semanticData->copyDataFrom( \SMW\ApplicationFactory::getInstance()->getStore()->getSemanticData( $dataItem ) );
135 5
			$this->m_dataitem = new SMWDIContainer( $semanticData );
136 5
			return true;
137
		} else {
138 1
			return false;
139
		}
140
	}
141
142 6
	public function getShortWikiText( $linked = null ) {
143 6
		if ( $this->m_caption !== false ) {
144
			return $this->m_caption;
145
		}
146 6
		return $this->makeOutputText( 0, $linked );
147
	}
148
149
	public function getShortHTMLText( $linker = null ) {
150
		if ( $this->m_caption !== false ) {
151
			return $this->m_caption;
152
		}
153
		return $this->makeOutputText( 1, $linker );
154
	}
155
156
	public function getLongWikiText( $linked = null ) {
157
		return $this->makeOutputText( 2, $linked );
158
	}
159
160
	public function getLongHTMLText( $linker = null ) {
161
		return $this->makeOutputText( 3, $linker );
162
	}
163
164 9
	public function getWikiValue() {
165 9
		return $this->makeOutputText( 4 );
166
	}
167
168
	/// @todo Allowed values for multi-valued properties are not supported yet.
169 19
	protected function checkAllowedValues() {
170 19
	}
171
172
	/**
173
	 * Make sure that the content is reset in this case.
174
	 * @todo This is not a full reset yet (the case that property is changed after a value
175
	 * was set does not occur in the normal flow of things, hence this has low priority).
176
	 */
177 15
	public function setProperty( SMWDIProperty $property ) {
178 15
		parent::setProperty( $property );
179 15
		$this->m_diProperties = null;
180 15
	}
181
182
	/**
183
	 * @since 2.1
184
	 *
185
	 * @param SMWDIProperty[] $properties
186
	 */
187 8
	public function setFieldProperties( array $properties ) {
188 8
		foreach ( $properties as $property ) {
189 8
			if ( $property instanceof SMWDIProperty ) {
190 8
				$this->m_diProperties[] = $property;
191
			}
192
		}
193 8
	}
194
195
////// Additional API for value lists
196
197
	/**
198
	 * @deprecated as of 1.6, use getDataItems instead
199
	 *
200
	 * @return array of SMWDataItem
201
	 */
202
	public function getDVs() {
203
		return $this->getDataItems();
204
	}
205
206
	/**
207
	 * Create a list (array with numeric keys) containing the datavalue
208
	 * objects that this SMWRecordValue object holds. Values that are not
209
	 * present are set to null. Note that the first index in the array is
210
	 * 0, not 1.
211
	 *
212
	 * @since 1.6
213
	 *
214
	 * @return array of SMWDataItem
215
	 */
216 8
	public function getDataItems() {
217 8
		if ( $this->isValid() ) {
218 8
			$result = array();
219 8
			$index = 0;
220 8
			foreach ( $this->getPropertyDataItems() as $diProperty ) {
221 8
				$values = $this->getDataItem()->getSemanticData()->getPropertyValues( $diProperty );
222 8
				if ( count( $values ) > 0 ) {
223 8
					$result[$index] = reset( $values );
224
				} else {
225
					$result[$index] = null;
226
				}
227 8
				$index += 1;
228
			}
229 8
			return $result;
230
		} else {
231 6
			return array();
232
		}
233
	}
234
235
	/**
236
	 * Return the array (list) of properties that the individual entries of
237
	 * this datatype consist of.
238
	 *
239
	 * @since 1.6
240
	 *
241
	 * @todo I18N for error message.
242
	 *
243
	 * @return array of SMWDIProperty
244
	 */
245 23
	public function getPropertyDataItems() {
246 23
		if ( is_null( $this->m_diProperties ) ) {
247 15
			$this->m_diProperties = self::findPropertyDataItems( $this->m_property );
248
249 15
			if ( count( $this->m_diProperties ) == 0 ) { // TODO internalionalize
250 6
				$this->addError( 'The list of properties to be used for the data fields has not been specified properly.' );
251
			}
252
		}
253
254 23
		return $this->m_diProperties;
255
	}
256
257
	/**
258
	 * Return the array (list) of properties that the individual entries of
259
	 * this datatype consist of.
260
	 *
261
	 * @since 1.6
262
	 *
263
	 * @param $diProperty mixed null or SMWDIProperty object for which to retrieve the types
264
	 *
265
	 * @return array of SMWDIProperty
266
	 */
267 15
	public static function findPropertyDataItems( $diProperty ) {
268 15
		if ( !is_null( $diProperty ) ) {
269 15
			$propertyDiWikiPage = $diProperty->getDiWikiPage();
270
271 15
			if ( !is_null( $propertyDiWikiPage ) ) {
272 15
				$listDiProperty = new SMW\DIProperty( '_LIST' );
273 15
				$dataItems = \SMW\ApplicationFactory::getInstance()->getStore()->getPropertyValues( $propertyDiWikiPage, $listDiProperty );
274
275 15
				if ( count( $dataItems ) == 1 ) {
276 15
					$propertyListValue = new SMWPropertyListValue( '__pls' );
277 15
					$propertyListValue->setDataItem( reset( $dataItems ) );
278
279 15
					if ( $propertyListValue->isValid() ) {
280 15
						return $propertyListValue->getPropertyDataItems();
281
					}
282
				}
283
			}
284
		}
285
286 6
		return array();
287
	}
288
289
////// Internal helper functions
290
291 11
	protected function makeOutputText( $type = 0, $linker = null ) {
292 11
		if ( !$this->isValid() ) {
293
			return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText();
294
		}
295
296 11
		$result = '';
297 11
		$i = 0;
298 11
		foreach ( $this->getPropertyDataItems() as $propertyDataItem ) {
299 11
			if ( $i == 1 ) {
300 11
				$result .= ( $type == 4 ) ? '; ' : ' (';
301 11
			} elseif ( $i > 1 ) {
302 1
				$result .= ( $type == 4 ) ? '; ' : ', ';
303
			}
304 11
			++$i;
305 11
			$propertyValues = $this->m_dataitem->getSemanticData()->getPropertyValues( $propertyDataItem ); // combining this with next line violates PHP strict standards
306 11
			$dataItem = reset( $propertyValues );
307 11
			if ( $dataItem !== false ) {
308 11
				$dataValue = DataValueFactory::getInstance()->newDataValueByItem( $dataItem, $propertyDataItem );
309 11
				$result .= $this->makeValueOutputText( $type, $dataValue, $linker );
310
			} else {
311 11
				$result .= '?';
312
			}
313
		}
314 11
		if ( ( $i > 1 ) && ( $type != 4 ) ) {
315 6
			$result .= ')';
316
		}
317
318 11
		return $result;
319
	}
320
321 11
	protected function makeValueOutputText( $type, $dataValue, $linker ) {
322
		switch ( $type ) {
323 11
			case 0:
324 6
			return $dataValue->getShortWikiText( $linker );
325 9
			case 1:
326
			return $dataValue->getShortHTMLText( $linker );
327 9
			case 2:
328
			return $dataValue->getShortWikiText( $linker );
329 9
			case 3:
330
			return $dataValue->getShortHTMLText( $linker );
331 9
			case 4:
332 9
			return str_replace( ";", "\;", $dataValue->getWikiValue() );
333
		}
334
	}
335
336
}
337
338