diff options
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/includes/SMW_PageSchemas.php')
-rw-r--r-- | www/wiki/extensions/SemanticMediaWiki/includes/SMW_PageSchemas.php | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/includes/SMW_PageSchemas.php b/www/wiki/extensions/SemanticMediaWiki/includes/SMW_PageSchemas.php new file mode 100644 index 00000000..8143ace2 --- /dev/null +++ b/www/wiki/extensions/SemanticMediaWiki/includes/SMW_PageSchemas.php @@ -0,0 +1,379 @@ +<?php + +/** + * Functions for handling Semantic MediaWiki data within the Page Schemas + * extension. + * + * @author Ankit Garg + * @author Yaron Koren + * @ingroup SMW + */ + +class SMWPageSchemas extends PSExtensionHandler { + + public static function getDisplayColor() { + return '#DEF'; + } + + public static function getTemplateDisplayString() { + return 'Connecting property'; + } + + public static function getFieldDisplayString() { + return 'Semantic property'; + } + + /** + * Returns the display info for the "connecting property" (if any) + * of the #subobject call (if any) in this template. + */ + public static function getTemplateDisplayValues( $templateXML ) { + foreach ( $templateXML->children() as $tag => $child ) { + if ( $tag == "semanticmediawiki_ConnectingProperty" ) { + $propName = $child->attributes()->name; + $values = []; + return [ $propName, $values ]; + } + } + return null; + } + + /** + * Returns the display info for the property (if any is defined) + * for a single field in the Page Schemas XML. + */ + public static function getFieldDisplayValues( $fieldXML ) { + foreach ( $fieldXML->children() as $tag => $child ) { + if ( $tag == "semanticmediawiki_Property" ) { + $propName = $child->attributes()->name; + $values = []; + foreach ( $child->children() as $prop => $value ) { + $values[$prop] = (string)$value; + } + return [ $propName, $values ]; + } + } + return null; + } + + /** + * Returns the set of SMW property data from the entire page schema. + */ + static function getAllPropertyData( $pageSchemaObj ) { + $propertyDataArray = []; + $psTemplates = $pageSchemaObj->getTemplates(); + foreach ( $psTemplates as $psTemplate ) { + $psTemplateFields = $psTemplate->getFields(); + foreach ( $psTemplateFields as $psTemplateField ) { + $prop_array = $psTemplateField->getObject('semanticmediawiki_Property'); + if ( empty( $prop_array ) ) { + continue; + } + // If property name is blank, set it to the + // field name. + if ( !array_key_exists( 'name', $prop_array ) || empty( $prop_array['name'] ) ) { + $prop_array['name'] = $psTemplateField->getName(); + } + $propertyDataArray[] = $prop_array; + } + } + return $propertyDataArray; + } + + /** + * Constructs XML for the "connecting property", based on what was + * submitted in the 'edit schema' form. + */ + public static function createTemplateXMLFromForm() { + global $wgRequest; + + $xmlPerTemplate = []; + foreach ( $wgRequest->getValues() as $var => $val ) { + if ( substr( $var, 0, 24 ) == 'smw_connecting_property_' ) { + $templateNum = substr( $var, 24 ); + $xml = '<semanticmediawiki_ConnectingProperty name="' . $val . '" />'; + $xmlPerTemplate[$templateNum] = $xml; + } + } + return $xmlPerTemplate; + } + + static function getConnectingPropertyName( $psTemplate ) { + // TODO - there should be a more direct way to get + // this data. + $smwConnectingPropertyArray = $psTemplate->getObject( 'semanticmediawiki_ConnectingProperty' ); + return PageSchemas::getValueFromObject( $smwConnectingPropertyArray, 'name' ); + } + + /** + * Sets the list of property pages defined by the passed-in + * Page Schemas object. + */ + public static function getPagesToGenerate( $pageSchemaObj ) { + $pagesToGenerate = []; + + $psTemplates = $pageSchemaObj->getTemplates(); + foreach ( $psTemplates as $psTemplate ) { + $smwConnectingPropertyName = self::getConnectingPropertyName( $psTemplate ); + if ( is_null( $smwConnectingPropertyName ) ) { + continue; + } + $pagesToGenerate[] = Title::makeTitleSafe( SMW_NS_PROPERTY, $smwConnectingPropertyName ); + } + + $propertyDataArray = self::getAllPropertyData( $pageSchemaObj ); + foreach ( $propertyDataArray as $propertyData ) { + $title = Title::makeTitleSafe( SMW_NS_PROPERTY, $propertyData['name'] ); + $pagesToGenerate[] = $title; + } + return $pagesToGenerate; + } + + /** + * Constructs XML for the SMW property, based on what was submitted + * in the 'edit schema' form. + */ + public static function createFieldXMLFromForm() { + global $wgRequest; + + $fieldNum = -1; + $xmlPerField = []; + foreach ( $wgRequest->getValues() as $var => $val ) { + if ( substr( $var, 0, 18 ) == 'smw_property_name_' ) { + $fieldNum = substr( $var, 18 ); + $xml = '<semanticmediawiki_Property name="' . $val . '" >'; + } elseif ( substr( $var, 0, 18 ) == 'smw_property_type_'){ + $xml .= '<Type>' . $val . '</Type>'; + } elseif ( substr( $var, 0, 16 ) == 'smw_linked_form_') { + if ( $val !== '' ) { + $xml .= '<LinkedForm>' . $val . '</LinkedForm>'; + } + } elseif ( substr( $var, 0, 11 ) == 'smw_values_') { + if ( $val !== '' ) { + // replace the comma substitution character that has no chance of + // being included in the values list - namely, the ASCII beep + $listSeparator = ','; + $allowed_values_str = str_replace( "\\$listSeparator", "\a", $val ); + $allowed_values_array = explode( $listSeparator, $allowed_values_str ); + foreach ( $allowed_values_array as $value ) { + // replace beep back with comma, trim + $value = str_replace( "\a", $listSeparator, trim( $value ) ); + $xml .= '<AllowedValue>' . $value . '</AllowedValue>'; + } + } + $xml .= '</semanticmediawiki_Property>'; + $xmlPerField[$fieldNum] = $xml; + } + } + return $xmlPerField; + } + + /** + * Returns the HTML necessary for getting information about the + * "connecting property" within the Page Schemas 'editschema' page. + */ + public static function getTemplateEditingHTML( $psTemplate) { + // Only display this if the Semantic Internal Objects extension + // isn't displaying something similar. + if ( class_exists( 'SIOPageSchemas' ) ) { + return null; + } + + $prop_array = []; + $hasExistingValues = false; + if ( !is_null( $psTemplate ) ) { + $prop_array = $psTemplate->getObject( 'semanticmediawiki_ConnectingProperty' ); + if ( !is_null( $prop_array ) ) { + $hasExistingValues = true; + } + } + $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)' . ' '; + $propName = PageSchemas::getValueFromObject( $prop_array, 'name' ); + $text .= Html::input( 'smw_connecting_property_num', $propName, [ 'size' => 15 ] ) . "\n"; + + return [ $text, $hasExistingValues ]; + } + + /** + * Returns the HTML necessary for getting information about a regular + * semantic property within the Page Schemas 'editschema' page. + */ + public static function getFieldEditingHTML( $psTemplateField ) { + global $smwgContLang; + + $prop_array = []; + $hasExistingValues = false; + if ( !is_null( $psTemplateField ) ) { + $prop_array = $psTemplateField->getObject('semanticmediawiki_Property'); + if ( !is_null( $prop_array ) ) { + $hasExistingValues = true; + } + } + $html_text = '<p>' . wfMessage( 'ps-optional-name' )->text() . ' '; + $propName = PageSchemas::getValueFromObject( $prop_array, 'name' ); + $html_text .= Html::input( 'smw_property_name_num', $propName, [ 'size' => 15 ] ) . "\n"; + $propType = PageSchemas::getValueFromObject( $prop_array, 'Type' ); + $select_body = ""; + $datatype_labels = $smwgContLang->getDatatypeLabels(); + foreach ( $datatype_labels as $label ) { + $optionAttrs = []; + if ( $label == $propType) { + $optionAttrs['selected'] = 'selected'; + } + $select_body .= "\t" . Xml::element( 'option', $optionAttrs, $label ) . "\n"; + } + $propertyDropdownAttrs = [ + 'id' => 'property_dropdown', + 'name' => 'smw_property_type_num', + 'value' => $propType + ]; + $html_text .= "Type: " . Xml::tags( 'select', $propertyDropdownAttrs, $select_body ) . "</p>\n"; + + // This can't be last, because of the hacky way the XML is + // ocnstructed from this form's output. + if ( defined( 'SF_VERSION' ) ) { + $html_text .= '<p>' . wfMessage( 'sf_createproperty_linktoform' )->text() . ' '; + $linkedForm = PageSchemas::getValueFromObject( $prop_array, 'LinkedForm' ); + $html_text .= Html::input( 'smw_linked_form_num', $linkedForm, [ 'size' => 15 ] ) . "\n"; + $html_text .= "(for Page properties only)</p>\n"; + } + + $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>'; + $allowedValsInputAttrs = [ + 'size' => 80 + ]; + $allowedValues = PageSchemas::getValueFromObject( $prop_array, 'allowed_values' ); + if ( is_null( $allowedValues ) ) { + $allowed_val_string = ''; + } else { + $allowed_val_string = implode( ', ', $allowedValues ); + } + $html_text .= '<p>' . Html::input( 'smw_values_num', $allowed_val_string, 'text', $allowedValsInputAttrs ) . "</p>\n"; + + return [ $html_text, $hasExistingValues ]; + } + + /** + * Creates the property page for each property specified in the + * passed-in Page Schemas XML object. + */ + public static function generatePages( $pageSchemaObj, $selectedPages ) { + global $smwgContLang, $wgUser; + + $datatypeLabels = $smwgContLang->getDatatypeLabels(); + $pageTypeLabel = $datatypeLabels['_wpg']; + + $jobs = []; + $jobParams = []; + $jobParams['user_id'] = $wgUser->getId(); + + // First, create jobs for all "connecting properties". + $psTemplates = $pageSchemaObj->getTemplates(); + foreach ( $psTemplates as $psTemplate ) { + $smwConnectingPropertyName = self::getConnectingPropertyName( $psTemplate ); + if ( is_null( $smwConnectingPropertyName ) ) { + continue; + } + $propTitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $smwConnectingPropertyName ); + if ( !in_array( $propTitle, $selectedPages ) ) { + continue; + } + + $jobParams['page_text'] = self::createPropertyText( $pageTypeLabel, null, null ); + $jobs[] = new PSCreatePageJob( $propTitle, $jobParams ); + } + + // Second, create jobs for all regular properties. + $propertyDataArray = self::getAllPropertyData( $pageSchemaObj ); + foreach ( $propertyDataArray as $propertyData ) { + $propTitle = Title::makeTitleSafe( SMW_NS_PROPERTY, $propertyData['name'] ); + if ( !in_array( $propTitle, $selectedPages ) ) { + continue; + } + $propertyType = array_key_exists( 'Type', $propertyData ) ? $propertyData['Type'] : null; + $propertyAllowedValues = array_key_exists( 'allowed_values', $propertyData ) ? $propertyData['allowed_values'] : null; + $propertyLinkedForm = array_key_exists( 'LinkedForm', $propertyData ) ? $propertyData['LinkedForm'] : null; + $jobParams['page_text'] = self::createPropertyText( $propertyType, $propertyAllowedValues, $propertyLinkedForm ); + $jobs[] = new PSCreatePageJob( $propTitle, $jobParams ); + } + if ( class_exists( 'JobQueueGroup' ) ) { + JobQueueGroup::singleton()->push( $jobs ); + } else { + // MW <= 1.20 + Job::batchInsert( $jobs ); + } + } + + /** + * Creates the text for a property page. + */ + static public function createPropertyText( $propertyType, $allowedValues, $linkedForm = null ) { + /** + * @var SMWLanguage $smwgContLang + */ + global $smwgContLang, $wgContLang; + + $propLabels = $smwgContLang->getPropertyLabels(); + $hasTypeLabel = $propLabels['_TYPE']; + $typeTag = "[[$hasTypeLabel::$propertyType]]"; + $text = wfMessage( 'smw-createproperty-isproperty', $typeTag )->inContentLanguage()->text(); + + if ( $linkedForm !== '' && defined( 'SF_VERSION' ) ) { + global $sfgContLang; + $sfPropLabels = $sfgContLang->getPropertyLabels(); + $defaultFormTag = "[[{$sfPropLabels[SF_SP_HAS_DEFAULT_FORM]}::$linkedForm]]"; + $text .= ' ' . wfMessage( 'sf_property_linkstoform', $defaultFormTag )->inContentLanguage()->text(); + } + + if ( $allowedValues != null) { + $text .= "\n\n" . wfMessage( 'smw-createproperty-allowedvals', $wgContLang->formatNum( count( $allowedValues ) ) )->inContentLanguage()->text(); + + foreach ( $allowedValues as $value ) { + $prop_labels = $smwgContLang->getPropertyLabels(); + $text .= "\n* [[" . $prop_labels['_PVAL'] . "::$value]]"; + } + } + + return $text; + } + + /** + * Returns either the "connecting property", or a field property, based + * on the XML passed from the Page Schemas extension. + */ + public static function createPageSchemasObject( $tagName, $xml ) { + if ( $tagName == "semanticmediawiki_ConnectingProperty" ) { + foreach ( $xml->children() as $tag => $child ) { + if ( $tag == $tagName ) { + $smw_array = []; + $propName = $child->attributes()->name; + $smw_array['name'] = (string)$propName; + foreach ( $child->children() as $prop => $value ) { + $smw_array[$prop] = (string)$value; + } + return $smw_array; + } + } + } elseif ( $tagName == "semanticmediawiki_Property" ) { + foreach ( $xml->children() as $tag => $child ) { + if ( $tag == $tagName ) { + $smw_array = []; + $propName = $child->attributes()->name; + $smw_array['name'] = (string)$propName; + $allowed_values = []; + $count = 0; + foreach ( $child->children() as $prop => $value ) { + if ( $prop == "AllowedValue" ) { + $allowed_values[$count++] = $value; + } else { + $smw_array[$prop] = (string)$value; + } + } + $smw_array['allowed_values'] = $allowed_values; + return $smw_array; + } + } + } + return null; + } +} |