These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Functions for handling Semantic MediaWiki data within the Page Schemas |
||
5 | * extension. |
||
6 | * |
||
7 | * @author Ankit Garg |
||
8 | * @author Yaron Koren |
||
9 | * @ingroup SMW |
||
10 | */ |
||
11 | |||
12 | class SMWPageSchemas extends PSExtensionHandler { |
||
13 | |||
14 | public static function getDisplayColor() { |
||
15 | return '#DEF'; |
||
16 | } |
||
17 | |||
18 | public static function getTemplateDisplayString() { |
||
19 | return 'Connecting property'; |
||
20 | } |
||
21 | |||
22 | public static function getFieldDisplayString() { |
||
23 | return 'Semantic property'; |
||
24 | } |
||
25 | |||
26 | /** |
||
27 | * Returns the display info for the "connecting property" (if any) |
||
28 | * of the #subobject call (if any) in this template. |
||
29 | */ |
||
30 | public static function getTemplateDisplayValues( $templateXML ) { |
||
31 | foreach ( $templateXML->children() as $tag => $child ) { |
||
32 | if ( $tag == "semanticmediawiki_ConnectingProperty" ) { |
||
33 | $propName = $child->attributes()->name; |
||
34 | $values = array(); |
||
35 | return array( $propName, $values ); |
||
36 | } |
||
37 | } |
||
38 | return null; |
||
39 | } |
||
40 | |||
41 | /** |
||
42 | * Returns the display info for the property (if any is defined) |
||
43 | * for a single field in the Page Schemas XML. |
||
44 | */ |
||
45 | public static function getFieldDisplayValues( $fieldXML ) { |
||
46 | foreach ( $fieldXML->children() as $tag => $child ) { |
||
47 | if ( $tag == "semanticmediawiki_Property" ) { |
||
48 | $propName = $child->attributes()->name; |
||
49 | $values = array(); |
||
50 | foreach ( $child->children() as $prop => $value ) { |
||
51 | $values[$prop] = (string)$value; |
||
52 | } |
||
53 | return array( $propName, $values ); |
||
54 | } |
||
55 | } |
||
56 | return null; |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * Returns the set of SMW property data from the entire page schema. |
||
61 | */ |
||
62 | static function getAllPropertyData( $pageSchemaObj ) { |
||
63 | $propertyDataArray = array(); |
||
64 | $psTemplates = $pageSchemaObj->getTemplates(); |
||
65 | foreach ( $psTemplates as $psTemplate ) { |
||
66 | $psTemplateFields = $psTemplate->getFields(); |
||
67 | foreach ( $psTemplateFields as $psTemplateField ) { |
||
68 | $prop_array = $psTemplateField->getObject('semanticmediawiki_Property'); |
||
69 | if ( empty( $prop_array ) ) { |
||
70 | continue; |
||
71 | } |
||
72 | // If property name is blank, set it to the |
||
73 | // field name. |
||
74 | if ( !array_key_exists( 'name', $prop_array ) || empty( $prop_array['name'] ) ) { |
||
75 | $prop_array['name'] = $psTemplateField->getName(); |
||
76 | } |
||
77 | $propertyDataArray[] = $prop_array; |
||
78 | } |
||
79 | } |
||
80 | return $propertyDataArray; |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Constructs XML for the "connecting property", based on what was |
||
85 | * submitted in the 'edit schema' form. |
||
86 | */ |
||
87 | public static function createTemplateXMLFromForm() { |
||
88 | global $wgRequest; |
||
89 | |||
90 | $xmlPerTemplate = array(); |
||
91 | foreach ( $wgRequest->getValues() as $var => $val ) { |
||
92 | if ( substr( $var, 0, 24 ) == 'smw_connecting_property_' ) { |
||
93 | $templateNum = substr( $var, 24 ); |
||
94 | $xml = '<semanticmediawiki_ConnectingProperty name="' . $val . '" />'; |
||
95 | $xmlPerTemplate[$templateNum] = $xml; |
||
96 | } |
||
97 | } |
||
98 | return $xmlPerTemplate; |
||
99 | } |
||
100 | |||
101 | static function getConnectingPropertyName( $psTemplate ) { |
||
102 | // TODO - there should be a more direct way to get |
||
103 | // this data. |
||
104 | $smwConnectingPropertyArray = $psTemplate->getObject( 'semanticmediawiki_ConnectingProperty' ); |
||
105 | return PageSchemas::getValueFromObject( $smwConnectingPropertyArray, 'name' ); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Sets the list of property pages defined by the passed-in |
||
110 | * Page Schemas object. |
||
111 | */ |
||
112 | public static function getPagesToGenerate( $pageSchemaObj ) { |
||
113 | $pagesToGenerate = array(); |
||
114 | |||
115 | $psTemplates = $pageSchemaObj->getTemplates(); |
||
116 | foreach ( $psTemplates as $psTemplate ) { |
||
117 | $smwConnectingPropertyName = self::getConnectingPropertyName( $psTemplate ); |
||
118 | if ( is_null( $smwConnectingPropertyName ) ) { |
||
119 | continue; |
||
120 | } |
||
121 | $pagesToGenerate[] = Title::makeTitleSafe( SMW_NS_PROPERTY, $smwConnectingPropertyName ); |
||
122 | } |
||
123 | |||
124 | $propertyDataArray = self::getAllPropertyData( $pageSchemaObj ); |
||
125 | foreach ( $propertyDataArray as $propertyData ) { |
||
126 | $title = Title::makeTitleSafe( SMW_NS_PROPERTY, $propertyData['name'] ); |
||
127 | $pagesToGenerate[] = $title; |
||
128 | } |
||
129 | return $pagesToGenerate; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Constructs XML for the SMW property, based on what was submitted |
||
134 | * in the 'edit schema' form. |
||
135 | */ |
||
136 | public static function createFieldXMLFromForm() { |
||
137 | global $wgRequest; |
||
138 | |||
139 | $fieldNum = -1; |
||
140 | $xmlPerField = array(); |
||
141 | foreach ( $wgRequest->getValues() as $var => $val ) { |
||
142 | if ( substr( $var, 0, 18 ) == 'smw_property_name_' ) { |
||
143 | $fieldNum = substr( $var, 18 ); |
||
144 | $xml = '<semanticmediawiki_Property name="' . $val . '" >'; |
||
145 | } elseif ( substr( $var, 0, 18 ) == 'smw_property_type_'){ |
||
146 | $xml .= '<Type>' . $val . '</Type>'; |
||
147 | } elseif ( substr( $var, 0, 16 ) == 'smw_linked_form_') { |
||
148 | if ( $val !== '' ) { |
||
149 | $xml .= '<LinkedForm>' . $val . '</LinkedForm>'; |
||
150 | } |
||
151 | } elseif ( substr( $var, 0, 11 ) == 'smw_values_') { |
||
152 | if ( $val !== '' ) { |
||
153 | // replace the comma substitution character that has no chance of |
||
154 | // being included in the values list - namely, the ASCII beep |
||
155 | $listSeparator = ','; |
||
156 | $allowed_values_str = str_replace( "\\$listSeparator", "\a", $val ); |
||
157 | $allowed_values_array = explode( $listSeparator, $allowed_values_str ); |
||
158 | foreach ( $allowed_values_array as $value ) { |
||
159 | // replace beep back with comma, trim |
||
160 | $value = str_replace( "\a", $listSeparator, trim( $value ) ); |
||
161 | $xml .= '<AllowedValue>' . $value . '</AllowedValue>'; |
||
162 | } |
||
163 | } |
||
164 | $xml .= '</semanticmediawiki_Property>'; |
||
165 | $xmlPerField[$fieldNum] = $xml; |
||
166 | } |
||
167 | } |
||
168 | return $xmlPerField; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Returns the HTML necessary for getting information about the |
||
173 | * "connecting property" within the Page Schemas 'editschema' page. |
||
174 | */ |
||
175 | public static function getTemplateEditingHTML( $psTemplate) { |
||
176 | // Only display this if the Semantic Internal Objects extension |
||
177 | // isn't displaying something similar. |
||
178 | if ( class_exists( 'SIOPageSchemas' ) ) { |
||
179 | return null; |
||
180 | } |
||
181 | |||
182 | $prop_array = array(); |
||
183 | $hasExistingValues = false; |
||
184 | if ( !is_null( $psTemplate ) ) { |
||
185 | $prop_array = $psTemplate->getObject( 'semanticmediawiki_ConnectingProperty' ); |
||
186 | if ( !is_null( $prop_array ) ) { |
||
187 | $hasExistingValues = true; |
||
188 | } |
||
189 | } |
||
190 | $text = '<p>' . 'Name of property to connect this template\'s fields to the rest of the page:' . ' ' . '(should only be used if this template can have multiple instances)' . ' '; |
||
191 | $propName = PageSchemas::getValueFromObject( $prop_array, 'name' ); |
||
192 | $text .= Html::input( 'smw_connecting_property_num', $propName, array( 'size' => 15 ) ) . "\n"; |
||
193 | |||
194 | return array( $text, $hasExistingValues ); |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Returns the HTML necessary for getting information about a regular |
||
199 | * semantic property within the Page Schemas 'editschema' page. |
||
200 | */ |
||
201 | public static function getFieldEditingHTML( $psTemplateField ) { |
||
202 | global $smwgContLang; |
||
203 | |||
204 | $prop_array = array(); |
||
205 | $hasExistingValues = false; |
||
206 | if ( !is_null( $psTemplateField ) ) { |
||
207 | $prop_array = $psTemplateField->getObject('semanticmediawiki_Property'); |
||
208 | if ( !is_null( $prop_array ) ) { |
||
209 | $hasExistingValues = true; |
||
210 | } |
||
211 | } |
||
212 | $html_text = '<p>' . wfMessage( 'ps-optional-name' )->text() . ' '; |
||
213 | $propName = PageSchemas::getValueFromObject( $prop_array, 'name' ); |
||
214 | $html_text .= Html::input( 'smw_property_name_num', $propName, array( 'size' => 15 ) ) . "\n"; |
||
215 | $propType = PageSchemas::getValueFromObject( $prop_array, 'Type' ); |
||
216 | $select_body = ""; |
||
217 | $datatype_labels = $smwgContLang->getDatatypeLabels(); |
||
218 | foreach ( $datatype_labels as $label ) { |
||
219 | $optionAttrs = array(); |
||
220 | if ( $label == $propType) { |
||
221 | $optionAttrs['selected'] = 'selected'; |
||
222 | } |
||
223 | $select_body .= "\t" . Xml::element( 'option', $optionAttrs, $label ) . "\n"; |
||
224 | } |
||
225 | $propertyDropdownAttrs = array( |
||
226 | 'id' => 'property_dropdown', |
||
227 | 'name' => 'smw_property_type_num', |
||
228 | 'value' => $propType |
||
229 | ); |
||
230 | $html_text .= "Type: " . Xml::tags( 'select', $propertyDropdownAttrs, $select_body ) . "</p>\n"; |
||
231 | |||
232 | // This can't be last, because of the hacky way the XML is |
||
233 | // ocnstructed from this form's output. |
||
234 | if ( defined( 'SF_VERSION' ) ) { |
||
235 | $html_text .= '<p>' . wfMessage( 'sf_createproperty_linktoform' )->text() . ' '; |
||
236 | $linkedForm = PageSchemas::getValueFromObject( $prop_array, 'LinkedForm' ); |
||
237 | $html_text .= Html::input( 'smw_linked_form_num', $linkedForm, array( 'size' => 15 ) ) . "\n"; |
||
238 | $html_text .= "(for Page properties only)</p>\n"; |
||
239 | } |
||
240 | |||
241 | $html_text .= '<p>If you want this property to only be allowed to have certain values, enter the list of allowed values, separated by commas (if a value contains a comma, replace it with "\,"):</p>'; |
||
242 | $allowedValsInputAttrs = array( |
||
243 | 'size' => 80 |
||
244 | ); |
||
245 | $allowedValues = PageSchemas::getValueFromObject( $prop_array, 'allowed_values' ); |
||
246 | if ( is_null( $allowedValues ) ) { |
||
247 | $allowed_val_string = ''; |
||
248 | } else { |
||
249 | $allowed_val_string = implode( ', ', $allowedValues ); |
||
250 | } |
||
251 | $html_text .= '<p>' . Html::input( 'smw_values_num', $allowed_val_string, 'text', $allowedValsInputAttrs ) . "</p>\n"; |
||
252 | |||
253 | return array( $html_text, $hasExistingValues ); |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * Creates the property page for each property specified in the |
||
258 | * passed-in Page Schemas XML object. |
||
259 | */ |
||
260 | public static function generatePages( $pageSchemaObj, $selectedPages ) { |
||
261 | global $smwgContLang, $wgUser; |
||
262 | |||
263 | $datatypeLabels = $smwgContLang->getDatatypeLabels(); |
||
264 | $pageTypeLabel = $datatypeLabels['_wpg']; |
||
265 | |||
266 | $jobs = array(); |
||
267 | $jobParams = array(); |
||
268 | $jobParams['user_id'] = $wgUser->getId(); |
||
269 | |||
270 | // First, create jobs for all "connecting properties". |
||
271 | $psTemplates = $pageSchemaObj->getTemplates(); |
||
272 | foreach ( $psTemplates as $psTemplate ) { |
||
273 | $smwConnectingPropertyName = self::getConnectingPropertyName( $psTemplate ); |
||
274 | if ( is_null( $smwConnectingPropertyName ) ) { |
||
275 | continue; |
||
276 | } |
||
277 | $propTitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $smwConnectingPropertyName ); |
||
278 | if ( !in_array( $propTitle, $selectedPages ) ) { |
||
279 | continue; |
||
280 | } |
||
281 | |||
282 | $jobParams['page_text'] = self::createPropertyText( $pageTypeLabel, null, null ); |
||
283 | $jobs[] = new PSCreatePageJob( $propTitle, $jobParams ); |
||
284 | } |
||
285 | |||
286 | // Second, create jobs for all regular properties. |
||
287 | $propertyDataArray = self::getAllPropertyData( $pageSchemaObj ); |
||
288 | foreach ( $propertyDataArray as $propertyData ) { |
||
289 | $propTitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $propertyData['name'] ); |
||
290 | if ( !in_array( $propTitle, $selectedPages ) ) { |
||
291 | continue; |
||
292 | } |
||
293 | $propertyType = array_key_exists( 'Type', $propertyData ) ? $propertyData['Type'] : null; |
||
294 | $propertyAllowedValues = array_key_exists( 'allowed_values', $propertyData ) ? $propertyData['allowed_values'] : null; |
||
295 | $propertyLinkedForm = array_key_exists( 'LinkedForm', $propertyData ) ? $propertyData['LinkedForm'] : null; |
||
296 | $jobParams['page_text'] = self::createPropertyText( $propertyType, $propertyAllowedValues, $propertyLinkedForm ); |
||
297 | $jobs[] = new PSCreatePageJob( $propTitle, $jobParams ); |
||
298 | } |
||
299 | if ( class_exists( 'JobQueueGroup' ) ) { |
||
300 | JobQueueGroup::singleton()->push( $jobs ); |
||
301 | } else { |
||
302 | // MW <= 1.20 |
||
303 | Job::batchInsert( $jobs ); |
||
304 | } |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * Creates the text for a property page. |
||
309 | */ |
||
310 | static public function createPropertyText( $propertyType, $allowedValues, $linkedForm = null ) { |
||
311 | /** |
||
312 | * @var SMWLanguage $smwgContLang |
||
313 | */ |
||
314 | global $smwgContLang, $wgContLang; |
||
0 ignored issues
–
show
|
|||
315 | |||
316 | $propLabels = $smwgContLang->getPropertyLabels(); |
||
317 | $hasTypeLabel = $propLabels['_TYPE']; |
||
318 | $typeTag = "[[$hasTypeLabel::$propertyType]]"; |
||
319 | $text = wfMessage( 'smw-createproperty-isproperty', $typeTag )->inContentLanguage()->text(); |
||
320 | |||
321 | if ( $linkedForm !== '' && defined( 'SF_VERSION' ) ) { |
||
322 | global $sfgContLang; |
||
323 | $sfPropLabels = $sfgContLang->getPropertyLabels(); |
||
324 | $defaultFormTag = "[[{$sfPropLabels[SF_SP_HAS_DEFAULT_FORM]}::$linkedForm]]"; |
||
325 | $text .= ' ' . wfMessage( 'sf_property_linkstoform', $defaultFormTag )->inContentLanguage()->text(); |
||
326 | } |
||
327 | |||
328 | if ( $allowedValues != null) { |
||
329 | $text .= "\n\n" . wfMessage( 'smw-createproperty-allowedvals', $wgContLang->formatNum( count( $allowedValues ) ) )->inContentLanguage()->text(); |
||
330 | |||
331 | foreach ( $allowedValues as $value ) { |
||
332 | $prop_labels = $smwgContLang->getPropertyLabels(); |
||
333 | $text .= "\n* [[" . $prop_labels['_PVAL'] . "::$value]]"; |
||
334 | } |
||
335 | } |
||
336 | |||
337 | return $text; |
||
338 | } |
||
339 | |||
340 | /** |
||
341 | * Returns either the "connecting property", or a field property, based |
||
342 | * on the XML passed from the Page Schemas extension. |
||
343 | */ |
||
344 | public static function createPageSchemasObject( $tagName, $xml ) { |
||
345 | if ( $tagName == "semanticmediawiki_ConnectingProperty" ) { |
||
346 | foreach ( $xml->children() as $tag => $child ) { |
||
347 | if ( $tag == $tagName ) { |
||
348 | $smw_array = array(); |
||
349 | $propName = $child->attributes()->name; |
||
350 | $smw_array['name'] = (string)$propName; |
||
351 | foreach ( $child->children() as $prop => $value ) { |
||
352 | $smw_array[$prop] = (string)$value; |
||
353 | } |
||
354 | return $smw_array; |
||
355 | } |
||
356 | } |
||
357 | } elseif ( $tagName == "semanticmediawiki_Property" ) { |
||
358 | foreach ( $xml->children() as $tag => $child ) { |
||
359 | if ( $tag == $tagName ) { |
||
360 | $smw_array = array(); |
||
361 | $propName = $child->attributes()->name; |
||
362 | $smw_array['name'] = (string)$propName; |
||
363 | $allowed_values = array(); |
||
364 | $count = 0; |
||
365 | foreach ( $child->children() as $prop => $value ) { |
||
366 | if ( $prop == "AllowedValue" ) { |
||
367 | $allowed_values[$count++] = $value; |
||
368 | } else { |
||
369 | $smw_array[$prop] = (string)$value; |
||
370 | } |
||
371 | } |
||
372 | $smw_array['allowed_values'] = $allowed_values; |
||
373 | return $smw_array; |
||
374 | } |
||
375 | } |
||
376 | } |
||
377 | return null; |
||
378 | } |
||
379 | } |
||
380 |
Instead of relying on
global
state, we recommend one of these alternatives:1. Pass all data via parameters
2. Create a class that maintains your state