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