static function newFromFormFieldTag($tag_components, $template_in_form, $form_is_disabled) { global $wgParser, $wgUser; $field_name = trim($tag_components[1]); // See if this field matches one of the fields defined for this // template - if it is, use all available information about // that field; if it's not, either include it in the form or // not, depending on whether the template has a 'strict' // setting in the form definition. $the_field = null; $all_fields = $template_in_form->getAllFields(); foreach ($all_fields as $cur_field) { if ($field_name == $cur_field->getFieldName()) { $the_field = $cur_field; break; } } if ($the_field == null) { if ($template_in_form->strictParsing()) { $dummy_ff = new SFFormField(); $dummy_ff->template_field = new SFTemplateField(); $dummy_ff->mIsList = false; return $dummy_ff; } $the_field = SFTemplateField::create($field_name, null); } // Create an SFFormField object, containing this field as well // as settings from the form definition file. $f = new SFFormField(); $f->template_field = $the_field; $f->mFieldArgs = array(); $semantic_property = null; $cargo_table = $cargo_field = null; $show_on_select = array(); $fullFieldName = $template_in_form->getTemplateName() . '[' . $field_name . ']'; // Cycle through the other components. for ($i = 2; $i < count($tag_components); $i++) { $component = trim($tag_components[$i]); if ($component == 'mandatory') { $f->mIsMandatory = true; } elseif ($component == 'hidden') { $f->mIsHidden = true; } elseif ($component == 'restricted') { $f->mIsRestricted = !$wgUser || !$wgUser->isAllowed('editrestrictedfields'); } elseif ($component == 'list') { $f->mIsList = true; } elseif ($component == 'unique') { $f->mFieldArgs['unique'] = true; } elseif ($component == 'edittools') { // free text only $f->mFieldArgs['edittools'] = true; } $sub_components = array_map('trim', explode('=', $component, 2)); if (count($sub_components) == 1) { // add handling for single-value params, for custom input types $f->mFieldArgs[$sub_components[0]] = true; if ($component == 'holds template') { $f->mIsHidden = true; $f->mHoldsTemplate = true; } } elseif (count($sub_components) == 2) { // First, set each value as its own entry in $this->mFieldArgs. $f->mFieldArgs[$sub_components[0]] = $sub_components[1]; // Then, do all special handling. if ($sub_components[0] == 'input type') { $f->mInputType = $sub_components[1]; } elseif ($sub_components[0] == 'default') { // We call recursivePreprocess() here, // and not the more standard // recursiveTagParse(), so that // wikitext in the value, and bare URLs, // will not get turned into HTML. $f->mDefaultValue = $wgParser->recursivePreprocess($sub_components[1]); } elseif ($sub_components[0] == 'preload') { $f->mPreloadPage = $sub_components[1]; } elseif ($sub_components[0] == 'show on select') { // html_entity_decode() is needed to turn '>' to '>' $vals = explode(';', html_entity_decode($sub_components[1])); foreach ($vals as $val) { $val = trim($val); if (empty($val)) { continue; } $option_div_pair = explode('=>', $val, 2); if (count($option_div_pair) > 1) { $option = $option_div_pair[0]; $div_id = $option_div_pair[1]; if (array_key_exists($div_id, $show_on_select)) { $show_on_select[$div_id][] = $option; } else { $show_on_select[$div_id] = array($option); } } else { $show_on_select[$val] = array(); } } } elseif ($sub_components[0] == 'autocomplete on property') { $f->mFieldArgs['autocomplete field type'] = 'property'; $f->mFieldArgs['autocompletion source'] = $sub_components[1]; } elseif ($sub_components[0] == 'autocomplete on category') { $f->mFieldArgs['autocomplete field type'] = 'category'; $f->mFieldArgs['autocompletion source'] = $sub_components[1]; } elseif ($sub_components[0] == 'autocomplete on concept') { $f->mFieldArgs['autocomplete field type'] = 'concept'; $f->mFieldArgs['autocompletion source'] = $sub_components[1]; } elseif ($sub_components[0] == 'autocomplete on namespace') { $f->mFieldArgs['autocomplete field type'] = 'namespace'; $autocompletion_source = $sub_components[1]; // Special handling for "main" (blank) // namespace. if ($autocompletion_source == "") { $autocompletion_source = "main"; } $f->mFieldArgs['autocompletion source'] = $autocompletion_source; } elseif ($sub_components[0] == 'autocomplete from url') { $f->mFieldArgs['autocomplete field type'] = 'external_url'; $f->mFieldArgs['autocompletion source'] = $sub_components[1]; // 'external' autocompletion is always done remotely, i.e. via API $f->mFieldArgs['remote autocompletion'] = true; } elseif ($sub_components[0] == 'values') { // Handle this one only after // 'delimiter' has also been set. $values = $wgParser->recursiveTagParse($sub_components[1]); } elseif ($sub_components[0] == 'values from property') { $propertyName = $sub_components[1]; $f->mPossibleValues = SFUtils::getAllValuesForProperty($propertyName); } elseif ($sub_components[0] == 'values from query') { $pages = SFUtils::getAllPagesForQuery($sub_components[1]); foreach ($pages as $page) { $page_name_for_values = $page->getDbKey(); $f->mPossibleValues[] = $page_name_for_values; } } elseif ($sub_components[0] == 'values from category') { $category_name = ucfirst($sub_components[1]); $f->mPossibleValues = SFUtils::getAllPagesForCategory($category_name, 10); } elseif ($sub_components[0] == 'values from concept') { $f->mPossibleValues = SFUtils::getAllPagesForConcept($sub_components[1]); } elseif ($sub_components[0] == 'values from namespace') { $f->mPossibleValues = SFUtils::getAllPagesForNamespace($sub_components[1]); } elseif ($sub_components[0] == 'values dependent on') { global $sfgDependentFields; $sfgDependentFields[] = array($sub_components[1], $fullFieldName); } elseif ($sub_components[0] == 'unique for category') { $f->mFieldArgs['unique'] = true; $f->mFieldArgs['unique_for_category'] = $sub_components[1]; } elseif ($sub_components[0] == 'unique for namespace') { $f->mFieldArgs['unique'] = true; $f->mFieldArgs['unique_for_namespace'] = $sub_components[1]; } elseif ($sub_components[0] == 'unique for concept') { $f->mFieldArgs['unique'] = true; $f->mFieldArgs['unique_for_concept'] = $sub_components[1]; } elseif ($sub_components[0] == 'property') { $semantic_property = $sub_components[1]; } elseif ($sub_components[0] == 'cargo table') { $cargo_table = $sub_components[1]; } elseif ($sub_components[0] == 'cargo field') { $cargo_field = $sub_components[1]; } elseif ($sub_components[0] == 'default filename') { $default_filename = str_replace('<page name>', $page_name, $sub_components[1]); // Parse value, so default filename can // include parser functions. $default_filename = $wgParser->recursiveTagParse($default_filename); $f->mFieldArgs['default filename'] = $default_filename; } elseif ($sub_components[0] == 'restricted') { $f->mIsRestricted = !array_intersect($wgUser->getEffectiveGroups(), array_map('trim', explode(',', $sub_components[1]))); } } } // end for if (!array_key_exists('delimiter', $f->mFieldArgs)) { $f->mFieldArgs['delimiter'] = ","; } $delimiter = $f->mFieldArgs['delimiter']; // If the 'values' parameter was set, separate it based on the // 'delimiter' parameter, if any. if (!empty($values)) { // Remove whitespaces, and un-escape characters $valuesArray = array_map('trim', explode($delimiter, $values)); $f->mPossibleValues = array_map('htmlspecialchars_decode', $valuesArray); } // If we're using Cargo, there's no equivalent for "values from // property" - instead, we just always get the values if a // field and table have been specified. if (is_null($f->mPossibleValues) && defined('CARGO_VERSION') && $cargo_table != null && $cargo_field != null) { // We only want the non-null values. Ideally this could // be done by calling getValuesForCargoField() with // an "IS NOT NULL" clause, but unfortunately that fails // for array/list fields. // Instead of getting involved with all that, we'll just // remove the null/blank values afterward. $cargoValues = SFUtils::getAllValuesForCargoField($cargo_table, $cargo_field); $f->mPossibleValues = array_filter($cargoValues, 'strlen'); } if (!is_null($f->mPossibleValues)) { if (array_key_exists('mapping template', $f->mFieldArgs)) { $f->mPossibleValues = SFUtils::getLabelsFromTemplate($f->mPossibleValues, $f->mFieldArgs['mapping template']); } elseif (array_key_exists('mapping property', $f->mFieldArgs)) { $f->mPossibleValues = SFUtils::getLabelsFromProperty($f->mPossibleValues, $f->mFieldArgs['mapping property']); } elseif (array_key_exists('mapping cargo table', $f->mFieldArgs) && array_key_exists('mapping cargo field', $f->mFieldArgs)) { $f->mPossibleValues = SFUtils::getLabelsFromCargoField($f->mPossibleValues, $f->mFieldArgs['mapping cargo table'], $f->mFieldArgs['mapping cargo field']); } } // Backwards compatibility. if ($f->mInputType == 'datetime with timezone') { $f->mInputType = 'datetime'; $f->mFieldArgs['include timezone'] = true; } elseif ($f->mInputType == 'text' || $f->mInputType == 'textarea') { // Backwards compatibility. $f->mFieldArgs['no autocomplete'] = true; } if ($template_in_form->allowsMultiple()) { $f->mFieldArgs['part_of_multiple'] = true; } if (count($show_on_select) > 0) { $f->mFieldArgs['show on select'] = $show_on_select; } // Disable this field if either the whole form is disabled, or // it's a restricted field and user doesn't have sysop privileges. $f->mIsDisabled = $form_is_disabled || $f->mIsRestricted; // Do some data storage specific to the Semantic MediaWiki and // Cargo extensions. if (defined('SMW_VERSION')) { // If a property was set in the form definition, // overwrite whatever is set in the template field - // this is somewhat of a hack, since parameters set in // the form definition are meant to go into the // SFFormField object, not the SFTemplateField object // it contains; // it seemed like too much work, though, to create an // SFFormField::setSemanticProperty() function just for // this call. if (!is_null($semantic_property)) { $f->template_field->setSemanticProperty($semantic_property); } else { $semantic_property = $f->template_field->getSemanticProperty(); } if (!is_null($semantic_property)) { global $sfgFieldProperties; $sfgFieldProperties[$fullFieldName] = $semantic_property; } } if (defined('CARGO_VERSION')) { if ($cargo_table != null && $cargo_field != null) { $f->template_field->setCargoFieldData($cargo_table, $cargo_field); } $fullCargoField = $f->template_field->getFullCargoField(); if (!is_null($fullCargoField)) { global $sfgCargoFields; $sfgCargoFields[$fullFieldName] = $fullCargoField; } } if ($template_in_form->getTemplateName() == null || $template_in_form->getTemplateName() === '') { $f->mInputName = $field_name; } elseif ($template_in_form->allowsMultiple()) { // 'num' will get replaced by an actual index, either in PHP // or in Javascript, later on $f->mInputName = $template_in_form->getTemplateName() . '[num][' . $field_name . ']'; $f->setFieldArg('origName', $template_in_form->getTemplateName() . '[' . $field_name . ']'); } else { $f->mInputName = $template_in_form->getTemplateName() . '[' . $field_name . ']'; } return $f; }