Extension:Semantic Google Maps/SF FormPrinter.inc

From MediaWiki.org
Jump to: navigation, search

The following hack works well for Semantic Forms 0.5. Copy code below to a file called 'SF_FormPrinter.inc' and put that file in the folder extensions/SemanticForms/includes/

<?php
/**
 * Handles the creation and running of a user-created form.
 *
 * @author Yaron Koren
 * @author Nils Oppermann
 * @author Jeffrey Stuckman
 */
 
class SFFormPrinter {
 
  function formHTML($form_def, $form_submitted, $source_is_page, $existing_page_content = null, $page_title = null) {
    global $wgRequest, $wgUser;
    global $gTabIndex; // used to represent the current tab index in the form
    global $gDisabledText; // disables all form elements if user doesn't have edit permission
 
    // initialize some variables
    $title = null;
    $gTabIndex = 0;
    if ( $wgUser->isAllowed('edit') ) {
      $gDisabledText = "";
      $form_text = "";
    } else {
      $gDisabledText = "disabled";
      // 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 = "";
    $js_validation_calls = array();
 
    // 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>' => ''));
 
    // 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;
    $all_values_for_template = array();
    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;
        $autocomplete_value_array = array();
        $autocomplete_value_array['mappings'] = 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]);
        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);
          // 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];
              }
            }
          }
          // if this is the first instance, add the label in the form
          if (($old_template_name != $template_name) && isset($template_label)) {
            $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) {
            if ($allow_multiple) {
              // find the number of instances of this template in the page -
              // if it's more than 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 (preg_match_all('/\{\{' . $tif->template_name . '(.*?)\}\}/mis', $existing_page_content, $matches)) {
                $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 (preg_match('/\{\{' . $tif->template_name . '(.*?)\}\}/mis', $existing_page_content, $matches)) {
              $existing_template_text = $matches[1];
              // create array of contents of this template
              // somewhat of a hack - this array starts out with one element,
              // so that adding fields with no corresponding key will give them
              // an index starting with 1, not 0, to match MediaWiki's counting
              // system
              $template_contents = array(null);
              // cycle through template call, splitting it up by pipes ('|'),
              // except when that pipe is part of a piped link
              $field = "";
              $uncompleted_square_brackets = 0;
              for ($i = 0; $i < strlen($existing_template_text); $i++) {
                $c = $existing_template_text[$i];
                if (($i == strlen($existing_template_text) - 1) ||
                    ($c == '|' && $uncompleted_square_brackets == 0)) {
                  if ($field != null) {
                    // if this was the last character in the template, append
                    // this character
                    if ($i == strlen($existing_template_text) - 1) {
                      $field .= $c;
                    }
                    // 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;
                  if ($c == '[') {
                    $uncompleted_square_brackets++;
                  } elseif ($c == ']' && $uncompleted_square_brackets > 0) {
                    $uncompleted_square_brackets--;
                  }
                }
              }
              // now remove this template from the text being edited
              $existing_page_content = str_replace($matches[0], '', $existing_page_content);
            }
          }
          // 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]);
              }
            }
          }
        } elseif ($tag_title == 'end template') {
          // 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;
        } elseif ($tag_title == 'field') {
          $field_name = trim($tag_components[1]);
          // cycle through the other components
          $is_mandatory = false;
          $is_hidden = false;
          $is_restricted = false;
          $input_type = null;
          $no_autocomplete = false;
          $autocomplete_category = null;
          $size = null;
          $num_rows = null;
          $num_cols = null;
          $default_value = "";
          $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;
            } else {
              $sub_components = explode('=', $component);
              if (count($sub_components) == 2) {
                if ($sub_components[0] == 'input type') {
                  $input_type = $sub_components[1];
                } elseif ($sub_components[0] == 'autocomplete on') {
                  $autocomplete_category = $sub_components[1];
                  // this field is overloaded - if it's empty, that indicates
                  // no automatic autocompleting should happen
                  if ($autocomplete_category == null) {
                    $no_autocomplete = true;
                  }
                } elseif ($sub_components[0] == 'size') {
                  $size = $sub_components[1];
                } elseif ($sub_components[0] == 'rows') {
                  $num_rows = $sub_components[1];
                } elseif ($sub_components[0] == 'cols') {
                  $num_cols = $sub_components[1];
                } elseif ($sub_components[0] == 'default') {
                  $default_value = $sub_components[1];
                } elseif ($sub_components[0] == 'preload') {
                  $preload_page = $sub_components[1];
                }
              }
            }
          }
          // get the value from the request, if it's there
          $cur_value = $template_instance_query_values[$field_name];
          if ($cur_value && ! is_array($cur_value)) {
            $cur_value = Sanitizer::safeEncodeAttribute($cur_value);
          }
          if (! $cur_value) {
            // set to default value specified in the form, if it's there
            $cur_value = $default_value;
          }
 
          // if the user is starting to edit a page, and that page contains
          // the current template being processed, get the current template
          // field's value in the existing page
          if ($source_is_page && ($existing_template_text != null)) {
            $cur_value = $template_contents[$field_name];
            if ($cur_value) {
              $cur_value = Sanitizer::safeEncodeAttribute($cur_value);
            }
          }
 
          // hack - if this is a 'restricted' field, and the user isn't
          // a sysop, set the global $gDisabledText temporarily to
          // 'disabled' - set it back at the end of this function
          $actual_disabled_text = $gDisabledText;
          // determine whether user is a sysop by whether or not they're
          // allowed to delete things - if there's a better way, please let
          // me know
          if ($is_restricted && (! $wgUser || ! $wgUser->isAllowed('delete'))) {
            // set background color to get around weird IE behavior (field
            // is disabled, but color stays white)
            $gDisabledText = "disabled";
            //$gDisabledText = "disabled style=\"background-color: #dddddd; border: 1px solid #ccccff;\"";
            //$gDisabledText = "disabled readonly";
          }
 
          // handle non-template fields - 'page title' and 'free text'
          if ($template_name == '') {
            if ($field_name == 'page title') {
              // the actual value should be non-null - stick it in
              $new_text = $page_title;
            } elseif ($field_name == 'free text') {
              // 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 = SFFormPrinter::hiddenFieldHTML('free_text', '<free_text>');
              } else {
                if ($num_rows == null) $num_rows = 5;
                if ($num_cols == null) $num_cols = 30;
                $new_text = SFFormPrinter::textAreaHTML($num_rows, $num_cols, 'free_text', '<free_text>', null);
              }
              $free_text_was_included = true;
              // add a similar placeholder to the data text
              $data_text .= "<free_text>\n\n";
            }
            $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc);
          } else { // this field is part of a template
            if (is_array($cur_value)) {
              // 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) {
                $words_for_false = explode(',', wfMsgForContent('smw_false_words'));
                // for the various languages, the second word in the 'false'
                // series tends to be "no" - go with that one
                if (count($words_for_false) > 2) {
                  $no = $words_for_false[1];
                } else {
                  $no = $words_for_false[0];
                }
                $cur_value_in_template = $no;
              } elseif (count($cur_value) == 2) {
                $words_for_true = explode(',', wfMsgForContent('smw_true_words'));
                // the second word in the 'true' series tends to be "yes" -
                // go with that one
                if (count($words_for_true) > 2) {
                  $yes = $words_for_true[1];
                } else {
                  $yes = $words_for_true[0];
                }
                $cur_value_in_template = $yes;
              } elseif (count($cur_value) == 3) {
                $month = $cur_value['month'];
                $day = $cur_value['day'];
                $year = $cur_value['year'];
                if ($month != '' && $day != '' && $year != '') {
                  $cur_value_in_template = "$month $day, $year";
                } 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 . ']';
            $new_text = SFFormPrinter::formTemplateFieldHTML($field_name, $input_name, $allow_multiple,
              $cur_value, $is_mandatory, $is_hidden, $is_restricted, $input_type, $size, $num_rows, $num_cols, $no_autocomplete,
              $autocomplete_category, $all_fields, $strict_parsing, $autocomplete_value_array);
 
            // if this was field was disabled due to being 'restricted',
            // restore $gDisabledText back to its actual value, and add
            // a hidden field holding the value of this field, because
            // disabled inputs for some reason don't submit their value
            if ($is_restricted && ! $wgUser->isAllowed('delete')) {
              $gDisabledText = $actual_disabled_text;
              if ($field_name == 'free text') {
                $new_text .= SFFormPrinter::hiddenFieldHTML('free_text', '<free_text>');
              } else {
                $new_text .= SFFormPrinter::hiddenFieldHTML($input_name, $cur_value);
              }
            }
 
            if ($new_text) {
              if (is_numeric($field_name)) {
                // if the value is null, don't include it at all -
                // TODO: this isn't quite right
                if ($cur_value_in_template != '')
                  $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
              if ($is_mandatory) {
                $input_id = "input_" . $gTabIndex;
                $info_id = "info_" . $gTabIndex;
                $js_validation_calls[] = "validate_mandatory_field ('$input_id', '$info_id')";
              }
            } else {
              $start_position = $brackets_end_loc;
            }
          }
        } else { // tag is not one of the three allowed values
          // ignore tag
          $start_position = $brackets_end_loc;
        }
      } // end while
 
      if (! $all_instances_printed && ($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";
        }
        $template_text .= "}}\n\n";
        // TODO - should instances of the same template not be separated
        // by a blank line? if so, the following code could be used:
        //if (($data_text != "") &&
        //    (! $allow_multiple || $old_template_name != $template_name)) {
        //  $data_text .= "\n";
        //}
        $data_text .= $template_text;
      }
      if ($allow_multiple) {
        if (! $all_instances_printed) {
          $section = str_replace('[num]', "[{$instance_num}a]", $section);
          $remove_text = wfMsg('sf_editdata_remove');
          $form_text .=<<<END
        <div id="wrapper_$gTabIndex" class="multiple_template">
        $section
        <input type="button" onclick="removeInstance('wrapper_$gTabIndex');" value="$remove_text" tabindex="$gTabIndex" />
        </div>
 
END;
          // this will cause the section to be re-parsed on the next go
          $section_num--;
        } 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="multiple_template" 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', '$gTabIndex');" value="$add_another" tabindex="$gTabIndex" /></p>
 
END;
        }
      } else {
        $form_text .= $section;
      }
 
    } // end for
 
    // if it wasn't already included in the form definition, put the
    // 'free text' input at the bottom of the form
    if (! $free_text_was_included) {
      $form_text .= '   <fieldset><legend>' . wfMsg('sf_editdata_freetextlabel') . "</legend>\n";
      $form_text .= SFFormPrinter::textAreaHTML(5, 30, 'free_text', '<free_text>', null);
      $form_text .= "    </fieldset>\n";
    }
    // get free text, and add to page data, as well as retroactively
    // inserting it into the form
    if ($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 = Sanitizer::safeEncodeAttribute($wgRequest->getVal('free_text'));
      if (! $free_text_was_included) {
        $data_text .= "<free_text>";
      }
    // of get it from the form definition
    } elseif ($preload_page != null) {
      $free_text = SFFormPrinter::getPreloadedText($preload_page);
    } else {
      $free_text = null;
    }
    // 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 general Javascript code
    $blank_error_str = wfMsg('sf_blank_error');
    $javascript_text .=<<<END
 
