Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Wikipedia: Mediawiki-CVS

SVN: [58566] tags/extensions/SemanticForms

 

 

Wikipedia mediawiki-cvs RSS feed   Index | Next | Previous | View Threaded


yaron at svn

Nov 4, 2009, 1:32 PM

Post #1 of 1 (15 views)
Permalink
SVN: [58566] tags/extensions/SemanticForms

http://www.mediawiki.org/wiki/Special:Code/MediaWiki/58566

Revision: 58566
Author: yaron
Date: 2009-11-04 21:32:32 +0000 (Wed, 04 Nov 2009)

Log Message:
-----------
Second tag for version 1.8.5, with some bug fixes

Added Paths:
-----------
tags/extensions/SemanticForms/REL_1_8_5_1/
tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc

Removed Paths:
-------------
tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc

Deleted: tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc
===================================================================
--- trunk/extensions/SemanticForms/includes/SF_FormPrinter.inc 2009-11-04 18:40:56 UTC (rev 58554)
+++ tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc 2009-11-04 21:32:32 UTC (rev 58566)
@@ -1,1344 +0,0 @@
-<?php
-/**
- * Handles the creation and running of a user-created form.
- *
- * @author Yaron Koren
- * @author Nils Oppermann
- * @author Jeffrey Stuckman
- * @author Harold Solbrig
- * @author Daniel Hansch
- */
-
-class SFFormPrinter {
-
- var $mSemanticTypeHooks;
- var $mInputTypeHooks;
- var $standardInputsIncluded;
- var $mPageTitle;
-
- function SFFormPrinter() {
- global $smwgContLang;
-
- // initialize the set of hooks for the entry-field functions to call for
- // fields of both a specific semantic "type" and a defined "input type"
- // in the form definition
- $this->mSemanticTypeHooks = array();
- if ($smwgContLang != null) {
- $datatypeLabels = $smwgContLang->getDatatypeLabels();
- $string_type = $datatypeLabels['_str'];
- $text_type = $datatypeLabels['_txt'];
- // type introduced in SMW 1.2
- if (array_key_exists('_cod', $datatypeLabels))
- $code_type = $datatypeLabels['_cod'];
- else
- $code_type = 'code';
- $url_type = $datatypeLabels['_uri'];
- $email_type = $datatypeLabels['_ema'];
- $number_type = $datatypeLabels['_num'];
- $bool_type = $datatypeLabels['_boo'];
- $date_type = $datatypeLabels['_dat'];
- $enum_type = 'enumeration'; // not a real type
- $page_type = $datatypeLabels['_wpg'];
- $this->setSemanticTypeHook($string_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'string'));
- $this->setSemanticTypeHook($string_type, true, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'string', 'is_list' => 'true', 'size' => '100'));
- $this->setSemanticTypeHook($text_type, false, array('SFFormInputs', 'textAreaHTML'), array());
- $this->setSemanticTypeHook($code_type, false, array('SFFormInputs', 'textAreaHTML'), array());
- $this->setSemanticTypeHook($url_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'URL'));
- $this->setSemanticTypeHook($email_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'email'));
- $this->setSemanticTypeHook($number_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'number'));
- $this->setSemanticTypeHook($bool_type, false, array('SFFormInputs', 'checkboxHTML'), array());
- $this->setSemanticTypeHook($date_type, false, array('SFFormInputs', 'dateEntryHTML'), array());
- $this->setSemanticTypeHook($enum_type, false, array('SFFormInputs', 'dropdownHTML'), array());
- $this->setSemanticTypeHook($enum_type, true, array('SFFormInputs', 'checkboxesHTML'), array());
- $this->setSemanticTypeHook($page_type, false, array('SFFormInputs', 'textInputWithAutocompleteHTML'), array('field_type' => 'page'));
- $this->setSemanticTypeHook($page_type, true, array('SFFormInputs', 'textInputWithAutocompleteHTML'), array('field_type' => 'page', 'size' => '100', 'is_list' => 'true'));
- }
- $this->mInputTypeHooks = array();
- $this->setInputTypeHook('text', array('SFFormInputs', 'textEntryHTML'), array());
- $this->setInputTypeHook('textarea', array('SFFormInputs', 'textAreaHTML'), array());
- $this->setInputTypeHook('date', array('SFFormInputs', 'dateEntryHTML'), array());
- $this->setInputTypeHook('datetime', array('SFFormInputs', 'dateTimeEntryHTML'), array('include_timezone' => false));
- $this->setInputTypeHook('datetime with timezone', array('SFFormInputs', 'dateTimeEntryHTML'), array('include_timezone' => true));
- $this->setInputTypeHook('year', array('SFFormInputs', 'textEntryHTML'), array('size' => 4));
- $this->setInputTypeHook('checkbox', array('SFFormInputs', 'checkboxHTML'), array());
- $this->setInputTypeHook('radiobutton', array('SFFormInputs', 'radiobuttonHTML'), array());
- $this->setInputTypeHook('checkboxes', array('SFFormInputs', 'checkboxesHTML'), array());
- $this->setInputTypeHook('listbox', array('SFFormInputs', 'listboxHTML'), array());
- $this->setInputTypeHook('category', array('SFFormInputs', 'categoryHTML'), array());
- $this->setInputTypeHook('categories', array('SFFormInputs', 'categoriesHTML'), array());
-
- // initialize other variables
- $this->standardInputsIncluded = false;
- }
-
- function setSemanticTypeHook($type, $is_list, $function_name, $default_args) {
- $this->mSemanticTypeHooks[$type][$is_list] = array($function_name, $default_args);
- }
-
- function setInputTypeHook($input_type, $function_name, $default_args) {
- $this->mInputTypeHooks[$input_type] = array($function_name, $default_args);
- }
-
-
- /**
- * Show the set of previous deletions for the page being added.
- * This function is copied almost exactly from EditPage::showDeletionLog() -
- * unfortunately, neither that function nor Article::showDeletionLog() can
- * be called from here, since they're both protected
- */
- function showDeletionLog( $out ) {
- // if MW doesn't have LogEventsList defined, exit immediately
- if (! class_exists('LogEventsList'))
- return false;
-
- global $wgUser;
- $loglist = new LogEventsList( $wgUser->getSkin(), $out );
- $pager = new LogPager( $loglist, 'delete', false, $this->mPageTitle->getPrefixedText() );
- $count = $pager->getNumRows();
- if ( $count > 0 ) {
- $pager->mLimit = 10;
- $out->addHTML( '<div class="mw-warning-with-logexcerpt">' );
- // the message name changed in MW 1.16
- if (! wfEmptyMsg( 'moveddeleted-notice', wfMsg('moveddeleted-notice') ))
- $out->addWikiMsg( 'moveddeleted-notice' );
- else
- $out->addWikiMsg( 'recreate-deleted-warn' );
- $out->addHTML(
- $loglist->beginLogEventsList() .
- $pager->getBody() .
- $loglist->endLogEventsList()
- );
- if($count > 10){
- $out->addHTML( $wgUser->getSkin()->link(
- SpecialPage::getTitleFor( 'Log' ),
- wfMsgHtml( 'deletelog-fulllog' ),
- array(),
- array(
- 'type' => 'delete',
- 'page' => $this->mPageTitle->getPrefixedText() ) ) );
- }
- $out->addHTML( '</div>' );
- return true;
- }
-
- return false;
- }
-
-
- function formHTML($form_def, $form_submitted, $source_is_page, $existing_page_content = null, $page_title = null, $page_name_formula = null, $is_query = false) {
- global $wgRequest, $wgUser, $wgParser;
- global $sfgTabIndex; // used to represent the current tab index in the form
- global $sfgFieldNum; // used for setting various HTML IDs
- global $sfgJSValidationCalls; // array of Javascript calls to determine if page can be saved
-
- // initialize some variables
- $sfgTabIndex = 1;
- $sfgFieldNum = 1;
- $source_page_matches_this_form = false;
- $form_page_title = NULL;
- $generated_page_name = $page_name_formula;
- // $form_is_partial is true if:
- // (a) 'partial' == 1 in the arguments
- // (b) 'partial form' is found in the form definition
- // in the latter case, it may remain false until close to the end of
- // the parsing, so we have to assume that it will become a possibility
- $form_is_partial = false;
- $new_text = "";
- // flag for placing "<onlyinclude>" tags in form output
- $onlyinclude_free_text = false;
-
- // if we have existing content and we're not in an active replacement
- // situation, preserve the original content. We do this because we want
- // to pass the original content on IF this is a partial form
- // TODO: A better approach here would be to pass the revision id of the
- // existing page content through the replace value, which would
- // minimize the html traffic and would allow us to do a concurrent
- // update check. For now, we pass it through the hidden text field...
-
- if (! $wgRequest->getCheck('partial')) {
- $original_page_content = $existing_page_content;
- } else {
- $original_page_content = null;
- if($wgRequest->getCheck('free_text')) {
- $existing_page_content= $wgRequest->getVal('free_text');
- $form_is_partial = true;
- }
- }
-
- // disable all form elements if user doesn't have edit permission -
- // two different checks are needed, because editing permissions can be
- // set in different ways
- // HACK - sometimes we don't know the page name in advance, but we still
- // need to set a title here for testing permissions
- if ($page_title == '')
- $this->mPageTitle = Title::newFromText("Semantic Forms permissions test");
- else
- $this->mPageTitle = Title::newFromText($page_title);
- global $wgOut;
- // show previous set of deletions for this page, if it's been deleted before
- if (! $form_submitted && ! $this->mPageTitle->exists())
- $this->showDeletionLog($wgOut);
- if (($wgUser->isAllowed('edit') && $this->mPageTitle->userCan('edit')) || $is_query) {
- $form_is_disabled = false;
- $form_text = "";
- // show "Your IP address will be recorded" warning if user is
- // anonymous, and it's not a query -
- // wikitext for bolding has to be replaced with HTML
- if ($wgUser->isAnon() && ! $is_query) {
- $anon_edit_warning = preg_replace("/'''(.*)'''/", "<strong>$1</strong>", wfMsg('anoneditwarning'));
- $form_text .= "<p>$anon_edit_warning</p>\n";
- }
- } else {
- $form_is_disabled = true;
- // display a message to the user explaining why they can't edit the
- // page - borrowed heavily from EditPage.php
- if ( $wgUser->isAnon() ) {
- $skin = $wgUser->getSkin();
- $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
- $loginLink = $skin->makeKnownLinkObj( $loginTitle, wfMsgHtml( 'loginreqlink' ) );
- $form_text = wfMsgWikiHtml( 'whitelistedittext', $loginLink );
- } else {
- $form_text = wfMsg( 'protectedpagetext' );
- }
- }
- $javascript_text = "";
- $sfgJSValidationCalls = array();
- $fields_javascript_text = "";
-
- // Remove <noinclude> sections and <includeonly> tags from form definition
- $form_def = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $form_def);
- $form_def = strtr($form_def, array('<includeonly>' => '', '</includeonly>' => ''));
-
- // parse wiki-text
- // add '<nowiki>' tags around every triple-bracketed form definition
- // element, so that the wiki parser won't touch it - the parser will
- // remove the '<nowiki>' tags, leaving us with what we need
- $form_def = "__NOEDITSECTION__" . strtr($form_def, array('{{{' => '<nowiki>{{{', '}}}' => '}}}</nowiki>'));
- $wgParser->mOptions = new ParserOptions();
- $wgParser->mOptions->initialiseFromUser($wgUser);
- $form_def = $wgParser->parse($form_def, $this->mPageTitle, $wgParser->mOptions)->getText();
-
- // turn form definition file into an array of sections, one for each
- // template definition (plus the first section)
- $form_def_sections = array();
- $start_position = 0;
- $section_start = 0;
- $free_text_was_included = false;
- $free_text_preload_page = null;
- $free_text_components = array();
- $all_values_for_template = array();
- // unencode and HTML-encoded representations of curly brackets and
- // pipes - this is a hack to allow for forms to include templates
- // that themselves contain form elements - the escaping is needed
- // to make sure that those elements don't get parsed too early
- $form_def = str_replace(array('&#123;', '&#124;', '&#125;'), array('{', '|', '}'), $form_def);
- // and another hack - replace the 'free text' standard input with
- // a field declaration to get it to be handled as a field
- $form_def = str_replace('standard input|free text', 'field|<freetext>', $form_def);
- while ($brackets_loc = strpos($form_def, "{{{", $start_position)) {
- $brackets_end_loc = strpos($form_def, "}}}", $brackets_loc);
- $bracketed_string = substr($form_def, $brackets_loc + 3, $brackets_end_loc - ($brackets_loc + 3));
- $tag_components = explode('|', $bracketed_string);
- $tag_title = trim($tag_components[0]);
- if ($tag_title == 'for template' || $tag_title == 'end template') {
- // create a section for everything up to here
- $section = substr($form_def, $section_start, $brackets_loc - $section_start);
- $form_def_sections[] = $section;
- $section_start = $brackets_loc;
- }
- $start_position = $brackets_loc + 1;
- } // end while
- $form_def_sections[] = trim(substr($form_def, $section_start));
-
- // cycle through form definition file (and possibly an existing article
- // as well), finding template and field declarations and replacing them
- // with form elements, either blank or pre-populated, as appropriate
- $all_fields = array();
- $data_text = "";
- $template_name = "";
- $allow_multiple = false;
- $instance_num = 0;
- $all_instances_printed = false;
- $strict_parsing = false;
- // initialize list of choosers (dropdowns with available templates)
- $choosers = array();
- for ($section_num = 0; $section_num < count($form_def_sections); $section_num++) {
- $tif = new SFTemplateInForm();
- $start_position = 0;
- $template_text = "";
- // the append is there to ensure that the original array doesn't get
- // modified; is it necessary?
- $section = " " . $form_def_sections[$section_num];
-
- while ($brackets_loc = strpos($section, '{{{', $start_position)) {
- $brackets_end_loc = strpos($section, "}}}", $brackets_loc);
- $bracketed_string = substr($section, $brackets_loc + 3, $brackets_end_loc - ($brackets_loc + 3));
- $tag_components = explode('|', $bracketed_string);
- $tag_title = trim($tag_components[0]);
- // =====================================================
- // for template processing
- // =====================================================
- if ($tag_title == 'for template') {
- $old_template_name = $template_name;
- $template_name = trim($tag_components[1]);
- $tif->template_name = $template_name;
- $query_template_name = str_replace(' ', '_', $template_name);
- // also replace periods with underlines, since that's what
- // POST does to strings anyway
- $query_template_name = str_replace('.', '_', $query_template_name);
- $chooser_name = false;
- $chooser_caption = false;
- // cycle through the other components
- for ($i = 2; $i < count($tag_components); $i++) {
- $component = $tag_components[$i];
- if ($component == 'multiple') $allow_multiple = true;
- if ($component == 'strict') $strict_parsing = true;
- $sub_components = explode('=', $component);
- if (count($sub_components) == 2) {
- if ($sub_components[0] == 'label') {
- $template_label = $sub_components[1];
- } elseif ($sub_components[0] == 'chooser') {
- $allow_multiple = true;
- $chooser_name = $sub_components[1];
- } elseif ($sub_components[0] == 'chooser caption') {
- $chooser_caption = $sub_components[1];
- }
- }
- }
- // if this is the first instance, add the label in the form
- if (($old_template_name != $template_name) && isset($template_label)) {
- // add a placeholder to the form text so the fieldset can be
- // hidden if chooser support demands it
- if ($chooser_name !== false)
- $form_text .= "<fieldset [[placeholder]] haschooser=true>\n";
- else
- $form_text .= "<fieldset>\n";
- $form_text .= "<legend>$template_label</legend>\n";
- }
- $template_text .= "{{" . $tif->template_name;
- $all_fields = $tif->getAllFields();
- // remove template tag
- $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- $template_instance_query_values = $wgRequest->getArray($query_template_name);
- // if we are editing a page, and this template can be found more than
- // once in that page, and multiple values are allowed, repeat this
- // section
- $existing_template_text = null;
- if ($source_is_page || $form_is_partial) {
- // replace underlines with spaces in template name, to allow for
- // searching on either
- $search_template_str = str_replace('_', ' ', $tif->template_name);
- $found_instance = preg_match('/{{' . $search_template_str . '\s*[\|}]/i', str_replace('_', ' ', $existing_page_content));
- if ($allow_multiple) {
- // find instances of this template in the page -
- // if there's at least one, re-parse this section of the
- // definition form for the subsequent template instances in
- // this page; if there's none, don't include fields at all.
- // there has to be a more efficient way to handle multiple
- // instances of templates, one that doesn't involve re-parsing
- // the same tags, but I don't know what it is.
- if ($found_instance) {
- $instance_num++;
- } else {
- $all_instances_printed = true;
- }
- }
- // get the first instance of this template on the page being edited,
- // even if there are more
- if ($found_instance && ($start_char = stripos(str_replace('_', ' ', $existing_page_content), '{{' . $search_template_str)) !== false) {
- $fields_start_char = $start_char + 2 + strlen($search_template_str);
- // skip ahead to the first real character
- while (in_array($existing_page_content[$fields_start_char], array(' ', '\n', '|'))) {
- $fields_start_char++;
- }
- $template_contents = array('0' => '');
- // cycle through template call, splitting it up by pipes ('|'),
- // except when that pipe is part of a piped link
- $field = "";
- $uncompleted_square_brackets = 0;
- $uncompleted_curly_brackets = 2;
- $template_ended = false;
- for ($i = $fields_start_char; ! $template_ended && ($i < strlen($existing_page_content)); $i++) {
- $c = $existing_page_content[$i];
- if ($c == '[') {
- $uncompleted_square_brackets++;
- } elseif ($c == ']' && $uncompleted_square_brackets > 0) {
- $uncompleted_square_brackets--;
- } elseif ($c == '{') {
- $uncompleted_curly_brackets++;
- } elseif ($c == '}' && $uncompleted_curly_brackets > 0) {
- $uncompleted_curly_brackets--;
- }
- // handle an end to a field and/or template declaration
- $template_ended = ($uncompleted_curly_brackets == 0 && $uncompleted_square_brackets == 0);
- $field_ended = ($c == '|' && $uncompleted_square_brackets == 0 && $uncompleted_curly_brackets <= 2);
- if ($template_ended || $field_ended) {
- // if this was the last character in the template, remove
- // the closing curly brackets
- if ($template_ended) {
- $field = substr($field, 0, -1);
- }
- // either there's an equals sign near the beginning or not -
- // handling is similar in either way; if there's no equals
- // sign, the index of this field becomes the key
- $sub_fields = explode('=', $field, 2);
- if (count($sub_fields) > 1) {
- $template_contents[trim($sub_fields[0])] = trim($sub_fields[1]);
- } else {
- $template_contents[] = trim($sub_fields[0]);
- }
- $field = '';
- } else {
- $field .= $c;
- }
- }
- $existing_template_text = substr($existing_page_content, $start_char, $i - $start_char);
- // now remove this template from the text being edited
- // if this is a partial form, establish a new insertion point
- if ($existing_page_content && $form_is_partial && $wgRequest->getCheck('partial')) {
- // if something already exists, set the new insertion point
- // to its position; otherwise just let it lie
- if (strpos($existing_page_content, $existing_template_text) !== false) {
- $existing_page_content = str_replace('{{{insertionpoint}}}', '', $existing_page_content);
- $existing_page_content = str_replace($existing_template_text, '{{{insertionpoint}}}', $existing_page_content);
- }
- } else {
- $existing_page_content = str_replace($existing_template_text, '', $existing_page_content);
- }
- // if this is not a multiple-instance template, and we've found
- // a match in the source page, there's a good chance that this
- // page was created with this form - note that, so we don't
- // send the user a warning
- // (multiple-instance templates have a greater chance of
- // getting repeated from one form to the next)
- if (! $allow_multiple) {
- $source_page_matches_this_form = true;
- }
- }
- }
- // if the input is from the form (meaning the user has hit one
- // of the bottom row of buttons), and we're dealing with a
- // multiple template, get the values for this instance of this
- // template, then delete them from the array, so we can get the
- // next group next time - the next() command for arrays doesn't
- // seem to work here
- if ((! $source_is_page) && $allow_multiple && $wgRequest) {
- $all_instances_printed = true;
- if ($old_template_name != $template_name) {
- $all_values_for_template = $wgRequest->getArray($query_template_name);
- }
- if ($all_values_for_template) {
- $cur_key = key($all_values_for_template);
- // skip the input coming in from the "starter" div
- if ($cur_key == 'num') {
- unset($all_values_for_template[$cur_key]);
- $cur_key = key($all_values_for_template);
- }
- if ($template_instance_query_values = current($all_values_for_template)) {
- $all_instances_printed = false;
- unset($all_values_for_template[$cur_key]);
- }
- }
- }
- // =====================================================
- // end template processing
- // =====================================================
- } elseif ($tag_title == 'end template') {
- if ($source_is_page) {
- // add any unhandled template fields in the page as hidden variables
- if (isset($template_contents))
- $form_text .= SFFormUtils::unhandledFieldsHTML($template_contents);
- }
- // remove this tag, reset some variables, and close off form HTML tag
- $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- $template_name = null;
- if (isset($template_label)) {
- $form_text .= "</fieldset>\n";
- unset ($template_label);
- }
- $allow_multiple = false;
- $all_instances_printed = false;
- $instance_num = 0;
- // if the hiding placeholder is still around, this fieldset should
- // be hidden because it is empty and choosers are being used. So,
- // hide it.
- $form_text = str_replace("[[placeholder]]", "style='display:none'", $form_text);
- // =====================================================
- // field processing
- // =====================================================
- } elseif ($tag_title == 'field') {
- $field_name = trim($tag_components[1]);
- // cycle through the other components
- $is_mandatory = false;
- $is_hidden = false;
- $is_restricted = false;
- $is_uploadable = false;
- $is_list = false;
- $input_type = null;
- $field_args = array();
- $default_value = "";
- $possible_values = null;
- $semantic_property = null;
- $preload_page = null;
- for ($i = 2; $i < count($tag_components); $i++) {
- $component = trim($tag_components[$i]);
- if ($component == 'mandatory') {
- $is_mandatory = true;
- } elseif ($component == 'hidden') {
- $is_hidden = true;
- } elseif ($component == 'restricted') {
- $is_restricted = true;
- } elseif ($component == 'uploadable') {
- $field_args['is_uploadable'] = true;
- } elseif ($component == 'list') {
- $is_list = true;
- } elseif ($component == 'autocomplete') {
- $field_args['autocomplete'] = true;
- } elseif ($component == 'no autocomplete') {
- $field_args['no autocomplete'] = true;
- } elseif ($component == 'remote autocompletion') {
- $field_args['remote autocompletion'] = true;
- } elseif ($component == 'edittools') { // free text only
- $free_text_components[] = 'edittools';
- } else {
- $sub_components = explode('=', $component);
- if (count($sub_components) == 1) {
- // add handling for single-value params, for custom input types
- $field_args[$sub_components[0]] = null;
- } elseif (count($sub_components) == 2) {
- if ($sub_components[0] == 'input type') {
- $input_type = $sub_components[1];
- } elseif ($sub_components[0] == 'default') {
- $default_value = $sub_components[1];
- } elseif ($sub_components[0] == 'preload') {
- // free text field has special handling
- if ($field_name == 'free text' || $field_name = '<freetext>') {
- $free_text_preload_page = $sub_components[1];
- } else {
- // this variable is not used
- $preload_page = $sub_components[1];
- }
- } elseif ($sub_components[0] == 'autocomplete on property') {
- // HACK - we need to figure out if this property is a
- // relation or attribute, i.e. whether it points to wiki
- // pages or not; so construct an SFTemplateField object
- // with this property, and determine it that way
- $property_name = $sub_components[1];
- $dummy_field = new SFTemplateField();
- $dummy_field->setSemanticProperty($property_name);
- if ($dummy_field->propertyIsOfType('_wpg'))
- $field_args['autocomplete field type'] = 'relation';
- else
- $field_args['autocomplete field type'] = 'attribute';
- $field_args['autocompletion source'] = $sub_components[1];
- } elseif ($sub_components[0] == 'autocomplete on') { // for backwards-compatibility
- $field_args['autocomplete field type'] = 'category';
- $field_args['autocompletion source'] = $sub_components[1];
- } elseif ($sub_components[0] == 'autocomplete on category') {
- $field_args['autocomplete field type'] = 'category';
- $field_args['autocompletion source'] = $sub_components[1];
- } elseif ($sub_components[0] == 'autocomplete on concept') {
- $field_args['autocomplete field type'] = 'concept';
- $field_args['autocompletion source'] = $sub_components[1];
- } elseif ($sub_components[0] == 'autocomplete on namespace') {
- $field_args['autocomplete field type'] = 'namespace';
- $autocompletion_source = $sub_components[1];
- // special handling for "main" (blank) namespace
- if ($autocompletion_source == "")
- $autocompletion_source = "main";
- $field_args['autocompletion source'] = $autocompletion_source;
- } elseif ($sub_components[0] == 'autocomplete from url') {
- $field_args['autocomplete field type'] = 'external_url';
- $field_args['autocompletion source'] = $sub_components[1];
- // 'external' autocompletion is always done remotely, i.e. via API
- $field_args['remote autocompletion'] = true;
- } elseif ($sub_components[0] == 'values') {
- // remove whitespaces, and un-escape characters
- $possible_values = array_map('trim', explode(',', $sub_components[1]));
- $possible_values = array_map('htmlspecialchars_decode', $possible_values);
- } elseif ($sub_components[0] == 'values from category') {
- $category_name = ucfirst($sub_components[1]);
- $possible_values = SFUtils::getAllPagesForCategory($category_name, 10);
- } elseif ($sub_components[0] == 'values from concept') {
- $possible_values = SFUtils::getAllPagesForConcept($sub_components[1]);
- } elseif ($sub_components[0] == 'property') {
- $semantic_property = $sub_components[1];
- } elseif ($sub_components[0] == 'default filename') {
- $default_filename = str_replace('&lt;page name&gt;', $page_title, $sub_components[1]);
- $field_args['default filename'] = $default_filename;
- } else {
- $field_args[$sub_components[0]] = $sub_components[1];
- }
- // for backwards compatibility
- if ($sub_components[0] == 'autocomplete on' && $sub_components[1] == null) {
- $field_args['no autocomplete'] = true;
- }
- }
- }
- }
- $field_args['part_of_multiple'] = $allow_multiple;
- // get the value from the request, if it's there, and if it's not
- // an array
- $escaped_field_name = str_replace("'", "\'", $field_name);
- if (isset($template_instance_query_values) &&
- $template_instance_query_values != null &&
- is_array($template_instance_query_values) &&
- array_key_exists($escaped_field_name, $template_instance_query_values)) {
- $field_query_val = $template_instance_query_values[$escaped_field_name];
- if ($form_submitted || ($field_query_val && ! is_array($field_query_val))) {
- $cur_value = $field_query_val;
- }
- } else
- $cur_value = '';
- if ($cur_value && ! is_array($cur_value)) {
- $cur_value = htmlspecialchars($cur_value);
- }
-
- if ($cur_value == null) {
- // set to default value specified in the form, if it's there
- $cur_value = $default_value;
- }
-
- // if the user is editing a page, and that page contains a call to
- // the template being processed, get the current field's value
- // from the template call
- if ($source_is_page && (! empty($existing_template_text))) {
- if (isset($template_contents[$field_name])) {
- $cur_value = $template_contents[$field_name];
- // now remove this value from $template_contents, so that
- // at the end we can have a list of all the fields that
- // weren't handled by the form
- unset($template_contents[$field_name]);
- } else {
- $cur_value = '';
- }
- }
-
- // handle the free text field - if it was declared as
- // "field|free text" (a deprecated usage), it has to be outside
- // of a template
- if (($template_name == '' && $field_name == 'free text') ||
- $field_name == '<freetext>') {
- // add placeholders for the free text in both the form and
- // the page, using <free_text> tags - once all the free text
- // is known (at the end), it will get substituted in
- if ($is_hidden) {
- $new_text = SFFormUtils::hiddenFieldHTML('free_text', '!free_text!');
- } else {
- if (! array_key_exists('rows', $field_args))
- $field_args['rows'] = 5;
- if (! array_key_exists('cols', $field_args))
- $field_args['cols'] = 80;
- $sfgTabIndex++;
- $sfgFieldNum++;
- list($new_text, $new_javascript_text) = SFFormInputs::textAreaHTML('!free_text!', 'free_text', false, ($form_is_disabled || $is_restricted), $field_args);
- if (in_array('edittools', $free_text_components)) {
- // borrowed from EditPage::showEditTools()
- $options[] = 'parse';
- $edittools_text = wfMsgExt( 'edittools', array( 'parse' ), array( 'content' ) );
-
- $new_text .=<<<END
- <div class="mw-editTools">
- $edittools_text
- </div>
-
-END;
- }
- $fields_javascript_text .= $new_javascript_text;
- }
- $free_text_was_included = true;
- // add a similar placeholder to the data text
- $data_text .= "!free_text!\n";
- }
-
- if ($template_name == '' || $field_name == '<freetext>') {
- $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- } else {
- if (is_array($cur_value)) {
- // first, check if it's a list
- if (array_key_exists('is_list', $cur_value) &&
- $cur_value['is_list'] == true) {
- $cur_value_in_template = "";
- if (array_key_exists('delimiter', $field_args)) {
- $delimiter = $field_args['delimiter'];
- } else {
- $delimiter = ",";
- }
- foreach ($cur_value as $key => $val) {
- if ($key !== "is_list") {
- if ($cur_value_in_template != "") {
- $cur_value_in_template .= $delimiter . " ";
- }
- $cur_value_in_template .= $val;
- }
- }
- } else {
- // otherwise:
- // if it has 1 or 2 elements, assume it's a checkbox; if it has
- // 3 elements, assume it's a date
- // - this handling will have to get more complex if other
- // possibilities get added
- if (count($cur_value) == 1) {
- // manually load SMW's message values here, in case they
- // didn't get loaded before
- wfLoadExtensionMessages('SemanticMediaWiki');
- $words_for_false = explode(',', wfMsgForContent('smw_false_words'));
- // for each language, there's a series of words that are
- // equal to false - get the word in the series that matches
- // "no"; generally, that's the third word
- $index_of_no = 2;
- if (count($words_for_false) > $index_of_no) {
- $no = ucwords($words_for_false[$index_of_no]);
- } elseif (count($words_for_false) == 0) {
- $no = "0"; // some safe value if no words are found
- } else {
- $no = ucwords($words_for_false[0]);
- }
- $cur_value_in_template = $no;
- } elseif (count($cur_value) == 2) {
- wfLoadExtensionMessages('SemanticMediaWiki');
- $words_for_true = explode(',', wfMsgForContent('smw_true_words'));
- // get the value in the 'true' series that tends to be "yes",
- // and go with that one - generally, that's the third word
- $index_of_yes = 2;
- if (count($words_for_true) > $index_of_yes) {
- $yes = ucwords($words_for_true[$index_of_yes]);
- } elseif (count($words_for_true) == 0) {
- $yes = "1"; // some safe value if no words are found
- } else {
- $yes = ucwords($words_for_true[0]);
- }
- $cur_value_in_template = $yes;
- // if it's 3 or greater, assume it's a date or datetime
- } elseif (count($cur_value) >= 3) {
- $month = $cur_value['month'];
- $day = $cur_value['day'];
- if ($day != '') {
- global $wgAmericanDates;
- if ($wgAmericanDates == false) {
- // pad out day to always be two digits
- $day = str_pad($day, 2, "0", STR_PAD_LEFT);
- }
- }
- $year = $cur_value['year'];
- $hour = $minute = $second = $ampm24h = $timezone = null;
- if (isset($cur_value['hour'])) $hour = $cur_value['hour'];
- if (isset($cur_value['minute'])) $minute = $cur_value['minute'];
- if (isset($cur_value['second'])) $second = $cur_value['second'];
- if (isset($cur_value['ampm24h'])) $ampm24h = $cur_value['ampm24h'];
- if (isset($cur_value['timezone'])) $timezone = $cur_value['timezone'];
- if ($month != '' && $day != '' && $year != '') {
- // special handling for American dates - otherwise, just
- // the standard year/month/day (where month is a number)
- global $wgAmericanDates;
- if ($wgAmericanDates == true) {
- $cur_value_in_template = "$month $day, $year";
- } else {
- $cur_value_in_template = "$year/$month/$day";
- }
- // include whatever time information we have
- if (! is_null($hour))
- $cur_value_in_template .= " " . str_pad(intval(substr($hour,0,2)),2,'0',STR_PAD_LEFT) . ":" . str_pad(intval(substr($minute,0,2)),2,'0',STR_PAD_LEFT);
- if (! is_null($second))
- $cur_value_in_template .= ":" . str_pad(intval(substr($second,0,2)),2,'0',STR_PAD_LEFT);
- if (! is_null($ampm24h))
- $cur_value_in_template .= " $ampm24h";
- if (! is_null($timezone))
- $cur_value_in_template .= " $timezone";
- } else {
- $cur_value_in_template = "";
- }
- }
- }
- } else { // value is not an array
- $cur_value_in_template = $cur_value;
- }
- if ($query_template_name == null || $query_template_name == '')
- $input_name = $field_name;
- elseif ($allow_multiple)
- // 'num' will get replaced by an actual index, either in PHP
- // or in Javascript, later on
- $input_name = $query_template_name . '[num][' . $field_name . ']';
- else
- $input_name = $query_template_name . '[' . $field_name . ']';
-
- // if we're creating the page name from a formula based on
- // form values, see if the current input is part of that formula,
- // and if so, substitute in the actual value
- if ($form_submitted && $generated_page_name != '') {
- // this line appears unnecessary
- //$generated_page_name = str_replace('.', '_', $generated_page_name);
- $generated_page_name = str_replace(' ', '_', $generated_page_name);
- $escaped_input_name = str_replace(' ', '_', $input_name);
- $generated_page_name = str_ireplace("<$escaped_input_name>", $cur_value_in_template, $generated_page_name);
- // once the substitution is done, replace underlines back
- // with spaces
- $generated_page_name = str_replace('_', ' ', $generated_page_name);
- }
- // disable this field if either the whole form is disabled, or
- // it's a restricted field and user doesn't have sysop privileges
- $is_disabled = ($form_is_disabled ||
- ($is_restricted && (! $wgUser || ! $wgUser->isAllowed('editrestrictedfields'))));
- // create an SFFormField instance based on all the
- // parameters in the form definition, and any information from
- // the template definition (contained in the $all_fields parameter)
- $form_field = SFFormField::createFromDefinition($field_name, $input_name,
- $is_mandatory, $is_hidden, $is_uploadable, $possible_values, $is_disabled,
- $is_list, $input_type, $field_args, $all_fields, $strict_parsing);
- // 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 ($semantic_property != null)
- $form_field->template_field->setSemanticProperty($semantic_property);
-
- // call hooks - unfortunately this has to be split into two
- // separate calls, because of the different variable names in
- // each case
- if ($form_submitted)
- wfRunHooks('sfCreateFormField', array(&$form_field, &$cur_value_in_template, true));
- else
- wfRunHooks('sfCreateFormField', array(&$form_field, &$cur_value, false));
- // if this is not part of a 'multiple' template, increment the
- // global tab index (used for correct tabbing)
- if (! $field_args['part_of_multiple'])
- $sfgTabIndex++;
- // increment the global field number regardless
- $sfgFieldNum++;
- // if the field is a date field, and its default value was set
- // to 'now', and it has no current value, set $cur_value to be
- // the current date
- if ($default_value == 'now' &&
- // if the date is hidden, cur_value will already be set
- // to the default value
- ($cur_value == '' || $cur_value == 'now')) {
- if ($input_type == 'date' || $input_type == 'datetime' ||
- $input_type == 'datetime with timezone' || $input_type == 'year' ||
- ($input_type == '' && $form_field->template_field->propertyIsOfType('_dat'))) {
- // get current time, for the time zone specified in the wiki
- global $wgLocaltimezone;
- putenv('TZ=' . $wgLocaltimezone);
- $cur_time = time();
- $year = date("Y", $cur_time);
- $month = date("n", $cur_time);
- $day = date("j", $cur_time);
- global $wgAmericanDates, $sfg24HourTime;
- if ($wgAmericanDates == true) {
- $month_names = SFFormUtils::getMonthNames();
- $month_name = $month_names[$month - 1];
- $cur_value_in_template = "$month_name $day, $year";
- } else {
- $cur_value_in_template = "$year/$month/$day";
- }
- if ($input_type == 'datetime' || $input_type == 'datetime with timezone') {
- if ($sfg24HourTime) {
- $hour = str_pad(intval(substr(date("G", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
- } else {
- $hour = str_pad(intval(substr(date("g", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
- }
- $minute = str_pad(intval(substr(date("i", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
- $second = str_pad(intval(substr(date("s", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
- if ($sfg24HourTime) {
- $cur_value_in_template .= " $hour:$minute:$second";
- } else {
- $ampm = date("A", $cur_time);
- $cur_value_in_template .= " $hour:$minute:$second $ampm";
- }
- }
- if ($input_type == 'datetime with timezone') {
- $timezone = date("T", $cur_time);
- $cur_value_in_template .= " $timezone";
- }
- }
- }
- // if the field is a text field, and its default value was set
- // to 'current user', and it has no current value, set $cur_value
- // to be the current user
- if ($default_value == 'current user' &&
- // if the date is hidden, cur_value will already be set
- // to the default value
- ($cur_value == '' || $cur_value == 'current user')) {
- if ($input_type == 'text' || $input_type == '') {
- $cur_value_in_template = $wgUser->getName();
- $cur_value = $cur_value_in_template;
- }
- }
- list($new_text, $new_javascript_text) = $this->formFieldHTML($form_field, $cur_value);
-
- $fields_javascript_text .= $new_javascript_text;
-
- // if this field is disabled, add a hidden field holding
- // the value of this field, because disabled inputs for some
- // reason don't submit their value
- if ($form_field->is_disabled) {
- if ($field_name == 'free text' || $field_name == '<freetext>') {
- $new_text .= SFFormUtils::hiddenFieldHTML('free_text', '!free_text!');
- } else {
- $new_text .= SFFormUtils::hiddenFieldHTML($input_name, $cur_value);
- }
- }
-
- if ($new_text) {
- // include the field name only for non-numeric field names
- if (is_numeric($field_name)) {
- $template_text .= "|$cur_value_in_template";
- } else {
- // if the value is null, don't include it at all
- if ($cur_value_in_template != '')
- $template_text .= "\n|$field_name=$cur_value_in_template";
- }
- $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- // also add to Javascript validation code
- $input_id = "input_" . $sfgFieldNum;
- $info_id = "info_" . $sfgFieldNum;
- if ($is_mandatory) {
- if ($input_type == 'date' || $input_type == 'datetime' || $input_type == 'datetime with timezone' ||
- ($input_type == '' && $form_field->template_field->propertyIsOfType('_dat'))) {
- $sfgJSValidationCalls[] = "validate_mandatory_field ('$input_id" . "_month', '$info_id')";
- $sfgJSValidationCalls[] = "validate_mandatory_field ('$input_id" . "_day', '$info_id')";
- $sfgJSValidationCalls[] = "validate_mandatory_field ('$input_id" . "_year', '$info_id')";
- if ($input_type == 'datetime' || $input_type == 'datetime with timezone') {
- // TODO - validate the time fields
- if ($input_type == 'datetime with timezone') {
- // TODO - validate the timezone
- }
- }
- } else {
- if ($allow_multiple) {
- if ($all_instances_printed) {
- $sfgJSValidationCalls[] = "validate_multiple_mandatory_fields($sfgFieldNum)";
- } else {
- $sfgJSValidationCalls[] = "validate_mandatory_field(\"input_$sfgFieldNum\", \"info_$sfgFieldNum\")";
- }
- } elseif (($form_field->template_field->is_list && $form_field->template_field->field_type == 'enumeration' && $input_type != 'listbox') || ($input_type == 'checkboxes')) {
- $sfgJSValidationCalls[] = "validate_mandatory_checkboxes('$input_id', '$info_id')";
- } elseif ($input_type == 'radiobutton' || $input_type == 'category') {
- // only add this if there's a "None" option
- if (empty($default_value)) {
- $sfgJSValidationCalls[] = "validate_mandatory_radiobutton('$input_id', '$info_id')";
- }
- } else {
- $sfgJSValidationCalls[] = "validate_mandatory_field('$input_id', '$info_id')";
- }
- }
- }
- } else {
- $start_position = $brackets_end_loc;
- }
- }
- // =====================================================
- // standard input processing
- // =====================================================
- } elseif ($tag_title == 'standard input') {
- // if it's a query, ignore all standard inputs
- if ($is_query) {
- $new_text = "";
- $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- continue;
- }
- // set a flag so that the standard 'form bottom' won't get displayed
- $this->standardInputsIncluded = true;
- // handle all the possible values
- $input_name = $tag_components[1];
- $input_label = null;
- // cycle through the other components
- for ($i = 2; $i < count($tag_components); $i++) {
- $component = $tag_components[$i];
- $sub_components = explode('=', $component);
- if (count($sub_components) == 1) {
- if ($sub_components[0] == 'edittools') {
- $free_text_components[] = 'edittools';
- }
- } elseif (count($sub_components) == 2) {
- if ($sub_components[0] == 'label') {
- $input_label = $sub_components[1];
- }
- // free text input needs more handling than the rest
- if ($input_name == 'free text' || $input_name == '<freetext>') {
- if ($sub_components[0] == 'preload') {
- $free_text_preload_page = $sub_components[1];
- }
- }
- }
- }
- if ($input_name == 'summary') {
- $new_text = SFFormUtils::summaryInputHTML($form_is_disabled, $input_label);
- } elseif ($input_name == 'minor edit') {
- $new_text = SFFormUtils::minorEditInputHTML($form_is_disabled, $input_label);
- } elseif ($input_name == 'watch') {
- $new_text = SFFormUtils::watchInputHTML($form_is_disabled, $input_label);
- } elseif ($input_name == 'save') {
- $new_text = SFFormUtils::saveButtonHTML($form_is_disabled, $input_label);
- } elseif ($input_name == 'preview') {
- $new_text = SFFormUtils::showPreviewButtonHTML($form_is_disabled, $input_label);
- } elseif ($input_name == 'changes') {
- $new_text = SFFormUtils::showChangesButtonHTML($form_is_disabled, $input_label);
- } elseif ($input_name == 'cancel') {
- $new_text = SFFormUtils::cancelLinkHTML($form_is_disabled, $input_label);
- }
- $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- // =====================================================
- // page info processing
- // =====================================================
- } elseif ($tag_title == 'info') {
- // TODO: Generate an error message if this is included more than once
- foreach(array_slice($tag_components, 1) as $component) {
- $sub_components = explode('=', $component, 2);
- $tag = $sub_components[0];
- if ($tag == 'add title') {
- // handle this only if we're adding a page
- if (! $this->mPageTitle->exists()) {
- $val = $sub_components[1];
- $form_page_title = $val;
- }
- }
- elseif($tag == 'edit title') {
- // handle this only if we're editing a page
- if ($this->mPageTitle->exists()) {
- $val = $sub_components[1];
- $form_page_title = $val;
- }
- }
- elseif($tag == 'partial form') {
- $form_is_partial = true;
- // replacement pages may have minimal matches...
- $source_page_matches_this_form = true;
- }
- elseif($tag == 'includeonly free text' || $tag == 'onlyinclude free text') {
- $onlyinclude_free_text = true;
- }
- }
- $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
- // =====================================================
- // default outer level processing
- // =====================================================
- } else { // tag is not one of the three allowed values
- // ignore tag
- $start_position = $brackets_end_loc;
- } // end if
- } // end while
-
- if (! $all_instances_printed ) {
- if ($template_text != '') {
- // for mostly aesthetic purposes, if the template call ends with
- // a bunch of pipes (i.e., it's an indexed template with unused
- // parameters at the end), remove the pipes
- $template_text = preg_replace('/\|*$/', '', $template_text);
- // add another newline before the final bracket, if this template
- // call is already more than one line
- if (strpos($template_text, "\n"))
- $template_text .= "\n";
- // if we're editing an existing page, and there were fields in
- // the template call not handled by this form, preserve those
- $template_text .= SFFormUtils::addUnhandledFields();
- $template_text .= "}}";
- $data_text .= $template_text . "\n";
- // if there is a placeholder in the text, we know that we are
- // doing a replace
- if ($existing_page_content && strpos($existing_page_content, '{{{insertionpoint}}}', 0) !== false) {
- $existing_page_content = preg_replace('/\{\{\{insertionpoint\}\}\}(\r?\n?)/',
- preg_replace('/\}\}/m', '}\xB2',
- preg_replace('/\{\{/m', '\xB2{', $template_text)) .
- "\n{{{insertionpoint}}}",
- $existing_page_content);
- // otherwise, if it's a partial form, we have to add the new
- // text somewhere
- } elseif ($form_is_partial && $wgRequest->getCheck('partial') ) {
- $existing_page_content = preg_replace('/\}\}/m', '}\xB2',
- preg_replace('/\{\{/m', '\xB2{', $template_text)) .
- "\n{{{insertionpoint}}}\n" . $existing_page_content;
- }
- }
- }
-
- if ($allow_multiple) {
- if (! $all_instances_printed) {
- // add the character "a" onto the instance number of this input
- // in the form, to differentiate the inputs the form starts out
- // with from any inputs added by the Javascript
- $section = str_replace('[num]', "[{$instance_num}a]", $section);
- $remove_text = wfMsg('sf_editdata_remove');
- $form_text .=<<<END
- <div id="wrapper_$sfgFieldNum" class="multipleTemplate">
- $section
- <input type="button" onclick="removeInstance('wrapper_$sfgFieldNum');" value="$remove_text" tabindex="$sfgTabIndex" class="remove" />
- </div>
-
-END;
- // this will cause the section to be re-parsed on the next go
- $section_num--;
- // because there is an instance, the fieldset will never be hidden,
- // even if choosers are being used. So, do not hide the fieldset.
- $form_text = str_replace("[[placeholder]]", "", $form_text);
- } else {
- // this is the last instance of this template - stick an 'add'
- // button in the form
- $form_text .=<<<END
- <div id="starter_$query_template_name" class="multipleTemplate" style="display: none;">
- $section
- </div>
- <div id="main_$query_template_name"></div>
-
-END;
- $add_another = wfMsg('sf_editdata_addanother');
- $form_text .=<<<END
- <p style="margin-left:10px;">
- <p><input type="button" onclick="addInstance('starter_$query_template_name', 'main_$query_template_name', '$sfgFieldNum');" value="$add_another" tabindex="$sfgTabIndex" class="addAnother" /></p>
-
-END;
- // if a chooser is being used for this template, add the template
- // to the chooser data array
- if ($chooser_name !== false)
- $choosers[$chooser_name][]= array($query_template_name, $sfgFieldNum, $chooser_caption);
- }
- } else {
- $form_text .= $section;
- }
-
- } // end for
-
- // if it wasn't included in the form definition, add the
- // 'free text' input as a hidden field at the bottom
- if (! $free_text_was_included) {
- $form_text .= SFFormUtils::hiddenFieldHTML('free_text', '!free_text!');
- }
- // get free text, and add to page data, as well as retroactively
- // inserting it into the form
-
- // If $form_is_partial is true then either:
- // (a) we're processing a replacement (param 'partial' == 1)
- // (b) we're sending out something to be replaced (param 'partial' is missing)
- if ($form_is_partial) {
- if(!$wgRequest->getCheck('partial')) {
- $free_text = $original_page_content;
- $form_text .= SFFormUtils::hiddenFieldHTML('partial', 1);
- } else {
- $free_text = null;
- $existing_page_content = preg_replace('/\xB2\{(.*?)\}\xB2/s', '{{\1}}', $existing_page_content);
- $existing_page_content = preg_replace('/\{\{\{insertionpoint\}\}\}/', '', $existing_page_content);
- $existing_page_content = Sanitizer::safeEncodeAttribute($existing_page_content);
- }
- } elseif ($source_is_page) {
- // if the page is the source, free_text will just be whatever in the
- // page hasn't already been inserted into the form
- $free_text = trim($existing_page_content);
- // or get it from a form submission
- } elseif ($wgRequest->getCheck('free_text')) {
- $free_text = $wgRequest->getVal('free_text');
- if (! $free_text_was_included) {
- $data_text .= "!free_text!";
- }
- // or get it from the form definition
- } elseif ($free_text_preload_page != null) {
- $free_text = SFFormUtils::getPreloadedText($free_text_preload_page);
- } else {
- $free_text = null;
- }
- if ($onlyinclude_free_text) {
- // modify free text and data text to insert <onlyinclude> tags
- $free_text = str_replace("<onlyinclude>",'', $free_text);
- $free_text = str_replace("</onlyinclude>",'', $free_text);
- $free_text = trim($free_text);
- $data_text = str_replace('!free_text!','<onlyinclude>!free_text!</onlyinclude>', $data_text);
- }
- // if the FCKeditor extension is installed, use that for the free text input
- global $wgFCKEditorDir;
- if ($wgFCKEditorDir) {
- $showFCKEditor = SFFormUtils::getShowFCKEditor();
- $free_text = str_replace( '"', '&quot;', $free_text );
- if(!$form_submitted && ($showFCKEditor & RTE_VISIBLE)) {
- $free_text = SFFormUtils::prepareTextForFCK($free_text);
- }
- } else {
- $showFCKEditor = 0;
- $free_text = Sanitizer::safeEncodeAttribute($free_text);
- }
- // now that we have it, substitute free text into the form and page
- $form_text = str_replace('!free_text!', $free_text, $form_text);
- $data_text = str_replace('!free_text!', $free_text, $data_text);
-
- // add a warning in, if we're editing an existing page and that page
- // appears to not have been created with this form
- if ($this->mPageTitle->exists() && ($existing_page_content != '') && ! $source_page_matches_this_form) {
- $form_text = ' <div class="warningMessage">' . wfMsg('sf_editdata_formwarning', $this->mPageTitle->getFullURL()) . "</div>\n" . $form_text;
- }
-
- //Substitute the choosers in here too.
- $chooser_count = 0;
- $chooser_text = "";
- $using_choosers = "false";
- foreach ($choosers as $choosername => $chooser) {
- if (count($chooser)!=0) {
- $chooser_count++;
- if ($chooser_count==1) {
- // emit the initial javascript code
- $using_choosers = "true";
- $chooser_text .= <<<END
-<script type="text/javascript">/* <![CDATA[ */
-
-function updatechooserbutton(f,n)
-{
- document.getElementById(n).disabled = (f.options[f.selectedIndex].value=="invalid");
-}
-
-function addInstanceFromChooser(chooserid)
-{
- var chooser = document.getElementById(chooserid);
- var optionstring = chooser.options[chooser.selectedIndex].value;
- var pos = optionstring.indexOf(",");
- var tabindex = optionstring.substr(0,pos);
- var chooservalue = optionstring.substr(pos+1);
- addInstance('starter_' + chooservalue, 'main_' + chooservalue, parseInt(tabindex));
-}
-
-//The fieldset containing the given element was just updated. If the fieldset is associated with a chooser,
-//ensure that the fieldset is hidden if and only if there are no template instances inside.
-function hideOrShowFieldset(element)
-{
- //Find fieldset
- while (element.tagName.toLowerCase() != "fieldset")
- element = element.parentNode;
- //Bail out if fieldset is not part of chooser
- if (!element.getAttribute("haschooser"))
- return;
- //Now look for "input" or "select" tags that don't look like they're part of the starter template
- var inputs = element.getElementsByTagName("input");
- var x;
- var show = false;
- for (x=0;x<inputs.length;x++)
- {
- if (inputs[x].type=="text" && inputs[x].name.indexOf("[num]") == -1)
- show = true;
- }
- var selects = element.getElementsByTagName("select");
- for (x=0;x<selects.length;x++)
- {
- if (selects[x].name.indexOf("[num]") == -1)
- show = true;
- }
- //Now show or hide fieldset
- element.style.display = (show?"block":"none");
-}
-/* ]]> */ </script>
-
-END;
- }
-
- $chooser_text .= "<p>$choosername:<select id='chooserselect$chooser_count' size='1' onchange='updatechooserbutton(this,\"chooserbutton$chooser_count\")'>\n";
- $chooser_text .= "<option value='invalid'>" . wfMsg('sf_createform_choosefield') . "</option>\n";
- foreach ($chooser as $chooser_item) {
- $chooser_value = str_replace('"','\\"',$chooser_item[0]);
- $tabindex = $chooser_item[1];
- $chooser_caption = $chooser_item[2];
- if ($chooser_caption === false)
- $chooser_caption = str_replace('_', ' ', $chooser_value);
- $chooser_text .= "<option value=\"$tabindex ,$chooser_value\">$chooser_caption</option>\n";
- }
- $chooser_text .= "</select>\n";
- }
- $chooser_text .= "<input type='button' onclick=\"addInstanceFromChooser('chooserselect$chooser_count');\" value='" . wfMsg('sf_editdata_addanother') . "' disabled='true' id='chooserbutton$chooser_count'></p>";
- }
-
- $form_text = str_replace('{{{choosers}}}', $chooser_text, $form_text);
-
- // add form bottom, if no custom "standard inputs" have been defined
- if ($is_query)
- $form_text .= SFFormUtils::queryFormBottom($form_is_disabled);
- elseif (! $this->standardInputsIncluded)
- $form_text .= SFFormUtils::formBottom($form_is_disabled);
- $starttime = wfTimestampNow();
- $page_article = new Article($this->mPageTitle);
- $edittime = $page_article->getTimestamp();
- $form_text .=<<<END
-
- <input type="hidden" value="$starttime" name="wpStarttime" />
- <input type="hidden" value="$edittime" name="wpEdittime" />
- </form>
-
-END;
-
- // add Javascript code for form-wide use
- $javascript_text .= SFFormUtils::validationJavascript();
- $javascript_text .= SFFormUtils::instancesJavascript($using_choosers);
- $javascript_text .= SFFormUtils::autocompletionJavascript();
- if ($free_text_was_included && $showFCKEditor > 0) {
- $javascript_text .= SFFormUtils::mainFCKJavascript($showFCKEditor);
- if ($showFCKEditor & (RTE_TOGGLE_LINK | RTE_POPUP)) {
- $javascript_text .= SFFormUTils::FCKToggleJavascript();
- }
- if ($showFCKEditor & RTE_POPUP) {
- $javascript_text .= SFFormUTils::FCKPopupJavascript();
- }
- }
-
- // send the autocomplete values to the browser, along with the mappings
- // of which values should apply to which fields
- // if doing a replace, the data text is actually the modified original page
- if($wgRequest->getCheck('partial'))
- $data_text = $existing_page_content;
- $javascript_text .= $fields_javascript_text;
- global $wgParser;
- $new_text = $wgParser->preprocess(str_replace( "{{!}}", "|", $form_page_title ), $this->mPageTitle, new ParserOptions());
- return array($form_text, "/*<![CDATA[*/ $javascript_text /*]]>*/",
- $data_text, $new_text, $generated_page_name);
- }
-
- /**
- * Create the HTML and Javascript to display this field within a form
- */
- function formFieldHTML($form_field, $cur_value) {
- global $smwgContLang;
-
- // also get the actual field, with all the semantic information (type is
- // SFTemplateField, instead of SFFormField)
- $template_field = $form_field->template_field;
-
- if ($form_field->is_hidden) {
- $text = SFFormUtils::hiddenFieldHTML($form_field->input_name, $cur_value);
- $javascript_text = "";
- } elseif ($form_field->input_type != '' &&
- array_key_exists($form_field->input_type, $this->mInputTypeHooks) &&
- $this->mInputTypeHooks[$form_field->input_type] != null) {
- $funcArgs = array();
- $funcArgs[] = $cur_value;
- $funcArgs[] = $form_field->input_name;
- $funcArgs[] = $form_field->is_mandatory;
- $funcArgs[] = $form_field->is_disabled;
- // last argument to function should be a hash, merging the default
- // values for this input type with all other properties set in
- // the form definition, plus some semantic-related arguments
- $hook_values = $this->mInputTypeHooks[$form_field->input_type];
- $other_args = $form_field->getArgumentsForInputCall($hook_values[1]);
- $funcArgs[] = $other_args;
- list($text, $javascript_text) = call_user_func_array($hook_values[0], $funcArgs);
- } else { // input type not defined in form
- $field_type = $template_field->field_type;
- $is_list = ($form_field->is_list || $template_field->is_list);
- if ($field_type != '' &&
- array_key_exists($field_type, $this->mSemanticTypeHooks) &&
- isset($this->mSemanticTypeHooks[$field_type][$is_list])) {
- $funcArgs = array();
- $funcArgs[] = $cur_value;
- $funcArgs[] = $form_field->input_name;
- $funcArgs[] = $form_field->is_mandatory;
- $funcArgs[] = $form_field->is_disabled;
- $hook_values = $this->mSemanticTypeHooks[$field_type][$is_list];
- $other_args = $form_field->getArgumentsForInputCall($hook_values[1]);
- $funcArgs[] = $other_args;
- list($text, $javascript_text) = call_user_func_array($hook_values[0], $funcArgs);
- } else { // anything else
- $other_args = $form_field->getArgumentsForInputCall();
- // special call to ensure that a list input is the right default size
- if ($form_field->is_list) {
- if (! array_key_exists('size', $other_args))
- $other_args['size'] = 100;
- }
- list($text, $javascript_text) = SFFormInputs::textEntryHTML($cur_value, $form_field->input_name, $form_field->is_mandatory, $form_field->is_disabled, $other_args);
- }
- }
- return array($text, $javascript_text);
- }
-
-}

Copied: tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc (from rev 58565, trunk/extensions/SemanticForms/includes/SF_FormPrinter.inc)
===================================================================
--- tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc (rev 0)
+++ tags/extensions/SemanticForms/REL_1_8_5_1/includes/SF_FormPrinter.inc 2009-11-04 21:32:32 UTC (rev 58566)
@@ -0,0 +1,1344 @@
+<?php
+/**
+ * Handles the creation and running of a user-created form.
+ *
+ * @author Yaron Koren
+ * @author Nils Oppermann
+ * @author Jeffrey Stuckman
+ * @author Harold Solbrig
+ * @author Daniel Hansch
+ */
+
+class SFFormPrinter {
+
+ var $mSemanticTypeHooks;
+ var $mInputTypeHooks;
+ var $standardInputsIncluded;
+ var $mPageTitle;
+
+ function SFFormPrinter() {
+ global $smwgContLang;
+
+ // initialize the set of hooks for the entry-field functions to call for
+ // fields of both a specific semantic "type" and a defined "input type"
+ // in the form definition
+ $this->mSemanticTypeHooks = array();
+ if ($smwgContLang != null) {
+ $datatypeLabels = $smwgContLang->getDatatypeLabels();
+ $string_type = $datatypeLabels['_str'];
+ $text_type = $datatypeLabels['_txt'];
+ // type introduced in SMW 1.2
+ if (array_key_exists('_cod', $datatypeLabels))
+ $code_type = $datatypeLabels['_cod'];
+ else
+ $code_type = 'code';
+ $url_type = $datatypeLabels['_uri'];
+ $email_type = $datatypeLabels['_ema'];
+ $number_type = $datatypeLabels['_num'];
+ $bool_type = $datatypeLabels['_boo'];
+ $date_type = $datatypeLabels['_dat'];
+ $enum_type = 'enumeration'; // not a real type
+ $page_type = $datatypeLabels['_wpg'];
+ $this->setSemanticTypeHook($string_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'string'));
+ $this->setSemanticTypeHook($string_type, true, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'string', 'is_list' => 'true', 'size' => '100'));
+ $this->setSemanticTypeHook($text_type, false, array('SFFormInputs', 'textAreaHTML'), array());
+ $this->setSemanticTypeHook($code_type, false, array('SFFormInputs', 'textAreaHTML'), array());
+ $this->setSemanticTypeHook($url_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'URL'));
+ $this->setSemanticTypeHook($email_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'email'));
+ $this->setSemanticTypeHook($number_type, false, array('SFFormInputs', 'textEntryHTML'), array('field_type' => 'number'));
+ $this->setSemanticTypeHook($bool_type, false, array('SFFormInputs', 'checkboxHTML'), array());
+ $this->setSemanticTypeHook($date_type, false, array('SFFormInputs', 'dateEntryHTML'), array());
+ $this->setSemanticTypeHook($enum_type, false, array('SFFormInputs', 'dropdownHTML'), array());
+ $this->setSemanticTypeHook($enum_type, true, array('SFFormInputs', 'checkboxesHTML'), array());
+ $this->setSemanticTypeHook($page_type, false, array('SFFormInputs', 'textInputWithAutocompleteHTML'), array('field_type' => 'page'));
+ $this->setSemanticTypeHook($page_type, true, array('SFFormInputs', 'textInputWithAutocompleteHTML'), array('field_type' => 'page', 'size' => '100', 'is_list' => 'true'));
+ }
+ $this->mInputTypeHooks = array();
+ $this->setInputTypeHook('text', array('SFFormInputs', 'textEntryHTML'), array());
+ $this->setInputTypeHook('textarea', array('SFFormInputs', 'textAreaHTML'), array());
+ $this->setInputTypeHook('date', array('SFFormInputs', 'dateEntryHTML'), array());
+ $this->setInputTypeHook('datetime', array('SFFormInputs', 'dateTimeEntryHTML'), array('include_timezone' => false));
+ $this->setInputTypeHook('datetime with timezone', array('SFFormInputs', 'dateTimeEntryHTML'), array('include_timezone' => true));
+ $this->setInputTypeHook('year', array('SFFormInputs', 'textEntryHTML'), array('size' => 4));
+ $this->setInputTypeHook('checkbox', array('SFFormInputs', 'checkboxHTML'), array());
+ $this->setInputTypeHook('radiobutton', array('SFFormInputs', 'radiobuttonHTML'), array());
+ $this->setInputTypeHook('checkboxes', array('SFFormInputs', 'checkboxesHTML'), array());
+ $this->setInputTypeHook('listbox', array('SFFormInputs', 'listboxHTML'), array());
+ $this->setInputTypeHook('category', array('SFFormInputs', 'categoryHTML'), array());
+ $this->setInputTypeHook('categories', array('SFFormInputs', 'categoriesHTML'), array());
+
+ // initialize other variables
+ $this->standardInputsIncluded = false;
+ }
+
+ function setSemanticTypeHook($type, $is_list, $function_name, $default_args) {
+ $this->mSemanticTypeHooks[$type][$is_list] = array($function_name, $default_args);
+ }
+
+ function setInputTypeHook($input_type, $function_name, $default_args) {
+ $this->mInputTypeHooks[$input_type] = array($function_name, $default_args);
+ }
+
+
+ /**
+ * Show the set of previous deletions for the page being added.
+ * This function is copied almost exactly from EditPage::showDeletionLog() -
+ * unfortunately, neither that function nor Article::showDeletionLog() can
+ * be called from here, since they're both protected
+ */
+ function showDeletionLog( $out ) {
+ // if MW doesn't have LogEventsList defined, exit immediately
+ if (! class_exists('LogEventsList'))
+ return false;
+
+ global $wgUser;
+ $loglist = new LogEventsList( $wgUser->getSkin(), $out );
+ $pager = new LogPager( $loglist, 'delete', false, $this->mPageTitle->getPrefixedText() );
+ $count = $pager->getNumRows();
+ if ( $count > 0 ) {
+ $pager->mLimit = 10;
+ $out->addHTML( '<div class="mw-warning-with-logexcerpt">' );
+ // the message name changed in MW 1.16
+ if (! wfEmptyMsg( 'moveddeleted-notice', wfMsg('moveddeleted-notice') ))
+ $out->addWikiMsg( 'moveddeleted-notice' );
+ else
+ $out->addWikiMsg( 'recreate-deleted-warn' );
+ $out->addHTML(
+ $loglist->beginLogEventsList() .
+ $pager->getBody() .
+ $loglist->endLogEventsList()
+ );
+ if($count > 10){
+ $out->addHTML( $wgUser->getSkin()->link(
+ SpecialPage::getTitleFor( 'Log' ),
+ wfMsgHtml( 'deletelog-fulllog' ),
+ array(),
+ array(
+ 'type' => 'delete',
+ 'page' => $this->mPageTitle->getPrefixedText() ) ) );
+ }
+ $out->addHTML( '</div>' );
+ return true;
+ }
+
+ return false;
+ }
+
+
+ function formHTML($form_def, $form_submitted, $source_is_page, $existing_page_content = null, $page_title = null, $page_name_formula = null, $is_query = false) {
+ global $wgRequest, $wgUser, $wgParser;
+ global $sfgTabIndex; // used to represent the current tab index in the form
+ global $sfgFieldNum; // used for setting various HTML IDs
+ global $sfgJSValidationCalls; // array of Javascript calls to determine if page can be saved
+
+ // initialize some variables
+ $sfgTabIndex = 1;
+ $sfgFieldNum = 1;
+ $source_page_matches_this_form = false;
+ $form_page_title = NULL;
+ $generated_page_name = $page_name_formula;
+ // $form_is_partial is true if:
+ // (a) 'partial' == 1 in the arguments
+ // (b) 'partial form' is found in the form definition
+ // in the latter case, it may remain false until close to the end of
+ // the parsing, so we have to assume that it will become a possibility
+ $form_is_partial = false;
+ $new_text = "";
+ // flag for placing "<onlyinclude>" tags in form output
+ $onlyinclude_free_text = false;
+
+ // if we have existing content and we're not in an active replacement
+ // situation, preserve the original content. We do this because we want
+ // to pass the original content on IF this is a partial form
+ // TODO: A better approach here would be to pass the revision id of the
+ // existing page content through the replace value, which would
+ // minimize the html traffic and would allow us to do a concurrent
+ // update check. For now, we pass it through the hidden text field...
+
+ if (! $wgRequest->getCheck('partial')) {
+ $original_page_content = $existing_page_content;
+ } else {
+ $original_page_content = null;
+ if($wgRequest->getCheck('free_text')) {
+ $existing_page_content= $wgRequest->getVal('free_text');
+ $form_is_partial = true;
+ }
+ }
+
+ // disable all form elements if user doesn't have edit permission -
+ // two different checks are needed, because editing permissions can be
+ // set in different ways
+ // HACK - sometimes we don't know the page name in advance, but we still
+ // need to set a title here for testing permissions
+ if ($page_title == '')
+ $this->mPageTitle = Title::newFromText("Semantic Forms permissions test");
+ else
+ $this->mPageTitle = Title::newFromText($page_title);
+ global $wgOut;
+ // show previous set of deletions for this page, if it's been deleted before
+ if (! $form_submitted && ! $this->mPageTitle->exists())
+ $this->showDeletionLog($wgOut);
+ if (($wgUser->isAllowed('edit') && $this->mPageTitle->userCan('edit')) || $is_query) {
+ $form_is_disabled = false;
+ $form_text = "";
+ // show "Your IP address will be recorded" warning if user is
+ // anonymous, and it's not a query -
+ // wikitext for bolding has to be replaced with HTML
+ if ($wgUser->isAnon() && ! $is_query) {
+ $anon_edit_warning = preg_replace("/'''(.*)'''/", "<strong>$1</strong>", wfMsg('anoneditwarning'));
+ $form_text .= "<p>$anon_edit_warning</p>\n";
+ }
+ } else {
+ $form_is_disabled = true;
+ // display a message to the user explaining why they can't edit the
+ // page - borrowed heavily from EditPage.php
+ if ( $wgUser->isAnon() ) {
+ $skin = $wgUser->getSkin();
+ $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
+ $loginLink = $skin->makeKnownLinkObj( $loginTitle, wfMsgHtml( 'loginreqlink' ) );
+ $form_text = wfMsgWikiHtml( 'whitelistedittext', $loginLink );
+ } else {
+ $form_text = wfMsg( 'protectedpagetext' );
+ }
+ }
+ $javascript_text = "";
+ $sfgJSValidationCalls = array();
+ $fields_javascript_text = "";
+
+ // Remove <noinclude> sections and <includeonly> tags from form definition
+ $form_def = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $form_def);
+ $form_def = strtr($form_def, array('<includeonly>' => '', '</includeonly>' => ''));
+
+ // parse wiki-text
+ // add '<nowiki>' tags around every triple-bracketed form definition
+ // element, so that the wiki parser won't touch it - the parser will
+ // remove the '<nowiki>' tags, leaving us with what we need
+ $form_def = "__NOEDITSECTION__" . strtr($form_def, array('{{{' => '<nowiki>{{{', '}}}' => '}}}</nowiki>'));
+ $wgParser->mOptions = new ParserOptions();
+ $wgParser->mOptions->initialiseFromUser($wgUser);
+ $form_def = $wgParser->parse($form_def, $this->mPageTitle, $wgParser->mOptions)->getText();
+
+ // turn form definition file into an array of sections, one for each
+ // template definition (plus the first section)
+ $form_def_sections = array();
+ $start_position = 0;
+ $section_start = 0;
+ $free_text_was_included = false;
+ $free_text_preload_page = null;
+ $free_text_components = array();
+ $all_values_for_template = array();
+ // unencode and HTML-encoded representations of curly brackets and
+ // pipes - this is a hack to allow for forms to include templates
+ // that themselves contain form elements - the escaping is needed
+ // to make sure that those elements don't get parsed too early
+ $form_def = str_replace(array('&#123;', '&#124;', '&#125;'), array('{', '|', '}'), $form_def);
+ // and another hack - replace the 'free text' standard input with
+ // a field declaration to get it to be handled as a field
+ $form_def = str_replace('standard input|free text', 'field|<freetext>', $form_def);
+ while ($brackets_loc = strpos($form_def, "{{{", $start_position)) {
+ $brackets_end_loc = strpos($form_def, "}}}", $brackets_loc);
+ $bracketed_string = substr($form_def, $brackets_loc + 3, $brackets_end_loc - ($brackets_loc + 3));
+ $tag_components = explode('|', $bracketed_string);
+ $tag_title = trim($tag_components[0]);
+ if ($tag_title == 'for template' || $tag_title == 'end template') {
+ // create a section for everything up to here
+ $section = substr($form_def, $section_start, $brackets_loc - $section_start);
+ $form_def_sections[] = $section;
+ $section_start = $brackets_loc;
+ }
+ $start_position = $brackets_loc + 1;
+ } // end while
+ $form_def_sections[] = trim(substr($form_def, $section_start));
+
+ // cycle through form definition file (and possibly an existing article
+ // as well), finding template and field declarations and replacing them
+ // with form elements, either blank or pre-populated, as appropriate
+ $all_fields = array();
+ $data_text = "";
+ $template_name = "";
+ $allow_multiple = false;
+ $instance_num = 0;
+ $all_instances_printed = false;
+ $strict_parsing = false;
+ // initialize list of choosers (dropdowns with available templates)
+ $choosers = array();
+ for ($section_num = 0; $section_num < count($form_def_sections); $section_num++) {
+ $tif = new SFTemplateInForm();
+ $start_position = 0;
+ $template_text = "";
+ // the append is there to ensure that the original array doesn't get
+ // modified; is it necessary?
+ $section = " " . $form_def_sections[$section_num];
+
+ while ($brackets_loc = strpos($section, '{{{', $start_position)) {
+ $brackets_end_loc = strpos($section, "}}}", $brackets_loc);
+ $bracketed_string = substr($section, $brackets_loc + 3, $brackets_end_loc - ($brackets_loc + 3));
+ $tag_components = explode('|', $bracketed_string);
+ $tag_title = trim($tag_components[0]);
+ // =====================================================
+ // for template processing
+ // =====================================================
+ if ($tag_title == 'for template') {
+ $old_template_name = $template_name;
+ $template_name = trim($tag_components[1]);
+ $tif->template_name = $template_name;
+ $query_template_name = str_replace(' ', '_', $template_name);
+ // also replace periods with underlines, since that's what
+ // POST does to strings anyway
+ $query_template_name = str_replace('.', '_', $query_template_name);
+ $chooser_name = false;
+ $chooser_caption = false;
+ // cycle through the other components
+ for ($i = 2; $i < count($tag_components); $i++) {
+ $component = $tag_components[$i];
+ if ($component == 'multiple') $allow_multiple = true;
+ if ($component == 'strict') $strict_parsing = true;
+ $sub_components = explode('=', $component);
+ if (count($sub_components) == 2) {
+ if ($sub_components[0] == 'label') {
+ $template_label = $sub_components[1];
+ } elseif ($sub_components[0] == 'chooser') {
+ $allow_multiple = true;
+ $chooser_name = $sub_components[1];
+ } elseif ($sub_components[0] == 'chooser caption') {
+ $chooser_caption = $sub_components[1];
+ }
+ }
+ }
+ // if this is the first instance, add the label in the form
+ if (($old_template_name != $template_name) && isset($template_label)) {
+ // add a placeholder to the form text so the fieldset can be
+ // hidden if chooser support demands it
+ if ($chooser_name !== false)
+ $form_text .= "<fieldset [[placeholder]] haschooser=true>\n";
+ else
+ $form_text .= "<fieldset>\n";
+ $form_text .= "<legend>$template_label</legend>\n";
+ }
+ $template_text .= "{{" . $tif->template_name;
+ $all_fields = $tif->getAllFields();
+ // remove template tag
+ $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ $template_instance_query_values = $wgRequest->getArray($query_template_name);
+ // if we are editing a page, and this template can be found more than
+ // once in that page, and multiple values are allowed, repeat this
+ // section
+ $existing_template_text = null;
+ if ($source_is_page || $form_is_partial) {
+ // replace underlines with spaces in template name, to allow for
+ // searching on either
+ $search_template_str = str_replace('_', ' ', $tif->template_name);
+ $found_instance = preg_match('/{{' . str_replace('/','\/',$search_template_str) . '\s*[\|}]/i', str_replace('_', ' ', $existing_page_content));
+ if ($allow_multiple) {
+ // find instances of this template in the page -
+ // if there's at least one, re-parse this section of the
+ // definition form for the subsequent template instances in
+ // this page; if there's none, don't include fields at all.
+ // there has to be a more efficient way to handle multiple
+ // instances of templates, one that doesn't involve re-parsing
+ // the same tags, but I don't know what it is.
+ if ($found_instance) {
+ $instance_num++;
+ } else {
+ $all_instances_printed = true;
+ }
+ }
+ // get the first instance of this template on the page being edited,
+ // even if there are more
+ if ($found_instance && ($start_char = stripos(str_replace('_', ' ', $existing_page_content), '{{' . $search_template_str)) !== false) {
+ $fields_start_char = $start_char + 2 + strlen($search_template_str);
+ // skip ahead to the first real character
+ while (in_array($existing_page_content[$fields_start_char], array(' ', '\n', '|'))) {
+ $fields_start_char++;
+ }
+ $template_contents = array('0' => '');
+ // cycle through template call, splitting it up by pipes ('|'),
+ // except when that pipe is part of a piped link
+ $field = "";
+ $uncompleted_square_brackets = 0;
+ $uncompleted_curly_brackets = 2;
+ $template_ended = false;
+ for ($i = $fields_start_char; ! $template_ended && ($i < strlen($existing_page_content)); $i++) {
+ $c = $existing_page_content[$i];
+ if ($c == '[') {
+ $uncompleted_square_brackets++;
+ } elseif ($c == ']' && $uncompleted_square_brackets > 0) {
+ $uncompleted_square_brackets--;
+ } elseif ($c == '{') {
+ $uncompleted_curly_brackets++;
+ } elseif ($c == '}' && $uncompleted_curly_brackets > 0) {
+ $uncompleted_curly_brackets--;
+ }
+ // handle an end to a field and/or template declaration
+ $template_ended = ($uncompleted_curly_brackets == 0 && $uncompleted_square_brackets == 0);
+ $field_ended = ($c == '|' && $uncompleted_square_brackets == 0 && $uncompleted_curly_brackets <= 2);
+ if ($template_ended || $field_ended) {
+ // if this was the last character in the template, remove
+ // the closing curly brackets
+ if ($template_ended) {
+ $field = substr($field, 0, -1);
+ }
+ // either there's an equals sign near the beginning or not -
+ // handling is similar in either way; if there's no equals
+ // sign, the index of this field becomes the key
+ $sub_fields = explode('=', $field, 2);
+ if (count($sub_fields) > 1) {
+ $template_contents[trim($sub_fields[0])] = trim($sub_fields[1]);
+ } else {
+ $template_contents[] = trim($sub_fields[0]);
+ }
+ $field = '';
+ } else {
+ $field .= $c;
+ }
+ }
+ $existing_template_text = substr($existing_page_content, $start_char, $i - $start_char);
+ // now remove this template from the text being edited
+ // if this is a partial form, establish a new insertion point
+ if ($existing_page_content && $form_is_partial && $wgRequest->getCheck('partial')) {
+ // if something already exists, set the new insertion point
+ // to its position; otherwise just let it lie
+ if (strpos($existing_page_content, $existing_template_text) !== false) {
+ $existing_page_content = str_replace('{{{insertionpoint}}}', '', $existing_page_content);
+ $existing_page_content = str_replace($existing_template_text, '{{{insertionpoint}}}', $existing_page_content);
+ }
+ } else {
+ $existing_page_content = str_replace($existing_template_text, '', $existing_page_content);
+ }
+ // if this is not a multiple-instance template, and we've found
+ // a match in the source page, there's a good chance that this
+ // page was created with this form - note that, so we don't
+ // send the user a warning
+ // (multiple-instance templates have a greater chance of
+ // getting repeated from one form to the next)
+ if (! $allow_multiple) {
+ $source_page_matches_this_form = true;
+ }
+ }
+ }
+ // if the input is from the form (meaning the user has hit one
+ // of the bottom row of buttons), and we're dealing with a
+ // multiple template, get the values for this instance of this
+ // template, then delete them from the array, so we can get the
+ // next group next time - the next() command for arrays doesn't
+ // seem to work here
+ if ((! $source_is_page) && $allow_multiple && $wgRequest) {
+ $all_instances_printed = true;
+ if ($old_template_name != $template_name) {
+ $all_values_for_template = $wgRequest->getArray($query_template_name);
+ }
+ if ($all_values_for_template) {
+ $cur_key = key($all_values_for_template);
+ // skip the input coming in from the "starter" div
+ if ($cur_key == 'num') {
+ unset($all_values_for_template[$cur_key]);
+ $cur_key = key($all_values_for_template);
+ }
+ if ($template_instance_query_values = current($all_values_for_template)) {
+ $all_instances_printed = false;
+ unset($all_values_for_template[$cur_key]);
+ }
+ }
+ }
+ // =====================================================
+ // end template processing
+ // =====================================================
+ } elseif ($tag_title == 'end template') {
+ if ($source_is_page) {
+ // add any unhandled template fields in the page as hidden variables
+ if (isset($template_contents))
+ $form_text .= SFFormUtils::unhandledFieldsHTML($template_contents);
+ }
+ // remove this tag, reset some variables, and close off form HTML tag
+ $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ $template_name = null;
+ if (isset($template_label)) {
+ $form_text .= "</fieldset>\n";
+ unset ($template_label);
+ }
+ $allow_multiple = false;
+ $all_instances_printed = false;
+ $instance_num = 0;
+ // if the hiding placeholder is still around, this fieldset should
+ // be hidden because it is empty and choosers are being used. So,
+ // hide it.
+ $form_text = str_replace("[[placeholder]]", "style='display:none'", $form_text);
+ // =====================================================
+ // field processing
+ // =====================================================
+ } elseif ($tag_title == 'field') {
+ $field_name = trim($tag_components[1]);
+ // cycle through the other components
+ $is_mandatory = false;
+ $is_hidden = false;
+ $is_restricted = false;
+ $is_uploadable = false;
+ $is_list = false;
+ $input_type = null;
+ $field_args = array();
+ $default_value = "";
+ $possible_values = null;
+ $semantic_property = null;
+ $preload_page = null;
+ for ($i = 2; $i < count($tag_components); $i++) {
+ $component = trim($tag_components[$i]);
+ if ($component == 'mandatory') {
+ $is_mandatory = true;
+ } elseif ($component == 'hidden') {
+ $is_hidden = true;
+ } elseif ($component == 'restricted') {
+ $is_restricted = true;
+ } elseif ($component == 'uploadable') {
+ $field_args['is_uploadable'] = true;
+ } elseif ($component == 'list') {
+ $is_list = true;
+ } elseif ($component == 'autocomplete') {
+ $field_args['autocomplete'] = true;
+ } elseif ($component == 'no autocomplete') {
+ $field_args['no autocomplete'] = true;
+ } elseif ($component == 'remote autocompletion') {
+ $field_args['remote autocompletion'] = true;
+ } elseif ($component == 'edittools') { // free text only
+ $free_text_components[] = 'edittools';
+ } else {
+ $sub_components = explode('=', $component);
+ if (count($sub_components) == 1) {
+ // add handling for single-value params, for custom input types
+ $field_args[$sub_components[0]] = null;
+ } elseif (count($sub_components) == 2) {
+ if ($sub_components[0] == 'input type') {
+ $input_type = $sub_components[1];
+ } elseif ($sub_components[0] == 'default') {
+ $default_value = $sub_components[1];
+ } elseif ($sub_components[0] == 'preload') {
+ // free text field has special handling
+ if ($field_name == 'free text' || $field_name = '<freetext>') {
+ $free_text_preload_page = $sub_components[1];
+ } else {
+ // this variable is not used
+ $preload_page = $sub_components[1];
+ }
+ } elseif ($sub_components[0] == 'autocomplete on property') {
+ // HACK - we need to figure out if this property is a
+ // relation or attribute, i.e. whether it points to wiki
+ // pages or not; so construct an SFTemplateField object
+ // with this property, and determine it that way
+ $property_name = $sub_components[1];
+ $dummy_field = new SFTemplateField();
+ $dummy_field->setSemanticProperty($property_name);
+ if ($dummy_field->propertyIsOfType('_wpg'))
+ $field_args['autocomplete field type'] = 'relation';
+ else
+ $field_args['autocomplete field type'] = 'attribute';
+ $field_args['autocompletion source'] = $sub_components[1];
+ } elseif ($sub_components[0] == 'autocomplete on') { // for backwards-compatibility
+ $field_args['autocomplete field type'] = 'category';
+ $field_args['autocompletion source'] = $sub_components[1];
+ } elseif ($sub_components[0] == 'autocomplete on category') {
+ $field_args['autocomplete field type'] = 'category';
+ $field_args['autocompletion source'] = $sub_components[1];
+ } elseif ($sub_components[0] == 'autocomplete on concept') {
+ $field_args['autocomplete field type'] = 'concept';
+ $field_args['autocompletion source'] = $sub_components[1];
+ } elseif ($sub_components[0] == 'autocomplete on namespace') {
+ $field_args['autocomplete field type'] = 'namespace';
+ $autocompletion_source = $sub_components[1];
+ // special handling for "main" (blank) namespace
+ if ($autocompletion_source == "")
+ $autocompletion_source = "main";
+ $field_args['autocompletion source'] = $autocompletion_source;
+ } elseif ($sub_components[0] == 'autocomplete from url') {
+ $field_args['autocomplete field type'] = 'external_url';
+ $field_args['autocompletion source'] = $sub_components[1];
+ // 'external' autocompletion is always done remotely, i.e. via API
+ $field_args['remote autocompletion'] = true;
+ } elseif ($sub_components[0] == 'values') {
+ // remove whitespaces, and un-escape characters
+ $possible_values = array_map('trim', explode(',', $sub_components[1]));
+ $possible_values = array_map('htmlspecialchars_decode', $possible_values);
+ } elseif ($sub_components[0] == 'values from category') {
+ $category_name = ucfirst($sub_components[1]);
+ $possible_values = SFUtils::getAllPagesForCategory($category_name, 10);
+ } elseif ($sub_components[0] == 'values from concept') {
+ $possible_values = SFUtils::getAllPagesForConcept($sub_components[1]);
+ } elseif ($sub_components[0] == 'property') {
+ $semantic_property = $sub_components[1];
+ } elseif ($sub_components[0] == 'default filename') {
+ $default_filename = str_replace('&lt;page name&gt;', $page_title, $sub_components[1]);
+ $field_args['default filename'] = $default_filename;
+ } else {
+ $field_args[$sub_components[0]] = $sub_components[1];
+ }
+ // for backwards compatibility
+ if ($sub_components[0] == 'autocomplete on' && $sub_components[1] == null) {
+ $field_args['no autocomplete'] = true;
+ }
+ }
+ }
+ }
+ $field_args['part_of_multiple'] = $allow_multiple;
+ // get the value from the request, if it's there, and if it's not
+ // an array
+ $escaped_field_name = str_replace("'", "\'", $field_name);
+ if (isset($template_instance_query_values) &&
+ $template_instance_query_values != null &&
+ is_array($template_instance_query_values) &&
+ array_key_exists($escaped_field_name, $template_instance_query_values)) {
+ $field_query_val = $template_instance_query_values[$escaped_field_name];
+ if ($form_submitted || ($field_query_val && ! is_array($field_query_val))) {
+ $cur_value = $field_query_val;
+ }
+ } else
+ $cur_value = '';
+ if ($cur_value && ! is_array($cur_value)) {
+ $cur_value = htmlspecialchars($cur_value);
+ }
+
+ if ($cur_value == null) {
+ // set to default value specified in the form, if it's there
+ $cur_value = $default_value;
+ }
+
+ // if the user is editing a page, and that page contains a call to
+ // the template being processed, get the current field's value
+ // from the template call
+ if ($source_is_page && (! empty($existing_template_text))) {
+ if (isset($template_contents[$field_name])) {
+ $cur_value = $template_contents[$field_name];
+ // now remove this value from $template_contents, so that
+ // at the end we can have a list of all the fields that
+ // weren't handled by the form
+ unset($template_contents[$field_name]);
+ } else {
+ $cur_value = '';
+ }
+ }
+
+ // handle the free text field - if it was declared as
+ // "field|free text" (a deprecated usage), it has to be outside
+ // of a template
+ if (($template_name == '' && $field_name == 'free text') ||
+ $field_name == '<freetext>') {
+ // add placeholders for the free text in both the form and
+ // the page, using <free_text> tags - once all the free text
+ // is known (at the end), it will get substituted in
+ if ($is_hidden) {
+ $new_text = SFFormUtils::hiddenFieldHTML('free_text', '!free_text!');
+ } else {
+ if (! array_key_exists('rows', $field_args))
+ $field_args['rows'] = 5;
+ if (! array_key_exists('cols', $field_args))
+ $field_args['cols'] = 80;
+ $sfgTabIndex++;
+ $sfgFieldNum++;
+ list($new_text, $new_javascript_text) = SFFormInputs::textAreaHTML('!free_text!', 'free_text', false, ($form_is_disabled || $is_restricted), $field_args);
+ if (in_array('edittools', $free_text_components)) {
+ // borrowed from EditPage::showEditTools()
+ $options[] = 'parse';
+ $edittools_text = wfMsgExt( 'edittools', array( 'parse' ), array( 'content' ) );
+
+ $new_text .=<<<END
+ <div class="mw-editTools">
+ $edittools_text
+ </div>
+
+END;
+ }
+ $fields_javascript_text .= $new_javascript_text;
+ }
+ $free_text_was_included = true;
+ // add a similar placeholder to the data text
+ $data_text .= "!free_text!\n";
+ }
+
+ if ($template_name == '' || $field_name == '<freetext>') {
+ $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ } else {
+ if (is_array($cur_value)) {
+ // first, check if it's a list
+ if (array_key_exists('is_list', $cur_value) &&
+ $cur_value['is_list'] == true) {
+ $cur_value_in_template = "";
+ if (array_key_exists('delimiter', $field_args)) {
+ $delimiter = $field_args['delimiter'];
+ } else {
+ $delimiter = ",";
+ }
+ foreach ($cur_value as $key => $val) {
+ if ($key !== "is_list") {
+ if ($cur_value_in_template != "") {
+ $cur_value_in_template .= $delimiter . " ";
+ }
+ $cur_value_in_template .= $val;
+ }
+ }
+ } else {
+ // otherwise:
+ // if it has 1 or 2 elements, assume it's a checkbox; if it has
+ // 3 elements, assume it's a date
+ // - this handling will have to get more complex if other
+ // possibilities get added
+ if (count($cur_value) == 1) {
+ // manually load SMW's message values here, in case they
+ // didn't get loaded before
+ wfLoadExtensionMessages('SemanticMediaWiki');
+ $words_for_false = explode(',', wfMsgForContent('smw_false_words'));
+ // for each language, there's a series of words that are
+ // equal to false - get the word in the series that matches
+ // "no"; generally, that's the third word
+ $index_of_no = 2;
+ if (count($words_for_false) > $index_of_no) {
+ $no = ucwords($words_for_false[$index_of_no]);
+ } elseif (count($words_for_false) == 0) {
+ $no = "0"; // some safe value if no words are found
+ } else {
+ $no = ucwords($words_for_false[0]);
+ }
+ $cur_value_in_template = $no;
+ } elseif (count($cur_value) == 2) {
+ wfLoadExtensionMessages('SemanticMediaWiki');
+ $words_for_true = explode(',', wfMsgForContent('smw_true_words'));
+ // get the value in the 'true' series that tends to be "yes",
+ // and go with that one - generally, that's the third word
+ $index_of_yes = 2;
+ if (count($words_for_true) > $index_of_yes) {
+ $yes = ucwords($words_for_true[$index_of_yes]);
+ } elseif (count($words_for_true) == 0) {
+ $yes = "1"; // some safe value if no words are found
+ } else {
+ $yes = ucwords($words_for_true[0]);
+ }
+ $cur_value_in_template = $yes;
+ // if it's 3 or greater, assume it's a date or datetime
+ } elseif (count($cur_value) >= 3) {
+ $month = $cur_value['month'];
+ $day = $cur_value['day'];
+ if ($day != '') {
+ global $wgAmericanDates;
+ if ($wgAmericanDates == false) {
+ // pad out day to always be two digits
+ $day = str_pad($day, 2, "0", STR_PAD_LEFT);
+ }
+ }
+ $year = $cur_value['year'];
+ $hour = $minute = $second = $ampm24h = $timezone = null;
+ if (isset($cur_value['hour'])) $hour = $cur_value['hour'];
+ if (isset($cur_value['minute'])) $minute = $cur_value['minute'];
+ if (isset($cur_value['second'])) $second = $cur_value['second'];
+ if (isset($cur_value['ampm24h'])) $ampm24h = $cur_value['ampm24h'];
+ if (isset($cur_value['timezone'])) $timezone = $cur_value['timezone'];
+ if ($month != '' && $day != '' && $year != '') {
+ // special handling for American dates - otherwise, just
+ // the standard year/month/day (where month is a number)
+ global $wgAmericanDates;
+ if ($wgAmericanDates == true) {
+ $cur_value_in_template = "$month $day, $year";
+ } else {
+ $cur_value_in_template = "$year/$month/$day";
+ }
+ // include whatever time information we have
+ if (! is_null($hour))
+ $cur_value_in_template .= " " . str_pad(intval(substr($hour,0,2)),2,'0',STR_PAD_LEFT) . ":" . str_pad(intval(substr($minute,0,2)),2,'0',STR_PAD_LEFT);
+ if (! is_null($second))
+ $cur_value_in_template .= ":" . str_pad(intval(substr($second,0,2)),2,'0',STR_PAD_LEFT);
+ if (! is_null($ampm24h))
+ $cur_value_in_template .= " $ampm24h";
+ if (! is_null($timezone))
+ $cur_value_in_template .= " $timezone";
+ } else {
+ $cur_value_in_template = "";
+ }
+ }
+ }
+ } else { // value is not an array
+ $cur_value_in_template = $cur_value;
+ }
+ if ($query_template_name == null || $query_template_name == '')
+ $input_name = $field_name;
+ elseif ($allow_multiple)
+ // 'num' will get replaced by an actual index, either in PHP
+ // or in Javascript, later on
+ $input_name = $query_template_name . '[num][' . $field_name . ']';
+ else
+ $input_name = $query_template_name . '[' . $field_name . ']';
+
+ // if we're creating the page name from a formula based on
+ // form values, see if the current input is part of that formula,
+ // and if so, substitute in the actual value
+ if ($form_submitted && $generated_page_name != '') {
+ // this line appears unnecessary
+ //$generated_page_name = str_replace('.', '_', $generated_page_name);
+ $generated_page_name = str_replace(' ', '_', $generated_page_name);
+ $escaped_input_name = str_replace(' ', '_', $input_name);
+ $generated_page_name = str_ireplace("<$escaped_input_name>", $cur_value_in_template, $generated_page_name);
+ // once the substitution is done, replace underlines back
+ // with spaces
+ $generated_page_name = str_replace('_', ' ', $generated_page_name);
+ }
+ // disable this field if either the whole form is disabled, or
+ // it's a restricted field and user doesn't have sysop privileges
+ $is_disabled = ($form_is_disabled ||
+ ($is_restricted && (! $wgUser || ! $wgUser->isAllowed('editrestrictedfields'))));
+ // create an SFFormField instance based on all the
+ // parameters in the form definition, and any information from
+ // the template definition (contained in the $all_fields parameter)
+ $form_field = SFFormField::createFromDefinition($field_name, $input_name,
+ $is_mandatory, $is_hidden, $is_uploadable, $possible_values, $is_disabled,
+ $is_list, $input_type, $field_args, $all_fields, $strict_parsing);
+ // 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 ($semantic_property != null)
+ $form_field->template_field->setSemanticProperty($semantic_property);
+
+ // call hooks - unfortunately this has to be split into two
+ // separate calls, because of the different variable names in
+ // each case
+ if ($form_submitted)
+ wfRunHooks('sfCreateFormField', array(&$form_field, &$cur_value_in_template, true));
+ else
+ wfRunHooks('sfCreateFormField', array(&$form_field, &$cur_value, false));
+ // if this is not part of a 'multiple' template, increment the
+ // global tab index (used for correct tabbing)
+ if (! $field_args['part_of_multiple'])
+ $sfgTabIndex++;
+ // increment the global field number regardless
+ $sfgFieldNum++;
+ // if the field is a date field, and its default value was set
+ // to 'now', and it has no current value, set $cur_value to be
+ // the current date
+ if ($default_value == 'now' &&
+ // if the date is hidden, cur_value will already be set
+ // to the default value
+ ($cur_value == '' || $cur_value == 'now')) {
+ if ($input_type == 'date' || $input_type == 'datetime' ||
+ $input_type == 'datetime with timezone' || $input_type == 'year' ||
+ ($input_type == '' && $form_field->template_field->propertyIsOfType('_dat'))) {
+ // get current time, for the time zone specified in the wiki
+ global $wgLocaltimezone;
+ putenv('TZ=' . $wgLocaltimezone);
+ $cur_time = time();
+ $year = date("Y", $cur_time);
+ $month = date("n", $cur_time);
+ $day = date("j", $cur_time);
+ global $wgAmericanDates, $sfg24HourTime;
+ if ($wgAmericanDates == true) {
+ $month_names = SFFormUtils::getMonthNames();
+ $month_name = $month_names[$month - 1];
+ $cur_value_in_template = "$month_name $day, $year";
+ } else {
+ $cur_value_in_template = "$year/$month/$day";
+ }
+ if ($input_type == 'datetime' || $input_type == 'datetime with timezone') {
+ if ($sfg24HourTime) {
+ $hour = str_pad(intval(substr(date("G", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
+ } else {
+ $hour = str_pad(intval(substr(date("g", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
+ }
+ $minute = str_pad(intval(substr(date("i", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
+ $second = str_pad(intval(substr(date("s", $cur_time),0,2)),2,'0',STR_PAD_LEFT);
+ if ($sfg24HourTime) {
+ $cur_value_in_template .= " $hour:$minute:$second";
+ } else {
+ $ampm = date("A", $cur_time);
+ $cur_value_in_template .= " $hour:$minute:$second $ampm";
+ }
+ }
+ if ($input_type == 'datetime with timezone') {
+ $timezone = date("T", $cur_time);
+ $cur_value_in_template .= " $timezone";
+ }
+ }
+ }
+ // if the field is a text field, and its default value was set
+ // to 'current user', and it has no current value, set $cur_value
+ // to be the current user
+ if ($default_value == 'current user' &&
+ // if the date is hidden, cur_value will already be set
+ // to the default value
+ ($cur_value == '' || $cur_value == 'current user')) {
+ if ($input_type == 'text' || $input_type == '') {
+ $cur_value_in_template = $wgUser->getName();
+ $cur_value = $cur_value_in_template;
+ }
+ }
+ list($new_text, $new_javascript_text) = $this->formFieldHTML($form_field, $cur_value);
+
+ $fields_javascript_text .= $new_javascript_text;
+
+ // if this field is disabled, add a hidden field holding
+ // the value of this field, because disabled inputs for some
+ // reason don't submit their value
+ if ($form_field->is_disabled) {
+ if ($field_name == 'free text' || $field_name == '<freetext>') {
+ $new_text .= SFFormUtils::hiddenFieldHTML('free_text', '!free_text!');
+ } else {
+ $new_text .= SFFormUtils::hiddenFieldHTML($input_name, $cur_value);
+ }
+ }
+
+ if ($new_text) {
+ // include the field name only for non-numeric field names
+ if (is_numeric($field_name)) {
+ $template_text .= "|$cur_value_in_template";
+ } else {
+ // if the value is null, don't include it at all
+ if ($cur_value_in_template != '')
+ $template_text .= "\n|$field_name=$cur_value_in_template";
+ }
+ $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ // also add to Javascript validation code
+ $input_id = "input_" . $sfgFieldNum;
+ $info_id = "info_" . $sfgFieldNum;
+ if ($is_mandatory) {
+ if ($input_type == 'date' || $input_type == 'datetime' || $input_type == 'datetime with timezone' ||
+ ($input_type == '' && $form_field->template_field->propertyIsOfType('_dat'))) {
+ $sfgJSValidationCalls[] = "validate_mandatory_field ('$input_id" . "_month', '$info_id')";
+ $sfgJSValidationCalls[] = "validate_mandatory_field ('$input_id" . "_day', '$info_id')";
+ $sfgJSValidationCalls[] = "validate_mandatory_field ('$input_id" . "_year', '$info_id')";
+ if ($input_type == 'datetime' || $input_type == 'datetime with timezone') {
+ // TODO - validate the time fields
+ if ($input_type == 'datetime with timezone') {
+ // TODO - validate the timezone
+ }
+ }
+ } else {
+ if ($allow_multiple) {
+ if ($all_instances_printed) {
+ $sfgJSValidationCalls[] = "validate_multiple_mandatory_fields($sfgFieldNum)";
+ } else {
+ $sfgJSValidationCalls[] = "validate_mandatory_field(\"input_$sfgFieldNum\", \"info_$sfgFieldNum\")";
+ }
+ } elseif (($form_field->template_field->is_list && $form_field->template_field->field_type == 'enumeration' && $input_type != 'listbox') || ($input_type == 'checkboxes')) {
+ $sfgJSValidationCalls[] = "validate_mandatory_checkboxes('$input_id', '$info_id')";
+ } elseif ($input_type == 'radiobutton' || $input_type == 'category') {
+ // only add this if there's a "None" option
+ if (empty($default_value)) {
+ $sfgJSValidationCalls[] = "validate_mandatory_radiobutton('$input_id', '$info_id')";
+ }
+ } else {
+ $sfgJSValidationCalls[] = "validate_mandatory_field('$input_id', '$info_id')";
+ }
+ }
+ }
+ } else {
+ $start_position = $brackets_end_loc;
+ }
+ }
+ // =====================================================
+ // standard input processing
+ // =====================================================
+ } elseif ($tag_title == 'standard input') {
+ // if it's a query, ignore all standard inputs
+ if ($is_query) {
+ $new_text = "";
+ $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ continue;
+ }
+ // set a flag so that the standard 'form bottom' won't get displayed
+ $this->standardInputsIncluded = true;
+ // handle all the possible values
+ $input_name = $tag_components[1];
+ $input_label = null;
+ // cycle through the other components
+ for ($i = 2; $i < count($tag_components); $i++) {
+ $component = $tag_components[$i];
+ $sub_components = explode('=', $component);
+ if (count($sub_components) == 1) {
+ if ($sub_components[0] == 'edittools') {
+ $free_text_components[] = 'edittools';
+ }
+ } elseif (count($sub_components) == 2) {
+ if ($sub_components[0] == 'label') {
+ $input_label = $sub_components[1];
+ }
+ // free text input needs more handling than the rest
+ if ($input_name == 'free text' || $input_name == '<freetext>') {
+ if ($sub_components[0] == 'preload') {
+ $free_text_preload_page = $sub_components[1];
+ }
+ }
+ }
+ }
+ if ($input_name == 'summary') {
+ $new_text = SFFormUtils::summaryInputHTML($form_is_disabled, $input_label);
+ } elseif ($input_name == 'minor edit') {
+ $new_text = SFFormUtils::minorEditInputHTML($form_is_disabled, $input_label);
+ } elseif ($input_name == 'watch') {
+ $new_text = SFFormUtils::watchInputHTML($form_is_disabled, $input_label);
+ } elseif ($input_name == 'save') {
+ $new_text = SFFormUtils::saveButtonHTML($form_is_disabled, $input_label);
+ } elseif ($input_name == 'preview') {
+ $new_text = SFFormUtils::showPreviewButtonHTML($form_is_disabled, $input_label);
+ } elseif ($input_name == 'changes') {
+ $new_text = SFFormUtils::showChangesButtonHTML($form_is_disabled, $input_label);
+ } elseif ($input_name == 'cancel') {
+ $new_text = SFFormUtils::cancelLinkHTML($form_is_disabled, $input_label);
+ }
+ $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ // =====================================================
+ // page info processing
+ // =====================================================
+ } elseif ($tag_title == 'info') {
+ // TODO: Generate an error message if this is included more than once
+ foreach(array_slice($tag_components, 1) as $component) {
+ $sub_components = explode('=', $component, 2);
+ $tag = $sub_components[0];
+ if ($tag == 'add title') {
+ // handle this only if we're adding a page
+ if (! $this->mPageTitle->exists()) {
+ $val = $sub_components[1];
+ $form_page_title = $val;
+ }
+ }
+ elseif($tag == 'edit title') {
+ // handle this only if we're editing a page
+ if ($this->mPageTitle->exists()) {
+ $val = $sub_components[1];
+ $form_page_title = $val;
+ }
+ }
+ elseif($tag == 'partial form') {
+ $form_is_partial = true;
+ // replacement pages may have minimal matches...
+ $source_page_matches_this_form = true;
+ }
+ elseif($tag == 'includeonly free text' || $tag == 'onlyinclude free text') {
+ $onlyinclude_free_text = true;
+ }
+ }
+ $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
+ // =====================================================
+ // default outer level processing
+ // =====================================================
+ } else { // tag is not one of the three allowed values
+ // ignore tag
+ $start_position = $brackets_end_loc;
+ } // end if
+ } // end while
+
+ if (! $all_instances_printed ) {
+ if ($template_text != '') {
+ // for mostly aesthetic purposes, if the template call ends with
+ // a bunch of pipes (i.e., it's an indexed template with unused
+ // parameters at the end), remove the pipes
+ $template_text = preg_replace('/\|*$/', '', $template_text);
+ // add another newline before the final bracket, if this template
+ // call is already more than one line
+ if (strpos($template_text, "\n"))
+ $template_text .= "\n";
+ // if we're editing an existing page, and there were fields in
+ // the template call not handled by this form, preserve those
+ $template_text .= SFFormUtils::addUnhandledFields();
+ $template_text .= "}}";
+ $data_text .= $template_text . "\n";
+ // if there is a placeholder in the text, we know that we are
+ // doing a replace
+ if ($existing_page_content && strpos($existing_page_content, '{{{insertionpoint}}}', 0) !== false) {
+ $existing_page_content = preg_replace('/\{\{\{insertionpoint\}\}\}(\r?\n?)/',
+ preg_replace('/\}\}/m', '}\xB2',
+ preg_replace('/\{\{/m', '\xB2{', $template_text)) .
+ "\n{{{insertionpoint}}}",
+ $existing_page_content);
+ // otherwise, if it's a partial form, we have to add the new
+ // text somewhere
+ } elseif ($form_is_partial && $wgRequest->getCheck('partial') ) {
+ $existing_page_content = preg_replace('/\}\}/m', '}\xB2',
+ preg_replace('/\{\{/m', '\xB2{', $template_text)) .
+ "\n{{{insertionpoint}}}\n" . $existing_page_content;
+ }
+ }
+ }
+
+ if ($allow_multiple) {
+ if (! $all_instances_printed) {
+ // add the character "a" onto the instance number of this input
+ // in the form, to differentiate the inputs the form starts out
+ // with from any inputs added by the Javascript
+ $section = str_replace('[num]', "[{$instance_num}a]", $section);
+ $remove_text = wfMsg('sf_editdata_remove');
+ $form_text .=<<<END
+ <div id="wrapper_$sfgFieldNum" class="multipleTemplate">
+ $section
+ <input type="button" onclick="removeInstance('wrapper_$sfgFieldNum');" value="$remove_text" tabindex="$sfgTabIndex" class="remove" />
+ </div>
+
+END;
+ // this will cause the section to be re-parsed on the next go
+ $section_num--;
+ // because there is an instance, the fieldset will never be hidden,
+ // even if choosers are being used. So, do not hide the fieldset.
+ $form_text = str_replace("[[placeholder]]", "", $form_text);
+ } else {
+ // this is the last instance of this template - stick an 'add'
+ // button in the form
+ $form_text .=<<<END
+ <div id="starter_$query_template_name" class="multipleTemplate" style="display: none;">
+ $section
+ </div>
+ <div id="main_$query_template_name"></div>
+
+END;
+ $add_another = wfMsg('sf_editdata_addanother');
+ $form_text .=<<<END
+ <p style="margin-left:10px;">
+ <p><input type="button" onclick="addInstance('starter_$query_template_name', 'main_$query_template_name', '$sfgFieldNum');" value="$add_another" tabindex="$sfgTabIndex" class="addAnother" /></p>
+
+END;
+ // if a chooser is being used for this template, add the template
+ // to the chooser data array
+ if ($chooser_name !== false)
+ $choosers[$chooser_name][]= array($query_template_name, $sfgFieldNum, $chooser_caption);
+ }
+ } else {
+ $form_text .= $section;
+ }
+
+ } // end for
+
+ // if it wasn't included in the form definition, add the
+ // 'free text' input as a hidden field at the bottom
+ if (! $free_text_was_included) {
+ $form_text .= SFFormUtils::hiddenFieldHTML('free_text', '!free_text!');
+ }
+ // get free text, and add to page data, as well as retroactively
+ // inserting it into the form
+
+ // If $form_is_partial is true then either:
+ // (a) we're processing a replacement (param 'partial' == 1)
+ // (b) we're sending out something to be replaced (param 'partial' is missing)
+ if ($form_is_partial) {
+ if(!$wgRequest->getCheck('partial')) {
+ $free_text = $original_page_content;
+ $form_text .= SFFormUtils::hiddenFieldHTML('partial', 1);
+ } else {
+ $free_text = null;
+ $existing_page_content = preg_replace('/\xB2\{(.*?)\}\xB2/s', '{{\1}}', $existing_page_content);
+ $existing_page_content = preg_replace('/\{\{\{insertionpoint\}\}\}/', '', $existing_page_content);
+ $existing_page_content = Sanitizer::safeEncodeAttribute($existing_page_content);
+ }
+ } elseif ($source_is_page) {
+ // if the page is the source, free_text will just be whatever in the
+ // page hasn't already been inserted into the form
+ $free_text = trim($existing_page_content);
+ // or get it from a form submission
+ } elseif ($wgRequest->getCheck('free_text')) {
+ $free_text = $wgRequest->getVal('free_text');
+ if (! $free_text_was_included) {
+ $data_text .= "!free_text!";
+ }
+ // or get it from the form definition
+ } elseif ($free_text_preload_page != null) {
+ $free_text = SFFormUtils::getPreloadedText($free_text_preload_page);
+ } else {
+ $free_text = null;
+ }
+ if ($onlyinclude_free_text) {
+ // modify free text and data text to insert <onlyinclude> tags
+ $free_text = str_replace("<onlyinclude>",'', $free_text);
+ $free_text = str_replace("</onlyinclude>",'', $free_text);
+ $free_text = trim($free_text);
+ $data_text = str_replace('!free_text!','<onlyinclude>!free_text!</onlyinclude>', $data_text);
+ }
+ // if the FCKeditor extension is installed, use that for the free text input
+ global $wgFCKEditorDir;
+ if ($wgFCKEditorDir) {
+ $showFCKEditor = SFFormUtils::getShowFCKEditor();
+ $free_text = str_replace( '"', '&quot;', $free_text );
+ if(!$form_submitted && ($showFCKEditor & RTE_VISIBLE)) {
+ $free_text = SFFormUtils::prepareTextForFCK($free_text);
+ }
+ } else {
+ $showFCKEditor = 0;
+ $free_text = Sanitizer::safeEncodeAttribute($free_text);
+ }
+ // now that we have it, substitute free text into the form and page
+ $form_text = str_replace('!free_text!', $free_text, $form_text);
+ $data_text = str_replace('!free_text!', $free_text, $data_text);
+
+ // add a warning in, if we're editing an existing page and that page
+ // appears to not have been created with this form
+ if ($this->mPageTitle->exists() && ($existing_page_content != '') && ! $source_page_matches_this_form) {
+ $form_text = ' <div class="warningMessage">' . wfMsg('sf_editdata_formwarning', $this->mPageTitle->getFullURL()) . "</div>\n" . $form_text;
+ }
+
+ //Substitute the choosers in here too.
+ $chooser_count = 0;
+ $chooser_text = "";
+ $using_choosers = "false";
+ foreach ($choosers as $choosername => $chooser) {
+ if (count($chooser)!=0) {
+ $chooser_count++;
+ if ($chooser_count==1) {
+ // emit the initial javascript code
+ $using_choosers = "true";
+ $chooser_text .= <<<END
+<script type="text/javascript">/* <![CDATA[ */
+
+function updatechooserbutton(f,n)
+{
+ document.getElementById(n).disabled = (f.options[f.selectedIndex].value=="invalid");
+}
+
+function addInstanceFromChooser(chooserid)
+{
+ var chooser = document.getElementById(chooserid);
+ var optionstring = chooser.options[chooser.selectedIndex].value;
+ var pos = optionstring.indexOf(",");
+ var tabindex = optionstring.substr(0,pos);
+ var chooservalue = optionstring.substr(pos+1);
+ addInstance('starter_' + chooservalue, 'main_' + chooservalue, parseInt(tabindex));
+}
+
+//The fieldset containing the given element was just updated. If the fieldset is associated with a chooser,
+//ensure that the fieldset is hidden if and only if there are no template instances inside.
+function hideOrShowFieldset(element)
+{
+ //Find fieldset
+ while (element.tagName.toLowerCase() != "fieldset")
+ element = element.parentNode;
+ //Bail out if fieldset is not part of chooser
+ if (!element.getAttribute("haschooser"))
+ return;
+ //Now look for "input" or "select" tags that don't look like they're part of the starter template
+ var inputs = element.getElementsByTagName("input");
+ var x;
+ var show = false;
+ for (x=0;x<inputs.length;x++)
+ {
+ if (inputs[x].type=="text" && inputs[x].name.indexOf("[num]") == -1)
+ show = true;
+ }
+ var selects = element.getElementsByTagName("select");
+ for (x=0;x<selects.length;x++)
+ {
+ if (selects[x].name.indexOf("[num]") == -1)
+ show = true;
+ }
+ //Now show or hide fieldset
+ element.style.display = (show?"block":"none");
+}
+/* ]]> */ </script>
+
+END;
+ }
+
+ $chooser_text .= "<p>$choosername:<select id='chooserselect$chooser_count' size='1' onchange='updatechooserbutton(this,\"chooserbutton$chooser_count\")'>\n";
+ $chooser_text .= "<option value='invalid'>" . wfMsg('sf_createform_choosefield') . "</option>\n";
+ foreach ($chooser as $chooser_item) {
+ $chooser_value = str_replace('"','\\"',$chooser_item[0]);
+ $tabindex = $chooser_item[1];
+ $chooser_caption = $chooser_item[2];
+ if ($chooser_caption === false)
+ $chooser_caption = str_replace('_', ' ', $chooser_value);
+ $chooser_text .= "<option value=\"$tabindex ,$chooser_value\">$chooser_caption</option>\n";
+ }
+ $chooser_text .= "</select>\n";
+ }
+ $chooser_text .= "<input type='button' onclick=\"addInstanceFromChooser('chooserselect$chooser_count');\" value='" . wfMsg('sf_editdata_addanother') . "' disabled='true' id='chooserbutton$chooser_count'></p>";
+ }
+
+ $form_text = str_replace('{{{choosers}}}', $chooser_text, $form_text);
+
+ // add form bottom, if no custom "standard inputs" have been defined
+ if ($is_query)
+ $form_text .= SFFormUtils::queryFormBottom($form_is_disabled);
+ elseif (! $this->standardInputsIncluded)
+ $form_text .= SFFormUtils::formBottom($form_is_disabled);
+ $starttime = wfTimestampNow();
+ $page_article = new Article($this->mPageTitle);
+ $edittime = $page_article->getTimestamp();
+ $form_text .=<<<END
+
+ <input type="hidden" value="$starttime" name="wpStarttime" />
+ <input type="hidden" value="$edittime" name="wpEdittime" />
+ </form>
+
+END;
+
+ // add Javascript code for form-wide use
+ $javascript_text .= SFFormUtils::validationJavascript();
+ $javascript_text .= SFFormUtils::instancesJavascript($using_choosers);
+ $javascript_text .= SFFormUtils::autocompletionJavascript();
+ if ($free_text_was_included && $showFCKEditor > 0) {
+ $javascript_text .= SFFormUtils::mainFCKJavascript($showFCKEditor);
+ if ($showFCKEditor & (RTE_TOGGLE_LINK | RTE_POPUP)) {
+ $javascript_text .= SFFormUTils::FCKToggleJavascript();
+ }
+ if ($showFCKEditor & RTE_POPUP) {
+ $javascript_text .= SFFormUTils::FCKPopupJavascript();
+ }
+ }
+
+ // send the autocomplete values to the browser, along with the mappings
+ // of which values should apply to which fields
+ // if doing a replace, the data text is actually the modified original page
+ if($wgRequest->getCheck('partial'))
+ $data_text = $existing_page_content;
+ $javascript_text .= $fields_javascript_text;
+ global $wgParser;
+ $new_text = $wgParser->preprocess(str_replace( "{{!}}", "|", $form_page_title ), $this->mPageTitle, new ParserOptions());
+ return array($form_text, "/*<![CDATA[*/ $javascript_text /*]]>*/",
+ $data_text, $new_text, $generated_page_name);
+ }
+
+ /**
+ * Create the HTML and Javascript to display this field within a form
+ */
+ function formFieldHTML($form_field, $cur_value) {
+ global $smwgContLang;
+
+ // also get the actual field, with all the semantic information (type is
+ // SFTemplateField, instead of SFFormField)
+ $template_field = $form_field->template_field;
+
+ if ($form_field->is_hidden) {
+ $text = SFFormUtils::hiddenFieldHTML($form_field->input_name, $cur_value);
+ $javascript_text = "";
+ } elseif ($form_field->input_type != '' &&
+ array_key_exists($form_field->input_type, $this->mInputTypeHooks) &&
+ $this->mInputTypeHooks[$form_field->input_type] != null) {
+ $funcArgs = array();
+ $funcArgs[] = $cur_value;
+ $funcArgs[] = $form_field->input_name;
+ $funcArgs[] = $form_field->is_mandatory;
+ $funcArgs[] = $form_field->is_disabled;
+ // last argument to function should be a hash, merging the default
+ // values for this input type with all other properties set in
+ // the form definition, plus some semantic-related arguments
+ $hook_values = $this->mInputTypeHooks[$form_field->input_type];
+ $other_args = $form_field->getArgumentsForInputCall($hook_values[1]);
+ $funcArgs[] = $other_args;
+ list($text, $javascript_text) = call_user_func_array($hook_values[0], $funcArgs);
+ } else { // input type not defined in form
+ $field_type = $template_field->field_type;
+ $is_list = ($form_field->is_list || $template_field->is_list);
+ if ($field_type != '' &&
+ array_key_exists($field_type, $this->mSemanticTypeHooks) &&
+ isset($this->mSemanticTypeHooks[$field_type][$is_list])) {
+ $funcArgs = array();
+ $funcArgs[] = $cur_value;
+ $funcArgs[] = $form_field->input_name;
+ $funcArgs[] = $form_field->is_mandatory;
+ $funcArgs[] = $form_field->is_disabled;
+ $hook_values = $this->mSemanticTypeHooks[$field_type][$is_list];
+ $other_args = $form_field->getArgumentsForInputCall($hook_values[1]);
+ $funcArgs[] = $other_args;
+ list($text, $javascript_text) = call_user_func_array($hook_values[0], $funcArgs);
+ } else { // anything else
+ $other_args = $form_field->getArgumentsForInputCall();
+ // special call to ensure that a list input is the right default size
+ if ($form_field->is_list) {
+ if (! array_key_exists('size', $other_args))
+ $other_args['size'] = 100;
+ }
+ list($text, $javascript_text) = SFFormInputs::textEntryHTML($cur_value, $form_field->input_name, $form_field->is_mandatory, $form_field->is_disabled, $other_args);
+ }
+ }
+ return array($text, $javascript_text);
+ }
+
+}



_______________________________________________
MediaWiki-CVS mailing list
MediaWiki-CVS[at]lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Wikipedia mediawiki-cvs RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.