Completed
Push — master ( 264630...c90943 )
by mw
230:08 queued 195:34
created

includes/SMW_PageSchemas.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
/**
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
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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