function validate_mandatory_field(field_id, info_id) {
        field = document.getElementById(field_id);
        if (field.value.replace(/\s+/, '') == '') {
                infobox = document.getElementById(info_id);
                infobox.innerHTML = "$blank_error_str";
                //field.style.border = "1px solid red";
                return false;
        } else {
                return true;
        }
}
 
function validate_all() {
        var num_errors = 0;
 
END;
    foreach ($js_validation_calls as $function_call) {
      $javascript_text .= "     if (!$function_call) num_errors += 1;\n";
    }
    $remove_text = wfMsg('sf_editdata_remove');
    $javascript_text .=<<<END
        return (num_errors == 0);
}
 
var num_elements = 0;
 
function addInstance(starter_div_id, main_div_id, tab_index)
{
        var starter_div = document.getElementById(starter_div_id);
        var main_div = document.getElementById(main_div_id);
        num_elements++;
 
        //Create the new instance
        var new_div = starter_div.cloneNode(true);
        var div_id = 'div_gen_' + num_elements;
        new_div.className = 'multiple_template';
        new_div.id = div_id;
        new_div.style.display = 'block';
 
        // make internal ID unique for the relevant divs and spans, and replace
        // the [num] index in the element names with an actual unique index
        var children = new_div.getElementsByTagName('*');
        var x;
        for (x=0;x<children.length;x++)
        {
                if (children[x].name)
                        children[x].name = children[x].name.replace(/\[num\]/g, '[' + num_elements + ']');
                if (children[x].id)
                        children[x].id = children[x].id
                                .replace(/input_/g, 'input_' + num_elements + '_')
                                .replace(/info_/g, 'info_' + num_elements + '_')
                                .replace(/div_/g, 'div_' + num_elements + '_');
        }
 
        //Create remove button
        var remove_button = document.createElement('input');
        remove_button.type = 'button';
        remove_button.value = '$remove_text';
        remove_button.tabIndex = tab_index;
        remove_button.onclick = removeInstanceEventHandler(div_id);
        new_div.appendChild(remove_button);
 
        //Add the new instance
        main_div.appendChild(new_div);
        attachAutocompleteToAllFields(new_div);
}
 
