public static function monthDropdownHTML($cur_month, $input_name, $is_disabled) { global $sfgTabIndex, $wgAmericanDates; $optionsText = ''; $month_names = SFFormUtils::getMonthNames(); // Add a "null" value at the beginning. array_unshift($month_names, null); foreach ($month_names as $i => $name) { if (is_null($name)) { $month_value = null; } else { // Pad out month to always be two digits. $month_value = $wgAmericanDates == true ? $name : str_pad($i, 2, '0', STR_PAD_LEFT); } $optionAttrs = array('value' => $month_value); if ($name == $cur_month || $i == $cur_month) { $optionAttrs['selected'] = 'selected'; } $optionsText .= Html::element('option', $optionAttrs, $name); } $selectAttrs = array('class' => 'monthInput', 'name' => $input_name . '[month]', 'tabindex' => $sfgTabIndex); if ($is_disabled) { $selectAttrs['disabled'] = 'disabled'; } $text = Html::rawElement('select', $selectAttrs, $optionsText); return $text; }
function doSpecialCreateForm($query) { global $wgOut, $wgRequest, $sfgScriptPath; $db = wfGetDB(DB_SLAVE); if (!is_null($query)) { $presetFormName = str_replace('_', ' ', $query); $wgOut->setPageTitle(wfMessage('sf-createform-with-name', $presetFormName)->text()); $form_name = $presetFormName; } else { $presetFormName = null; $form_name = $wgRequest->getVal('form_name'); } // Create Javascript to populate fields to let the user input // parameters for the field, based on the input type selected // in the dropdown. $url = Skin::makeSpecialUrl('CreateForm', "showinputtypeoptions=' + this.val() + '&formfield=' + this.attr('formfieldid') + '"); foreach ($wgRequest->getValues() as $param => $value) { $url .= '¶ms[' . Xml::escapeJsString($param) . ']=' . Xml::escapeJsString($value); } $wgOut->addModules('ext.semanticforms.collapsible'); $section_name_error_str = '<font color="red" id="section_error">' . wfMessage('sf_blank_error')->escaped() . '</font>'; $wgOut->addScript("<script>\njQuery.fn.displayInputParams = function() {\n\tinputParamsDiv = this.closest('.formField').find('.otherInputParams');\n\tjQuery.ajax({\n\t\turl: '{$url}',\n\t\tcontext: document.body,\n\t\tsuccess: function(data){\n\t\t\tinputParamsDiv.html(data);\n\t\t}\n\t});\n};\njQuery(document).ready(function() {\n\tjQuery('.inputTypeSelector').change( function() {\n\t\tjQuery(this).displayInputParams();\n\t});\n\tjQuery('#addsection').click( function(event) {\n\tif(jQuery('#sectionname').val() == '') {\n\t\t\tevent.preventDefault();\n\t\t\tjQuery('#section_error').remove();\n\t\t\tjQuery('<div/>').append('{$section_name_error_str}').appendTo('#sectionerror');\n\t}\n });\n});\n</script>"); // Get the names of all templates on this site. $all_templates = array(); $res = $db->select('page', 'page_title', array('page_namespace' => NS_TEMPLATE, 'page_is_redirect' => 0), __METHOD__, array('ORDER BY' => 'page_title')); if ($db->numRows($res) > 0) { while ($row = $db->fetchRow($res)) { $template_name = str_replace('_', ' ', $row[0]); $all_templates[] = $template_name; } } $deleted_template_loc = null; $deleted_section_loc = null; // To keep the templates and sections $form_items = array(); // Handle inputs. foreach ($wgRequest->getValues() as $var => $val) { # ignore variables that are not of the right form if (strpos($var, "_") != false) { # get the template declarations and work from there list($action, $id) = explode("_", $var, 2); if ($action == "template") { // If the button was pressed to remove // this template, just don't add it to // the array. if ($wgRequest->getVal("del_{$id}") != null) { $deleted_template_loc = $id; } else { $form_template = SFTemplateInForm::create($val, $wgRequest->getVal("label_{$id}"), $wgRequest->getVal("allow_multiple_{$id}")); $form_items[] = array('type' => 'template', 'name' => $form_template->getTemplateName(), 'item' => $form_template); } } elseif ($action == "section") { if ($wgRequest->getVal("delsection_{$id}") != null) { $deleted_section_loc = $id; } else { $form_section = SFPageSection::create($val); $form_items[] = array('type' => 'section', 'name' => $form_section->getSectionName(), 'item' => $form_section); } } } } if ($wgRequest->getVal('add_field') != null) { $form_template = SFTemplateInForm::create($wgRequest->getVal('new_template'), "", false); $template_loc = $wgRequest->getVal('before_template'); $template_count = 0; if ($template_loc === null) { $new_template_loc = 0; $template_loc = 0; } else { // Count the number of templates before the // location of the template to be added for ($i = 0; $i < $template_loc; $i++) { if ($form_items[$i]['type'] == 'template') { $template_count++; } } $new_template_loc = $template_count; } // @HACK - array_splice() doesn't work for objects, so // we have to first insert a stub element into the // array, then replace that with the actual object. array_splice($form_items, $template_loc, 0, "stub"); $form_items[$template_loc] = array('type' => 'template', 'name' => $form_template->getTemplateName(), 'item' => $form_template); } else { $template_loc = null; $new_template_loc = null; } if ($wgRequest->getVal('add_section') != null) { $form_section = SFPageSection::create($wgRequest->getVal('sectionname')); $section_loc = $wgRequest->getVal('before_section'); $section_count = 0; if ($section_loc === null) { $new_section_loc = 0; $section_loc = 0; } else { // Count the number of sections before the // location of the section to be added for ($i = 0; $i < $section_loc; $i++) { if ($form_items[$i]['type'] == 'section') { $section_count++; } } $new_section_loc = $section_count; } // The same used hack for templates array_splice($form_items, $section_loc, 0, "stub"); $form_items[$section_loc] = array('type' => 'section', 'name' => $form_section->getSectionName(), 'item' => $form_section); } else { $section_loc = null; $new_section_loc = null; } // Now cycle through the templates and fields, modifying each // one per the query variables. $templates = 0; $sections = 0; foreach ($form_items as $fi) { if ($fi['type'] == 'template') { foreach ($fi['item']->getFields() as $j => $field) { $old_i = SFFormUtils::getChangedIndex($templates, $new_template_loc, $deleted_template_loc); foreach ($wgRequest->getValues() as $key => $value) { if (($pos = strpos($key, '_' . $old_i . '_' . $j)) != false) { $paramName = substr($key, 0, $pos); // Spaces got replaced by // underlines in the query. $paramName = str_replace('_', ' ', $paramName); } else { continue; } if ($paramName == 'label') { $field->template_field->setLabel($value); } elseif ($paramName == 'input type') { $input_type = $wgRequest->getVal("input_type_" . $old_i . "_" . $j); if ($input_type == 'hidden') { $field->template_field->setInputType($input_type); $field->setIsHidden(true); } elseif (substr($input_type, 0, 1) == '.') { // It's the default input type - // don't do anything. } else { $field->template_field->setInputType($input_type); } } else { if (!empty($value)) { if ($value == 'on') { $value = true; } $field->setFieldArg($paramName, $value); } } } } $templates++; } elseif ($fi['type'] == 'section') { $section = $fi['item']; $old_i = SFFormUtils::getChangedIndex($sections, $new_section_loc, $deleted_section_loc); foreach ($wgRequest->getValues() as $key => $value) { if (($pos = strpos($key, '_section_' . $old_i)) != false) { $paramName = substr($key, 0, $pos); $paramName = str_replace('_', ' ', $paramName); } else { continue; } if (!empty($value)) { if ($value == 'on') { $value = true; } if ($paramName == 'level') { $section->setSectionLevel($value); } elseif ($paramName == 'hidden') { $section->setIsHidden($value); } elseif ($paramName == 'restricted') { $section->setIsRestricted($value); } elseif ($paramName == 'mandatory') { $section->setIsMandatory($value); } else { $section->setSectionArgs($paramName, $value); } } } $sections++; } } $form = SFForm::create($form_name, $form_items); // If a submit button was pressed, create the form-definition // file, then redirect. $save_page = $wgRequest->getCheck('wpSave'); $preview_page = $wgRequest->getCheck('wpPreview'); if ($save_page || $preview_page) { $validToken = $this->getUser()->matchEditToken($wgRequest->getVal('csrf'), 'CreateForm'); if (!$validToken) { $text = "This appears to be a cross-site request forgery; canceling save."; $wgOut->addHTML($text); return; } // Validate form name. if ($form->getFormName() == "") { $form_name_error_str = wfMessage('sf_blank_error')->text(); } else { // Redirect to wiki interface. $wgOut->setArticleBodyOnly(true); $title = Title::makeTitleSafe(SF_NS_FORM, $form->getFormName()); $full_text = $form->createMarkup(); $text = SFUtils::printRedirectForm($title, $full_text, "", $save_page, $preview_page, false, false, false, null, null); $wgOut->addHTML($text); return; } } $text = "\t" . '<form action="" method="post">' . "\n"; if (is_null($presetFormName)) { // Set 'title' field, in case there's no URL niceness $text .= Html::hidden('title', $this->getTitle()->getPrefixedText()); $text .= "\n\t<p>" . wfMessage('sf_createform_nameinput')->escaped() . ' ' . wfMessage('sf_createform_nameinputdesc')->escaped() . Html::input('form_name', $form_name, 'text', array('size' => 25)); if (!empty($form_name_error_str)) { $text .= "\t" . Html::element('font', array('color' => 'red'), $form_name_error_str); } $text .= "</p>\n"; } $text .= $form->creationHTML(); $text .= "<h2> " . wfMessage('sf_createform_addelements')->escaped() . " </h2>"; $text .= "\t<p>" . wfMessage('sf_createform_addtemplate')->escaped() . "\n"; $select_body = ""; foreach ($all_templates as $template) { $select_body .= "\t" . Html::element('option', array('value' => $template), $template) . "\n"; } $text .= "\t" . Html::rawElement('select', array('name' => 'new_template'), $select_body) . "\n"; // If a template has already been added, show a dropdown letting // the user choose where in the list to add a new dropdown. $select_body = ""; foreach ($form_items as $i => $fi) { if ($fi['type'] == 'template') { $option_str = wfMessage('sf_createform_template')->escaped(); } elseif ($fi['type'] == 'section') { $option_str = wfMessage('sf_createform_pagesection')->escaped(); } $option_str .= $fi['name']; $select_body .= "\t" . Html::element('option', array('value' => $i), $option_str) . "\n"; } $final_index = count($form_items); $at_end_msg = wfMessage('sf_createform_atend')->escaped(); $select_body .= "\t" . Html::element('option', array('value' => $final_index, 'selected' => 'selected'), $at_end_msg); // Selection for before which item this template should be placed if (count($form_items) > 0) { $text .= wfMessage('sf_createform_before')->escaped(); $text .= Html::rawElement('select', array('name' => 'before_template'), $select_body) . "\n"; } // Disable 'save' and 'preview' buttons if user has not yet // added any templates. $add_button_text = wfMessage('sf_createform_add')->text(); $text .= "\t" . Html::input('add_field', $add_button_text, 'submit') . "\n"; // The form HTML for page sections $text .= "</br></br>" . Html::rawElement('span', null, wfMessage('sf_createform_addsection')->text() . ":") . "\n"; $text .= Html::input('sectionname', '', 'text', array('size' => '30', 'placeholder' => wfMessage('sf_createform_sectionname')->text(), 'id' => 'sectionname')) . "\n"; // Selection for before which item this section should be placed if (count($form_items) > 0) { $text .= wfMessage('sf_createform_before')->escaped(); $text .= Html::rawElement('select', array('name' => 'before_section'), $select_body) . "\n"; } $add_section_text = wfMessage('sf_createform_addsection')->text(); $text .= "\t" . Html::input('add_section', $add_section_text, 'submit', array('id' => 'addsection')); $text .= "\n\t" . Html::rawElement('div', array('id' => 'sectionerror')); $text .= <<<END </p> \t<br /> END; $text .= "\t" . Html::hidden('csrf', $this->getUser()->getEditToken('CreateForm')) . "\n"; $saveAttrs = array('id' => 'wpSave'); if (count($form_items) == 0) { $saveAttrs['disabled'] = true; } $editButtonsText = "\t" . Html::input('wpSave', wfMessage('savearticle')->text(), 'submit', $saveAttrs) . "\n"; $previewAttrs = array('id' => 'wpPreview'); if (count($form_items) == 0) { $previewAttrs['disabled'] = true; } $editButtonsText .= "\t" . Html::input('wpPreview', wfMessage('preview')->text(), 'submit', $previewAttrs) . "\n"; $text .= "\t" . Html::rawElement('div', array('class' => 'editButtons'), Html::rawElement('p', array(), $editButtonsText) . "\n") . "\n"; // Explanatory message if buttons are disabled because no // templates have been added. if (count($form_items) == 0) { $text .= "\t" . Html::element('p', null, "(" . wfMessage('sf_createform_additembeforesave')->text() . ")"); } $text .= <<<END \t</form> END; $wgOut->addExtensionStyle($sfgScriptPath . "/skins/SemanticForms.css"); $wgOut->addHTML($text); //Don't submit the form if enter is pressed on a text input box or a select $wgOut->addScript('<script> jQuery("input,select").keypress(function(event) { return event.keyCode != 13; }); </script>'); }
static function printForm(&$form_name, &$target_name, $alt_forms = array(), $redirectOnError = false) { global $wgOut, $wgRequest, $wgUser, $sfgFormPrinter; // initialize some variables $target_title = null; $page_name_formula = null; $form_title = Title::makeTitleSafe(SF_NS_FORM, $form_name); // If the given form is not a valid title, bail out. if (!$form_title) { return 'sf_formedit_badurl'; } $form_article = new Article($form_title, 0); $form_definition = $form_article->getContent(); // If the form page is a redirect, use the other form // instead. if ($form_title->isRedirect()) { $form_title = Title::newFromRedirectRecurse($form_definition); $form_article = new Article($form_title, 0); $form_definition = $form_article->getContent(); } $form_definition = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $form_definition); if (is_null($target_name)) { $target_name = ''; } if ($target_name === '') { // parse the form to see if it has a 'page name' value set $matches; if (preg_match('/{{{info.*page name\\s*=\\s*(.*)}}}/m', $form_definition, $matches)) { $page_name_elements = SFUtils::getFormTagComponents($matches[1]); $page_name_formula = $page_name_elements[0]; } elseif (count($alt_forms) == 0) { return 'sf_formedit_badurl'; } } else { $target_title = Title::newFromText($target_name); if ($target_title && $target_title->exists()) { if ($wgRequest->getVal('query') == 'true') { $page_contents = null; //$page_is_source = false; } else { // If page already exists and 'redlink' // is in the query string, redirect to // the actual page, just like // MediaWiki does it. if ($wgRequest->getBool('redlink')) { $wgOut->redirect($target_title->getFullURL()); wfProfileOut(__METHOD__); return; } $target_article = new Article($target_title, 0); $page_contents = $target_article->getContent(); //$page_is_source = true; } } else { $target_name = str_replace('_', ' ', $target_name); } } if (!$form_title || !$form_title->exists()) { if (count($alt_forms) > 0) { $text = '<div class="infoMessage">' . wfMsg('sf_formedit_altformsonly') . ' ' . self::printAltFormsList($alt_forms, $form_name) . "</div>\n"; } else { $text = Html::rawElement('p', array('class' => 'error'), wfMsgExt('sf_formstart_badform', 'parseinline', SFUtils::linkText(SF_NS_FORM, $form_name))) . "\n"; } } elseif ($target_name === '' && $page_name_formula === '') { $text = Html::element('p', array('class' => 'error'), wfMsg('sf_formedit_badurl')) . "\n"; } else { $save_page = $wgRequest->getCheck('wpSave'); $preview_page = $wgRequest->getCheck('wpPreview'); $diff_page = $wgRequest->getCheck('wpDiff'); $form_submitted = $save_page || $preview_page || $diff_page; // get 'preload' query value, if it exists if (!$form_submitted) { if ($wgRequest->getCheck('preload')) { $page_is_source = true; $page_contents = SFFormUtils::getPreloadedText($wgRequest->getVal('preload')); } else { // let other extensions preload the page, if they want wfRunHooks('sfEditFormPreloadText', array(&$page_contents, $target_title, $form_title)); $page_is_source = $page_contents != null; } } else { $page_is_source = false; $page_contents = null; } list($form_text, $javascript_text, $data_text, $form_page_title, $generated_page_name) = $sfgFormPrinter->formHTML($form_definition, $form_submitted, $page_is_source, $form_article->getID(), $page_contents, $target_name, $page_name_formula); // Before we do anything else, set the form header // title - this needs to be done after formHTML() is // called, because otherwise it doesn't take hold // for some reason if the form is disabled. if (empty($target_title)) { $s = wfMsg('sf_formedit_createtitlenotarget', $form_title->getText()); } elseif ($target_title->exists()) { $s = wfMsg('sf_formedit_edittitle', $form_title->getText(), $target_title->getPrefixedText()); } else { $s = wfMsg('sf_formedit_createtitle', $form_title->getText(), $target_title->getPrefixedText()); } $wgOut->setPageTitle($s); if ($form_submitted) { if (!is_null($page_name_formula) && $page_name_formula !== '') { $target_name = $generated_page_name; // prepend a super-page, if one was specified if ($wgRequest->getCheck('super_page')) { $target_name = $wgRequest->getVal('super_page') . '/' . $target_name; } // prepend a namespace, if one was specified if ($wgRequest->getCheck('namespace')) { $target_name = $wgRequest->getVal('namespace') . ':' . $target_name; } // replace "unique number" tag with one // that won't get erased by the next line $target_name = preg_replace('/<unique number(.*)>/', '{num\\1}', $target_name, 1); // if any formula stuff is still in the // name after the parsing, just remove it $target_name = StringUtils::delimiterReplace('<', '>', '', $target_name); // now run the parser on it global $wgParser; // ...but first, replace spaces back // with underlines, in case a magic word // or parser function name contains // underlines - hopefully this won't // cause problems of its own $target_name = str_replace(' ', '_', $target_name); $target_name = $wgParser->preprocess($target_name, $wgOut->getTitle(), ParserOptions::newFromUser(null)); $title_number = ""; $isRandom = false; $randomNumHasPadding = false; $randomNumDigits = 6; if (strpos($target_name, '{num') !== false) { // Random number if (preg_match('/{num;random(;(0)?([1-9][0-9]*))?}/', $target_name, $matches)) { $isRandom = true; $randomNumHasPadding = array_key_exists(2, $matches); $randomNumDigits = array_key_exists(3, $matches) ? $matches[3] : $randomNumDigits; $title_number = self::makeRandomNumber($randomNumDigits, $randomNumHasPadding); } else { // get unique number start value // from target name; if it's not // there, or it's not a positive // number, start it out as blank preg_match('/{num.*start[_]*=[_]*([^;]*).*}/', $target_name, $matches); if (count($matches) == 2 && is_numeric($matches[1]) && $matches[1] >= 0) { // the "start" value" $title_number = $matches[1]; } } // set target title $target_title = Title::newFromText(preg_replace('/{num.*}/', $title_number, $target_name)); // if title exists already // cycle through numbers for // this tag until we find one // that gives a nonexistent page // title while ($target_title->exists()) { if ($isRandom) { $title_number = self::makeRandomNumber($randomNumDigits, $randomNumHasPadding); } elseif ($title_number == "") { $title_number = 2; } else { $title_number = str_pad($title_number + 1, strlen($title_number), '0', STR_PAD_LEFT); } $target_title = Title::newFromText(preg_replace('/{num.*}/', $title_number, $target_name)); } $target_name = $target_title->getPrefixedText(); } else { $target_title = Title::newFromText($target_name); } } if (is_null($target_title)) { if ($target_name) { return array('sf_formstart_badtitle', array($target_name)); } else { return 'sf_formedit_emptytitle'; } } if ($save_page) { $permErrors = $target_title->getUserPermissionsErrors('edit', $wgUser); if ($permErrors) { // just return the first error and let them fix it one by one return array_shift($permErrors); } // Set up all the variables for the // page save. $data = array('wpTextbox1' => $data_text, 'wpSummary' => $wgRequest->getVal('wpSummary'), 'wpStarttime' => $wgRequest->getVal('wpStarttime'), 'wpEdittime' => $wgRequest->getVal('wpEdittime'), 'wpEditToken' => $wgUser->isLoggedIn() ? $wgUser->editToken() : EDIT_TOKEN_SUFFIX, 'wpSave' => '', 'action' => 'submit'); if ($wgRequest->getCheck('wpMinoredit')) { $data['wpMinoredit'] = true; } if ($wgRequest->getCheck('wpWatchthis')) { $data['wpWatchthis'] = true; } $request = new FauxRequest($data, true); // Find existing article if it exists, // or create a new one. $article = new Article($target_title, 0); $editor = new EditPage($article); $editor->importFormData($request); // Try to save the page! $resultDetails = array(); $saveResult = $editor->internalAttemptSave($resultDetails); // Return value was made an object in MW 1.19 if (is_object($saveResult)) { $saveResultCode = $saveResult->value; } else { $saveResultCode = $saveResult; } if (($saveResultCode == EditPage::AS_HOOK_ERROR || $saveResultCode == EditPage::AS_HOOK_ERROR_EXPECTED) && $redirectOnError) { $wgOut->clearHTML(); $wgOut->setArticleBodyOnly(true); // Lets other code process additional form-definition syntax wfRunHooks('sfWritePageData', array($form_name, $target_title, &$data_text)); $text = SFUtils::printRedirectForm($target_title, $data_text, $wgRequest->getVal('wpSummary'), $save_page, $preview_page, $diff_page, $wgRequest->getCheck('wpMinoredit'), $wgRequest->getCheck('wpWatchthis'), $wgRequest->getVal('wpStarttime'), $wgRequest->getVal('wpEdittime')); } else { if ($saveResultCode == EditPage::AS_SUCCESS_UPDATE || $saveResultCode == EditPage::AS_SUCCESS_NEW_ARTICLE) { $wgOut->redirect($target_title->getFullURL()); } return SFUtils::processEditErrors($saveResultCode); } } else { // Lets other code process additional form-definition syntax wfRunHooks('sfWritePageData', array($form_name, $target_title, &$data_text)); $text = SFUtils::printRedirectForm($target_title, $data_text, $wgRequest->getVal('wpSummary'), $save_page, $preview_page, $diff_page, $wgRequest->getCheck('wpMinoredit'), $wgRequest->getCheck('wpWatchthis'), $wgRequest->getVal('wpStarttime'), $wgRequest->getVal('wpEdittime')); // extract its data } } else { // override the default title for this page if // a title was specified in the form if ($form_page_title != null) { if ($target_name === '') { $wgOut->setPageTitle($form_page_title); } else { $wgOut->setPageTitle("{$form_page_title}: {$target_title->getPrefixedText()}"); } } $text = ""; if (count($alt_forms) > 0) { $text .= '<div class="infoMessage">' . wfMsg('sf_formedit_altforms') . ' '; $text .= self::printAltFormsList($alt_forms, $target_name); $text .= "</div>\n"; } $text .= '<form name="createbox" id="sfForm" method="post" class="createbox">'; $pre_form_html = ''; wfRunHooks('sfHTMLBeforeForm', array(&$target_title, &$pre_form_html)); $text .= $pre_form_html; $text .= $form_text; } } SFUtils::addJavascriptAndCSS(); if (!empty($javascript_text)) { $wgOut->addScript(' <script type="text/javascript">' . "\n{$javascript_text}\n" . '</script>' . "\n"); } $wgOut->addHTML($text); return null; }
/** * This function is the real heart of the entire Semantic Forms * extension. It handles two main actions: (1) displaying a form on the * screen, given a form definition and possibly page contents (if an * existing page is being edited); and (2) creating actual page * contents, if the form was already submitted by the user. * * It also does some related tasks, like figuring out the page name (if * only a page formula exists). */ function formHTML($form_def, $form_submitted, $source_is_page, $form_id = null, $existing_page_content = null, $page_name = null, $page_name_formula = null, $is_query = false, $is_embedded = 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 // initialize some variables $wiki_page = new SFWikiPage(); $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 = ""; // 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 a hidden text field. if (!$wgRequest->getCheck('partial')) { $original_page_content = $existing_page_content; } else { $original_page_content = null; if ($wgRequest->getCheck('sf_free_text')) { if (!isset($existing_page_content) || $existing_page_content == '') { $existing_page_content = $wgRequest->getVal('sf_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 ($is_embedded) { // If this is an embedded form (probably a 'RunQuery'), // just use the name of the actual page we're on. global $wgTitle; $this->mPageTitle = $wgTitle; } elseif ($is_query) { // We're in Special:RunQuery - just use that as the // title. global $wgTitle; $this->mPageTitle = $wgTitle; } elseif ($page_name === '' || $page_name === null) { $this->mPageTitle = Title::newFromText($wgRequest->getVal('namespace') . ":Semantic Forms permissions test"); } else { $this->mPageTitle = Title::newFromText($page_name); } global $wgOut; // Show previous set of deletions for this page, if it's been // deleted before. if (!$form_submitted && ($this->mPageTitle && !$this->mPageTitle->exists() && is_null($page_name_formula))) { $this->showDeletionLog($wgOut); } // Unfortunately, we can't just call userCan() here because, // since MW 1.16, it has a bug in which it ignores a setting of // "$wgEmailConfirmToEdit = true;". Instead, we'll just get the // permission errors from the start, and use those to determine // whether the page is editable. if (!$is_query) { // $userCanEditPage = ( $wgUser->isAllowed( 'edit' ) && $this->mPageTitle->userCan( 'edit' ) ); $permissionErrors = $this->mPageTitle->getUserPermissionsErrors('edit', $wgUser); // The handling of $wgReadOnly and $wgReadOnlyFile // has to be done separately. if (wfReadOnly()) { $permissionErrors = array(array('readonlytext', array(wfReadOnlyReason()))); } $userCanEditPage = count($permissionErrors) == 0; Hooks::run('sfUserCanEditPage', array($this->mPageTitle, &$userCanEditPage)); } $form_text = ""; if ($is_query || $userCanEditPage) { $form_is_disabled = false; // Show "Your IP address will be recorded" warning if // user is anonymous, and it's not a query. if ($wgUser->isAnon() && !$is_query) { // Based on code in MediaWiki's EditPage.php. $anonEditWarning = wfMessage('anoneditwarning', '{{fullurl:Special:UserLogin|returnto={{FULLPAGENAMEE}}}}', '{{fullurl:Special:UserLogin/signup|returnto={{FULLPAGENAMEE}}}}')->parse(); $form_text .= Html::rawElement('div', array('id' => 'mw-anon-edit-warning', 'class' => 'warningbox'), $anonEditWarning); } } else { $form_is_disabled = true; $wgOut->setPageTitle(wfMessage('badaccess')->text()); $wgOut->addWikiText($wgOut->formatPermissionsErrorMessage($permissionErrors, 'edit')); $wgOut->addHTML("\n<hr />\n"); } // $oldParser = $wgParser; // $wgParser = unserialize( serialize( $oldParser ) ); // deep clone of parser if (!$wgParser->Options()) { $wgParser->Options(ParserOptions::newFromUser($wgUser)); } $wgParser->Title($this->mPageTitle); // This is needed in order to make sure $parser->mLinkHolders // is set. $wgParser->clearState(); $form_def = SFFormUtils::getFormDefinition($wgParser, $form_def, $form_id); // 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; // Unencode any 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 was needed // to make sure that those elements don't get parsed too early. $form_def = str_replace(array('{', '|', '}'), 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 = SFUtils::getFormTagComponents($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 the 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. $tif = null; // This array will keep track of all the replaced @<name>@ strings $placeholderFields = array(); for ($section_num = 0; $section_num < count($form_def_sections); $section_num++) { $start_position = 0; // 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 = SFUtils::getFormTagComponents($bracketed_string); $tag_title = trim($tag_components[0]); // ===================================================== // for template processing // ===================================================== if ($tag_title == 'for template') { if ($tif) { $previous_template_name = $tif->getTemplateName(); } else { $previous_template_name = ''; } $template_name = str_replace('_', ' ', $tag_components[1]); $is_new_template = $template_name != $previous_template_name; if ($is_new_template) { $tif = SFTemplateInForm::newFromFormTag($tag_components); } // Remove template tag. $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc); // 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. if ($source_is_page) { $tif->setPageRelatedInfo($existing_page_content); // Get the first instance of // this template on the page // being edited, even if there // are more. if ($tif->pageCallsThisTemplate()) { $tif->setFieldValuesFromPage($existing_page_content); $existing_template_text = $tif->getFullTextInPage(); // 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("\n" . '{{{insertionpoint}}}', '', $existing_page_content); $existing_page_content = str_replace($existing_template_text, '{{{insertionpoint}}}', $existing_page_content); } } else { $existing_page_content = $this->strReplaceFirst($existing_template_text, '', $existing_page_content); } // If 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. $source_page_matches_this_form = true; } } if ($form_submitted) { $tif->setFieldValuesFromSubmit(); } $tif->checkIfAllInstancesPrinted($form_submitted, $source_is_page); if (!$tif->allInstancesPrinted()) { $wiki_page->addTemplate($tif); } // ===================================================== // end template processing // ===================================================== } elseif ($tag_title == 'end template') { if ($source_is_page) { // Add any unhandled template fields // in the page as hidden variables. $form_text .= SFFormUtils::unhandledFieldsHTML($tif); } // Remove this tag from the $section variable. $section = substr_replace($section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc); $tif = null; // ===================================================== // field processing // ===================================================== } elseif ($tag_title == 'field') { // If the template is null, that (hopefully) // means we're handling the free text field. // Make the template a dummy variable. if ($tif == null) { $tif = new SFTemplateInForm(); } // We get the field name both here // and in the SFFormField constructor, // because SFFormField isn't equipped // to deal with the <freetext> hack, // among others. $field_name = trim($tag_components[1]); $form_field = SFFormField::newFromFormFieldTag($tag_components, $tif, $form_is_disabled); $cur_value = $form_field->getCurrentValue($tif->getValuesFromSubmit(), $form_submitted, $source_is_page); if ($form_field->holdsTemplate()) { $placeholderFields[] = self::placeholderFormat($tif->getTemplateName(), $field_name); } // 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 && ($tif->getFullTextInPage() != '' && !$form_submitted)) { if ($tif->hasValueFromPageForField($field_name)) { // Get value, and remove it, // so that at the end we // can have a list of all // the fields that weren't // handled by the form. $cur_value = $tif->getAndRemoveValueFromPageForField($field_name); // If the field is a placeholder, the contents of this template // parameter should be treated as elements parsed by an another // multiple template form. // By putting that at the very end of the parsed string, we'll // have it processed as a regular multiple template form. if ($form_field->holdsTemplate()) { $existing_page_content .= $cur_value; } } elseif (isset($cur_value) && !empty($cur_value)) { // Do nothing. } else { $cur_value = ''; } } // Handle the free text field. if ($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 ($form_field->isHidden()) { $new_text = Html::hidden('sf_free_text', '!free_text!'); } else { $sfgTabIndex++; $sfgFieldNum++; if ($cur_value === '' || is_null($cur_value)) { $default_value = '!free_text!'; } else { $default_value = $cur_value; } $new_text = SFTextAreaInput::getHTML($default_value, 'sf_free_text', false, $form_is_disabled || $form_field->isRestricted(), $form_field->getFieldArgs()); if ($form_field->hasFieldArg('edittools')) { // borrowed from EditPage::showEditTools() $edittools_text = $wgParser->recursiveTagParse(wfMessage('edittools', array('content'))->text()); $new_text .= <<<END \t\t<div class="mw-editTools"> \t\t{$edittools_text} \t\t</div> END; } } $free_text_was_included = true; $wiki_page->addFreeTextSection(); } if ($tif->getTemplateName() === '' || $field_name == '<freetext>') { $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc); } else { if (is_array($cur_value)) { // @TODO - is this code ever called? $delimiter = $form_field->getFieldArg('is_list'); // first, check if it's a list if (array_key_exists('is_list', $cur_value) && $cur_value['is_list'] == true) { $cur_value_in_template = ""; 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 { // If it's not a list, it's probably from a checkbox or date input - // convert the values into a string. $cur_value_in_template = self::getStringFromPassedInArray($cur_value, $delimiter); } } else { // value is not an array $cur_value_in_template = $cur_value; } // 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 to be unnecessary. // $generated_page_name = str_replace('.', '_', $generated_page_name); $generated_page_name = str_replace(' ', '_', $generated_page_name); $escaped_input_name = str_replace(' ', '_', $form_field->getInputName()); $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); } // Call hooks - unfortunately this has to be split into two // separate calls, because of the different variable names in // each case. if ($form_submitted) { Hooks::run('sfCreateFormField', array(&$form_field, &$cur_value_in_template, true)); } else { if (!empty($cur_value) && ($form_field->hasFieldArg('mapping template') || $form_field->hasFieldArg('mapping property') || $form_field->hasFieldArg('mapping cargo table') && $form_field->hasFieldArg('mapping cargo field'))) { $cur_value = SFUtils::valuesToLabels($cur_value, $delimiter, $form_field->getPossibleValues()); } Hooks::run('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 (!$form_field->hasFieldArg('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 ($form_field->getDefaultValue() == 'now' && ($cur_value == '' || $cur_value == 'now')) { $input_type = $form_field->getInputType(); if ($input_type == 'date' || $input_type == 'datetime' || $input_type == 'year' || $input_type == '' && $form_field->getTemplateField()->getPropertyType() == '_dat') { $cur_value_in_template = self::getStringForCurrentTime($input_type == 'datetime', $form_field->hasFieldArg('include 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 ($form_field->getDefaultValue() == 'current user' && ($cur_value === '' || $cur_value == 'current user')) { $cur_value_in_template = $wgUser->getName(); $cur_value = $cur_value_in_template; } // If all instances have been // printed, that means we're // now printing a "starter" // div - set the current value // to null. // (Ideally it wouldn't get // set at all, but that seems a // little harder.) if ($tif->allInstancesPrinted()) { $cur_value = null; } $new_text = $this->formFieldHTML($form_field, $cur_value); $new_text .= $form_field->additionalHTMLForInput($cur_value, $field_name, $tif->getTemplateName()); if ($new_text) { $wiki_page->addTemplateParam($template_name, $tif->getInstanceNum(), $field_name, $cur_value_in_template); $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc); } else { $start_position = $brackets_end_loc; } } // ===================================================== // standard input processing // ===================================================== } elseif ($tag_title == 'standard input') { // handle all the possible values $input_name = $tag_components[1]; $input_label = null; $attr = array(); // if it's a query, ignore all standard inputs except run query if ($is_query && $input_name != 'run query' || !$is_query && $input_name == 'run 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; // cycle through the other components $is_checked = false; for ($i = 2; $i < count($tag_components); $i++) { $component = $tag_components[$i]; $sub_components = array_map('trim', explode('=', $component)); if (count($sub_components) == 1) { if ($sub_components[0] == 'checked') { $is_checked = true; } } elseif (count($sub_components) == 2) { switch ($sub_components[0]) { case 'label': $input_label = $wgParser->recursiveTagParse($sub_components[1]); break; case 'class': case 'style': $attr[$sub_components[0]] = $sub_components[1]; break; } } } if ($input_name == 'summary') { $value = $wgRequest->getVal('wpSummary'); $new_text = SFFormUtils::summaryInputHTML($form_is_disabled, $input_label, $attr, $value); } elseif ($input_name == 'minor edit') { $is_checked = $wgRequest->getCheck('wpMinoredit'); $new_text = SFFormUtils::minorEditInputHTML($form_submitted, $form_is_disabled, $is_checked, $input_label, $attr); } elseif ($input_name == 'watch') { $is_checked = $wgRequest->getCheck('wpWatchthis'); $new_text = SFFormUtils::watchInputHTML($form_submitted, $form_is_disabled, $is_checked, $input_label, $attr); } elseif ($input_name == 'save') { $new_text = SFFormUtils::saveButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'save and continue') { $new_text = SFFormUtils::saveAndContinueButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'preview') { $new_text = SFFormUtils::showPreviewButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'changes') { $new_text = SFFormUtils::showChangesButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'cancel') { $new_text = SFFormUtils::cancelLinkHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'run query') { $new_text = SFFormUtils::runQueryButtonHTML($form_is_disabled, $input_label, $attr); } $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc); // ===================================================== // for section processing // ===================================================== } elseif ($tag_title == 'section') { $section_name = trim($tag_components[1]); $page_section_in_form = SFPageSection::newFromFormTag($tag_components); // Split the existing page contents into the textareas in the form. $default_value = ""; $section_start_loc = 0; if ($source_is_page && $existing_page_content !== null) { // For the last section of the page, there is no trailing newline in // $existing_page_content, but the code below expects it. This code // ensures that there is always trailing newline. T72202 if (substr($existing_page_content, -1) !== "\n") { $existing_page_content .= "\n"; } $equalsSigns = str_pad('', $page_section_in_form->getSectionLevel(), '='); $searchStr = '/^' . preg_quote($equalsSigns, '/') . '[ ]*?' . preg_quote($section_name, '/') . '[ ]*?' . preg_quote($equalsSigns, '/') . '$/m'; if (preg_match($searchStr, $existing_page_content, $matches, PREG_OFFSET_CAPTURE)) { $section_start_loc = $matches[0][1]; $header_text = $matches[0][0]; $existing_page_content = str_replace($header_text, '', $existing_page_content); } else { $section_start_loc = 0; } $section_end_loc = -1; // get the position of the next template or section defined in the form $next_section_start_loc = strpos($section, '{{{', $brackets_end_loc); if ($next_section_start_loc == false) { $section_end_loc = strpos($existing_page_content, '{{', $section_start_loc); } else { $next_section_end_loc = strpos($section, '}}}', $next_section_start_loc); $bracketed_string_next_section = substr($section, $next_section_start_loc + 3, $next_section_end_loc - ($next_section_start_loc + 3)); $tag_components_next_section = SFUtils::getFormTagComponents($bracketed_string_next_section); $tag_title_next_section = trim($tag_components_next_section[0]); if ($tag_title_next_section == 'section') { if (preg_match('/(^={1,6}[ ]*?' . $tag_components_next_section[1] . '[ ]*?={1,6}\\s*?$)/m', $existing_page_content, $matches, PREG_OFFSET_CAPTURE)) { $section_end_loc = $matches[0][1]; } } } if ($section_end_loc === -1) { $section_text = $existing_page_content; $existing_page_content = ''; } else { $section_text = substr($existing_page_content, $section_start_loc, $section_end_loc - $section_start_loc); $existing_page_content = substr($existing_page_content, $section_end_loc); } } // If input is from the form. if (!$source_is_page && $wgRequest) { $text_per_section = $wgRequest->getArray('_section'); $section_text = $text_per_section[trim($section_name)]; $wiki_page->addSection($section_name, $page_section_in_form->getSectionLevel(), $section_text); } $section_text = trim($section_text); // Set input name for query string. $input_name = '_section' . '[' . trim($section_name) . ']'; $other_args = $page_section_in_form->getSectionArgs(); $other_args['isSection'] = true; if ($page_section_in_form->isMandatory()) { $other_args['mandatory'] = true; } if ($page_section_in_form->isHidden()) { $form_section_text = Html::hidden($input_name, $section_text); } else { $form_section_text = SFTextAreaInput::getHTML($section_text, $input_name, false, $form_is_disabled || $page_section_in_form->isRestricted(), $other_args); } $section = substr_replace($section, $form_section_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 = array_map('trim', explode('=', $component, 2)); // Tag names are case-insensitive $tag = strtolower($sub_components[0]); if ($tag == 'create title' || $tag == 'add title') { // Handle this only if // we're adding a page. if (!$is_query && !$this->mPageTitle->exists()) { $form_page_title = $sub_components[1]; } } elseif ($tag == 'edit title') { // Handle this only if // we're editing a page. if (!$is_query && $this->mPageTitle->exists()) { $form_page_title = $sub_components[1]; } } elseif ($tag == 'query title') { // Handle this only if // we're in 'RunQuery'. if ($is_query) { $form_page_title = $sub_components[1]; } } 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') { $wiki_page->makeFreeTextOnlyInclude(); } elseif ($tag == 'query form at top') { // TODO - this should be made a field of // some non-static class that actually // prints the form, instead of requiring // a global variable. global $sfgRunQueryFormAtTop; $sfgRunQueryFormAtTop = 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 the tag. $start_position = $brackets_end_loc; } // end if } // end while if ($tif && (!$tif->allowsMultiple() || $tif->allInstancesPrinted())) { $template_text = $wiki_page->createTemplateCallsForTemplateName($tif->getTemplateName()); // 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', '}�', preg_replace('/\\{\\{/m', '�{', $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', '}�', preg_replace('/\\{\\{/m', '�{', $template_text)) . "{{{insertionpoint}}}" . $existing_page_content; } } if ($tif && $tif->allowsMultiple()) { if ($tif->getInstanceNum() == 0) { $multipleTemplateHTML = $this->multipleTemplateStartHTML($tif); } else { $multipleTemplateHTML = ''; } if (!$tif->allInstancesPrinted()) { $multipleTemplateHTML .= $this->multipleTemplateInstanceHTML($tif, $form_is_disabled, $section); } else { $multipleTemplateHTML .= $this->multipleTemplateEndHTML($tif, $form_is_disabled, $section); } $placeholder = $tif->getPlaceholder(); if ($placeholder != null) { $multipleTemplateHTML .= self::makePlaceholderInFormHTML($placeholder); } if ($tif->allInstancesPrinted() && $tif->getLabel() != null) { $multipleTemplateHTML .= "</fieldset>\n"; } if ($placeholder == null) { // The normal process. $form_text .= $multipleTemplateHTML; } else { // The template text won't be appended // at the end of the template like for // usual multiple template forms. // The HTML text will instead be stored in // the $multipleTemplateHTML variable, // and then added in the right // @insertHTML_".$placeHolderField."@"; position // Optimization: actually, instead of // separating the processes, the usual // multiple template forms could also be // handled this way if a fitting // placeholder tag was added. // We replace the HTML into the current // placeholder tag, but also add another // placeholder tag, to keep track of it. $form_text = str_replace(self::makePlaceholderInFormHTML($placeholder), $multipleTemplateHTML, $form_text); } if (!$tif->allInstancesPrinted()) { // This will cause the section to be // re-parsed on the next go. $section_num--; $tif->incrementInstanceNum(); } } else { $form_text .= $section; } } // end for // Cleanup - everything has been browsed. // Remove all the remaining placeholder // tags in the HTML and wiki-text. foreach ($placeholderFields as $stringToReplace) { // Remove the @<insertHTML>@ tags from the generated // HTML form. $form_text = str_replace(self::makePlaceholderInFormHTML($stringToReplace), '', $form_text); } // 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 .= Html::hidden('sf_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; } else { $free_text = null; $existing_page_content = preg_replace(array('/�\\{/m', '/\\}�/m'), array('{{', '}}'), $existing_page_content); $existing_page_content = str_replace('{{{insertionpoint}}}', '', $existing_page_content); } $form_text .= Html::hidden('partial', 1); } 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('sf_free_text')) { $free_text = $wgRequest->getVal('sf_free_text'); if (!$free_text_was_included) { $wiki_page->addFreeTextSection(); } } else { $free_text = null; } if ($wiki_page->freeTextOnlyInclude()) { $free_text = str_replace("<onlyinclude>", '', $free_text); $free_text = str_replace("</onlyinclude>", '', $free_text); $free_text = trim($free_text); } $page_text = ''; // The first hook here is deprecated. Use the second. // Note: Hooks::run can take a third argument which indicates // a deprecated hook, but it expects a MediaWiki version, not // an extension version. Hooks::run('sfModifyFreeTextField', array(&$free_text, $existing_page_content)); Hooks::run('sfBeforeFreeTextSubstitution', array(&$free_text, $existing_page_content, &$page_text)); // Now that we have it, add free text to the page, and // substitute it into the form. if ($form_submitted) { $wiki_page->setFreeText($free_text); $page_text = $wiki_page->createPageText(); } $escaped_free_text = Sanitizer::safeEncodeAttribute($free_text); $form_text = str_replace('!free_text!', $escaped_free_text, $form_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 (!$is_query && is_null($page_name_formula) && $this->mPageTitle->exists() && $existing_page_content !== '' && !$source_page_matches_this_form) { $form_text = "\t" . '<div class="warningbox">' . wfMessage('sf_formedit_formwarning', $this->mPageTitle->getFullURL())->text() . "</div>\n<br clear=\"both\" />\n" . $form_text; } // Add form bottom, if no custom "standard inputs" have been defined. if (!$this->standardInputsIncluded) { if ($is_query) { $form_text .= SFFormUtils::queryFormBottom($form_is_disabled); } else { $form_text .= SFFormUtils::formBottom($form_submitted, $form_is_disabled); } } if (!$is_query) { $form_text .= Html::hidden('wpStarttime', wfTimestampNow()); $article = new Article($this->mPageTitle, 0); $form_text .= Html::hidden('wpEdittime', $article->getTimestamp()); $form_text .= Html::hidden('wpEditToken', $wgUser->getEditToken()); } $form_text .= "\t</form>\n"; $wgParser->replaceLinkHolders($form_text); Hooks::run('sfRenderingEnd', array(&$form_text)); // Add general Javascript code. $javascript_text = ""; Hooks::run('sfAddJavascriptToForm', array(&$javascript_text)); // Send the autocomplete values to the browser, along with the // mappings of which values should apply to which fields. // If doing a replace, the page text is actually the modified // original page. if ($wgRequest->getCheck('partial')) { $page_text = $existing_page_content; } if (!$is_embedded) { $form_page_title = $wgParser->recursiveTagParse(str_replace("{{!}}", "|", $form_page_title)); } else { $form_page_title = null; } // If the form has already been submitted, i.e. this is just // the redirect page, get rid of all the Javascript, to avoid // JS errors. if ($form_submitted) { $javascript_text = ''; } // $wgParser = $oldParser; return array($form_text, $javascript_text, $page_text, $form_page_title, $generated_page_name); }
function execute( $query ) { global $wgOut, $wgRequest; $this->setHeaders(); $form_name = $wgRequest->getVal( 'form' ); $target_namespace = $wgRequest->getVal( 'namespace' ); $super_page = $wgRequest->getVal( 'super_page' ); $params = $wgRequest->getVal( 'params' ); // If the query string did not contain a form name, try the URL if ( ! $form_name ) { $queryparts = explode( '/', $query, 2 ); $form_name = isset( $queryparts[0] ) ? $queryparts[0] : ''; // If a target was specified, it means we should // redirect to 'FormEdit' for this target page. if ( isset( $queryparts[1] ) ) { $target_name = $queryparts[1]; $this->doRedirect( $form_name, $target_name, $params ); } // Get namespace from the URL, if it's there. if ( $namespace_label_loc = strpos( $form_name, "/Namespace:" ) ) { $target_namespace = substr( $form_name, $namespace_label_loc + 11 ); $form_name = substr( $form_name, 0, $namespace_label_loc ); } } // Remove forbidden characters from the form name. $forbidden_chars = array( '"', "'", '<', '>', '{', '}', '(', ')', '[', ']', '=' ); $form_name = str_replace( $forbidden_chars, "", $form_name ); // Get title of form. $form_title = Title::makeTitleSafe( SF_NS_FORM, $form_name ); // Handle submission of this form. $form_submitted = $wgRequest->getCheck( 'page_name' ); if ( $form_submitted ) { $page_name = $wgRequest->getVal( 'page_name' ); // This form can be used to create a sub-page for an // existing page if ( !is_null( $super_page ) && $super_page !== '' ) { $page_name = "$super_page/$page_name"; } if ( $page_name !== '' ) { // Append the namespace prefix to the page name, // if this namespace was not already entered. if ( strpos( $page_name, $target_namespace . ':' ) === false && !is_null( $target_namespace ) ) $page_name = $target_namespace . ':' . $page_name; // If there was no page title, it's probably an // invalid page name, containing forbidden // characters - in that case, display an error // message. $page_title = Title::newFromText( $page_name ); if ( !$page_title ) { $wgOut->addHTML( htmlspecialchars( wfMsg( 'sf_formstart_badtitle', $page_name ) ) ); return; } else { $this->doRedirect( $form_name, $page_name, $params ); return; } } } if ( ( !$form_title || !$form_title->exists() ) && ( $form_name !== '' ) ) { $text = Html::rawElement( 'p', array( 'class' => 'error' ), wfMsgExt( 'sf_formstart_badform', 'parseinline', SFUtils::linkText( SF_NS_FORM, $form_name ) ) ) . "\n"; } else { if ( $form_name === '' ) { $description = htmlspecialchars( wfMsg( 'sf_formstart_noform_docu', $form_name ) ); } else { $description = htmlspecialchars( wfMsg( 'sf_formstart_docu', $form_name ) ); } $text = <<<END <form action="" method="post"> <p>$description</p> <p><input type="text" size="40" name="page_name" /> END; // If no form was specified, display a dropdown letting // the user choose the form. if ( $form_name === '' ) $text .= SFUtils::formDropdownHTML(); $text .= "\t</p>\n"; $text .= SFFormUtils::hiddenFieldHTML( 'namespace', $target_namespace ); $text .= SFFormUtils::hiddenFieldHTML( 'super_page', $super_page ); $text .= SFFormUtils::hiddenFieldHTML( 'params', $params ); $text .= "\t" . Html::input( null, wfMsg( 'sf_formstart_createoredit' ), 'submit' ) . "\n"; $text .= "\t</form>\n"; } $wgOut->addHTML( $text ); }
private static function getAllValuesForProperty($property_name, $substring, $basePropertyName = null, $baseValue = null) { global $sfgMaxAutocompleteValues, $sfgCacheAutocompleteValues, $sfgAutocompleteCacheTimeout; global $smwgDefaultStore; $values = array(); $db = wfGetDB(DB_SLAVE); $sqlOptions = array(); $sqlOptions['LIMIT'] = $sfgMaxAutocompleteValues; $property = SMWPropertyValue::makeUserProperty($property_name); $propertyHasTypePage = $property->getPropertyTypeID() == '_wpg'; $property_name = str_replace(' ', '_', $property_name); $conditions = array('p_ids.smw_title' => $property_name); // Use cache if allowed if ($sfgCacheAutocompleteValues) { $cache = SFFormUtils::getFormCache(); // Remove trailing whitespace to avoid unnecessary database selects $cacheKeyString = $property_name . '::' . rtrim($substring); if (!is_null($basePropertyName)) { $cacheKeyString .= ',' . $basePropertyName . ',' . $baseValue; } $cacheKey = wfMemcKey('sf-autocomplete', md5($cacheKeyString)); $values = $cache->get($cacheKey); if (!empty($values)) { // Return with results immediately return $values; } } if ($propertyHasTypePage) { $valueField = 'o_ids.smw_title'; if ($smwgDefaultStore === 'SMWSQLStore3') { $idsTable = $db->tableName('smw_object_ids'); $propsTable = $db->tableName('smw_di_wikipage'); } else { $idsTable = $db->tableName('smw_ids'); $propsTable = $db->tableName('smw_rels2'); } $fromClause = "{$propsTable} p JOIN {$idsTable} p_ids ON p.p_id = p_ids.smw_id JOIN {$idsTable} o_ids ON p.o_id = o_ids.smw_id"; } else { if ($smwgDefaultStore === 'SMWSQLStore3') { $valueField = 'p.o_hash'; $idsTable = $db->tableName('smw_object_ids'); $propsTable = $db->tableName('smw_di_blob'); } else { $valueField = 'p.value_xsd'; $idsTable = $db->tableName('smw_ids'); $propsTable = $db->tableName('smw_atts2'); } $fromClause = "{$propsTable} p JOIN {$idsTable} p_ids ON p.p_id = p_ids.smw_id"; } if (!is_null($basePropertyName)) { $baseProperty = SMWPropertyValue::makeUserProperty($basePropertyName); $basePropertyHasTypePage = $baseProperty->getPropertyTypeID() == '_wpg'; $basePropertyName = str_replace(' ', '_', $basePropertyName); $conditions['base_p_ids.smw_title'] = $basePropertyName; if ($basePropertyHasTypePage) { if ($smwgDefaultStore === 'SMWSQLStore3') { $idsTable = $db->tableName('smw_object_ids'); $propsTable = $db->tableName('smw_di_wikipage'); } else { $idsTable = $db->tableName('smw_ids'); $propsTable = $db->tableName('smw_rels2'); } $fromClause .= " JOIN {$propsTable} p_base ON p.s_id = p_base.s_id"; $fromClause .= " JOIN {$idsTable} base_p_ids ON p_base.p_id = base_p_ids.smw_id JOIN {$idsTable} base_o_ids ON p_base.o_id = base_o_ids.smw_id"; $baseValue = str_replace(' ', '_', $baseValue); $conditions['base_o_ids.smw_title'] = $baseValue; } else { if ($smwgDefaultStore === 'SMWSQLStore3') { $baseValueField = 'p_base.o_hash'; $idsTable = $db->tableName('smw_object_ids'); $propsTable = $db->tableName('smw_di_blob'); } else { $baseValueField = 'p_base.value_xsd'; $idsTable = $db->tableName('smw_ids'); $propsTable = $db->tableName('smw_atts2'); } $fromClause .= " JOIN {$propsTable} p_base ON p.s_id = p_base.s_id"; $fromClause .= " JOIN {$idsTable} base_p_ids ON p_base.p_id = base_p_ids.smw_id"; $conditions[$baseValueField] = $baseValue; } } if (!is_null($substring)) { // "Page" type property valeus are stored differently // in the DB, i.e. underlines instead of spaces. $conditions[] = SFUtils::getSQLConditionForAutocompleteInColumn($valueField, $substring, $propertyHasTypePage); } $sqlOptions['ORDER BY'] = $valueField; $res = $db->select($fromClause, "DISTINCT {$valueField}", $conditions, __METHOD__, $sqlOptions); while ($row = $db->fetchRow($res)) { $values[] = str_replace('_', ' ', $row[0]); } $db->freeResult($res); if ($sfgCacheAutocompleteValues) { // Save to cache. $cache->set($cacheKey, $values, $sfgAutocompleteCacheTimeout); } return $values; }
/** * Create the HTML and Javascript to display this field within a form */ function formFieldHTML( $form_field, $cur_value ) { // Also get the actual field, with all the semantic information // (type is SFTemplateField, instead of SFFormField) $template_field = $form_field->getTemplateField(); if ( $form_field->isHidden() ) { $text = SFFormUtils::hiddenFieldHTML( $form_field->getInputName(), $cur_value ); } elseif ( $form_field->getInputType() !== '' && array_key_exists( $form_field->getInputType(), $this->mInputTypeHooks ) && $this->mInputTypeHooks[$form_field->getInputType()] != null ) { $funcArgs = array(); $funcArgs[] = $cur_value; $funcArgs[] = $form_field->getInputName(); $funcArgs[] = $form_field->isMandatory(); $funcArgs[] = $form_field->isDisabled(); // 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->getInputType()]; $other_args = $form_field->getArgumentsForInputCall( $hook_values[1] ); $funcArgs[] = $other_args; $text = call_user_func_array( $hook_values[0], $funcArgs ); } else { // input type not defined in form $property_type = $template_field->getPropertyType(); $is_list = ( $form_field->isList() || $template_field->isList() ); if ( $property_type !== '' && array_key_exists( $property_type, $this->mSemanticTypeHooks ) && isset( $this->mSemanticTypeHooks[$property_type][$is_list] ) ) { $funcArgs = array(); $funcArgs[] = $cur_value; $funcArgs[] = $form_field->getInputName(); $funcArgs[] = $form_field->isMandatory(); $funcArgs[] = $form_field->isDisabled(); $hook_values = $this->mSemanticTypeHooks[$property_type][$is_list]; $other_args = $form_field->getArgumentsForInputCall( $hook_values[1] ); $funcArgs[] = $other_args; $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->isList() ) { if ( ! array_key_exists( 'size', $other_args ) ) { $other_args['size'] = 100; } } $text = SFTextInput::getHTML( $cur_value, $form_field->getInputName(), $form_field->isMandatory(), $form_field->isDisabled(), $other_args ); } } return $text; }
/** * This function is the real heart of the entire Semantic Forms * extension. It handles two main actions: (1) displaying a form on the * screen, given a form definition and possibly page contents (if an * existing page is being edited); and (2) creating actual page * contents, if the form was already submitted by the user. * * It also does some related tasks, like figuring out the page name (if * only a page formula exists). */ function formHTML($form_def, $form_submitted, $source_is_page, $form_id = null, $existing_page_content = null, $page_name = null, $page_name_formula = null, $is_query = false, $is_embedded = 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 wfProfileIn(__METHOD__); // 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 a hidden text field. if (!$wgRequest->getCheck('partial')) { $original_page_content = $existing_page_content; } else { $original_page_content = null; if ($wgRequest->getCheck('sf_free_text')) { $existing_page_content = $wgRequest->getVal('sf_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 ($is_embedded) { // If this is an embedded form (probably a 'RunQuery'), // just use the name of the actual page we're on. global $wgTitle; $this->mPageTitle = $wgTitle; } elseif ($is_query) { $this->mPageTitle = Title::newFromText('RunQuery dummy title'); } elseif ($page_name === '' || $page_name === null) { $this->mPageTitle = Title::newFromText($wgRequest->getVal('namespace') . ":Semantic Forms permissions test"); } else { $this->mPageTitle = Title::newFromText($page_name); } global $wgOut; // show previous set of deletions for this page, if it's been deleted before if (!$form_submitted && ($this->mPageTitle && !$this->mPageTitle->exists())) { $this->showDeletionLog($wgOut); } // Unfortunately, we can't just call userCan() here because, // since MW 1.16, it has a bug in which it ignores a setting of // "$wgEmailConfirmToEdit = true;". Instead, we'll just get the // permission errors from the start, and use those to determine whether // the page is editable. if (!$is_query) { // $userCanEditPage = ( $wgUser->isAllowed( 'edit' ) && $this->mPageTitle->userCan( 'edit' ) ); $permissionErrors = $this->mPageTitle->getUserPermissionsErrors('edit', $wgUser); // The handling of $wgReadOnly and $wgReadOnlyFile // has to be done separately. if (wfReadOnly()) { global $wgReadOnly; $permissionErrors = array(array('readonlytext', array(wfReadOnlyReason()))); } $userCanEditPage = count($permissionErrors) == 0; wfRunHooks('sfUserCanEditPage', array($this->mPageTitle, &$userCanEditPage)); } $form_text = ""; if ($is_query || $userCanEditPage) { $form_is_disabled = false; // Show "Your IP address will be recorded" warning if // user is anonymous, and it's not a query - // wiki-text 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; $wgOut->setPageTitle(wfMsg('badaccess')); $wgOut->addWikiText($wgOut->formatPermissionsErrorMessage($permissionErrors, 'edit')); $wgOut->addHTML("\n<hr />\n"); } // $oldParser = $wgParser; // $wgParser = unserialize( serialize( $oldParser ) ); // deep clone of parser if (!$wgParser->Options()) { $wgParser->Options(ParserOptions::newFromUser($wgUser)); } $wgParser->Title($this->mPageTitle); // $wgParser->clearState(); $form_def = SFFormUtils::getFormDefinition($wgParser, $form_def, $form_id); // 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 any 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 was needed // to make sure that those elements don't get parsed too early. $form_def = str_replace(array('{', '|', '}'), 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 = SFUtils::getFormTagComponents($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 the 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; // Placeholder name in the form $curPlaceholder = null; // Used to store the HTML code of the multiple template, to reinsert it into the right spot // This array will keep track of all the replaced @<name>@ strings $placeholderFields = array(); for ($section_num = 0; $section_num < count($form_def_sections); $section_num++) { $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]; $multipleTemplateString = ""; 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 = SFUtils::getFormTagComponents($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 = SFTemplateInForm::create($template_name); $query_template_name = str_replace(' ', '_', $template_name); $add_button_text = wfMsg('sf_formedit_addanother'); // Also replace periods with underlines, since that's what // POST does to strings anyway. $query_template_name = str_replace('.', '_', $query_template_name); // ...and escape apostrophes. $query_template_name = str_replace("'", "\\'", $query_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 = array_map('trim', explode('=', $component, 2)); if (count($sub_components) == 2) { if ($sub_components[0] == 'label') { $template_label = $sub_components[1]; } elseif ($sub_components[0] == 'add button text') { $add_button_text = $sub_components[1]; } elseif ($sub_components[0] == 'embed in field') { // Placeholder on form template level. Assume that the template form def // will have a multiple+placeholder parameters, and get the placeholder value. // We expect something like TemplateName[fieldName], and convert it to the // TemplateName___fieldName form used internally. preg_match('/\\s*(.*)\\[(.*)\\]\\s*/', $sub_components[1], $matches); $curPlaceholder = count($matches) > 2 ? self::placeholderFormat($matches[1], $matches[2]) : null; unset($matches); } } } // If this is the first instance, add // the label into the form, if there is // one, and add the appropriate wrapper // div, if this is a multiple-instance // template. if ($old_template_name != $template_name) { if (isset($template_label)) { $multipleTemplateString .= "<fieldset>\n"; $multipleTemplateString .= Html::element('legend', null, $template_label) . "\n"; } // If $curPlaceholder is set, it means we want to insert a // multiple template form's HTML into the main form's HTML. // So, the HTML will be stored in $multipleTemplateString. if ($allow_multiple) { $multipleTemplateString .= "\t" . '<div class="multipleTemplateWrapper">' . "\n"; $multipleTemplateString .= "\t" . '<div class="multipleTemplateList">' . "\n"; } } if ($curPlaceholder == null) { $form_text .= $multipleTemplateString; } $template_text .= "{{" . $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('_', ' ', $template_name); $preg_match_template_str = str_replace(array('/', '(', ')'), array('\\/', '\\(', '\\)'), $search_template_str); $found_instance = preg_match('/{{' . $preg_match_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) { $matches = array(); $search_pattern = '/{{' . $preg_match_template_str . '\\s*[\\|}]/i'; $content_str = str_replace('_', ' ', $existing_page_content); preg_match($search_pattern, $content_str, $matches, PREG_OFFSET_CAPTURE); // is this check necessary? if (array_key_exists(0, $matches) && array_key_exists(1, $matches[0])) { $start_char = $matches[0][1]; $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++; } // If the next character is a pipe, skip that too. if ($existing_page_content[$fields_start_char] == '|') { $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; } } // If there are uncompleted opening brackets, the whole form will get messed up - // display a warning. // (If there are too many *closing* brackets, some template stuff will end up in // the "free text" field - which is bad, but it's harder for the code to detect // the problem - though hopefully, easier for users.) if ($uncompleted_curly_brackets > 0 || $uncompleted_square_brackets > 0) { $form_text .= "\t" . '<div class="warningbox">' . wfMsg('sf_formedit_mismatchedbrackets', $this->mPageTitle->getFullURL(array('action' => 'edit'))) . "</div>\n<br clear=\"both\" />\n"; } $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 = $this->strReplaceFirst($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) // - on second thought, allow even the presence of multiple- // instance templates to validate that this is the correct // form: the problem is that some forms contain *only* mutliple- // instance templates. // 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 // TODO: this code is probably no longer necessary 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_name, $template_contents); $template_contents = null; } } // 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) && $curPlaceholder == null) { $form_text .= "</fieldset>\n"; unset($template_label); } $allow_multiple = false; $all_instances_printed = false; $instance_num = 0; // ===================================================== // field processing // ===================================================== } elseif ($tag_title == 'field') { $field_name = trim($tag_components[1]); $fullFieldName = $template_name . '[' . $field_name . ']'; // 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(); $show_on_select = array(); $default_value = null; $values = null; $possible_values = null; $semantic_property = null; $preload_page = null; $holds_template = false; 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 = !$wgUser || !$wgUser->isAllowed('editrestrictedfields'); } elseif ($component == 'list') { $is_list = true; } elseif ($component == 'edittools') { // free text only $free_text_components[] = 'edittools'; } $sub_components = array_map('trim', explode('=', $component, 2)); if (count($sub_components) == 1) { // add handling for single-value params, for custom input types $field_args[$sub_components[0]] = true; if ($component == 'holds template') { $is_hidden = true; $holds_template = true; $placeholderFields[] = self::placeholderFormat($template_name, $field_name); } } elseif (count($sub_components) == 2) { // First, set each value as its own entry in $field_args. $field_args[$sub_components[0]] = $sub_components[1]; // Then, do all special handling. if ($sub_components[0] == 'input type') { $input_type = $sub_components[1]; } elseif ($sub_components[0] == 'default') { $default_value = $wgParser->recursiveTagParse($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 { $preload_page = $sub_components[1]; } } elseif ($sub_components[0] == 'show on select') { // html_entity_decode() is needed to turn '>' to '>' $vals = explode(';', html_entity_decode($sub_components[1])); foreach ($vals as $val) { $val = trim($val); if (empty($val)) { continue; } $option_div_pair = explode('=>', $val, 2); if (count($option_div_pair) > 1) { $option = $option_div_pair[0]; $div_id = $option_div_pair[1]; if (array_key_exists($div_id, $show_on_select)) { $show_on_select[$div_id][] = $option; } else { $show_on_select[$div_id] = array($option); } } else { $show_on_select[$val] = array(); } } } elseif ($sub_components[0] == 'autocomplete on property') { $property_name = $sub_components[1]; $propValue = SMWPropertyValue::makeUserProperty($property_name); if ($propValue->getPropertyTypeID() == '_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 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') { // Handle this one only after 'delimiter' has // also been set. $values = $sub_components[1]; } elseif ($sub_components[0] == 'values from property') { $propertyName = $sub_components[1]; $possible_values = SFUtils::getAllValuesForProperty($propertyName); } 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] == 'values from namespace') { $possible_values = SFUtils::getAllPagesForNamespace($sub_components[1]); } elseif ($sub_components[0] == 'values dependent on') { global $sfgDependentFields; $sfgDependentFields[] = array($sub_components[1], $fullFieldName); } elseif ($sub_components[0] == 'property') { $semantic_property = $sub_components[1]; } elseif ($sub_components[0] == 'default filename') { $default_filename = str_replace('<page name>', $page_name, $sub_components[1]); // Parse value, so default filename can include parser functions. $default_filename = $wgParser->recursiveTagParse($default_filename); $field_args['default filename'] = $default_filename; } elseif ($sub_components[0] == 'restricted') { $is_restricted = !array_intersect($wgUser->getEffectiveGroups(), array_map('trim', explode(',', $sub_components[1]))); } } } // end for // Backwards compatibility if ($input_type == 'datetime with timezone') { $input_type = 'datetime'; $field_args['include timezone'] = true; } elseif ($input_type == 'text' || $input_type == 'textarea') { // Also for backwards compatibility, // in that once b/c goes away, // this will no longer be // necessary. $field_args['no autocomplete'] = true; } if ($allow_multiple) { $field_args['part_of_multiple'] = $allow_multiple; } if (count($show_on_select) > 0) { $field_args['show on select'] = $show_on_select; } // Get the value from the request, if // it's there, and if it's not an array. $cur_value = null; $escaped_field_name = str_replace("'", "\\'", $field_name); if (isset($template_instance_query_values) && $template_instance_query_values != null && is_array($template_instance_query_values)) { // If the field name contains an // apostrophe, the array sometimes // has the apostrophe escaped, and // sometimes not. For now, just check // for both versions. // @TODO - figure this out. $field_query_val = null; if (array_key_exists($escaped_field_name, $template_instance_query_values)) { $field_query_val = $template_instance_query_values[$escaped_field_name]; } elseif (array_key_exists($field_name, $template_instance_query_values)) { $field_query_val = $template_instance_query_values[$field_name]; } if ($form_submitted || $field_query_val != '' && !is_array($field_query_val)) { $cur_value = $field_query_val; } } if (empty($cur_value) && !$form_submitted) { if (!is_null($default_value)) { // Set to the default value specified in the form, if it's there. $cur_value = $default_value; } elseif ($preload_page) { $cur_value = SFFormUtils::getPreloadedText($preload_page); } } // 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]; // If the field is a placeholder, the contents of this template // parameter should be treated as elements parsed by an another // multiple template form. // By putting that at the very end of the parsed string, we'll // have it processed as a regular multiple template form. if ($holds_template) { $existing_page_content = $existing_page_content . $cur_value; } // 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 ($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 = Html::hidden('sf_free_text', '!free_text!'); } else { $sfgTabIndex++; $sfgFieldNum++; if ($cur_value === '' || is_null($cur_value)) { $default_value = '!free_text!'; } else { $default_value = $cur_value; // If the FCKeditor extension is installed and // active, the default value needs to be parsed // for use in the editor. global $wgFCKEditorDir; if ($wgFCKEditorDir && strpos($existing_page_content, '__NORICHEDITOR__') === false) { $showFCKEditor = SFFormUtils::getShowFCKEditor(); if (!$form_submitted && $showFCKEditor & RTE_VISIBLE) { $default_value = SFFormUtils::prepareTextForFCK($cur_value); } } } $new_text = SFTextAreaInput::getHTML($default_value, 'sf_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 = $wgParser->recursiveTagParse(wfMsg('edittools', array('content'))); $new_text .= <<<END \t\t<div class="mw-editTools"> \t\t{$edittools_text} \t\t</div> END; } } $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) { $cur_value_in_template = SFUtils::getWordForYesOrNo(false); } elseif (count($cur_value) == 2) { $cur_value_in_template = SFUtils::getWordForYesOrNo(true); // 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 ($template_name == null || $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 = $template_name . '[num][' . $field_name . ']'; $field_args['origName'] = $template_name . '[' . $field_name . ']'; } else { $input_name = $template_name . '[' . $field_name . ']'; } // If the 'values' parameter was set, separate it based on the // 'delimiter' parameter, if any. if (!empty($values)) { if (array_key_exists('delimiter', $field_args)) { $delimiter = $field_args['delimiter']; } else { $delimiter = ","; } // Remove whitespaces, and un-escape characters $possible_values = array_map('trim', explode($delimiter, $values)); $possible_values = array_map('htmlspecialchars_decode', $possible_values); } // 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 to be 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; // 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); } $semantic_property = $form_field->template_field->getSemanticProperty(); if (!is_null($semantic_property)) { global $sfgFieldProperties; $sfgFieldProperties[$fullFieldName] = $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 (!array_key_exists('part_of_multiple', $field_args)) { $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' && ($cur_value === '' || $cur_value == 'now')) { if ($input_type == 'date' || $input_type == 'datetime' || $input_type == 'year' || $input_type === '' && $form_field->getTemplateField()->getPropertyType() == '_dat') { // Get current time, for the time zone specified in the wiki. global $wgLocaltimezone; if (isset($wgLocaltimezone)) { $serverTimezone = date_default_timezone_get(); date_default_timezone_set($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 (isset($wgLocaltimezone)) { date_default_timezone_set($serverTimezone); } if ($input_type == 'datetime') { 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 (array_key_exists('include timezone', $field_args)) { $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' && ($cur_value === '' || $cur_value == 'current user')) { $cur_value_in_template = $wgUser->getName(); $cur_value = $cur_value_in_template; } // Generate a hidden field with a placeholder value that will be replaced // by the multiple-instances template output at form submission. //// <input type="hidden" value="@replace_Town___mayors@" name="Town[town_mayors]" /> if ($holds_template) { $cur_value = self::makePlaceholderInWikiText(self::placeholderFormat($template_name, $field_name)); } $new_text = $this->formFieldHTML($form_field, $cur_value); // Add a field just after the hidden field, within the HTML, to locate // where the multiple-templates HTML, stored in $multipleTemplateString, // should be inserted. if ($holds_template) { $new_text .= self::makePlaceholderInFormHTML(self::placeholderFormat($template_name, $field_name)); } // 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->isDisabled()) { if ($field_name == 'free text' || $field_name == '<freetext>') { $new_text .= Html::hidden('sf_free_text', '!free_text!'); } else { $new_text .= Html::hidden($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); } else { $start_position = $brackets_end_loc; } } // ===================================================== // standard input processing // ===================================================== } elseif ($tag_title == 'standard input') { // handle all the possible values $input_name = $tag_components[1]; $input_label = null; $attr = array(); // if it's a query, ignore all standard inputs except run query if ($is_query && $input_name != 'run query' || !$is_query && $input_name == 'run 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; // cycle through the other components for ($i = 2; $i < count($tag_components); $i++) { $component = $tag_components[$i]; $sub_components = array_map('trim', explode('=', $component)); if (count($sub_components) == 1) { if ($sub_components[0] == 'edittools') { $free_text_components[] = 'edittools'; } } elseif (count($sub_components) == 2) { switch ($sub_components[0]) { case 'label': $input_label = $sub_components[1]; break; case 'class': case 'style': $attr[$sub_components[0]] = $sub_components[1]; break; } // 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, $attr); } elseif ($input_name == 'minor edit') { $new_text = SFFormUtils::minorEditInputHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'watch') { $new_text = SFFormUtils::watchInputHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'save') { $new_text = SFFormUtils::saveButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'save and continue') { $new_text = SFFormUtils::saveAndContinueButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'preview') { $new_text = SFFormUtils::showPreviewButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'changes') { $new_text = SFFormUtils::showChangesButtonHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'cancel') { $new_text = SFFormUtils::cancelLinkHTML($form_is_disabled, $input_label, $attr); } elseif ($input_name == 'run query') { $new_text = SFFormUtils::runQueryButtonHTML($form_is_disabled, $input_label, $attr); } $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 = array_map('trim', explode('=', $component, 2)); // Tag names are case-insensitive $tag = strtolower($sub_components[0]); if ($tag == 'create title' || $tag == 'add title') { // Handle this only if // we're adding a page. if (!$is_query && !$this->mPageTitle->exists()) { $form_page_title = $sub_components[1]; } } elseif ($tag == 'edit title') { // Handle this only if // we're editing a page. if (!$is_query && $this->mPageTitle->exists()) { $form_page_title = $sub_components[1]; } } elseif ($tag == 'query title') { // Handle this only if // we're in 'RunQuery'. if ($is_query) { $form_page_title = $sub_components[1]; } } 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; } elseif ($tag == 'query form at top') { // TODO - this should be made a field of // some non-static class that actually // prints the form, instead of requiring // a global variable. global $sfgRunQueryFormAtTop; $sfgRunQueryFormAtTop = 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 the 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. if (!$allow_multiple) { $template_text .= SFFormUtils::addUnhandledFields($template_name); } $template_text .= "}}"; // The base $template_text will contain strings like "@replace_xxx@" // in the hidden fields when the form is submitted. // On the following loops, the text for the multiple-instance templates // is progressively reinserted in the main data, always keeping a // trailing @replace_xxx@ for a given field // The trailing @replace_xxx@ is then deleted at the end. // Note: this cleanup step could also be done with a regexp, instead of // keeping a track array (e.g., /@replace_(.*)@/) $reptmp = self::makePlaceholderInWikiText($curPlaceholder); if ($curPlaceholder != null && $data_text && strpos($data_text, $reptmp, 0) !== false) { $data_text = preg_replace('/' . $reptmp . '/', $template_text . $reptmp, $data_text); } else { $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', '}�', preg_replace('/\\{\\{/m', '�{', $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', '}�', preg_replace('/\\{\\{/m', '�{', $template_text)) . "\n{{{insertionpoint}}}\n" . $existing_page_content; } } } if ($allow_multiple) { if ($curPlaceholder == null) { // The normal process. $form_text .= $this->multipleTemplateInstanceHTML($form_is_disabled, $all_instances_printed, $section, $instance_num, $add_button_text); } else { // if ( $curPlaceholder != null ){ // The template text won't be appended at the end of the template like for usual multiple template forms. // The HTML text will then be stored in the $multipleTemplateString variable, // and then added in the right @insertHTML_".$placeHolderField."@"; position // Optimization: actually, instead of separating the processes, the usual multiple // template forms could also be handled this way if a fitting placeholder tag was added. $multipleTemplateString .= $this->multipleTemplateInstanceHTML($form_is_disabled, $all_instances_printed, $section, $instance_num, $add_button_text); // We replace the $multipleTemplateString HTML into the // current placeholder tag, but also add another // placeholder tag, to keep track of it. $multipleTemplateString .= self::makePlaceholderInFormHTML($curPlaceholder); if (isset($template_label)) { $multipleTemplateString .= "</fieldset>\n"; unset($template_label); } $form_text = preg_replace('/' . self::makePlaceholderInFormHTML($curPlaceholder) . '/', $multipleTemplateString, $form_text); } if (!$all_instances_printed) { // This will cause the section to be // re-parsed on the next go. $section_num--; } } else { // if ( $allow_multiple ) { $form_text .= $section; } $curPlaceholder = null; // var_dump($wgParser->getOutput()->getModules()); } // end for // Cleanup - everything has been browsed. // Remove all the remaining placeholder // tags in the HTML and wiki-text. foreach ($placeholderFields as $stringToReplace) { // remove the @<replacename>@ tags from the data that is submitted $data_text = preg_replace('/' . self::makePlaceholderInWikiText($stringToReplace) . '/', '', $data_text); // remove the @<insertHTML>@ tags from the generated HTML form $form_text = preg_replace('/' . self::makePlaceholderInFormHTML($stringToReplace) . '/', '', $form_text); } // 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 .= Html::hidden('sf_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 .= Html::hidden('partial', 1); } else { $free_text = null; $existing_page_content = preg_replace(array('/�\\{/m', '/\\}�/m'), array('{{', '}}'), $existing_page_content); $existing_page_content = preg_replace('/\\{\\{\\{insertionpoint\\}\\}\\}/', '', $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('sf_free_text')) { $free_text = $wgRequest->getVal('sf_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); } wfRunHooks('sfModifyFreeTextField', array(&$free_text, $existing_page_content)); // if the FCKeditor extension is installed, use that for the free text input global $wgFCKEditorDir; if ($wgFCKEditorDir && strpos($existing_page_content, '__NORICHEDITOR__') === false) { $showFCKEditor = SFFormUtils::getShowFCKEditor(); if (!$form_submitted && $showFCKEditor & RTE_VISIBLE) { $free_text = SFFormUtils::prepareTextForFCK($free_text); } } else { $showFCKEditor = 0; } // now that we have it, substitute free text into the form and page $escaped_free_text = Sanitizer::safeEncodeAttribute($free_text); $form_text = str_replace('!free_text!', $escaped_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 (!$is_query && $this->mPageTitle->exists() && $existing_page_content !== '' && !$source_page_matches_this_form) { $form_text = "\t" . '<div class="warningbox">' . wfMsg('sf_formedit_formwarning', $this->mPageTitle->getFullURL()) . "</div>\n<br clear=\"both\" />\n" . $form_text; } // add form bottom, if no custom "standard inputs" have been defined if (!$this->standardInputsIncluded) { if ($is_query) { $form_text .= SFFormUtils::queryFormBottom($form_is_disabled); } else { $form_text .= SFFormUtils::formBottom($form_is_disabled); } } if (!$is_query) { $form_text .= Html::hidden('wpStarttime', wfTimestampNow()); $article = new Article($this->mPageTitle, 0); $form_text .= Html::hidden('wpEdittime', $article->getTimestamp()); } $form_text .= "\t</form>\n"; // Add general Javascript code. wfRunHooks('sfAddJavascriptToForm', array(&$javascript_text)); // @TODO The FCKeditor Javascript should be handled within // the FCKeditor extension itself, using the hook. $javascript_text = ""; if ($free_text_was_included && $showFCKEditor > 0) { $javascript_text .= SFFormUtils::mainFCKJavascript($showFCKEditor, $field_args); 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; } if (!$is_embedded) { $form_page_title = $wgParser->recursiveTagParse(str_replace("{{!}}", "|", $form_page_title)); } else { $form_page_title = null; } // If the form has already been submitted, i.e. this is just // the redirect page, get rid of all the Javascript, to avoid // JS errors. if ($form_submitted) { $javascript_text = ''; } $parserOutput = $wgParser->getOutput(); $wgOut->addParserOutputNoText($parserOutput); // $wgParser = $oldParser; wfProfileOut(__METHOD__); return array($form_text, $javascript_text, $data_text, $form_page_title, $generated_page_name); }
function printPage( $form_name, $embedded = false ) { global $wgOut, $wgRequest, $sfgFormPrinter, $wgParser, $sfgRunQueryFormAtTop; // Get contents of form-definition page. $form_title = Title::makeTitleSafe( SF_NS_FORM, $form_name ); if ( !$form_title || !$form_title->exists() ) { if ( $form_name === '' ) { $text = Html::element( 'p', array( 'class' => 'error' ), wfMsg( 'sf_runquery_badurl' ) ) . "\n"; } else { $text = Html::rawElement( 'p', array( 'class' => 'error' ), wfMsgExt( 'sf_formstart_badform', 'parseinline', SFUtils::linkText( SF_NS_FORM, $form_name ) ) ) . "\n"; } $wgOut->addHTML( $text ); return; } // Initialize variables. $form_article = new Article( $form_title, 0 ); $form_definition = $form_article->getContent(); $submit_url = $form_title->getLocalURL( 'action=submit' ); if ( $embedded ) { $run_query = false; $content = null; $raw = false; } else { $run_query = $wgRequest->getCheck( 'wpRunQuery' ); $content = $wgRequest->getVal( 'wpTextbox1' ); $raw = $wgRequest->getBool( 'raw', false ); } $form_submitted = ( $run_query ); if ( $raw ) { $wgOut->setArticleBodyOnly( true ); } // If user already made some action, ignore the edited // page and just get data from the query string. if ( !$embedded && $wgRequest->getVal( 'query' ) == 'true' ) { $edit_content = null; $is_text_source = false; } elseif ( $content != null ) { $edit_content = $content; $is_text_source = true; } else { $edit_content = null; $is_text_source = true; } list ( $form_text, $javascript_text, $data_text, $form_page_title ) = $sfgFormPrinter->formHTML( $form_definition, $form_submitted, $is_text_source, $form_article->getID(), $edit_content, null, null, true, $embedded ); $text = ""; if ( $form_submitted ) { global $wgUser, $wgTitle, $wgOut; $wgParser->mOptions = ParserOptions::newFromUser( $wgUser ); // @TODO - fix RunQuery's parsing so that this check // isn't needed. if ( $wgParser->getOutput() == null ) { $headItems = array(); } else { $headItems = $wgParser->getOutput()->getHeadItems(); } foreach ( $headItems as $key => $item ) { $wgOut->addHeadItem( $key, "\t\t" . $item . "\n" ); } } // Get the text of the results. $resultsText = ''; if ( $form_submitted ) { $resultsText = $wgParser->parse( $data_text, $wgTitle, $wgParser->mOptions )->getText(); } // Get the full text of the form. $fullFormText = ''; $additionalQueryHeader = ''; $dividerText = ''; if ( !$raw ) { // Create the "additional query" header, and the // divider text - one of these (depending on whether // the query form is at the top or bottom) is displayed // if the form has already been submitted. if ( $form_submitted ) { $additionalQueryHeader = "\n" . Html::element( 'h2', null, wfMsg( 'sf_runquery_additionalquery' ) ) . "\n"; $dividerText = "\n<hr style=\"margin: 15px 0;\" />\n"; } $action = htmlspecialchars( $this->getTitle( $form_name )->getLocalURL() ); $fullFormText .= <<<END <form id="sfForm" name="createbox" action="$action" method="post" class="createbox"> END; $fullFormText .= SFFormUtils::hiddenFieldHTML( 'query', 'true' ); $fullFormText .= $form_text; } // Either display the query form at the top, and the results at // the bottom, or the other way around, depending on the // settings - the display is slightly different in each case. if ( $sfgRunQueryFormAtTop ) { $text .= $fullFormText; $text .= $dividerText; $text .= $resultsText; } else { $text .= $resultsText; $text .= $additionalQueryHeader; $text .= $fullFormText; } if ( $embedded ) { $text = "<div class='runQueryEmbedded'>$text</div>"; } // Armor against doBlockLevels() $text = preg_replace( '/^ +/m', '', $text ); // Now write everything to the screen. $wgOut->addHTML( $text ); SFUtils::addJavascriptAndCSS( $embedded ? $wgParser : null ); $script = "\t\t" . '<script type="text/javascript">' . "\n" . $javascript_text . '</script>' . "\n"; if ( $embedded ) { $wgParser->getOutput()->addHeadItem( $script ); } else { $wgOut->addScript( $script ); $po = $wgParser->getOutput(); if ( $po ) { $wgOut->addParserOutputNoText( $po ); } } // Finally, set the page title - for MW 1.16, this has to be // called after addParserOutputNoText() for it to take effect. if ( !$embedded ) { if ( $form_page_title != null ) { $wgOut->setPageTitle( $form_page_title ); } else { $s = wfMsg( 'sf_runquery_title', $form_title->getText() ); $wgOut->setPageTitle( $s ); } } }
function getCurrentValue($template_instance_query_values, $form_submitted, $source_is_page) { // Get the value from the request, if // it's there, and if it's not an array. $cur_value = null; $field_name = $this->template_field->getFieldName(); $delimiter = $this->mFieldArgs['delimiter']; $escaped_field_name = str_replace("'", "\\'", $field_name); if (isset($template_instance_query_values) && $template_instance_query_values != null && is_array($template_instance_query_values)) { // If the field name contains an apostrophe, the array // sometimes has the apostrophe escaped, and sometimes // not. For now, just check for both versions. // @TODO - figure this out. $field_query_val = null; if (array_key_exists($escaped_field_name, $template_instance_query_values)) { $field_query_val = $template_instance_query_values[$escaped_field_name]; } elseif (array_key_exists($field_name, $template_instance_query_values)) { $field_query_val = $template_instance_query_values[$field_name]; } if ($form_submitted && $field_query_val != '') { $map_field = false; if (array_key_exists('map_field', $template_instance_query_values) && array_key_exists($field_name, $template_instance_query_values['map_field'])) { $map_field = true; } if (is_array($field_query_val)) { $cur_values = array(); if ($map_field && !is_null($this->mPossibleValues)) { $cur_values = array(); foreach ($field_query_val as $key => $val) { $val = trim($val); if ($key === 'is_list') { $cur_values[$key] = $val; } else { $cur_values[] = SFUtils::labelToValue($val, $this->mPossibleValues); } } } else { foreach ($field_query_val as $key => $val) { $cur_values[$key] = $val; } } return SFFormPrinter::getStringFromPassedInArray($cur_values, $delimiter); } else { $field_query_val = trim($field_query_val); if ($map_field && !is_null($this->mPossibleValues)) { // this should be replaced with an input type neutral way of // figuring out if this scalar input type is a list if ($this->mInputType == "tokens") { $is_list = true; } if ($is_list) { $cur_values = array_map('trim', explode($delimiter, $field_query_val)); foreach ($cur_values as $key => $value) { $cur_values[$key] = SFUtils::labelToValue($value, $this->mPossibleValues); } return implode($delimiter, $cur_values); } return SFUtils::labelToValue($field_query_val, $this->mPossibleValues); } return $field_query_val; } } if (!$form_submitted && $field_query_val != '') { if (is_array($field_query_val)) { return SFFormPrinter::getStringFromPassedInArray($field_query_val, $delimiter); } return $field_query_val; } } if (!$source_is_page && empty($cur_value) && !$form_submitted) { if (!is_null($this->mDefaultValue)) { // Set to the default value specified in the form, if it's there. return $this->mDefaultValue; } elseif ($this->mPreloadPage) { return SFFormUtils::getPreloadedText($this->mPreloadPage); } } return $cur_value; // null }
private static function getAllValuesForCargoField($cargoTable, $cargoField, $fieldIsArray, $substring, $baseCargoTable = null, $baseCargoField = null, $baseValue = null) { global $sfgMaxAutocompleteValues, $sfgCacheAutocompleteValues, $sfgAutocompleteCacheTimeout; global $sfgAutocompleteOnAllChars; $values = array(); $tablesStr = $cargoTable; $fieldsStr = $cargoField; $joinOnStr = ''; $whereStr = ''; // Use cache if allowed if ($sfgCacheAutocompleteValues) { $cache = SFFormUtils::getFormCache(); // Remove trailing whitespace to avoid unnecessary database selects $cacheKeyString = $cargoTable . '|' . $cargoField . '|' . rtrim($substring); if (!is_null($baseCargoTable)) { $cacheKeyString .= '|' . $baseCargoTable . '|' . $baseCargoField . '|' . $baseValue; } $cacheKey = wfMemcKey('sf-autocomplete', md5($cacheKeyString)); $values = $cache->get($cacheKey); if (!empty($values)) { // Return with results immediately return $values; } } if (!is_null($baseCargoTable) && !is_null($baseCargoField)) { if ($baseCargoTable != $cargoTable) { $tablesStr .= ", {$baseCargoTable}"; $joinOnStr = "{$cargoTable}._pageName = {$baseCargoTable}._pageName"; } $whereStr = "{$baseCargoTable}.{$baseCargoField} = \"{$baseValue}\""; } if (!is_null($substring)) { if ($whereStr != '') { $whereStr .= " AND "; } $operator = $fieldIsArray ? "HOLDS LIKE" : "LIKE"; if ($sfgAutocompleteOnAllChars) { $whereStr .= "({$cargoField} {$operator} \"%{$substring}%\")"; } else { $whereStr .= "({$cargoField} {$operator} \"{$substring}%\" OR {$cargoField} {$operator} \"% {$substring}%\")"; } } $sqlQuery = CargoSQLQuery::newFromValues($tablesStr, $fieldsStr, $whereStr, $joinOnStr, $cargoField, $havingStr = null, $cargoField, $sfgMaxAutocompleteValues); $cargoFieldAlias = str_replace('_', ' ', $cargoField); $queryResults = $sqlQuery->run(); foreach ($queryResults as $row) { // @TODO - this check should not be neceaary. if (($value = $row[$cargoFieldAlias]) != '') { $values[] = $value; } } if ($sfgCacheAutocompleteValues) { // Save to cache. $cache->set($cacheKey, $values, $sfgAutocompleteCacheTimeout); } return $values; }
public function formSerialize($form_def = '', $source_is_page = false, $existing_page_content = null, $page_title = null) { // public function formSerialize($form_def, $source_is_page, $existing_page_content = null, $page_title = null, $page_name_formula = null) { 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 # define a var for all fields $__fields = array(); // initialize some variables $sfgTabIndex = 1; $sfgFieldNum = 1; $source_page_matches_this_form = false; $form_page_title = NULL; // $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 = ""; // 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); } if ($wgUser->isAllowed('edit') && $this->mPageTitle->userCanEdit()) { $form_is_disabled = false; $form_text = ""; // show "Your IP address will be recorded" warning if user is // anonymous - wikitext for bolding has to be replaced with HTML if ($wgUser->isAnon()) { $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 global $sfgDisableWikiTextParsing; if (!$sfgDisableWikiTextParsing) { $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; $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('{', '|', '}'), 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; # reads all the fields of the template definition page $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; // replace underlines with spaces in template name, to allow for // searching on either $search_template_str = str_replace('_', ' ', $tif->template_name); if ($source_is_page || $form_is_partial) { 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 (stripos(str_replace('_', ' ', $existing_page_content), '{{' . $search_template_str) !== false) { $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 (($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; 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]); } } } // save the template name $field = array(); $field['tmpl_name'] = $tif->template_name; // ===================================================== // end template processing // ===================================================== } 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; // 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); $__fields["template" . count($__fields)] = $field; // ===================================================== // 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; $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; } 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] == '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] == 'values') { $possible_values = explode(',', $sub_components[1]); } elseif ($sub_components[0] == 'values from category') { $possible_values = SFUtils::getAllPagesForCategory($sub_components[1], 10); } elseif ($sub_components[0] == 'values from concept') { $possible_values = SFUtils::getAllPagesForConcept($sub_components[1]); } 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 && array_key_exists($escaped_field_name, $template_instance_query_values)) { $field_query_val = $template_instance_query_values[$escaped_field_name]; if ($field_query_val && !is_array($field_query_val)) { $cur_value = $field_query_val; } } else { $cur_value = ''; } if ($cur_value && !is_array($cur_value)) { # no escaping needed // $cur_value = str_replace('"', '"', $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 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 && !empty($existing_template_text)) { if (isset($template_contents[$field_name])) { $cur_value = $template_contents[$field_name]; } else { $cur_value = ''; } if ($cur_value) { # no escaping needed // $cur_value = str_replace('"', '"', $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); $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 == '') { $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']; 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 (isset($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 (isset($second)) { $cur_value_in_template .= ":" . str_pad(intval(substr($second, 0, 2)), 2, '0', STR_PAD_LEFT); } if (isset($ampm24h)) { $cur_value_in_template .= " {$ampm24h}"; } if (isset($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 . ']'; } // 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 SFFormTemplateField instance based on all the // parameters in the form definition, and any information from // the template definition (contained in the $all_fields parameter) # creation of a form field from the definition page $possible_values['_element'] = "value"; $form_field = $this->createFromDefinitionForSerialization($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 this is not part of a 'multiple' template, incrememt 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' && ($cur_value == '' || $cur_value == 'now')) { if ($input_type == 'date' || $input_type == 'datetime' || $input_type == 'datetime with timezone' || $input_type == '' && $form_field->template_field->field_type == 'Date') { $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' && ($cur_value == '' || $cur_value == 'current user')) { if ($input_type == 'text' || $input_type == '') { $cur_value_in_template = $wgUser->getName(); $cur_value = $cur_value_in_template; } } # field + field value $form_field->cur_value = $cur_value; # possible_values hack $__tmpValues = $form_field->template_field->possible_values; $form_field->template_field->possible_values = array(); if ($__tmpValues != NULL) { foreach ($__tmpValues as $key => $value) { $form_field->template_field->possible_values["value" . $key] = $value; } } $field["field" . count($field)] = $this->toArrayForSerialize($form_field); $new_text = "dummy"; // set only in order to break if ($new_text) { $section = substr_replace($section, $new_text, $brackets_loc, $brackets_end_loc + 3 - $brackets_loc); } else { $start_position = $brackets_end_loc; } } } else { // tag is not one of the three allowed values // ignore tag $start_position = $brackets_end_loc; } // end if } // end while } // end for // 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('/²\\{(.*?)\\}²/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; } # the free text is set here // if the FCKeditor extension is installed, use that for the free text input global $wgFCKEditorDir; if ($wgFCKEditorDir) { $showFCKEditor = SFFormUtils::getShowFCKEditor(); $free_text = htmlspecialchars($free_text); if ($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); # return the fields return $__fields; }
public static function getHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) { global $sfgTabIndex, $sfgFieldNum, $sfgShowOnSelect; $checkbox_class = ( $is_mandatory ) ? 'mandatoryField' : 'createboxInput'; $span_class = 'checkboxSpan'; if ( array_key_exists( 'class', $other_args ) ) { $span_class .= ' ' . $other_args['class']; } $input_id = "input_$sfgFieldNum"; // get list delimiter - default is comma if ( array_key_exists( 'delimiter', $other_args ) ) { $delimiter = $other_args['delimiter']; } else { $delimiter = ','; } $cur_values = SFUtils::getValuesArray( $cur_value, $delimiter ); if ( ( $possible_values = $other_args['possible_values'] ) == null ) { $possible_values = array(); } $text = ''; foreach ( $possible_values as $key => $possible_value ) { $cur_input_name = $input_name . '[' . $key . ']'; if ( array_key_exists( 'value_labels', $other_args ) && is_array( $other_args['value_labels'] ) && array_key_exists( $possible_value, $other_args['value_labels'] ) ) { $label = $other_args['value_labels'][$possible_value]; } else { $label = $possible_value; } $checkbox_attrs = array( 'id' => $input_id, 'tabindex' => $sfgTabIndex, 'class' => $checkbox_class, ); if ( in_array( $possible_value, $cur_values ) ) { $checkbox_attrs['checked'] = 'checked'; } if ( $is_disabled ) { $checkbox_attrs['disabled'] = 'disabled'; } $checkbox_input = Html::input( $cur_input_name, $possible_value, 'checkbox', $checkbox_attrs ); // Make a span around each checkbox, for CSS purposes. $text .= "\t" . Html::rawElement( 'span', array( 'class' => $span_class ), $checkbox_input . ' ' . $label ) . "\n"; $sfgTabIndex++; $sfgFieldNum++; } $outerSpanID = "span_$sfgFieldNum"; $outerSpanClass = 'checkboxesSpan'; if ( $is_mandatory ) { $outerSpanClass .= ' mandatoryFieldSpan'; } if ( array_key_exists( 'show on select', $other_args ) ) { $outerSpanClass .= ' sfShowIfChecked'; foreach ( $other_args['show on select'] as $div_id => $options ) { if ( array_key_exists( $outerSpanID, $sfgShowOnSelect ) ) { $sfgShowOnSelect[$outerSpanID][] = array( $options, $div_id ); } else { $sfgShowOnSelect[$outerSpanID] = array( array( $options, $div_id ) ); } } } $text .= SFFormUtils::hiddenFieldHTML( $input_name . '[is_list]', 1 ); $outerSpanAttrs = array( 'id' => $outerSpanID, 'class' => $outerSpanClass ); $text = "\t" . Html::rawElement( 'span', $outerSpanAttrs, $text ) . "\n"; return $text; }
public static function getHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) { // escape if CategoryTree extension isn't included if ( !function_exists( 'efCategoryTreeParserHook' ) ) { return null; } global $sfgTabIndex, $sfgFieldNum, $wgCapitalLinks; $input_id = "input_$sfgFieldNum"; // get list delimiter - default is comma if ( array_key_exists( 'delimiter', $other_args ) ) { $delimiter = $other_args['delimiter']; } else { $delimiter = ','; } $cur_values = SFUtils::getValuesArray( $cur_value, $delimiter ); if ( array_key_exists( 'top category', $other_args ) ) { $top_category = $other_args['top category']; } else { // escape - we can't do anything return null; } $hideroot = array_key_exists( 'hideroot', $other_args ); if ( array_key_exists( 'height', $other_args ) ) { $height = $other_args['height']; } else { $height = '100'; } if ( array_key_exists( 'width', $other_args ) ) { $width = $other_args['width']; } else { $width = '500'; } global $wgCategoryTreeMaxDepth; $wgCategoryTreeMaxDepth = 10; $tree = efCategoryTreeParserHook( $top_category, array( 'mode' => 'categories', 'namespaces' => array( NS_CATEGORY ), 'depth' => 10, 'hideroot' => $hideroot, ) ); // Some string that will hopefully never show up in a category, // template or field name. $dummy_str = 'REPLACE THIS STRING!'; $tree = preg_replace( '/(<a class="CategoryTreeLabel.*>)(.*)(<\/a>)/', '<input id="' . $input_id . '" tabindex="' . $sfgTabIndex . '" name="' . $input_name . '[' . $dummy_str . ']" value="$2" type="checkbox"> $1$2$3', $tree ); // replace values one at a time, by an incrementing index - // inspired by http://bugs.php.net/bug.php?id=11457 $i = 0; while ( ( $a = strpos( $tree, $dummy_str ) ) > 0 ) { $tree = substr( $tree, 0, $a ) . $i++ . substr( $tree, $a + strlen( $dummy_str ) ); } // set all checkboxes matching $cur_values to checked foreach ( $cur_values as $value ) { // Capitalize the first letter, if first letters // always get capitalized. if ( $wgCapitalLinks ) { global $wgContLang; $value = $wgContLang->ucfirst( $value ); } $tree = str_replace( "value=\"$value\"", "value=\"$value\" checked=\"checked\"", $tree ); } // if it's disabled, set all to disabled if ( $is_disabled ) { $tree = str_replace( 'type="checkbox"', 'type="checkbox" disabled', $tree ); } // Get rid of all the 'no subcategories' messages. $tree = str_replace( '<div class="CategoryTreeChildren" style="display:block"><i class="CategoryTreeNotice">' . wfMsg( 'categorytree-no-subcategories' ) . '</i></div>', '', $tree ); $text = '<div style="overflow: auto; padding: 5px; border: 1px #aaaaaa solid; max-height: ' . $height . 'px; width: ' . $width . 'px;">' . $tree . '</div>'; $text .= SFFormUtils::hiddenFieldHTML( $input_name . '[is_list]', 1 ); $spanClass = 'checkboxesSpan'; if ( $is_mandatory ) { $spanClass .= ' mandatoryFieldSpan'; } $text = "\n" . Html::rawElement( 'span', array( 'class' => $spanClass ), $text ) . "\n"; return $text; }
static function renderFormInput ( &$parser ) { global $wgVersion; $params = func_get_args(); array_shift( $params ); // don't need the parser // set defaults $inFormName = $inValue = $inButtonStr = $inQueryStr = ''; $inAutocompletionSource = ''; $inRemoteAutocompletion = false; $inSize = 25; $classStr = ""; // assign params - support unlabelled params, for backwards compatibility foreach ( $params as $i => $param ) { $elements = explode( '=', $param, 2 ); $param_name = null; $value = trim( $param ); if ( count( $elements ) > 1 ) { $param_name = trim( $elements[0] ); $value = trim( $parser->recursiveTagParse( $elements[1] ) ); } if ( $param_name == 'form' ) $inFormName = $value; elseif ( $param_name == 'size' ) $inSize = $value; elseif ( $param_name == 'default value' ) $inValue = $value; elseif ( $param_name == 'button text' ) $inButtonStr = $value; elseif ( $param_name == 'query string' ) $inQueryStr = $value; elseif ( $param_name == 'autocomplete on category' ) { $inAutocompletionSource = $value; $autocompletion_type = 'category'; } elseif ( $param_name == 'autocomplete on namespace' ) { $inAutocompletionSource = $value; $autocompletion_type = 'namespace'; } elseif ( $param_name == 'remote autocompletion' ) { $inRemoteAutocompletion = true; } elseif ( $param_name == null && $value == 'popup' ) { self::loadScriptsForPopupForm( $parser ); $classStr = 'popupforminput'; } elseif ( $i == 0 ) $inFormName = $param; elseif ( $i == 1 ) $inSize = $param; elseif ( $i == 2 ) $inValue = $param; elseif ( $i == 3 ) $inButtonStr = $param; elseif ( $i == 4 ) $inQueryStr = $param; } $fs = SFUtils::getSpecialPage( 'FormStart' ); $fs_url = $fs->getTitle()->getLocalURL(); $str = <<<END <form name="createbox" action="$fs_url" method="get" class="$classStr"> <p> END; $formInputAttrs = array( 'size' => $inSize ); // Now apply the necessary settings and Javascript, depending // on whether or not there's autocompletion (and whether the // autocompletion is local or remote). $input_num = 1; if ( empty( $inAutocompletionSource ) ) { $formInputAttrs['class'] = 'formInput'; } else { self::$num_autocompletion_inputs++; $input_num = self::$num_autocompletion_inputs; // place the necessary Javascript on the page, and // disable the cache (so the Javascript will show up) - // if there's more than one autocompleted #forminput // on the page, we only need to do this the first time if ( $input_num == 1 ) { $parser->disableCache(); SFUtils::addJavascriptAndCSS(); } $inputID = 'input_' . $input_num; $formInputAttrs['id'] = $inputID; $formInputAttrs['class'] = 'autocompleteInput createboxInput formInput'; if ( $inRemoteAutocompletion ) { $formInputAttrs['autocompletesettings'] = $inAutocompletionSource; $formInputAttrs['autocompletedatatype'] = $autocompletion_type; } else { $autocompletion_values = SFUtils::getAutocompleteValues( $inAutocompletionSource, $autocompletion_type ); global $sfgAutocompleteValues; $sfgAutocompleteValues[$inputID] = $autocompletion_values; $formInputAttrs['autocompletesettings'] = $inputID; } } $str .= "\t" . Html::input( 'page_name', $inValue, 'text', $formInputAttrs ) . "\n"; // if the form start URL looks like "index.php?title=Special:FormStart" // (i.e., it's in the default URL style), add in the title as a // hidden value if ( ( $pos = strpos( $fs_url, "title=" ) ) > - 1 ) { $str .= SFFormUtils::hiddenFieldHTML( "title", urldecode( substr( $fs_url, $pos + 6 ) ) ); } if ( $inFormName == '' ) { $str .= SFUtils::formDropdownHTML(); } else { $str .= SFFormUtils::hiddenFieldHTML( "form", $inFormName ); } // Recreate the passed-in query string as a set of hidden // variables. // Change HTML-encoded ampersands to URL-encoded ampersands, so // that the string doesn't get split up on the '&'. $inQueryStr = str_replace( '&', '%26', $inQueryStr ); $query_components = explode( '&', $inQueryStr ); foreach ( $query_components as $component ) { // change URL-encoded ampersands back $component = str_replace( '%26', '&', $component ); $subcomponents = explode( '=', $component, 2 ); $key = ( isset( $subcomponents[0] ) ) ? $subcomponents[0] : ''; $val = ( isset( $subcomponents[1] ) ) ? $subcomponents[1] : ''; if ( ! empty( $key ) ) { $str .= '\t\t\t' . Html::hidden( $key, $val ) . "\n"; } } $button_str = ( $inButtonStr != '' ) ? $inButtonStr : wfMsg( 'sf_formstart_createoredit' ); $str .= <<<END <input type="submit" value="$button_str" /></p> </form> END; if ( ! empty( $inAutocompletionSource ) ) { $str .= "\t\t\t" . Html::element( 'div', array( 'class' => 'page_name_auto_complete', 'id' => "div_$input_num", ), // it has to be <div></div>, not // <div />, to work properly - stick // in a space as the content ' ' ) . "\n"; } // hack to remove newline from beginning of output, thanks to // http://jimbojw.com/wiki/index.php?title=Raw_HTML_Output_from_a_MediaWiki_Parser_Function return $parser->insertStripItem( $str, $parser->mStripState ); }
static function formBottom($is_disabled) { global $wgUser; $summary_text = SFFormUtils::summaryInputHTML($is_disabled); $text = <<<END \t<br /><br /> \t<div class='editOptions'> {$summary_text}\t<br /> END; if ($wgUser->isAllowed('minoredit')) { $text .= SFFormUtils::minorEditInputHTML($is_disabled); } if ($wgUser->isLoggedIn()) { $text .= SFFormUtils::watchInputHTML($is_disabled); } $text .= <<<END \t<br /> \t<div class='editButtons'> END; $text .= SFFormUtils::saveButtonHTML($is_disabled); $text .= SFFormUtils::showPreviewButtonHTML($is_disabled); $text .= SFFormUtils::showChangesButtonHTML($is_disabled); $text .= SFFormUtils::cancelLinkHTML($is_disabled); $text .= <<<END \t</div><!-- editButtons --> \t</div><!-- editOptions --> END; return $text; }
function execute( $query ) { global $wgOut, $wgRequest, $wgUser, $sfgScriptPath; $this->setHeaders(); // Cycle through the query values, setting the appropriate // local variables. $category_name = $wgRequest->getVal( 'category_name' ); $default_form = $wgRequest->getVal( 'default_form' ); $parent_category = $wgRequest->getVal( 'parent_category' ); $category_name_error_str = null; $save_page = $wgRequest->getCheck( 'wpSave' ); $preview_page = $wgRequest->getCheck( 'wpPreview' ); if ( $save_page || $preview_page ) { // Validate category name if ( $category_name === '' ) { $category_name_error_str = wfMsg( 'sf_blank_error' ); } else { // Redirect to wiki interface $wgOut->setArticleBodyOnly( true ); $title = Title::makeTitleSafe( NS_CATEGORY, $category_name ); $full_text = SFCreateCategory::createCategoryText( $default_form, $category_name, $parent_category ); $text = SFUtils::printRedirectForm( $title, $full_text, "", $save_page, $preview_page, false, false, false, null, null ); $wgOut->addHTML( $text ); return; } } $all_forms = SFUtils::getAllForms(); // Set 'title' as hidden field, in case there's no URL niceness global $wgContLang; $mw_namespace_labels = $wgContLang->getNamespaces(); $special_namespace = $mw_namespace_labels[NS_SPECIAL]; $text = <<<END <form action="" method="get"> END; $text .= SFFormUtils::hiddenFieldHTML( 'title', "$special_namespace:CreateCategory" ); $firstRow = wfMsg( 'sf_createcategory_name' ) . ' ' . Html::input( 'category_name', null, 'text', array( 'size' => 25 ) ) . "\n"; if ( !is_null( $category_name_error_str ) ) { $firstRow .= Html::element( 'span', array( 'style' => 'color: red;' ), $category_name_error_str ) . "\n"; } $firstRow .= "\t" . wfMsg( 'sf_createcategory_defaultform' ) . "\n"; $formSelector = "\t" . Html::element( 'option', null, null ). "\n"; foreach ( $all_forms as $form ) { $formSelector .= "\t" . Html::element( 'option', null, $form ) . "\n"; } $firstRow .= Html::rawElement( 'select', array( 'id' => 'form_dropdown', 'name' => 'default_form' ), $formSelector ); $text .= Html::rawElement( 'p', null, $firstRow ); $subcategory_label = wfMsg( 'sf_createcategory_makesubcategory' ); $text .= <<<END <p>$subcategory_label <select id="category_dropdown" name="parent_category"> <option></option> END; $categories = SFUtils::getCategoriesForPage(); foreach ( $categories as $category ) { $category = str_replace( '_', ' ', $category ); $text .= "\t" . Html::element( 'option', null, $category ) . "\n"; } $text .= "\t</select>\n"; $editButtonsText = "\t" . Html::input( 'wpSave', wfMsg( 'savearticle' ), 'submit', array( 'id' => 'wpSave' ) ) . "\n"; $editButtonsText .= "\t" . Html::input( 'wpPreview', wfMsg( 'preview' ), 'submit', array( 'id' => 'wpPreview' ) ) . "\n"; $text .= "\t" . Html::rawElement( 'div', array( 'class' => 'editButtons' ), $editButtonsText ) . "\n"; $text .= <<<END <br /><hr /<br /> END; $sk = $wgUser->getSkin(); $create_form_link = SFUtils::linkForSpecialPage( $sk, 'CreateForm' ); $text .= "\t" . Html::rawElement( 'p', null, $create_form_link . '.' ) . "\n"; $text .= "\t</form>\n"; $wgOut->addExtensionStyle( $sfgScriptPath . "/skins/SemanticForms.css" ); $wgOut->addHTML( $text ); }
function printCreateTemplateForm() { global $wgOut, $wgRequest, $wgUser, $sfgScriptPath; self::addJavascript(); $text = ''; $save_page = $wgRequest->getCheck( 'wpSave' ); $preview_page = $wgRequest->getCheck( 'wpPreview' ); if ( $save_page || $preview_page ) { $fields = array(); // Cycle through the query values, setting the // appropriate local variables. foreach ( $wgRequest->getValues() as $var => $val ) { $var_elements = explode( "_", $var ); // we only care about query variables of the form "a_b" if ( count( $var_elements ) != 2 ) continue; list ( $field_field, $id ) = $var_elements; if ( $field_field == 'name' && $id != 'starter' ) { $field = SFTemplateField::create( $val, $wgRequest->getVal( 'label_' . $id ), $wgRequest->getVal( 'semantic_property_' . $id ), $wgRequest->getCheck( 'is_list_' . $id ) ); $fields[] = $field; } } // Assemble the template text, and submit it as a wiki // page. $wgOut->setArticleBodyOnly( true ); $template_name = $wgRequest->getVal( 'template_name' ); $title = Title::makeTitleSafe( NS_TEMPLATE, $template_name ); $category = $wgRequest->getVal( 'category' ); $aggregating_property = $wgRequest->getVal( 'semantic_property_aggregation' ); $aggregation_label = $wgRequest->getVal( 'aggregation_label' ); $template_format = $wgRequest->getVal( 'template_format' ); $full_text = SFTemplateField::createTemplateText( $template_name, $fields, null, $category, $aggregating_property, $aggregation_label, $template_format ); $text = SFUtils::printRedirectForm( $title, $full_text, "", $save_page, $preview_page, false, false, false, null, null ); $wgOut->addHTML( $text ); return; } $text .= ' <form id="createTemplateForm" action="" method="post">' . "\n"; // Set 'title' field, in case there's no URL niceness $text .= SFFormUtils::hiddenFieldHTML( 'title', $this->getTitle()->getPrefixedText() ); $text .= "\t<p id=\"template_name_p\">" . wfMsg( 'sf_createtemplate_namelabel' ) . ' <input size="25" id="template_name" name="template_name" /></p>' . "\n"; $text .= "\t<p>" . wfMsg( 'sf_createtemplate_categorylabel' ) . ' <input size="25" name="category" /></p>' . "\n"; $text .= "\t<fieldset>\n"; $text .= "\t" . Html::element( 'legend', null, wfMsg( 'sf_createtemplate_templatefields' ) ) . "\n"; $text .= "\t" . Html::element( 'p', null, wfMsg( 'sf_createtemplate_fieldsdesc' ) ) . "\n"; $all_properties = self::getAllPropertyNames(); $text .= '<div id="fieldsList">' . "\n"; $text .= self::printFieldEntryBox( "1", $all_properties ); $text .= self::printFieldEntryBox( "starter", $all_properties, false ); $text .= "</div>\n"; $add_field_button = Html::input( null, wfMsg( 'sf_createtemplate_addfield' ), 'button', array( 'onclick' => "createTemplateAddField()" ) ); $text .= Html::rawElement( 'p', null, $add_field_button ) . "\n"; $text .= "\t</fieldset>\n"; $text .= "\t<fieldset>\n"; $text .= "\t" . Html::element( 'legend', null, wfMsg( 'sf_createtemplate_aggregation' ) ) . "\n"; $text .= "\t" . Html::element( 'p', null, wfMsg( 'sf_createtemplate_aggregationdesc' ) ) . "\n"; $text .= "\t<p>" . wfMsg( 'sf_createtemplate_semanticproperty' ) . ' ' . self::printPropertiesDropdown( $all_properties, "aggregation" ) . "</p>\n"; $text .= "\t<p>" . wfMsg( 'sf_createtemplate_aggregationlabel' ) . ' ' . Html::input( 'aggregation_label', null, 'text', array( 'size' => '25' ) ) . "</p>\n"; $text .= "\t</fieldset>\n"; $text .= "\t<p>" . wfMsg( 'sf_createtemplate_outputformat' ) . "\n"; $text .= "\t" . Html::input( 'template_format', 'standard', 'radio', array( 'checked' => true, ), null ) . ' ' . wfMsg( 'sf_createtemplate_standardformat' ) . "\n"; $text .= "\t" . Html::input( 'template_format', 'infobox', 'radio', null ) . ' ' . wfMsg( 'sf_createtemplate_infoboxformat' ) . "</p>\n"; $save_button_text = wfMsg( 'savearticle' ); $preview_button_text = wfMsg( 'preview' ); $text .= <<<END <div class="editButtons"> <input type="submit" id="wpSave" name="wpSave" value="$save_button_text" /> <input type="submit" id="wpPreview" name="wpPreview" value="$preview_button_text" /> </div> </form> END; $sk = $wgUser->getSkin(); $create_property_link = SFUtils::linkForSpecialPage( $sk, 'CreateProperty' ); $text .= "\t<br /><hr /><br />\n"; $text .= "\t" . Html::rawElement( 'p', null, $create_property_link . '.' ) . "\n"; $wgOut->addExtensionStyle( $sfgScriptPath . "/skins/SemanticForms.css" ); $wgOut->addHTML( $text ); }
private function printForm(&$parameters, WebRequest &$request) { global $wgOut, $sfgFormPrinter; // Prepare parameters for SFFormPrinter::formHTML // there is no ONE target page $targetTitle = null; // formDefinition $formName = $request->getText('form'); // if query string did not contain these variables, try the URL if ($formName === '') { $queryparts = explode('/', $parameters); $formName = isset($queryparts[0]) ? $queryparts[0] : null; // if the form name wasn't in the URL either, throw an error if (is_null($formName) || $formName === '') { throw new SPSException(SPSUtils::buildMessage('spserror-noformname')); } } $formTitle = Title::makeTitleSafe(SF_NS_FORM, $formName); if (!$formTitle->exists()) { throw new SPSException(SPSUtils::buildMessage('spserror-formunknown', $formName)); } $formArticle = new Article($formTitle); $formDefinition = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $formArticle->getContent()); // formSubmitted $formSubmitted = false; // pageContents $pageContents = null; // get 'preload' query value, if it exists if ($request->getCheck('preload')) { $pageContents = SFFormUtils::getPreloadedText($request->getVal('preload')); } else { // let other extensions preload the page, if they want wfRunHooks('sfEditFormPreloadText', array(&$pageContents, $targetTitle, $formTitle)); } // pageIsSource $pageIsSource = $pageContents != null; // pageNameFormula // parse the form to see if it has a 'page name' value set $matches; if (preg_match('/{{{info.*page name\\s*=\\s*(.*)}}}/m', $formDefinition, $matches)) { $pageNameElements = SFUtils::getFormTagComponents($matches[1]); $pageNameFormula = $pageNameElements[0]; } else { return 'sf_formedit_badurl'; } // get the iterator parameters $iteratorData = $this->buildIteratorParameters($request); // Call SFFormPrinter::formHTML list($formText, $javascriptText, $dataText, $formPageTitle, $generatedPageName) = $sfgFormPrinter->formHTML($formDefinition, $formSubmitted, $pageIsSource, $formArticle->getID(), $pageContents, '', $pageNameFormula); // Set Special page main header; // override the default title for this page if a title was specified in the form if ($formPageTitle != null) { $wgOut->setPageTitle($formPageTitle); } else { $wgOut->setPageTitle(SPSUtils::buildMessage('sf_formedit_createtitlenotarget', $formTitle->getText())); } $preFormHtml = ''; wfRunHooks('sfHTMLBeforeForm', array(&$targetTitle, &$preFormHtml)); $text = '<form name="createbox" id="sfForm" action="" method="post" class="createbox">' . $preFormHtml . "\n" . SFFormUtils::hiddenFieldHTML('iteratordata', $iteratorData) . $formText; SFUtils::addJavascriptAndCSS(); if (!empty($javascriptText)) { $wgOut->addScript(' <script type="text/javascript">' . "\n{$javascriptText}\n" . '</script>' . "\n"); } $wgOut->addHTML($text); return null; }
public static function getHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) { global $sfgTabIndex, $sfgFieldNum, $sfgShowOnSelect; $className = ( $is_mandatory ) ? 'mandatoryField' : 'createboxInput'; if ( array_key_exists( 'class', $other_args ) ) { $className .= ' ' . $other_args['class']; } $input_id = "input_$sfgFieldNum"; // get list delimiter - default is comma if ( array_key_exists( 'delimiter', $other_args ) ) { $delimiter = $other_args['delimiter']; } else { $delimiter = ','; } $cur_values = SFUtils::getValuesArray( $cur_value, $delimiter ); $className .= ' sfShowIfSelected'; if ( ( $possible_values = $other_args['possible_values'] ) == null ) { $possible_values = array(); } $optionsText = ''; foreach ( $possible_values as $possible_value ) { if ( array_key_exists( 'value_labels', $other_args ) && is_array( $other_args['value_labels'] ) && array_key_exists( $possible_value, $other_args['value_labels'] ) ) { $optionLabel = $other_args['value_labels'][$possible_value]; } else { $optionLabel = $possible_value; } $optionAttrs = array( 'value' => $possible_value ); if ( in_array( $possible_value, $cur_values ) ) { $optionAttrs['selected'] = 'selected'; } $optionsText .= Html::element( 'option', $optionAttrs, $optionLabel ); } $selectAttrs = array( 'id' => $input_id, 'tabindex' => $sfgTabIndex, 'name' => $input_name . '[]', 'class' => $className, 'multiple' => 'multiple' ); if ( array_key_exists( 'size', $other_args ) ) { $selectAttrs['size'] = $other_args['size']; } if ( $is_disabled ) { $selectAttrs['disabled'] = 'disabled'; } $text = Html::rawElement( 'select', $selectAttrs, $optionsText ); $text .= SFFormUtils::hiddenFieldHTML( $input_name . '[is_list]', 1 ); if ( $is_mandatory ) { $text = Html::rawElement( 'span', array( 'class' => 'inputSpan mandatoryFieldSpan' ), $text ); } if ( array_key_exists( 'show on select', $other_args ) ) { foreach ( $other_args['show on select'] as $div_id => $options ) { if ( array_key_exists( $input_id, $sfgShowOnSelect ) ) { $sfgShowOnSelect[$input_id][] = array( $options, $div_id ); } else { $sfgShowOnSelect[$input_id] = array( array( $options, $div_id ) ); } } } return $text; }
function doSpecialCreateForm() { global $wgOut, $wgRequest, $wgUser, $sfgScriptPath; $db = wfGetDB( DB_SLAVE ); // Create Javascript to populate fields to let the user input // parameters for the field, based on the input type selected // in the dropdown. $skin = $wgUser->getSkin(); $url = $skin->makeSpecialUrl( 'CreateForm', "showinputtypeoptions=' + this.val() + '&formfield=' + this.attr('formfieldid') + '" ); foreach ( $wgRequest->getValues() as $param => $value ) { $url .= '¶ms[' . Xml::escapeJsString( $param ) . ']=' . Xml::escapeJsString( $value ); } // Only add 'collapsible' ability if the ResourceLoader exists, // i.e. for MW 1.17 - adding backwards compatibility doesn't // seem worth it for this relatively minor piece of // functionality. if ( method_exists( $wgOut, 'addModules' ) ) { $wgOut->addModules( 'ext.semanticforms.collapsible' ); } $wgOut->addScript("<script> jQuery.fn.displayInputParams = function() { inputParamsDiv = this.closest('.formField').find('.otherInputParams'); jQuery.ajax({ url: '$url', context: document.body, success: function(data){ inputParamsDiv.html(data); } }); }; jQuery(document).ready(function() { jQuery('.inputTypeSelector').change( function() { jQuery(this).displayInputParams(); }); }); </script>"); // Get the names of all templates on this site. $all_templates = array(); $res = $db->select( 'page', 'page_title', array( 'page_namespace' => NS_TEMPLATE, 'page_is_redirect' => 0 ), array( 'ORDER BY' => 'page_title' ) ); if ( $db->numRows( $res ) > 0 ) { while ( $row = $db->fetchRow( $res ) ) { $template_name = str_replace( '_', ' ', $row[0] ); $all_templates[] = $template_name; } } $form_templates = array(); $i = 1; $deleted_template_loc = null; # handle inputs $form_name = $wgRequest->getVal( 'form_name' ); foreach ( $wgRequest->getValues() as $var => $val ) { # ignore variables that are not of the right form if ( strpos( $var, "_" ) != false ) { # get the template declarations and work from there list ( $action, $id ) = explode( "_", $var, 2 ); if ( $action == "template" ) { // If the button was pressed to remove // this template, just don't add it to // the array. if ( $wgRequest->getVal( "del_$id" ) != null ) { $deleted_template_loc = $id; } else { $form_template = SFTemplateInForm::create( $val, $wgRequest->getVal( "label_$id" ), $wgRequest->getVal( "allow_multiple_$id" ) ); $form_templates[] = $form_template; } } } } if ( $wgRequest->getVal( 'add_field' ) != null ) { $form_template = SFTemplateInForm::create( $wgRequest->getVal( 'new_template' ), "", false ); $new_template_loc = $wgRequest->getVal( 'before_template' ); if ( $new_template_loc === null ) { $new_template_loc = 0; } // @HACK - array_splice() doesn't work for objects, so // we have to first insert a stub element into the // array, then replace that with the actual object. array_splice( $form_templates, $new_template_loc, 0, "stub" ); $form_templates[$new_template_loc] = $form_template; } else { $new_template_loc = null; } // Now cycle through the templates and fields, modifying each // one per the query variables. foreach ( $form_templates as $i => $ft ) { foreach ( $ft->getFields() as $j => $field ) { // handle the change in indexing if a new template was // inserted before the end, or one was deleted $old_i = $i; if ( $new_template_loc != null ) { if ( $i > $new_template_loc ) { $old_i = $i - 1; } elseif ( $i == $new_template_loc ) { // it's the new template; it shouldn't // get any query-string data $old_i = - 1; } } elseif ( $deleted_template_loc != null ) { if ( $i >= $deleted_template_loc ) { $old_i = $i + 1; } } foreach ( $wgRequest->getValues() as $key => $value ) { if ( ( $pos = strpos( $key, '_' . $old_i . '_' . $j ) ) != false ) { $paramName = substr( $key, 0, $pos ); // Spaces got replaced by // underlines in the query. $paramName = str_replace( '_', ' ', $paramName ); } else { continue; } if ( $paramName == 'label' ) { $field->template_field->setLabel( $value ); } elseif ( $paramName == 'input type' ) { $input_type = $wgRequest->getVal( "input_type_" . $old_i . "_" . $j ); if ( $input_type == 'hidden' ) { $field->template_field->setInputType( $input_type ); $field->setIsHidden( true ); } elseif ( substr( $input_type, 0, 1 ) == '.' ) { // It's the default input type - // don't do anything. } else { $field->template_field->setInputType( $input_type ); } } else { if ( ! empty( $value ) ) { if ( $value == 'on' ) { $value = true; } $field->setFieldArg( $paramName, $value ); } } } } } $form = SFForm::create( $form_name, $form_templates ); // If a submit button was pressed, create the form-definition // file, then redirect. $save_page = $wgRequest->getCheck( 'wpSave' ); $preview_page = $wgRequest->getCheck( 'wpPreview' ); if ( $save_page || $preview_page ) { // Validate form name if ( $form->getFormName() == "" ) { $form_name_error_str = wfMsg( 'sf_blank_error' ); } else { // Redirect to wiki interface $wgOut->setArticleBodyOnly( true ); $title = Title::makeTitleSafe( SF_NS_FORM, $form->getFormName() ); $full_text = $form->createMarkup(); $text = SFUtils::printRedirectForm( $title, $full_text, "", $save_page, $preview_page, false, false, false, null, null ); $wgOut->addHTML( $text ); return; } } $text = "\t" . '<form action="" method="post">' . "\n"; // Set 'title' field, in case there's no URL niceness $text .= SFFormUtils::hiddenFieldHTML( 'title', $this->getTitle()->getPrefixedText() ); $text .= "\t<p>" . wfMsg( 'sf_createform_nameinput' ) . ' ' . wfMsg( 'sf_createform_nameinputdesc' ) . ' <input size=25 name="form_name" value="' . $form_name . '" />'; if ( ! empty( $form_name_error_str ) ) $text .= "\t" . Html::element( 'font', array( 'color' => 'red' ), $form_name_error_str ); $text .= "</p>\n"; $text .= $form->creationHTML(); $text .= "\t<p>" . wfMsg( 'sf_createform_addtemplate' ) . "\n"; $select_body = ""; foreach ( $all_templates as $template ) { $select_body .= " " . Html::element( 'option', array( 'value' => $template ), $template ) . "\n"; } $text .= "\t" . Html::rawElement( 'select', array( 'name' => 'new_template' ), $select_body ) . "\n"; // If a template has already been added, show a dropdown letting // the user choose where in the list to add a new dropdown. if ( count( $form_templates ) > 0 ) { $before_template_msg = wfMsg( 'sf_createform_beforetemplate' ); $text .= $before_template_msg; $select_body = ""; foreach ( $form_templates as $i => $ft ) { $select_body .= "\t" . Html::element( 'option', array( 'value' => $i ), $ft->getTemplateName() ) . "\n"; } $final_index = count( $form_templates ); $at_end_msg = wfMsg( 'sf_createform_atend' ); $select_body .= "\t" . Html::element( 'option', array( 'value' => $final_index, 'selected' => 'selected' ), $at_end_msg ); $text .= Html::rawElement( 'select', array( 'name' => 'before_template' ), $select_body ) . "\n"; } // Disable 'save' and 'preview' buttons if user has not yet // added any templates. $disabled_text = ( count( $form_templates ) == 0 ) ? "disabled" : ""; $add_button_text = wfMsg( 'sf_createform_add' ); $sk = $wgUser->getSkin(); $create_template_link = SFUtils::linkForSpecialPage( $sk, 'CreateTemplate' ); $text .= "\t" . Html::input( 'add_field', $add_button_text, 'submit' ); $text .= <<<END </p> <br /> END; $saveAttrs = array( 'id' => 'wpSave' ); if ( count( $form_templates ) == 0 ) { $saveAttrs['disabled'] = true; } $editButtonsText = "\t" . Html::input( 'wpSave', wfMsg( 'savearticle' ), 'submit', $saveAttrs ) . "\n"; $previewAttrs = array( 'id' => 'wpPreview' ); if ( count( $form_templates ) == 0 ) { $previewAttrs['disabled'] = true; } $editButtonsText .= "\t" . Html::input( 'wpPreview', wfMsg( 'preview' ), 'submit', $previewAttrs ) . "\n"; $text .= "\t" . Html::rawElement( 'div', array( 'class' => 'editButtons' ), Html::rawElement( 'p', array(), $editButtonsText ) . "\n" ) . "\n"; // Explanatory message if buttons are disabled because no // templates have been added. if ( count( $form_templates ) == 0 ) { $text .= "\t" . Html::element( 'p', null, "(" . wfMsg( 'sf_createtemplate_addtemplatebeforesave' ) . ")" ); } $text .= <<<END </form> <hr /><br /> END; $text .= "\t" . Html::rawElement( 'p', null, $create_template_link . '.' ); $wgOut->addExtensionStyle( $sfgScriptPath . "/skins/SemanticForms.css" ); $wgOut->addHTML( $text ); }
private static function getAllValuesForProperty($property_name, $substring, $base_property_name = null, $base_value = null) { global $sfgMaxAutocompleteValues, $sfgCacheAutocompleteValues, $sfgAutocompleteCacheTimeout; $values = array(); $db = wfGetDB(DB_SLAVE); $sql_options = array(); $sql_options['LIMIT'] = $sfgMaxAutocompleteValues; $property = SMWPropertyValue::makeUserProperty($property_name); $is_relation = $property->getPropertyTypeID() == '_wpg'; $property_name = str_replace(' ', '_', $property_name); $conditions = array('p_ids.smw_title' => $property_name); // Use cache if allowed if ($sfgCacheAutocompleteValues) { $cache = SFFormUtils::getFormCache(); // Remove trailing whitespace to avoid unnecessary database selects $cacheKeyString = $property_name . '::' . rtrim($substring); if (!is_null($base_property_name)) { $cacheKeyString .= ',' . $base_property_name . ',' . $base_value; } $cacheKey = wfMemcKey('sf-autocomplete', md5($cacheKeyString)); $values = $cache->get($cacheKey); if (!empty($values)) { // Return with results immediately return $values; } } if ($is_relation) { $value_field = 'o_ids.smw_title'; $from_clause = $db->tableName('smw_rels2') . " r JOIN " . $db->tableName('smw_ids') . " p_ids ON r.p_id = p_ids.smw_id JOIN " . $db->tableName('smw_ids') . " o_ids ON r.o_id = o_ids.smw_id"; } else { $value_field = 'a.value_xsd'; $from_clause = $db->tableName('smw_atts2') . " a JOIN " . $db->tableName('smw_ids') . " p_ids ON a.p_id = p_ids.smw_id"; } if (!is_null($base_property_name)) { $base_property = SMWPropertyValue::makeUserProperty($base_property_name); $base_is_relation = $base_property->getPropertyTypeID() == '_wpg'; $base_property_name = str_replace(' ', '_', $base_property_name); $conditions['base_p_ids.smw_title'] = $base_property_name; $main_prop_alias = $is_relation ? 'r' : 'a'; if ($base_is_relation) { $from_clause .= " JOIN " . $db->tableName('smw_rels2') . " r_base ON {$main_prop_alias}.s_id = r_base.s_id"; $from_clause .= " JOIN " . $db->tableName('smw_ids') . " base_p_ids ON r_base.p_id = base_p_ids.smw_id JOIN " . $db->tableName('smw_ids') . " base_o_ids ON r_base.o_id = base_o_ids.smw_id"; $base_value = str_replace(' ', '_', $base_value); $conditions['base_o_ids.smw_title'] = $base_value; } else { $from_clause .= " JOIN " . $db->tableName('smw_atts2') . " a_base ON {$main_prop_alias}.s_id = a_base.s_id"; $from_clause .= " JOIN " . $db->tableName('smw_ids') . " base_p_ids ON a_base.p_id = base_p_ids.smw_id"; $conditions['a_base.value_xsd'] = $base_value; } } if (!is_null($substring)) { $conditions[] = SFUtils::getSQLConditionForAutocompleteInColumn($value_field, $substring); } $sql_options['ORDER BY'] = $value_field; $res = $db->select($from_clause, "DISTINCT {$value_field}", $conditions, __METHOD__, $sql_options); while ($row = $db->fetchRow($res)) { $values[] = str_replace('_', ' ', $row[0]); } $db->freeResult($res); if ($sfgCacheAutocompleteValues) { // Save to cache. $cache->set($cacheKey, $values, $sfgAutocompleteCacheTimeout); } return $values; }
function execute( $query ) { global $wgOut, $wgRequest, $wgUser, $sfgScriptPath; global $wgLang, $smwgContLang; # Check permissions if ( !$wgUser->isAllowed( 'createclass' ) ) { $this->displayRestrictionError(); return; } $this->setHeaders(); $wgOut->addExtensionStyle( $sfgScriptPath . "/skins/SemanticForms.css" ); $numStartingRows = 10; self::addJavascript( $numStartingRows ); $property_name_error_str = ''; $save_page = $wgRequest->getCheck( 'save' ); if ( $save_page ) { $template_name = trim( $wgRequest->getVal( "template_name" ) ); $form_name = trim( $wgRequest->getVal( "form_name" ) ); $category_name = trim( $wgRequest->getVal( "category_name" ) ); if ( $template_name === '' | $form_name === '' || $category_name === '' ) { $wgOut->addWikiMsg( 'sf_createclass_missingvalues' ); return; } $fields = array(); $jobs = array(); // cycle through all the rows passed in for ( $i = 1; $wgRequest->getCheck( "property_name_$i" ); $i++ ) { // go through the query values, setting the appropriate local variables $property_name = trim( $wgRequest->getVal( "property_name_$i" ) ); if ( empty( $property_name ) ) continue; $field_name = trim( $wgRequest->getVal( "field_name_$i" ) ); if ( $field_name === '' ) $field_name = $property_name; $property_type = $wgRequest->getVal( "property_type_$i" ); $allowed_values = $wgRequest->getVal( "allowed_values_$i" ); $is_list = $wgRequest->getCheck( "is_list_$i" ); // create an SFTemplateField based on these // values, and add it to the $fields array $field = SFTemplateField::create( $field_name, $field_name, $property_name, $is_list ); $fields[] = $field; // create the property, and make a job for it $full_text = SFCreateProperty::createPropertyText( $property_type, '', $allowed_values ); $property_title = Title::makeTitleSafe( SMW_NS_PROPERTY, $property_name ); $params = array(); $params['user_id'] = $wgUser->getId(); $params['page_text'] = $full_text; $jobs[] = new SFCreatePageJob( $property_title, $params ); } // create the template, and save it $full_text = SFTemplateField::createTemplateText( $template_name, $fields, null, $category_name, null, null, null ); $template_title = Title::makeTitleSafe( NS_TEMPLATE, $template_name ); $template_article = new Article( $template_title, 0 ); $edit_summary = ''; $template_article->doEdit( $full_text, $edit_summary ); // create the form, and make a job for it $form_template = SFTemplateInForm::create( $template_name, '', false ); $form_templates = array( $form_template ); $form = SFForm::create( $form_name, $form_templates ); $full_text = $form->createMarkup(); $form_title = Title::makeTitleSafe( SF_NS_FORM, $form_name ); $params = array(); $params['user_id'] = $wgUser->getId(); $params['page_text'] = $full_text; $jobs[] = new SFCreatePageJob( $form_title, $params ); // create the category, and make a job for it $full_text = SFCreateCategory::createCategoryText( $form_name, $category_name, '' ); $category_title = Title::makeTitleSafe( NS_CATEGORY, $category_name ); $params = array(); $params['user_id'] = $wgUser->getId(); $params['page_text'] = $full_text; $jobs[] = new SFCreatePageJob( $category_title, $params ); Job::batchInsert( $jobs ); $wgOut->addWikiMsg( 'sf_createclass_success' ); return; } $datatype_labels = $smwgContLang->getDatatypeLabels(); // make links to all the other 'Create...' pages, in order to // link to them at the top of the page $sk = $wgUser->getSkin(); $creation_links = array(); $creation_links[] = SFUtils::linkForSpecialPage( $sk, 'CreateProperty' ); $creation_links[] = SFUtils::linkForSpecialPage( $sk, 'CreateTemplate' ); $creation_links[] = SFUtils::linkForSpecialPage( $sk, 'CreateForm' ); $creation_links[] = SFUtils::linkForSpecialPage( $sk, 'CreateCategory' ); $create_class_docu = wfMsg( 'sf_createclass_docu', $wgLang->listToText( $creation_links ) ); $leave_field_blank = wfMsg( 'sf_createclass_leavefieldblank' ); $form_name_label = wfMsg( 'sf_createclass_nameinput' ); $template_name_label = wfMsg( 'sf_createtemplate_namelabel' ); $category_name_label = wfMsg( 'sf_createcategory_name' ); $property_name_label = wfMsg( 'sf_createproperty_propname' ); $field_name_label = wfMsg( 'sf_createtemplate_fieldname' ); $type_label = wfMsg( 'sf_createproperty_proptype' ); $allowed_values_label = wfMsg( 'sf_createclass_allowedvalues' ); $list_of_values_label = wfMsg( 'sf_createclass_listofvalues' ); $text = <<<END <form action="" method="post"> <p>$create_class_docu</p> <p>$leave_field_blank</p> <p>$template_name_label <input type="text" size="30" name="template_name"></p> <p>$form_name_label <input type="text" size="30" name="form_name"></p> <p>$category_name_label <input type="text" size="30" name="category_name"></p> <div> <table id="mainTable"> <tr> <th colspan="2">$property_name_label</th> <th>$field_name_label</th> <th>$type_label</th> <th>$allowed_values_label</th> <th>$list_of_values_label</th> </tr> END; // Make one more row than what we're displaying - use the // last row as a "starter row", to be cloned when the // "Add another" button is pressed. for ( $i = 1; $i <= $numStartingRows + 1; $i++ ) { if ( $i == $numStartingRows + 1 ) { $rowString = 'id="starterRow" style="display: none"'; $n = 'starter'; } else { $rowString = ''; $n = $i; } $text .= <<<END <tr $rowString> <td>$n.</td> <td><input type="text" size="25" name="property_name_$n" /></td> <td><input type="text" size="25" name="field_name_$n" /></td> <td> <select name="property_type_$n"> END; $optionsStr =""; foreach ( $datatype_labels as $label ) { $text .= " <option>$label</option>\n"; $optionsStr .= $label . ","; } $text .= <<<END </select> </td> <td><input type="text" size="25" name="allowed_values_$n" /></td> <td><input type="checkbox" name="is_list_$n" /></td> END; } $text .= <<<END </tr> </table> </div> END; $add_another_button = Html::element( 'input', array( 'type' => 'button', 'value' => wfMsg( 'sf_formedit_addanother' ), 'onclick' => "createClassAddRow()" ) ); $text .= Html::rawElement( 'p', null, $add_another_button ) . "\n"; // Set 'title' as hidden field, in case there's no URL niceness $cc = $this->getTitle(); $text .= SFFormUtils::hiddenFieldHTML( 'title', SFUtils::titleURLString( $cc ) ); $text .= Html::element( 'input', array( 'type' => 'submit', 'name' => 'save', 'value' => wfMsg( 'sf_createclass_create' ) ) ); $text .= "</form>\n"; $wgOut->addHTML( $text ); }
/** * Prints the mini-form contained at the bottom of various pages, that * allows pages to spoof a normal edit page, that can preview, save, * etc. */ public static function printRedirectForm( $title, $page_contents, $edit_summary, $is_save, $is_preview, $is_diff, $is_minor_edit, $watch_this, $start_time, $edit_time ) { global $wgUser, $sfgScriptPath; if ( $is_save ) { $action = "wpSave"; } elseif ( $is_preview ) { $action = "wpPreview"; } else { // $is_diff $action = "wpDiff"; } $text = <<<END <p style="position: absolute; left: 45%; top: 45%;"><img src="$sfgScriptPath/skins/loading.gif" /></p> END; $form_body = SFFormUtils::hiddenFieldHTML( 'wpTextbox1', $page_contents ); $form_body .= SFFormUtils::hiddenFieldHTML( 'wpSummary', $edit_summary ); $form_body .= SFFormUtils::hiddenFieldHTML( 'wpStarttime', $start_time ); $form_body .= SFFormUtils::hiddenFieldHTML( 'wpEdittime', $edit_time ); $form_body .= SFFormUtils::hiddenFieldHTML( 'wpEditToken', $wgUser->isLoggedIn() ? $wgUser->editToken() : EDIT_TOKEN_SUFFIX ); $form_body .= SFFormUtils::hiddenFieldHTML( $action, null ); if ( $is_minor_edit ) { $form_body .= SFFormUtils::hiddenFieldHTML( 'wpMinoredit' , null ); } if ( $watch_this ) { $form_body .= SFFormUtils::hiddenFieldHTML( 'wpWatchthis', null ); } $text .= Html::rawElement( 'form', array( 'id' => 'editform', 'name' => 'editform', 'method' => 'post', 'action' => $title instanceof Title ? $title->getLocalURL( 'action=submit' ) : $title ), $form_body ); $text .= <<<END <script type="text/javascript"> window.onload = function() { document.editform.submit(); } </script> END; wfRunHooks( 'sfPrintRedirectForm', array( $is_save, $is_preview, $is_diff, &$text ) ); return $text; }