Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 197 |
|
0.00% |
0 / 35 |
CRAP | |
0.00% |
0 / 1 |
PFTemplateField | |
0.00% |
0 / 197 |
|
0.00% |
0 / 35 |
10920 | |
0.00% |
0 / 1 |
create | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
30 | |||
toWikitext | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
210 | |||
newFromParams | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
182 | |||
setTypeAndPossibleValues | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
72 | |||
setSemanticProperty | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
setCargoFieldData | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
72 | |||
getFieldName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getValueLabels | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getLabel | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSemanticProperty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getPropertyType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getExpectedCargoField | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getFullCargoField | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
getFieldType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRealFieldType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getPossibleValues | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getHierarchyStructure | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isList | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDelimiter | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDisplay | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNSText | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNamespace | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getCategory | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getForm | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
isMandatory | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isUnique | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRegex | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getHoldsTemplate | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setLabel | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setNamespace | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setNSText | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
setFieldType | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
setPossibleValues | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setHierarchyStructure | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
createText | |
0.00% |
0 / 34 |
|
0.00% |
0 / 1 |
342 |
1 | <?php |
2 | /** |
3 | * Defines a class, PFTemplateField, that represents a field in a template, |
4 | * including any possible Cargo or SMW storage it may have. Used in both |
5 | * creating templates and displaying user-created forms. |
6 | * |
7 | * @author Yaron Koren |
8 | * @file |
9 | * @ingroup PF |
10 | */ |
11 | |
12 | class PFTemplateField { |
13 | private $mFieldName; |
14 | private $mValueLabels; |
15 | private $mLabel; |
16 | |
17 | /** |
18 | * SMW-specific fields |
19 | */ |
20 | private $mSemanticProperty; |
21 | private $mPropertyType; |
22 | |
23 | /** |
24 | * Cargo-specific fields |
25 | */ |
26 | private $mCargoTable; |
27 | private $mCargoField; |
28 | private $mFieldType; |
29 | private $mRealFieldType = null; |
30 | private $mHierarchyStructure; |
31 | |
32 | private $mPossibleValues; |
33 | private $mIsList; |
34 | private $mDelimiter; |
35 | private $mDisplay; |
36 | private $mNSText = null; |
37 | private $mNamespace = 0; |
38 | private $mCategory = null; |
39 | private $mForm = null; |
40 | private $mIsMandatory = false; |
41 | private $mIsUnique = false; |
42 | private $mRegex = null; |
43 | private $mHoldsTemplate = null; |
44 | |
45 | static function create( $name, $label, $semanticProperty = null, $isList = null, $delimiter = null, $display = null ) { |
46 | $f = new PFTemplateField(); |
47 | $f->mFieldName = trim( str_replace( '\\', '', $name ) ); |
48 | if ( $label !== null ) { |
49 | // Keep this field null if no value was set. |
50 | $f->mLabel = trim( str_replace( '\\', '', $label ) ); |
51 | } |
52 | if ( $semanticProperty !== null ) { |
53 | $f->setSemanticProperty( $semanticProperty ); |
54 | } |
55 | $f->mIsList = $isList; |
56 | $f->mDelimiter = $delimiter; |
57 | $f->mDisplay = $display; |
58 | // Delimiter should default to ','. |
59 | if ( $isList && !$delimiter ) { |
60 | $f->mDelimiter = ','; |
61 | } |
62 | return $f; |
63 | } |
64 | |
65 | public function toWikitext() { |
66 | $attribsStrings = []; |
67 | // Only include the label if it's different from the field name. |
68 | if ( $this->mLabel != '' && |
69 | ( $this->mLabel !== $this->mFieldName ) ) { |
70 | $attribsStrings['label'] = $this->mLabel; |
71 | } |
72 | if ( $this->mCargoField != '' && $this->mCargoField !== str_replace( ' ', '_', $this->mFieldName ) ) { |
73 | $attribsStrings['cargo field'] = $this->mCargoField; |
74 | } |
75 | // Only set list and delimiter information if there's no Cargo |
76 | // field - if there is, they will be set in #cargo_declare. |
77 | if ( $this->mCargoField == '' ) { |
78 | if ( $this->mIsList == true ) { |
79 | $attribsStrings['list'] = true; |
80 | if ( $this->mDelimiter != ',' ) { |
81 | $attribsStrings['delimiter'] = $this->mDelimiter; |
82 | } |
83 | } |
84 | } |
85 | if ( $this->mSemanticProperty != '' ) { |
86 | $attribsStrings['property'] = $this->mSemanticProperty; |
87 | } |
88 | if ( $this->mNSText != null ) { |
89 | $attribsStrings['namespace'] = $this->mNSText; |
90 | } |
91 | if ( $this->mDisplay != '' ) { |
92 | $attribsStrings['display'] = $this->mDisplay; |
93 | } |
94 | $text = $this->mFieldName; |
95 | if ( count( $attribsStrings ) > 0 ) { |
96 | $attribsFullStrings = []; |
97 | foreach ( $attribsStrings as $key => $value ) { |
98 | if ( $value === true ) { |
99 | $attribsFullStrings[] = $key; |
100 | } else { |
101 | $attribsFullStrings[] = "$key=$value"; |
102 | } |
103 | } |
104 | $text .= ' (' . implode( ';', $attribsFullStrings ) . ')'; |
105 | } |
106 | return $text; |
107 | } |
108 | |
109 | static function newFromParams( $fieldName, $fieldParams ) { |
110 | $f = new PFTemplateField(); |
111 | $f->mFieldName = $fieldName; |
112 | foreach ( $fieldParams as $key => $value ) { |
113 | if ( $key == 'label' ) { |
114 | $f->mLabel = $value; |
115 | } elseif ( $key == 'cargo field' ) { |
116 | $f->mCargoField = $value; |
117 | } elseif ( $key == 'property' ) { |
118 | $f->setSemanticProperty( $value ); |
119 | } elseif ( $key == 'list' ) { |
120 | $f->mIsList = true; |
121 | } elseif ( $key == 'delimiter' ) { |
122 | $f->mDelimiter = $value; |
123 | } elseif ( $key == 'namespace' ) { |
124 | $f->setNSText( $value ); |
125 | } elseif ( $key == 'display' ) { |
126 | $f->mDisplay = $value; |
127 | } elseif ( $key == 'holds template' ) { |
128 | $f->mHoldsTemplate = $value; |
129 | } elseif ( $key == 'category' ) { |
130 | $f->mCategory = $value; |
131 | } |
132 | } |
133 | // Delimiter should default to ','. |
134 | if ( $f->mIsList && !$f->mDelimiter ) { |
135 | $f->mDelimiter = ','; |
136 | } |
137 | return $f; |
138 | } |
139 | |
140 | function setTypeAndPossibleValues() { |
141 | if ( !defined( 'SMW_NS_PROPERTY' ) ) { |
142 | return; |
143 | } |
144 | |
145 | // The presence of "-" at the beginning of a property name |
146 | // (which happens if PF tries to parse an inverse query) |
147 | // leads to an error in SMW - just exit if that's the case. |
148 | if ( strpos( $this->mSemanticProperty, '-' ) === 0 ) { |
149 | return; |
150 | } |
151 | |
152 | $proptitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $this->mSemanticProperty ); |
153 | if ( $proptitle === null ) { |
154 | return; |
155 | } |
156 | |
157 | $store = PFUtils::getSMWStore(); |
158 | // this returns an array of objects |
159 | $allowed_values = PFValuesUtils::getSMWPropertyValues( $store, $proptitle, "Allows value" ); |
160 | if ( empty( $allowed_values ) ) { |
161 | $allowed_values = PFValuesUtils::getSMWPropertyValues( $store, $proptitle, "Allows value list" ); |
162 | } |
163 | $label_formats = PFValuesUtils::getSMWPropertyValues( $store, $proptitle, "Has field label format" ); |
164 | $propValue = SMWDIProperty::newFromUserLabel( $this->mSemanticProperty ); |
165 | $this->mPropertyType = $propValue->findPropertyTypeID(); |
166 | |
167 | foreach ( $allowed_values as $allowed_value ) { |
168 | // HTML-unencode each value |
169 | $wiki_value = html_entity_decode( $allowed_value ); |
170 | $this->mPossibleValues[] = $wiki_value; |
171 | if ( count( $label_formats ) > 0 ) { |
172 | $label_format = $label_formats[0]; |
173 | $prop_instance = SMWDataValueFactory::findTypeID( $this->mPropertyType ); |
174 | $label_value = SMWDataValueFactory::newTypeIDValue( $prop_instance, $wiki_value ); |
175 | $label_value->setOutputFormat( $label_format ); |
176 | $this->mValueLabels[$wiki_value] = html_entity_decode( $label_value->getWikiValue() ); |
177 | } |
178 | } |
179 | |
180 | // HACK - if there were any possible values, set the property |
181 | // type to be 'enumeration', regardless of what the actual type is |
182 | if ( count( $this->mPossibleValues ) > 0 ) { |
183 | $this->mPropertyType = 'enumeration'; |
184 | } |
185 | } |
186 | |
187 | /** |
188 | * Called if a matching property is found for a template field when |
189 | * a template is parsed during the creation of a form. |
190 | * @param string $semantic_property |
191 | */ |
192 | function setSemanticProperty( $semantic_property ) { |
193 | $this->mSemanticProperty = str_replace( '\\', '', $semantic_property ); |
194 | $this->mPossibleValues = []; |
195 | // set field type and possible values, if any |
196 | $this->setTypeAndPossibleValues(); |
197 | } |
198 | |
199 | /** |
200 | * Equivalent to setSemanticProperty(), but called when using Cargo |
201 | * instead of SMW. |
202 | * @param string $tableName |
203 | * @param string $fieldName |
204 | * @param CargoFieldDescription|null $fieldDescription |
205 | */ |
206 | function setCargoFieldData( $tableName, $fieldName, $fieldDescription = null ) { |
207 | $this->mCargoTable = $tableName; |
208 | $this->mCargoField = $fieldName; |
209 | |
210 | if ( $fieldDescription === null ) { |
211 | $fieldDescription = PFUtils::getCargoFieldDescription( $tableName, $fieldName ); |
212 | if ( $fieldDescription == null ) { |
213 | return; |
214 | } |
215 | } |
216 | |
217 | // We have some "pseudo-types", used for setting the correct |
218 | // form input. |
219 | if ( $fieldDescription->mAllowedValues != null ) { |
220 | if ( $fieldDescription->mIsHierarchy == true ) { |
221 | $this->mFieldType = 'Hierarchy'; |
222 | $this->mHierarchyStructure = $fieldDescription->mHierarchyStructure; |
223 | } else { |
224 | $this->mFieldType = 'Enumeration'; |
225 | } |
226 | $this->mRealFieldType = $fieldDescription->mType; |
227 | } elseif ( $fieldDescription->mType == 'Text' && $fieldDescription->mSize != '' && $fieldDescription->mSize <= 100 ) { |
228 | $this->mFieldType = 'String'; |
229 | } else { |
230 | $this->mFieldType = $fieldDescription->mType; |
231 | } |
232 | $this->mIsList = $fieldDescription->mIsList; |
233 | $this->mDelimiter = $fieldDescription->getDelimiter(); |
234 | $this->mPossibleValues = $fieldDescription->mAllowedValues; |
235 | $this->mIsMandatory = $fieldDescription->mIsMandatory; |
236 | $this->mIsUnique = $fieldDescription->mIsUnique; |
237 | $this->mRegex = $fieldDescription->mRegex; |
238 | } |
239 | |
240 | function getFieldName() { |
241 | return $this->mFieldName; |
242 | } |
243 | |
244 | function getValueLabels() { |
245 | return $this->mValueLabels; |
246 | } |
247 | |
248 | function getLabel() { |
249 | return $this->mLabel; |
250 | } |
251 | |
252 | function getSemanticProperty() { |
253 | return $this->mSemanticProperty; |
254 | } |
255 | |
256 | function getPropertyType() { |
257 | return $this->mPropertyType; |
258 | } |
259 | |
260 | function getExpectedCargoField() { |
261 | if ( $this->mCargoField != '' ) { |
262 | return $this->mCargoField; |
263 | } else { |
264 | return str_replace( ' ', '_', $this->mFieldName ); |
265 | } |
266 | } |
267 | |
268 | function getFullCargoField() { |
269 | if ( $this->mCargoTable == '' || $this->mCargoField == '' ) { |
270 | return null; |
271 | } |
272 | return $this->mCargoTable . '|' . $this->mCargoField; |
273 | } |
274 | |
275 | function getFieldType() { |
276 | return $this->mFieldType; |
277 | } |
278 | |
279 | function getRealFieldType() { |
280 | return $this->mRealFieldType; |
281 | } |
282 | |
283 | function getPossibleValues() { |
284 | if ( $this->mPossibleValues == null ) { |
285 | return []; |
286 | } |
287 | return $this->mPossibleValues; |
288 | } |
289 | |
290 | function getHierarchyStructure() { |
291 | return $this->mHierarchyStructure; |
292 | } |
293 | |
294 | function isList() { |
295 | return $this->mIsList; |
296 | } |
297 | |
298 | function getDelimiter() { |
299 | return $this->mDelimiter; |
300 | } |
301 | |
302 | function getDisplay() { |
303 | return $this->mDisplay; |
304 | } |
305 | |
306 | function getNSText() { |
307 | return $this->mNSText; |
308 | } |
309 | |
310 | function getNamespace() { |
311 | return $this->mNamespace; |
312 | } |
313 | |
314 | function getCategory() { |
315 | return $this->mCategory; |
316 | } |
317 | |
318 | function getForm() { |
319 | // @todo - add alternate forms here too. |
320 | if ( $this->mForm !== null ) { |
321 | return $this->mForm; |
322 | } |
323 | |
324 | $defaultFormForNamespace = PFFormLinker::getDefaultFormForNamespace( $this->mNamespace ); |
325 | if ( $defaultFormForNamespace !== null ) { |
326 | $this->mForm = $defaultFormForNamespace; |
327 | return $defaultFormForNamespace; |
328 | } |
329 | |
330 | if ( $this->mCategory != null ) { |
331 | $categoryPage = Title::makeTitleSafe( NS_CATEGORY, $this->mCategory ); |
332 | $defaultFormForCategory = PFFormLinker::getDefaultForm( $categoryPage ); |
333 | if ( $defaultFormForCategory !== null ) { |
334 | $this->mForm = $defaultFormForCategory; |
335 | return $defaultFormForCategory; |
336 | } |
337 | } |
338 | |
339 | return null; |
340 | } |
341 | |
342 | function isMandatory() { |
343 | return $this->mIsMandatory; |
344 | } |
345 | |
346 | function isUnique() { |
347 | return $this->mIsUnique; |
348 | } |
349 | |
350 | function getRegex() { |
351 | return $this->mRegex; |
352 | } |
353 | |
354 | function getHoldsTemplate() { |
355 | return $this->mHoldsTemplate; |
356 | } |
357 | |
358 | function setLabel( $label ) { |
359 | $this->mLabel = $label; |
360 | } |
361 | |
362 | function setNamespace( $namespace ) { |
363 | $this->mNSText = PFUtils::getCanonicalName( $namespace ); |
364 | $this->mNamespace = $namespace; |
365 | } |
366 | |
367 | function setNSText( $nsText ) { |
368 | $this->mNSText = $nsText; |
369 | // Translate from text to ID. |
370 | $dummyTitle = Title::newFromText( $nsText . ':ABC' ); |
371 | $this->mNamespace = $dummyTitle->getNamespace(); |
372 | } |
373 | |
374 | function setFieldType( $fieldType ) { |
375 | $this->mFieldType = $fieldType; |
376 | |
377 | if ( $fieldType == 'File' ) { |
378 | $this->mNSText = PFUtils::getCanonicalName( NS_FILE ); |
379 | $this->mNamespace = NS_FILE; |
380 | } |
381 | } |
382 | |
383 | function setPossibleValues( $possibleValues ) { |
384 | $this->mPossibleValues = $possibleValues; |
385 | } |
386 | |
387 | function setHierarchyStructure( $hierarchyStructure ) { |
388 | $this->mHierarchyStructure = $hierarchyStructure; |
389 | } |
390 | |
391 | function createText( $cargoInUse ) { |
392 | $fieldProperty = $this->mSemanticProperty; |
393 | // If this field is meant to contain a list, and the field has |
394 | // an associated SMW property, add on an 'arraymap' function, |
395 | // which will call the property tag on every element in the |
396 | // list. If, on the other hand, it uses Cargo, use #arraymap |
397 | // just for the link - but only if it's of type "Page". |
398 | if ( $this->mIsList && ( $fieldProperty != '' || |
399 | ( $cargoInUse && $this->mFieldType == 'Page' ) ) ) { |
400 | // Find a string that's not in the property |
401 | // name, to be used as the variable. |
402 | // Default is "x" - also use this if all the attempts fail. |
403 | $var = "x"; |
404 | if ( strstr( $fieldProperty, $var ) ) { |
405 | $var_options = [ 'y', 'z', 'xx', 'yy', 'zz', 'aa', 'bb', 'cc' ]; |
406 | foreach ( $var_options as $option ) { |
407 | if ( !strstr( $fieldProperty, $option ) ) { |
408 | $var = $option; |
409 | break; |
410 | } |
411 | } |
412 | } |
413 | $text = "{{#arraymap:{{{" . $this->mFieldName . '|}}}|' . $this->mDelimiter . "|$var|[["; |
414 | if ( $fieldProperty == '' ) { |
415 | $text .= "$var]]"; |
416 | } elseif ( $this->mNamespace == 0 ) { |
417 | $text .= "$fieldProperty::$var]]"; |
418 | } else { |
419 | $text .= $this->mNamespace . ":$var]] {{#set:" . $fieldProperty . "=$var}} "; |
420 | } |
421 | // If the delimiter isn't a comma, use that as the "new delimiter" as well. |
422 | if ( $this->mDelimiter !== ',' ) { |
423 | $text .= '|' . $this->mDelimiter . '\s'; |
424 | } |
425 | // Close #arraymap call. |
426 | $text .= "}}\n"; |
427 | return $text; |
428 | } |
429 | |
430 | // Not a list. |
431 | $fieldParam = '{{{' . $this->mFieldName . '|}}}'; |
432 | if ( $this->mNamespace == 0 ) { |
433 | $fieldString = $fieldParam; |
434 | } else { |
435 | $fieldString = $this->mNamespace . ':' . $fieldParam; |
436 | } |
437 | |
438 | if ( $fieldProperty == '' ) { |
439 | if ( $cargoInUse && ( $this->mFieldType == 'Page' || $this->mFieldType == 'File' ) ) { |
440 | $fieldString = "[[$fieldString]]"; |
441 | // Add an #if around the link, to prevent |
442 | // anything from getting displayed on the |
443 | // screen for blank values, if the |
444 | // ParserFunctions extension is installed. |
445 | if ( ExtensionRegistry::getInstance()->isLoaded( 'ParserFunctions' ) ) { |
446 | $fieldString = "{{#if:$fieldParam|$fieldString}}"; |
447 | } |
448 | return $fieldString; |
449 | } |
450 | return $fieldString; |
451 | } elseif ( $this->mNamespace == 0 ) { |
452 | return "[[$fieldProperty::$fieldString]]"; |
453 | } else { |
454 | // Special handling is needed, for at |
455 | // least the File and Category namespaces. |
456 | return "[[$fieldString]] {{#set:$fieldProperty=$fieldString}}"; |
457 | } |
458 | } |
459 | |
460 | } |