function removeInstanceEventHandler(this_div_id)
{
        return function()
        {
                removeInstance(this_div_id);
        };
}
 
function removeInstance(div_id) {
        var olddiv = document.getElementById(div_id);
        olddiv.parentNode.removeChild(olddiv);
}
 
var autocompletestrings = new Array();
var autocompletemappings = new Array();
 
//Activate autocomplete functionality for every field on the document
function attachAutocompleteToAllDocumentFields()
{
        var forms = document.getElementsByTagName("form");
        var x;
        for (x=0;x<forms.length;x++)
        {
                if (forms[x].name == "createbox")
                {
                        attachAutocompleteToAllFields(forms[x]);
                }       
        }
}
 
//Activate autocomplete functionality for every field under the specified element
function attachAutocompleteToAllFields(base)
{
        var inputs = base.getElementsByTagName("input");
        var y;
        for (y=0;y<inputs.length;y++)
        {
                attachAutocompleteToField(inputs[y].id);
        }
}
 
//Activate autocomplete functionality for the specified field
function attachAutocompleteToField(input_id)
{
        //Check input id for the proper format, to ensure this is for SF
        if (input_id.substr(0,6) == 'input_')
        {
                //Extract the field ID number from the input field
                var field_num = parseInt(input_id.substring(input_id.lastIndexOf('_') + 1, input_id.length),10);
                //Add the autocomplete string, if a mapping exists.
                if (autocompletemappings[field_num])
                {
                        var div_id = input_id.replace(/input_/g, 'div_');
                        new Autocompleter.Local(input_id, div_id, autocompletestrings[autocompletemappings[field_num]], {});
                }
        }
}
 
Event.observe(window, 'load', attachAutocompleteToAllDocumentFields);
 
