Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 21 |
CRAP | |
0.00% |
0 / 364 |
PFTemplate | |
0.00% |
0 / 1 |
|
0.00% |
0 / 21 |
22952 | |
0.00% |
0 / 364 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
newFromName | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
loadTemplateParams | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 14 |
|||
getTemplateParams | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
loadTemplateFields | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 12 |
|||
loadTemplateFieldsSMWAndOther | |
0.00% |
0 / 1 |
552 | |
0.00% |
0 / 49 |
|||
loadPropertySettingInTemplate | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
loadTemplateFieldsCargo | |
0.00% |
0 / 1 |
462 | |
0.00% |
0 / 63 |
|||
getCargoTableAndSchema | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 11 |
|||
getTemplateFields | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
getFieldNamed | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 4 |
|||
setConnectingProperty | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
setCategoryName | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
setCargoTable | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
setAggregatingInfo | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
setFormat | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
createCargoDeclareCall | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 21 |
|||
createCargoStoreCall | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 10 |
|||
createText | |
0.00% |
0 / 1 |
4422 | |
0.00% |
0 / 138 |
|||
createTextForField | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 12 |
|||
printCategoryTag | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
<?php | |
/** | |
* Defines a class, PFTemplate, that represents a MediaWiki "infobox" | |
* template that holds structured data, which may or may not be | |
* additionally stored by Cargo and/or Semantic MediaWiki. | |
* | |
* @author Yaron Koren | |
* @file | |
* @ingroup PF | |
*/ | |
use MediaWiki\MediaWikiServices; | |
class PFTemplate { | |
private $mTemplateName; | |
private $mTemplateText; | |
private $mTemplateFields; | |
private $mTemplateParams; | |
private $mConnectingProperty; | |
private $mCategoryName; | |
private $mCargoTable; | |
private $mAggregatingProperty; | |
private $mAggregationLabel; | |
private $mTemplateFormat; | |
private $mFieldStart; | |
private $mFieldEnd; | |
private $mTemplateStart; | |
private $mTemplateEnd; | |
public function __construct( $templateName, $templateFields ) { | |
$this->mTemplateName = $templateName; | |
$this->mTemplateFields = $templateFields; | |
} | |
public static function newFromName( $templateName ) { | |
$template = new PFTemplate( $templateName, [] ); | |
$template->loadTemplateParams(); | |
$template->loadTemplateFields(); | |
return $template; | |
} | |
/** | |
* Get (and store in memory) the values from this template's | |
* #template_params call, if it exists. | |
*/ | |
public function loadTemplateParams() { | |
$embeddedTemplate = null; | |
$templateTitle = Title::makeTitleSafe( NS_TEMPLATE, $this->mTemplateName ); | |
$services = MediaWikiServices::getInstance(); | |
if ( method_exists( $services, 'getPageProps' ) ) { | |
// MW 1.36+ | |
$pageProps = $services->getPageProps(); | |
} else { | |
$pageProps = PageProps::getInstance(); | |
} | |
$properties = $pageProps->getProperties( | |
[ $templateTitle ], [ 'PageFormsTemplateParams' ] | |
); | |
if ( count( $properties ) == 0 ) { | |
return; | |
} | |
$paramsForPage = reset( $properties ); | |
$paramsForProperty = reset( $paramsForPage ); | |
$this->mTemplateParams = unserialize( $paramsForProperty ); | |
} | |
public function getTemplateParams() { | |
return $this->mTemplateParams; | |
} | |
/** | |
* @todo - fix so that this function only gets called once per | |
* template; right now it seems to get called once per field. (!) | |
*/ | |
function loadTemplateFields() { | |
$templateTitle = Title::makeTitleSafe( NS_TEMPLATE, $this->mTemplateName ); | |
if ( !isset( $templateTitle ) ) { | |
return; | |
} | |
$templateText = PFUtils::getPageText( $templateTitle ); | |
// Ignore 'noinclude' sections and 'includeonly' tags. | |
$templateText = StringUtils::delimiterReplace( '<noinclude>', '</noinclude>', '', $templateText ); | |
$this->mTemplateText = strtr( $templateText, [ '<includeonly>' => '', '</includeonly>' => '' ] ); | |
// The Cargo-based function is more specific; it only gets | |
// data structure information from the template schema. If | |
// there's no Cargo schema for this template, we call | |
// loadTemplateFieldsSMWAndOther(), which doesn't require the | |
// presence of SMW and can get non-SMW information as well. | |
if ( defined( 'CARGO_VERSION' ) ) { | |
$this->loadTemplateFieldsCargo( $templateTitle ); | |
if ( count( $this->mTemplateFields ) > 0 ) { | |
return; | |
} | |
} | |
$this->loadTemplateFieldsSMWAndOther(); | |
} | |
/** | |
* Get the fields of the template, along with the semantic property | |
* attached to each one (if any), by parsing the text of the template. | |
*/ | |
function loadTemplateFieldsSMWAndOther() { | |
$templateFields = []; | |
$fieldNamesArray = []; | |
// The way this works is that fields are found and then stored | |
// in an array based on their location in the template text, so | |
// that they can be returned in the order in which they appear | |
// in the template, not the order in which they were found. | |
// Some fields can be found more than once (especially if | |
// they're part of an "#if" statement), so they're only | |
// recorded the first time they're found. | |
// Replace all calls to #set within #arraymap with standard | |
// SMW tags. This is done so that they will later get | |
// parsed correctly. | |
// This is "cheating", since it modifies the template text | |
// (the rest of the function doesn't do that), but trying to | |
// get the #arraymap check regexp to find both kinds of SMW | |
// property tags seemed too hard to do. | |
$this->mTemplateText = preg_replace( '/#arraymap.*{{\s*#set:\s*([^=]*)=([^}]*)}}/', '[[$1:$2]]', $this->mTemplateText ); | |
// Look for "arraymap" parser function calls that map a | |
// property onto a list. | |
$ret = preg_match_all( '/{{#arraymap:{{{([^|}]*:?[^|}]*)[^\[]*\[\[([^:]*:?[^:]*)::/mis', $this->mTemplateText, $matches ); | |
if ( $ret ) { | |
foreach ( $matches[1] as $i => $field_name ) { | |
if ( !in_array( $field_name, $fieldNamesArray ) ) { | |
$propertyName = $matches[2][$i]; | |
$this->loadPropertySettingInTemplate( $field_name, $propertyName, true ); | |
$fieldNamesArray[] = $field_name; | |
} | |
} | |
} elseif ( $ret === false ) { | |
// There was an error in the preg_match_all() | |
// call - let the user know about it. | |
if ( preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR ) { | |
print 'Page Forms error: backtrace limit exceeded during parsing! Please increase the value of <a href="http://www.php.net/manual/en/pcre.configuration.php#ini.pcre.backtrack-limit">pcre.backtrack_limit</a> in php.ini or LocalSettings.php.'; | |
} | |
} | |
// Look for normal property calls. | |
if ( preg_match_all( '/\[\[([^:|\[\]]*:*?[^:|\[\]]*)::{{{([^\]\|}]*).*?\]\]/mis', $this->mTemplateText, $matches ) ) { | |
foreach ( $matches[1] as $i => $propertyName ) { | |
$field_name = trim( $matches[2][$i] ); | |
if ( !in_array( $field_name, $fieldNamesArray ) ) { | |
$propertyName = trim( $propertyName ); | |
$this->loadPropertySettingInTemplate( $field_name, $propertyName, false ); | |
$fieldNamesArray[] = $field_name; | |
} | |
} | |
} | |
// Then, get calls to #set, #set_internal and #subobject. | |
// (Thankfully, they all have similar syntax). | |
if ( preg_match_all( '/#(set|set_internal|subobject):(.*?}}})\s*}}/mis', $this->mTemplateText, $matches ) ) { | |
foreach ( $matches[2] as $match ) { | |
if ( preg_match_all( '/([^|{]*?)=\s*{{{([^|}]*)/mis', $match, $matches2 ) ) { | |
foreach ( $matches2[1] as $i => $propertyName ) { | |
$fieldName = trim( $matches2[2][$i] ); | |
if ( !in_array( $fieldName, $fieldNamesArray ) ) { | |
$propertyName = trim( $propertyName ); | |
$this->loadPropertySettingInTemplate( $fieldName, $propertyName, false ); | |
$fieldNamesArray[] = $fieldName; | |
} | |
} | |
} | |
} | |
} | |
// Then, get calls to #declare. (This is really rather | |
// optional, since no one seems to use #declare.) | |
if ( preg_match_all( '/#declare:(.*?)}}/mis', $this->mTemplateText, $matches ) ) { | |
foreach ( $matches[1] as $match ) { | |
$setValues = explode( '|', $match ); | |
foreach ( $setValues as $valuePair ) { | |
$keyAndVal = explode( '=', $valuePair ); | |
if ( count( $keyAndVal ) == 2 ) { | |
$propertyName = trim( $keyAndVal[0] ); | |
$fieldName = trim( $keyAndVal[1] ); | |
if ( !in_array( $fieldName, $fieldNamesArray ) ) { | |
$this->loadPropertySettingInTemplate( $fieldName, $propertyName, false ); | |
$fieldNamesArray[] = $fieldName; | |
} | |
} | |
} | |
} | |
} | |
// Finally, get any non-semantic fields defined. | |
if ( preg_match_all( '/{{{([^|}]*)/mis', $this->mTemplateText, $matches ) ) { | |
foreach ( $matches[1] as $fieldName ) { | |
$fieldName = trim( $fieldName ); | |
if ( !empty( $fieldName ) && ( !in_array( $fieldName, $fieldNamesArray ) ) ) { | |
$cur_pos = stripos( $this->mTemplateText, $fieldName ); | |
$this->mTemplateFields[$cur_pos] = PFTemplateField::create( $fieldName, PFUtils::getContLang()->ucfirst( $fieldName ) ); | |
$fieldNamesArray[] = $fieldName; | |
} | |
} | |
} | |
ksort( $this->mTemplateFields ); | |
} | |
/** | |
* For a field name and its attached property name located in the | |
* template text, create an PFTemplateField object out of it, and | |
* add it to $this->mTemplateFields. | |
* @param string $fieldName | |
* @param string $propertyName | |
* @param bool $isList | |
*/ | |
function loadPropertySettingInTemplate( $fieldName, $propertyName, $isList ) { | |
$templateField = PFTemplateField::create( | |
$fieldName, PFUtils::getContLang()->ucfirst( $fieldName ), $propertyName, | |
$isList | |
); | |
$cur_pos = stripos( $this->mTemplateText, $fieldName . '|' ); | |
$this->mTemplateFields[$cur_pos] = $templateField; | |
} | |
function loadTemplateFieldsCargo( $templateTitle ) { | |
$cargoFieldsOfTemplateParams = []; | |
// First, get the table name, and fields, declared for this | |
// template, if any. | |
list( $tableName, $tableSchema ) = $this->getCargoTableAndSchema( $templateTitle ); | |
if ( $tableName == null ) { | |
$fieldDescriptions = []; | |
} else { | |
$fieldDescriptions = $tableSchema->mFieldDescriptions; | |
} | |
// If #template_params was declared for this template, our | |
// job is easy - we just go through the declared fields, get | |
// the Cargo data for each field if it exists, and populate | |
// $mTemplateFields with it. | |
if ( $this->mTemplateParams !== null ) { | |
foreach ( $this->mTemplateParams as $fieldName => $fieldParams ) { | |
$templateField = PFTemplateField::newFromParams( $fieldName, $fieldParams ); | |
$cargoField = $templateField->getExpectedCargoField(); | |
if ( array_key_exists( $cargoField, $fieldDescriptions ) ) { | |
$fieldDescription = $fieldDescriptions[$cargoField]; | |
$templateField->setCargoFieldData( $tableName, $cargoField, $fieldDescription ); | |
} | |
$this->mTemplateFields[$fieldName] = $templateField; | |
} | |
return; | |
} | |
// If there are no declared template params *or* Cargo fields, | |
// exit. | |
if ( count( $fieldDescriptions ) == 0 ) { | |
return; | |
} | |
// No #template_params call, so we have to do a more manual | |
// process. | |
// Match template params to Cargo table fields, by parsing | |
// call(s) to #cargo_store. | |
// Let's find every #cargo_store tag. | |
// Unfortunately, it doesn't seem possible to use a regexp | |
// search for this, because it's hard to know which set of | |
// double brackets represents the end of such a call. Instead, | |
// we'll do some manual parsing. | |
$cargoStoreLocations = []; | |
$curPos = 0; | |
while ( true ) { | |
$newPos = strpos( $this->mTemplateText, "#cargo_store:", $curPos ); | |
if ( $newPos === false ) { | |
break; | |
} | |
$curPos = $newPos + 13; | |
$cargoStoreLocations[] = $curPos; | |
} | |
$cargoStoreCalls = []; | |
foreach ( $cargoStoreLocations as $locNum => $startPos ) { | |
$numUnclosedBrackets = 2; | |
if ( $locNum < count( $cargoStoreLocations ) - 1 ) { | |
$lastPos = $cargoStoreLocations[$locNum + 1]; | |
} else { | |
$lastPos = strlen( $this->mTemplateText ) - 1; | |
} | |
$curCargoStoreCall = ''; | |
$curPos = $startPos; | |
while ( $curPos <= $lastPos ) { | |
$curChar = $this->mTemplateText[$curPos]; | |
$curCargoStoreCall .= $curChar; | |
if ( $curChar == '}' ) { | |
$numUnclosedBrackets--; | |
} elseif ( $curChar == '{' ) { | |
$numUnclosedBrackets++; | |
} | |
if ( $numUnclosedBrackets == 0 ) { | |
break; | |
} | |
$curPos++; | |
} | |
$cargoStoreCalls[] = $curCargoStoreCall; | |
} | |
foreach ( $cargoStoreCalls as $cargoStoreCall ) { | |
if ( preg_match_all( '/([^|{]*?)=\s*{{{([^|}]*)/mis', $cargoStoreCall, $matches ) ) { | |
foreach ( $matches[1] as $i => $cargoFieldName ) { | |
$templateParameter = trim( $matches[2][$i] ); | |
$cargoFieldsOfTemplateParams[$templateParameter] = $cargoFieldName; | |
} | |
} | |
} | |
// Now, combine the two sets of information into an array of | |
// PFTemplateFields objects. | |
// First, go through the #cargo_store parameters, add add them | |
// all to the array, matching them with Cargo field descriptions | |
// where possible. | |
foreach ( $cargoFieldsOfTemplateParams as $templateParameter => $cargoField ) { | |
$templateField = PFTemplateField::create( $templateParameter, $templateParameter ); | |
if ( array_key_exists( $cargoField, $fieldDescriptions ) ) { | |
$fieldDescription = $fieldDescriptions[$cargoField]; | |
$templateField->setCargoFieldData( $tableName, $cargoField, $fieldDescription ); | |
} | |
$this->mTemplateFields[] = $templateField; | |
} | |
// Now, go through the Cargo field descriptions, and add | |
// whichever ones were not in #cargo_store (as of version 3.0, | |
// Cargo does not require template parameters to be passed in | |
// to #cargo_store). | |
foreach ( $fieldDescriptions as $cargoField => $fieldDescription ) { | |
$templateParameter = array_search( $cargoField, $cargoFieldsOfTemplateParams ); | |
if ( $templateParameter !== false ) { | |
continue; | |
} | |
$templateParameter = str_replace( '_', ' ', $cargoField ); | |
$templateField = PFTemplateField::create( $templateParameter, $templateParameter ); | |
$templateField->setCargoFieldData( $tableName, $cargoField, $fieldDescription ); | |
$this->mTemplateFields[] = $templateField; | |
} | |
} | |
function getCargoTableAndSchema( $templateTitle ) { | |
$templatePageID = $templateTitle->getArticleID(); | |
$tableSchemaString = CargoUtils::getPageProp( $templatePageID, 'CargoFields' ); | |
// See if there even is DB storage for this template - if not, | |
// exit. | |
if ( $tableSchemaString === null ) { | |
// There's no declared table - but see if there's an | |
// attached table. | |
list( $tableName, $isDeclared ) = CargoUtils::getTableNameForTemplate( $templateTitle ); | |
if ( $tableName == null ) { | |
return [ null, null ]; | |
} | |
$mainTemplatePageID = CargoUtils::getTemplateIDForDBTable( $tableName ); | |
$tableSchemaString = CargoUtils::getPageProp( $mainTemplatePageID, 'CargoFields' ); | |
} else { | |
$tableName = CargoUtils::getPageProp( $templatePageID, 'CargoTableName' ); | |
} | |
$tableSchema = CargoTableSchema::newFromDBString( $tableSchemaString ); | |
return [ $tableName, $tableSchema ]; | |
} | |
public function getTemplateFields() { | |
return $this->mTemplateFields; | |
} | |
public function getFieldNamed( $fieldName ) { | |
foreach ( $this->mTemplateFields as $curField ) { | |
if ( $curField->getFieldName() == $fieldName ) { | |
return $curField; | |
} | |
} | |
return null; | |
} | |
public function setConnectingProperty( $connectingProperty ) { | |
$this->mConnectingProperty = $connectingProperty; | |
} | |
public function setCategoryName( $categoryName ) { | |
$this->mCategoryName = $categoryName; | |
} | |
public function setCargoTable( $cargoTable ) { | |
$this->mCargoTable = str_replace( ' ', '_', $cargoTable ); | |
} | |
public function setAggregatingInfo( $aggregatingProperty, $aggregationLabel ) { | |
$this->mAggregatingProperty = $aggregatingProperty; | |
$this->mAggregationLabel = $aggregationLabel; | |
} | |
public function setFormat( $templateFormat ) { | |
$this->mTemplateFormat = $templateFormat; | |
} | |
public function createCargoDeclareCall() { | |
$text = '{{#cargo_declare:'; | |
$text .= '_table=' . $this->mCargoTable; | |
foreach ( $this->mTemplateFields as $i => $field ) { | |
if ( $field->getFieldType() == '' ) { | |
continue; | |
} | |
$text .= '|'; | |
$text .= str_replace( ' ', '_', $field->getFieldName() ) . '='; | |
if ( $field->isList() ) { | |
$delimiter = $field->getDelimiter(); | |
if ( $delimiter == '' ) { | |
$delimiter = ','; | |
} | |
$text .= "List ($delimiter) of "; | |
} | |
$text .= $field->getFieldType(); | |
if ( $field->getHierarchyStructure() ) { | |
$hierarchyStructureString = $field->getHierarchyStructure(); | |
$text .= " (hierarchy;allowed values=$hierarchyStructureString)"; | |
} elseif ( count( $field->getPossibleValues() ) > 0 ) { | |
$allowedValuesString = implode( ',', $field->getPossibleValues() ); | |
$text .= " (allowed values=$allowedValuesString)"; | |
} | |
} | |
$text .= '}}'; | |
return $text; | |
} | |
public function createCargoStoreCall() { | |
$text = '{{#cargo_store:'; | |
$text .= '_table=' . $this->mCargoTable; | |
if ( defined( 'CargoStore::PARAMS_OPTIONAL' ) ) { | |
// Cargo 3.0+ | |
$text .= '}}'; | |
return $text; | |
} | |
foreach ( $this->mTemplateFields as $i => $field ) { | |
$text .= '|' . | |
str_replace( ' ', '_', $field->getFieldName() ) . | |
'={{{' . $field->getFieldName() . '|}}}'; | |
} | |
$text .= ' }}'; | |
return $text; | |
} | |
/** | |
* Creates the text of a template, when called from | |
* Special:CreateTemplate, Special:CreateClass or the Page Schemas | |
* extension. | |
* @return string | |
*/ | |
public function createText() { | |
// Avoid PHP 7.1 warning from passing $this by reference | |
$template = $this; | |
Hooks::run( 'PageForms::CreateTemplateText', [ &$template ] ); | |
$text = <<<END | |
<noinclude> | |
{{#template_params: | |
END; | |
foreach ( $this->mTemplateFields as $i => $field ) { | |
if ( $field->getFieldName() == '' ) { | |
continue; | |
} | |
if ( $i > 0 ) { | |
$text .= "|"; | |
} | |
$text .= $field->toWikitext(); | |
} | |
if ( defined( 'CARGO_VERSION' ) && !defined( 'SMW_VERSION' ) && $this->mCargoTable != '' ) { | |
$cargoInUse = true; | |
$cargoDeclareCall = $this->createCargoDeclareCall() . "\n"; | |
$cargoStoreCall = $this->createCargoStoreCall(); | |
} else { | |
$cargoInUse = false; | |
$cargoDeclareCall = ''; | |
$cargoStoreCall = ''; | |
} | |
$text .= <<<END | |
}} | |
$cargoDeclareCall</noinclude><includeonly>$cargoStoreCall | |
END; | |
if ( !defined( 'SMW_VERSION' ) ) { | |
$text .= "\n{{#template_display:"; | |
if ( $this->mTemplateFormat != null ) { | |
$text .= "_format=" . $this->mTemplateFormat; | |
} | |
$text .= "}}"; | |
$text .= $this->printCategoryTag(); | |
$text .= "</includeonly>"; | |
return $text; | |
} | |
// Before text | |
$text .= $this->mTemplateStart; | |
// $internalObjText can be either a call to #set_internal | |
// or to #subobject (or null); which one we go with | |
// depends on whether Semantic Internal Objects is installed, | |
// and on the SMW version. | |
// Thankfully, the syntaxes of #set_internal and #subobject | |
// are quite similar, so we don't need too much extra logic. | |
$internalObjText = null; | |
if ( $this->mConnectingProperty ) { | |
global $smwgDefaultStore; | |
if ( defined( 'SIO_VERSION' ) ) { | |
$useSubobject = false; | |
$internalObjText = '{{#set_internal:' . $this->mConnectingProperty; | |
} elseif ( $smwgDefaultStore == "SMWSQLStore3" ) { | |
$useSubobject = true; | |
$internalObjText = '{{#subobject:-|' . $this->mConnectingProperty . '={{PAGENAME}}'; | |
} | |
} | |
$setText = ''; | |
// Topmost part of table depends on format. | |
if ( !$this->mTemplateFormat ) { | |
$this->mTemplateFormat = 'standard'; | |
} | |
if ( $this->mTemplateFormat == 'standard' ) { | |
$tableText = '{| class="wikitable"' . "\n"; | |
} elseif ( $this->mTemplateFormat == 'infobox' ) { | |
// A CSS style can't be used, unfortunately, since most | |
// MediaWiki setups don't have an 'infobox' or | |
// comparable CSS class. | |
$tableText = <<<END | |
{| style="width: 30em; font-size: 90%; border: 1px solid #aaaaaa; background-color: #f9f9f9; color: black; margin-bottom: 0.5em; margin-left: 1em; padding: 0.2em; float: right; clear: right; text-align:left;" | |
! style="text-align: center; background-color:#ccccff;" colspan="2" |<span style="font-size: larger;">{{PAGENAME}}</span> | |
|- | |
END; | |
} else { | |
$tableText = ''; | |
} | |
foreach ( $this->mTemplateFields as $i => $field ) { | |
if ( $field->getFieldName() == '' ) { | |
continue; | |
} | |
$fieldParam = '{{{' . $field->getFieldName() . '|}}}'; | |
if ( $field->getNamespace() === null ) { | |
$fieldString = $fieldParam; | |
} else { | |
$fieldString = $field->getNamespace() . ':' . $fieldParam; | |
} | |
$separator = ''; | |
$fieldLabel = $field->getLabel(); | |
if ( $fieldLabel == '' ) { | |
$fieldLabel = $field->getFieldName(); | |
} | |
$fieldDisplay = $field->getDisplay(); | |
$fieldProperty = $field->getSemanticProperty(); | |
$fieldIsList = $field->isList(); | |
// Header/field label column | |
if ( $fieldDisplay === null ) { | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
if ( $i > 0 ) { | |
$tableText .= "|-\n"; | |
} | |
$tableText .= '! ' . $fieldLabel . "\n"; | |
} elseif ( $this->mTemplateFormat == 'plain' ) { | |
$tableText .= "\n'''" . $fieldLabel . ":''' "; | |
} elseif ( $this->mTemplateFormat == 'sections' ) { | |
$tableText .= "\n==" . $fieldLabel . "==\n"; | |
} | |
} elseif ( $fieldDisplay == 'nonempty' ) { | |
if ( $this->mTemplateFormat == 'plain' || $this->mTemplateFormat == 'sections' ) { | |
$tableText .= "\n"; | |
} | |
$tableText .= '{{#if:' . $fieldParam . '|'; | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
if ( $i > 0 ) { | |
$tableText .= "\n{{!}}-\n"; | |
} | |
$tableText .= '! ' . $fieldLabel . "\n"; | |
$separator = '{{!}}'; | |
} elseif ( $this->mTemplateFormat == 'plain' ) { | |
$tableText .= "'''" . $fieldLabel . ":''' "; | |
$separator = ''; | |
} elseif ( $this->mTemplateFormat == 'sections' ) { | |
$tableText .= '==' . $fieldLabel . "==\n"; | |
$separator = ''; | |
} | |
} else { | |
// If it's 'hidden', do nothing | |
} | |
// Value column | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
if ( $fieldDisplay == 'hidden' ) { | |
} elseif ( $fieldDisplay == 'nonempty' ) { | |
// $tableText .= "{{!}} "; | |
} else { | |
$tableText .= "| "; | |
} | |
} | |
// If we're using Cargo, fields can simply be displayed | |
// normally - no need for any special tags - *unless* | |
// the field holds a list of Page values, in which case | |
// we need to apply #arraymap. | |
$isCargoListOfPages = $cargoInUse && $field->isList() && $field->getFieldType() == 'Page'; | |
if ( !$fieldProperty && !$isCargoListOfPages ) { | |
if ( $separator != '' ) { | |
$tableText .= "$separator "; | |
} | |
$tableText .= $this->createTextForField( $field ); | |
if ( $fieldDisplay == 'nonempty' ) { | |
$tableText .= " }}"; | |
} | |
$tableText .= "\n"; | |
} elseif ( $internalObjText !== null ) { | |
if ( $separator != '' ) { | |
$tableText .= "$separator "; | |
} | |
$tableText .= $this->createTextForField( $field ); | |
if ( $fieldDisplay == 'nonempty' ) { | |
$tableText .= " }}"; | |
} | |
$tableText .= "\n"; | |
if ( $field->isList() ) { | |
if ( $useSubobject ) { | |
$internalObjText .= '|' . $fieldProperty . '=' . $fieldString . '|+sep=,'; | |
} else { | |
$internalObjText .= '|' . $fieldProperty . '#list=' . $fieldString; | |
} | |
} else { | |
$internalObjText .= '|' . $fieldProperty . '=' . $fieldString; | |
} | |
} elseif ( $fieldDisplay == 'hidden' ) { | |
if ( $fieldIsList ) { | |
$setText .= $fieldProperty . '#list=' . $fieldString . '|'; | |
} else { | |
$setText .= $fieldProperty . '=' . $fieldString . '|'; | |
} | |
} elseif ( $fieldDisplay == 'nonempty' ) { | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
$tableText .= '{{!}} '; | |
} | |
$tableText .= $this->createTextForField( $field ) . "\n}}\n"; | |
} else { | |
$tableText .= $this->createTextForField( $field ) . "\n"; | |
} | |
} | |
// Add an inline query to the output text, for | |
// aggregation, if a property was specified. | |
if ( $this->mAggregatingProperty !== null && $this->mAggregatingProperty !== '' ) { | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
if ( count( $this->mTemplateFields ) > 0 ) { | |
$tableText .= "|-\n"; | |
} | |
$tableText .= <<<END | |
! $this->mAggregationLabel | |
| | |
END; | |
} elseif ( $this->mTemplateFormat == 'plain' ) { | |
$tableText .= "\n'''" . $this->mAggregationLabel . ":''' "; | |
} elseif ( $this->mTemplateFormat == 'sections' ) { | |
$tableText .= "\n==" . $this->mAggregationLabel . "==\n"; | |
} | |
$tableText .= "{{#ask:[[" . $this->mAggregatingProperty . "::{{SUBJECTPAGENAME}}]]|format=list}}\n"; | |
} | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
$tableText .= "|}"; | |
} | |
// Leave out newlines if there's an internal property | |
// set here (which would mean that there are meant to be | |
// multiple instances of this template.) | |
if ( $internalObjText === null ) { | |
if ( $this->mTemplateFormat == 'standard' || $this->mTemplateFormat == 'infobox' ) { | |
$tableText .= "\n"; | |
} | |
} else { | |
$internalObjText .= "}}"; | |
$text .= $internalObjText; | |
} | |
// Add a call to #set, if necessary | |
if ( $setText !== '' ) { | |
$setText = '{{#set:' . $setText . "}}\n"; | |
$text .= $setText; | |
} | |
$text .= $tableText; | |
$text .= $this->printCategoryTag(); | |
// After text | |
$text .= $this->mTemplateEnd; | |
$text .= "</includeonly>\n"; | |
return $text; | |
} | |
function createTextForField( $field ) { | |
$text = ''; | |
$fieldStart = $this->mFieldStart; | |
Hooks::run( 'PageForms::TemplateFieldStart', [ $field, &$fieldStart ] ); | |
if ( $fieldStart != '' ) { | |
$text .= "$fieldStart "; | |
} | |
$cargoInUse = defined( 'CARGO_VERSION' ) && !defined( 'SMW_VERSION' ) && $this->mCargoTable != ''; | |
$text .= $field->createText( $cargoInUse ); | |
$fieldEnd = $this->mFieldEnd; | |
Hooks::run( 'PageForms::TemplateFieldEnd', [ $field, &$fieldEnd ] ); | |
if ( $fieldEnd != '' ) { | |
$text .= " $fieldEnd"; | |
} | |
return $text; | |
} | |
function printCategoryTag() { | |
if ( ( $this->mCategoryName === '' || $this->mCategoryName === null ) ) { | |
return ''; | |
} | |
$namespaceLabels = PFUtils::getContLang()->getNamespaces(); | |
$categoryNamespace = $namespaceLabels[NS_CATEGORY]; | |
return "\n[[$categoryNamespace:" . $this->mCategoryName . "]]\n"; | |
} | |
} |