END;
 
        //Send the autocomplete values to the browser, along with the mappings of which values should apply to which fields
        foreach ($autocomplete_value_array as $autocomplete_key => $autocomplete_string)
        {
                if ($autocomplete_key == "mappings")
                {
                        foreach ($autocomplete_string as $field_number => $field_key)
                        {
                                $javascript_text .= "autocompletemappings[$field_number] = '" . str_replace("'", "\'", $field_key) . "';\n";
                        }
                }
                else
                {
                        $javascript_text .= "autocompletestrings['" . str_replace("'", "\'", $autocomplete_key) . "'] = $autocomplete_string;\n";
                }
        }
    return array($form_text, $javascript_text, $title, $data_text);
  }
 
  function formTemplateFieldHTML($field_name, $input_name, $part_of_multiple, $cur_value, $is_mandatory, $is_hidden, $is_restricted, $input_type, $size, $num_rows, $num_cols, $no_autocomplete, $autocomplete_category, $all_fields, $strict_parsing, &$out_autocomplete_values) {
   global $gTabIndex;
 
    // see if this field matches one of the fields defined for this template -
    // if it is, use all available information about that field; if it's not,
    // either include it in the form or not, depending on whether template
    // has 'strict' setting in the form definition
    $the_field = null;
    foreach ($all_fields as $cur_field) {
      if ($field_name == $cur_field->field_name) {
        $the_field = $cur_field;
        break;
      }
    }
    if ($the_field == null) {
      if ($strict_parsing)
        return null;
      $the_field = new SFTemplateField();
    }
 
    // if this is not part of a 'multiple' template, incrememt the
    // global tab index (used for correct tabbing, and for creating
    // unique div IDs.)
    if (! $part_of_multiple)
      $gTabIndex++;
 
    // populate field object with settings from the form definition file
    $the_field->is_mandatory = $is_mandatory;
    $the_field->is_hidden = $is_hidden;
    $the_field->is_restricted = $is_restricted;
    $the_field->input_type = $input_type;
    $the_field->size = $size;
    $the_field->num_rows = $num_rows;
    $the_field->num_cols = $num_cols;
    $the_field->no_autocomplete = $no_autocomplete;
    $the_field->autocomplete_category = $autocomplete_category;
    $the_field->input_name = $input_name;
    $the_field->part_of_multiple = $part_of_multiple;
    $text = SFFormPrinter::formFieldHTML($the_field, $cur_value, $out_autocomplete_values);
    return $text;
  }
 
  function formFieldHTML($template_field, $cur_value, &$out_autocomplete_values) {
    global $smwgContLang;
        //When a field is generated that requires autocomplete, the autocomplete string will be added to out_autocomplete_values. Then, at the end,
        //Javascript will be generated to activate autocomplete field at once.
 
    if ($template_field->is_hidden) {
      $text = SFFormPrinter::hiddenFieldHTML($template_field->input_name, $cur_value);
    } elseif ($template_field->autocomplete_category != null) {
      $size = $template_field->size;
      if ($size == null) $size = 35;
      $text = SFFormPrinter::textEntryWithAutocompleteHTML($size, $template_field->input_name, $template_field->part_of_multiple, $template_field->autocomplete_category, false, $cur_value, $out_autocomplete_values);
    } elseif ($template_field->input_type == 'text') {
      $size = $template_field->size;
      if ($size == null) $size = 35;
      $text = SFFormPrinter::textEntryHTML($size, $template_field->input_name, $cur_value);
    } elseif ($template_field->input_type == 'textarea') {
      $num_rows = $template_field->num_rows;
      if ($num_rows == null) $num_rows = 4;
      $num_cols = $template_field->num_cols;
      if ($num_cols == null) $num_cols = 40;
      $text = SFFormPrinter::textAreaHTML($num_rows, $num_cols, $template_field->input_name, $cur_value);
    } elseif ($template_field->input_type == 'date') {
      $text = SFFormPrinter::dateEntryHTML($template_field->input_name, $cur_value);
        } elseif ($template_field->input_type == 'coordinatesmap') {
      $text = SFFormPrinter::coordinatesmapEntryHTML($template_field->input_name, $cur_value);  
    } elseif ($template_field->input_type == 'checkbox') {
      $text = SFFormPrinter::checkboxHTML($template_field->input_name, $cur_value);
    } elseif ($template_field->attr_or_rel == "relation") {
      $size = $template_field->size;
      if ($size == null) $size = 35;
      if ($template_field->no_autocomplete) {
        $text = SFFormPrinter::textEntryHTML($size, $template_field->input_name, $cur_value);
      } else {
        $text = SFFormPrinter::textEntryWithAutocompleteHTML($size, $template_field->input_name, $template_field->part_of_multiple, $template_field->semantic_field, true, $cur_value, $out_autocomplete_values);
      }
    } else { // input type not defined in form, and not a relation
      $attr_type = $template_field->attribute_type;
      $size = $template_field->size;
      if ($attr_type == $smwgContLang->smwDatatypeLabels['smw_enum']) {
        // prepend the "None" option if it's not a mandatory field
        $include_none = ! $template_field->is_mandatory;
        $text = SFFormPrinter::dropdownHTML($template_field->input_name, $template_field->possible_values, $include_none, $cur_value);
      } elseif ($attr_type == $smwgContLang->smwDatatypeLabels['smw_datetime']) {
        $text = SFFormPrinter::dateEntryHTML($template_field->input_name, $cur_value);
      } elseif ($attr_type == $smwgContLang->smwDatatypeLabels['smw_float'] || $attr_type == $smwgContLang->smwDatatypeLabels['smw_int']) {
        if ($size == null) $size = 10;
        $text = SFFormPrinter::textEntryHTML($size, $template_field->input_name, $cur_value);
      } elseif ($attr_type == $smwgContLang->smwDatatypeLabels['smw_url']) {
        if ($size == null) $size = 100;
        $text = SFFormPrinter::textEntryHTML($size, $template_field->input_name, $cur_value);
      } elseif ($attr_type == $smwgContLang->smwDatatypeLabels['smw_bool']) {
        $text = SFFormPrinter::checkboxHTML($template_field->input_name, $cur_value);
      } else { // String or anything else
        if ($size == null) $size = 35;
        $text = SFFormPrinter::textEntryHTML($size, $template_field->input_name, $cur_value);
      }
    }
    return $text;
  }
 
  function createAutocompleteValuesString($field_name, $is_relation) {
    global $sfgMaxAutocompleteValues;
    $fname = 'SFFormPrinter::createAutocompleteValuesString';
    $db = & wfGetDB( DB_SLAVE );
    $sql_options = array();
    $sql_options['LIMIT'] = $sfgMaxAutocompleteValues;
    // the query depends on whether this field is a relation or a category
    if ($is_relation) {
      $conditions = "relation_title = '$field_name'";
      $sql_options['ORDER BY'] = 'object_title';
      $res = $db->select( $db->tableName('smw_relations'),
                          'DISTINCT object_title',
                          $conditions, $fname, $sql_options);
    } else {
      $conditions = "cl_from = page_id AND cl_to = '$field_name'";
      $sql_options['ORDER BY'] = 'page_title';
      $res = $db->select( $db->tableNames('categorylinks', 'page'),
                          'page_title',
                          $conditions, $fname, $sql_options);
    }
    if ($db->numRows( $res ) > 0) {
      $names_array = array();
      while ($row = $db->fetchRow($res)) {
        $cur_value = str_replace("'", "\'", $row[0]);
        $names_array[] = str_replace('_', ' ', $cur_value);
      }
      $array_str = "['" . implode("', '", $names_array) . "']";
    }
    $db->freeResult($res);
    return $array_str;
  }
 
  function textEntryHTML($size, $input_name, $cur_value) {
    global $gTabIndex, $gDisabledText;
    $input_id = "input_$gTabIndex";
    $info_id = "info_$gTabIndex";
 
    $text =<<<END
                <input id="$input_id" tabindex="$gTabIndex" class="createboxInput" name="$input_name" type="text"
        value="$cur_value" size="$size" $gDisabledText/>
        <span id="$info_id" class="error_message"></span>
 
END;
    return $text;
  }
 
  function dropdownHTML($input_name, $possible_values, $include_none, $cur_value) {
    global $gTabIndex, $gDisabledText;
 
    $text = '     <select tabindex="' . $gTabIndex . '" name="' . $input_name . '" ' . $gDisabledText . '>';
    if ($include_none)
      $text .= "  <option value=\"\">[None]</option>\n";
    foreach ($possible_values as $possible_value) {
      $text .= "  <option value=\"$possible_value\"";
      if ($possible_value == $cur_value) {$text .= " selected=\"selected\""; }
      $text .= ">$possible_value</option>\n";
    }
    $text .=<<<END
        </select>
        <span id="$info_id" class="error_message"></span>
 
END;
    return $text;
  }
 
  function textEntryWithAutocompleteHTML($size, $input_name, $part_of_multiple, $semantic_field_name, $is_relation, $cur_value, &$out_autocomplete_values) {
    global $gTabIndex, $gDisabledText;
    $gTabIndex++;
 
    $input_id = "input_" . $gTabIndex;
    $info_id = "info_" . $gTabIndex;
    $div_name = "div_" . $gTabIndex;
    $text =<<<END
        <input tabindex="$gTabIndex" id="$input_id" name="$input_name" type="text"
        value="" size="$size" $gDisabledText/>
        <span id="$info_id" class="error_message"></span>
        <div class="page_name_auto_complete" id="$div_name" style="display:none"></div>
<script type="text/javascript">
 
END;
        $options_str_key = $semantic_field_name . ',' . $is_relation;
        if (!$out_autocomplete_values[$options_str_key])
                $out_autocomplete_values[$options_str_key] = SFFormPrinter::createAutocompleteValuesString(str_replace(' ', '_', $semantic_field_name), $is_relation);
        $out_autocomplete_values['mappings'][$gTabIndex] = $options_str_key;
    if ($cur_value) {
      $text .= "document.getElementById('$input_id').value = \"$cur_value\"\n";
    }
    $text .= "</script>\n";
    return $text;
  }
 
  function textAreaHTML($rows, $cols, $input_name, $cur_value) {
    global $gTabIndex, $gDisabledText;
    $input_id = "input_$gTabIndex";
    $info_id = "info_$gTabIndex";
 
    $text =<<<END
        <textarea tabindex="$gTabIndex" id="$input_id" name="$input_name" rows=$rows cols=$cols $gDisabledText/>$cur_value</textarea>
        <span id="$info_id" class="error_message"></span>
 
END;
    return $text;
  }
 
  function monthDropdownHTML($cur_month, $input_name) {
    global $gTabIndex, $gDisabledText;
 
    $text = '   <select tabindex="' . $gTabIndex . '" id="input_' . $gTabIndex . '" name="' . $input_name . "[month]\" $gDisabledText>\n";
    $month_names = array(
      wfMsgForContent('sf_january'),
      wfMsgForContent('sf_february'),
      wfMsgForContent('sf_march'),
      wfMsgForContent('sf_april'),
      wfMsgForContent('sf_may'),
      wfMsgForContent('sf_june'),
      wfMsgForContent('sf_july'),
      wfMsgForContent('sf_august'),
      wfMsgForContent('sf_september'),
      wfMsgForContent('sf_october'),
      wfMsgForContent('sf_november'),
      wfMsgForContent('sf_december')
    );
    foreach ($month_names as $name) {
      $text .= "        <option value=\"$name\"";
      if ($name == $cur_month) {$text .= " selected=\"selected\""; }
      $text .= ">$name</option>\n";
    }
    $text .= "  </select>\n";
    return $text;
  }
 
  function dateEntryHTML($input_name, $date) {
    global $gTabIndex, $gDisabledText;
 
    if ($date) {
      // can show up here either as an array or a string, depending on
      // whether it came from user input or a wiki page
      if (is_array($date)) {
        $year = $date['year'];
        $month = $date['month'];
        $day = $date['day'];
      } else {
        $actual_date = strtotime($date);
        $year = date("Y", $actual_date);
        $month = date("F", $actual_date);
        $day = date("j", $actual_date);
      }
    } else {
      $cur_date = getdate();
      $year = $cur_date[year];
      $month = $cur_date[month];
      $day = null; // no need for day
    }
    $text .= SFFormPrinter::monthDropdownHTML($month, $input_name);
    $text .= '  <input tabindex="' . $gTabIndex . '" id="input_' . $gTabIndex . '" name="' . $input_name . '[day]" type="text" value="' . $day . '" size="2"/ ' . $gDisabledText . '>' . "\n";
    $text .= '  <input tabindex="' . $gTabIndex . '" id="input_' . $gTabIndex . '" name="' . $input_name . '[year]" type="text" value="' . $year . '" size="4"/ ' . $gDisabledText . '>' . "\n";
    $info_id = "info_$gTabIndex";
    $text .= "  <span id=\"$info_id\" class=\"error_message\"></span>";
    return $text;
  }
 
  function ConvertCoordinates($format,$coordinates) {  
 
        $coordinates = preg_split("/,/", $coordinates);
 
        switch ($format) {
                case 'lat':
                        $lat = floatval($coordinates[0]);
                        if (preg_match("/S/",$coordinates[0])) {$lat *= -1;}
                        return $lat;
                case 'lon':
                        $lon = floatval($coordinates[1]);
                        if (preg_match("/W/",$coordinates[1])) {$lon *= -1;}
                        return $lon;
        }               
 
}
 
function coordinatesmapEntryHTML($input_name, $coordinates) {
    global $gTabIndex, $gDisabledText, $wgJsMimeType, $wgGoogleMapsKey;;
 
    if ($coordinates) {
      // can show up here either as an array or a string, depending on
      // whether it came from user input or a wiki page
      if (is_array($coordinates)) {
                $flat = 666; // todo if relevant
                $flon = 666;        
      } else {
        $flat = SFFormPrinter::ConvertCoordinates('lat',$coordinates);
                $flon = SFFormPrinter::ConvertCoordinates('lon',$coordinates);
      }
    }
 
                $wgGoogleMapsOnThisPage = 66;
                $width = '200';
                $height = '200';
                $class = 'smwf_map';
                $zoom = '16';
                $type = 'G_HYBRID_MAP';
                $controls = 'GSmallMapControl';
                if ($flat == 0) { $lat = '50';} else {$lat = $flat;}
                if ($flon == 0) { $lon = '5';} else {$lon = $flon;}
 
                // input field
                $text .= '  <input tabindex="' . $gTabIndex . '" id="input_' . $gTabIndex . '" name="' . $input_name . '[coordinates]" type="text" value="';
                if (!$flat == 0 && !$flat == 0) { $text .= $flat . ',' . $flon; }
                $text .= '" size="40"/ ' . $gDisabledText . '>' . "\n";
        $info_id = "info_$gTabIndex";
                $text .= "      <span id=\"$info_id\" class=\"error_message\"></span>";
 
                // map div
                $text .= '<div id="map'.$wgGoogleMapsOnThisPage.'" class="'.$class.'" ';
                $text .= 'style="';
                if ($width) {$text .= 'width: '.$width.'px; '; }
                if ($height) {$text .= 'height: '.$height.'px; ';}
                $text .= $style.'" ></div>';
 
                //geocoder html
                $text .= '
     <p>        
        <input size="60" id= "geocode" name="geocode" value="Stationstraat 3 Maastricht Netherlands" type="text">
        <a href="#" onClick="showAddress(document.forms[0].geocode.value); return false">Lookup coordinates</a> 
     </p>
   <br />';
 
                // map javascript
                $text .= '<script src="http://maps.google.com/maps?file=api&v=2&key='.$wgGoogleMapsKey.'" type="'.$wgJsMimeType.'"></script>';
                $text .= "<script type=\"text/javascript\">
function showAddress(address) {
        makeMap{$wgGoogleMapsOnThisPage}();
        if (geocoder) {
        geocoder.getLatLng(
          address,
          function(point) {
            if (!point) {
              alert(address + \" not found\");
            } else {
                                map.clearOverlays()
                                map.setCenter(point, 14);
                        var marker = new GMarker(point);  
                        map.addOverlay(marker);
                                document.getElementById(\"input_" . $gTabIndex . "\").value = convertLatToDMS(point.y)+', '+convertLngToDMS(point.x);
          }
          }
        );
      }
    }           
function convertLatToDMS (val) {
  if (val < 0) {
    return Math.abs(val) + \"\u00B0 \" + \"S\";
  } else {
    return Math.abs(val) + \"\u00B0 \" + \"N\";
  }
}
 
function convertLngToDMS (val) {
  if (val < 0) {
    return Math.abs(val) + \"\u00B0 \" + \"W\";
  } else {
    return Math.abs(val) + \"\u00B0 \" + \"E\";
  }
} function addLoadEvent(func) {  var oldonload = window.onload;  if (typeof oldonload == 'function') {  window.onload = function() {  oldonload();  func();  };  } else {  window.onload = func;  }  }  window.unload = GUnload;</script>";
 
                $text .= "<script type=\"text/javascript\"> function makeMap{$wgGoogleMapsOnThisPage}() { if (GBrowserIsCompatible()) {window.map = new GMap2(document.getElementById(\"map{$wgGoogleMapsOnThisPage}\")); geocoder = new GClientGeocoder(); map.addControl(new {$controls}()); map.addControl(new GMapTypeControl()); map.setCenter(new GLatLng({$lat}, {$lon}), {$zoom}, {$type}); var point = new GLatLng({$lat}, {$lon}); var marker = new GMarker(point); map.addOverlay(marker); GEvent.addListener(map, \"click\", function(overlay, point) {      place = null;      if (overlay) {      map.removeOverlay (overlay);      } else {        var marker = new GMarker (point);        map.clearOverlays();        document.getElementById(\"input_" . $gTabIndex . "\").value = convertLatToDMS(point.y)+', '+convertLngToDMS(point.x);      map.addOverlay(marker);        map.panTo(point);      }    });  } else { document.write('should show map'); } } addLoadEvent(makeMap{$wgGoogleMapsOnThisPage});</script>";
 
 
    return $text;
  }
 
  function radioButtonHTML($input_name, $cur_value, $options_array) {
    global $gTabIndex, $gDisabledText;
 
    if ($title)
      $text .= "     <strong>$title:</strong>\n";
    foreach ($options_array as $i => $option) {
      $text .= '        <input type="radio" tabindex="' . $gTabIndex . '" name="' . $input_name . '" value="' . $option . '"';
      if ($cur_value == $option || (! $cur_value && $i == 0))
        $text .= " checked";
      $text .= " $gDisabledText/> $option\n";
    }
    return $text;
  }
 
  function checkboxHTML($input_name, $cur_value) {
    global $gTabIndex, $gDisabledText;
    $info_id = "info_$gTabIndex";
 
    // can show up here either as an array or a string, depending on
    // whether it came from user input or a wiki page
    if (is_array($cur_value)) {
      $checked_str = ($cur_value[value] == 'on') ? " checked" : "";
    } else {
      // default to false - no need to check if it matches a 'false' word
      $vlc = strtolower(trim($cur_value));
      if (in_array($vlc, explode(',', wfMsgForContent('smw_true_words')), TRUE)) {
        $checked_str = " checked";
      } else {
        $checked_str = "";
      }
    }
    $text =<<<END
        <input name="{$input_name}[is_checkbox]" type="hidden" value="true" />
        <input id="input_$gTabIndex" name="{$input_name}[value]" type="checkbox" tabindex="$gTabIndex " $checked_str $gDisabledText/>
        <span id="$info_id" class="error_message"></span>
 
END;
    return $text;
  }
 
  function hiddenFieldHTML($input_name, $cur_value) {
    $text =<<<END
        <input type="hidden" name="$input_name" value="$cur_value" />
 
END;
    return $text;
  }
 
  function redirectText($page_name, $data_text) {
    global $wgUser, $wgRequest;
 
    // first, add various hidden fields that allow for editing
    $title = Title::newFromText($page_name);
    $article = new Article($title);
    $starttime = wfTimestampNow();
    $edittime = $article->getTimestamp();
    if ( $wgUser->isLoggedIn() )
      $token = htmlspecialchars($wgUser->editToken());
    else
      $token = "";
    if ($wgRequest->getCheck('wpSave'))
      $page_action = "wpSave";
    elseif ($wgRequest->getVal('wpPreview'))
      $page_action = "wpPreview";
    else # if $wgRequest->getVal('wpDiff')
      $page_action = "wpDiff";
 
    global $wgScript;
    $encoded_page_name = urlencode($page_name);
    $text = <<<END
        <form id="editform" name="editform" method="post" action="$wgScript?title=$encoded_page_name&amp;action=submit">
        <input type="hidden" name="wpTextbox1" id="wpTextbox1" value="$data_text" />
    <input type="hidden" name="wpStarttime" value="$starttime" />
    <input type="hidden" name="wpEdittime" value="$edittime" />
    <input type="hidden" name="wpEditToken" value="$token" />
    <input type="hidden" name="wpSummary" value="{$wgRequest->getVal('wpSummary')}" />
 
END;
    if ($wgRequest->getCheck('wpMinoredit'))
      $text .= '    <input type="hidden" name="wpMinoredit">' . "\n";
    if ($wgRequest->getCheck('wpWatchthis'))
      $text .= '    <input type="hidden" name="wpWatchthis">' . "\n";
 
    $text .= <<<END
    <input type="hidden" name="$page_action" />
        </form>
        <script type="text/javascript">
        document.editform.submit();
        </script>
 
END;
    return $text;
  }
 
  // Much of this function is based on MediaWiki's EditPage::showEditForm()
  function formBottom($target_title = null) {
    global $wgVersion, $wgUser, $wgRightsText, $wgParser;
    global $gTabIndex, $gDisabledText;
    $sk = $wgUser->getSkin();
 
    $copywarn = "<div id=\"editpage-copywarn\">\n" .
      wfMsg( $wgRightsText ? 'copyrightwarning' : 'copyrightwarning2',
             '[[' . wfMsgForContent( 'copyrightpage' ) . ']]',
             null,
             $wgRightsText ) . "\n</div>";
    $title = new Title();
    $options = new ParserOptions();
    $copywarn_output = $wgParser->parse($copywarn, $title, $options);
    $copywarn_text = $copywarn_output->getText();
    $summary_text = wfMsg('summary');
    if ($target_title == null)
      $cancel = '';
    else
      $cancel = $sk->makeKnownLink( $target_title->getPrefixedText(),
                  wfMsgExt('cancel', array('parseinline')) );
 
        //Fix so extension works with MediaWiki 1.7
        if (substr_compare($wgVersion, '1.7', 0, 3) == 0)
        {
                $edithelpurl = $sk->makeInternalOrExternalUrl( wfMsgForContent( 'edithelppage' ));
        }
        else
        {
                $edithelpurl = Skin::makeInternalOrExternalUrl( wfMsgForContent( 'edithelppage' ));
        }
 
    $edithelp = '<a target="helpwindow" href="'.$edithelpurl.'">'.
    htmlspecialchars( wfMsg( 'edithelp' ) ).'</a> '.
    htmlspecialchars( wfMsg( 'newwindow' ) );
 
    $gTabIndex++;
    $text =<<<END
        $copywarn_text
        <span id='wpSummaryLabel'><label for='wpSummary'>{$summary_text}:</label></span>
        <div class='editOptions'>
        <input tabindex="$gTabIndex" type='text' value="" name='wpSummary' id='wpSummary' maxlength='200' size='60' $gDisabledText/><br />
 
END;
    $minor   = wfMsgExt('minoredit', array('parseinline'));
    if ( $wgUser->isAllowed('minoredit') ) {
      $gTabIndex++;
      $text .=
        "<input tabindex='$gTabIndex' type='checkbox' value='1' name='wpMinoredit'" .
        " accesskey='".wfMsg('accesskey-minoredit')."' id='wpMinoredit' $gDisabledText/>\n".
        "<label for='wpMinoredit' title='".wfMsg('tooltip-minoredit')."'>{$minor}</label>\n";
     }
 
    $watchthis = wfMsgExt('watchthis', array('parseinline'));
    if ( $wgUser->isLoggedIn() ) {
      $gTabIndex++;
      $text .= "<input tabindex='$gTabIndex' type='checkbox' name='wpWatchthis'".
        " accesskey=\"".htmlspecialchars(wfMsg('accesskey-watch'))."\" id='wpWatchthis' $gDisabledText/>\n".
        "<label for='wpWatchthis' title=\"" .
        htmlspecialchars(wfMsg('tooltip-watch'))."\">{$watchthis}</label>\n";
    }
 
    $gTabIndex++;
    $temp = array(
      'id'        => 'wpSave',
      'name'      => 'wpSave',
      'type'      => 'submit',
      'tabindex'  => $gTabIndex,
      'value'     => wfMsg('savearticle'),
      'accesskey' => wfMsg('accesskey-save'),
      'title'     => wfMsg('tooltip-save'),
      $gDisabledText => '',
    );
    $save_button = wfElement('input', $temp, '');
 
    $gTabIndex++;
    $temp = array(
      'id'        => 'wpPreview',
      'name'      => 'wpPreview',
      'type'      => 'submit',
      'tabindex'  => $gTabIndex,
      'value'     => wfMsg('showpreview'),
      'accesskey' => wfMsg('accesskey-preview'),
      'title'     => wfMsg('tooltip-preview'),
      $gDisabledText => '',
    );
    $preview_button = wfElement('input', $temp, '');
 
    $gTabIndex++;
    $temp = array(
      'id'        => 'wpDiff',
      'name'      => 'wpDiff',
      'type'      => 'submit',
      'tabindex'  => $gTabIndex,
      'value'     => wfMsg('showdiff'),
      'accesskey' => wfMsg('accesskey-diff'),
      'title'     => wfMsg('tooltip-diff'),
      $gDisabledText => '',
    );
    $diff_button = wfElement('input', $temp, '');
 
    $text .=<<<END
        <br />
        <div class='editButtons'>
                $save_button
                $preview_button
                $diff_button
                <span class='editHelp'>{$cancel} | {$edithelp}</span>
        </div><!-- editButtons -->
        </div><!-- editOptions -->
        </form>
 
END;
    return $text;
  }
 
  // based on MediaWiki's EditPage::getPreloadedText()
  function getPreloadedText($preload) {
    if ( $preload === '' )
       return '';
    else {
      $preloadTitle = Title::newFromText( $preload );
        if ( isset( $preloadTitle ) && $preloadTitle->userCanRead() ) {
          $rev=Revision::newFromTitle($preloadTitle);
        if ( is_object( $rev ) ) {
          $text = $rev->getText();
          // Remove <noinclude> sections and <includeonly> tags from text
          $text = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $text);
          $text = strtr($text, array('<includeonly>' => '', '</includeonly>' => ''));
          return $text;
        } else
          return '';
        }
     }
  } 
 
}
 
?>
Personal tools
Namespaces

Variants
Actions
Navigation
Support
Download
Development
Communication
Print/export
Toolbox