Yaron Koren has submitted this change and it was merged. Change subject: Added "SFWikiPage" classes, intended for creation of page text ......................................................................
Added "SFWikiPage" classes, intended for creation of page text Also slightly modified the relevant SF tests Change-Id: Ia643c7ee0c8692bc18f0200de270b4c317eb2603 --- M SemanticForms.php M extension.json M includes/SF_FormPrinter.php M includes/SF_FormUtils.php M includes/SF_PageSection.php M includes/SF_TemplateInForm.php A includes/wikipage/SF_WikiPage.php A includes/wikipage/SF_WikiPageFreeText.php A includes/wikipage/SF_WikiPageSection.php A includes/wikipage/SF_WikiPageTemplate.php A includes/wikipage/SF_WikiPageTemplateParam.php M tests/phpunit/includes/SF_FormPrinterTest.php 12 files changed, 423 insertions(+), 165 deletions(-) Approvals: Yaron Koren: Checked; Looks good to me, approved jenkins-bot: Verified diff --git a/SemanticForms.php b/SemanticForms.php index fd6a444..3e2b6a5 100644 --- a/SemanticForms.php +++ b/SemanticForms.php @@ -226,6 +226,11 @@ $GLOBALS['wgAutoloadClasses']['SFTokensInput'] = __DIR__ . '/includes/forminputs/SF_TokensInput.php'; $GLOBALS['wgAutoloadClasses']['SFGoogleMapsInput'] = __DIR__ . '/includes/forminputs/SF_GoogleMapsInput.php'; $GLOBALS['wgAutoloadClasses']['SFOpenLayersInput'] = __DIR__ . '/includes/forminputs/SF_OpenLayersInput.php'; +$GLOBALS['wgAutoloadClasses']['SFWikiPage'] = __DIR__ . '/includes/wikipage/SF_WikiPage.php'; +$GLOBALS['wgAutoloadClasses']['SFWikiPageTemplate'] = __DIR__ . '/includes/wikipage/SF_WikiPageTemplate.php'; +$GLOBALS['wgAutoloadClasses']['SFWikiPageTemplateParam'] = __DIR__ . '/includes/wikipage/SF_WikiPageTemplateParam.php'; +$GLOBALS['wgAutoloadClasses']['SFWikiPageSection'] = __DIR__ . '/includes/wikipage/SF_WikiPageSection.php'; +$GLOBALS['wgAutoloadClasses']['SFWikiPageFreeText'] = __DIR__ . '/includes/wikipage/SF_WikiPageFreeText.php'; $GLOBALS['wgJobClasses']['createPage'] = 'SFCreatePageJob'; $GLOBALS['wgAutoloadClasses']['SFCreatePageJob'] = __DIR__ . '/includes/SF_CreatePageJob.php'; diff --git a/extension.json b/extension.json index 5c797ed..4266314 100644 --- a/extension.json +++ b/extension.json @@ -114,6 +114,11 @@ "SFTokensInput": "includes/forminputs/SF_TokensInput.php", "SFGoogleMapsInput": "includes/forminputs/SF_GoogleMapsInput.php", "SFOpenLayersInput": "includes/forminputs/SF_OpenLayersInput.php", + "SFWikiPage": "includes/wikipage/SF_WikiPage.php", + "SFWikiPageTemplate": "includes/wikipage/SF_WikiPageTemplate.php", + "SFWikiPageTemplateParam": "includes/wikipage/SF_WikiPageTemplateParam.php", + "SFWikiPageSection": "includes/wikipage/SF_WikiPageSection.php", + "SFWikiPageFreeText": "includes/wikipage/SF_WikiPageFreeText.php", "SFCreatePageJob": "includes/SF_CreatePageJob.php", "SF_Language": "languages/SF_Language.php" }, diff --git a/includes/SF_FormPrinter.php b/includes/SF_FormPrinter.php index bcef713..10ec236 100644 --- a/includes/SF_FormPrinter.php +++ b/includes/SF_FormPrinter.php @@ -272,10 +272,6 @@ return $templateName . '___' . $fieldName; } - static function makePlaceholderInWikiText( $str ) { - return '@replace_' . $str . '@'; - } - static function makePlaceholderInFormHTML( $str ) { return '@insertHTML_' . $str . '@'; } @@ -544,6 +540,7 @@ 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; @@ -556,8 +553,6 @@ // 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 @@ -693,14 +688,12 @@ // existing article as well, finding template and field // declarations and replacing them with form elements, either // blank or pre-populated, as appropriate. - $data_text = ""; $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; - $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]; @@ -719,12 +712,11 @@ } else { $previous_template_name = ''; } - $template_name = $tag_components[1]; + $template_name = str_replace( '_', ' ', $tag_components[1] ); $is_new_template = ( $template_name != $previous_template_name ); if ( $is_new_template ) { $tif = SFTemplateInForm::newFromFormTag( $tag_components ); } - $template_text .= "{{" . $tif->getTemplateName(); // Remove template tag. $section = substr_replace( $section, '', $brackets_loc, $brackets_end_loc + 3 - $brackets_loc ); // If we are editing a page, and this @@ -765,6 +757,8 @@ } $tif->checkIfAllInstancesPrinted( $form_submitted, $source_is_page ); + + $wiki_page->addTemplate( $tif ); // ===================================================== // end template processing @@ -857,8 +851,7 @@ } } $free_text_was_included = true; - // add a similar placeholder to the data text - $data_text .= "!free_text!\n"; + $wiki_page->addFreeTextSection(); } if ( $tif->getTemplateName() === '' || $field_name == '<freetext>' ) { @@ -950,13 +943,6 @@ $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 ( $form_field->holdsTemplate() ) { - $cur_value = self::makePlaceholderInWikiText( self::placeholderFormat( $tif->getTemplateName(), $field_name ) ); - } - // If all instances have been // printed, that means we're // now printing a "starter" @@ -973,15 +959,7 @@ $new_text .= $form_field->additionalHTMLForInput( $cur_value, $field_name, $tif->getTemplateName() ); 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"; - } - } + $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; @@ -1093,11 +1071,6 @@ } } - // Generate the wikitext for the section header - $header_string = str_repeat( "=", $header_level ); - $header_text = $header_string . $section_name . $header_string . "\n"; - $data_text .= $header_text; - // split the existing page contents into the textareas in the form $default_value = ""; $section_start_loc = 0; @@ -1141,14 +1114,9 @@ //if input is from the form $section_text = ""; if ( ( ! $source_is_page ) && $wgRequest ) { - $section_text = $wgRequest->getArray( '_section' ); - $default_value = $section_text[trim( $section_name )]; - - if ( $default_value == "" || $default_value == null ) { - $data_text .= $default_value . "\n\n"; - } else { - $data_text .= rtrim( $default_value ) . "\n\n"; - } + $text_per_section = $wgRequest->getArray( '_section' ); + $section_text = $text_per_section[trim( $section_name )]; + $wiki_page->addSection( $section_name, $header_level, $section_text ); } //set input name for query string @@ -1196,7 +1164,7 @@ // 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; + $wiki_page->makeFreeTextOnlyInclude(); } elseif ( $tag == 'query form at top' ) { // TODO - this should be made a field of // some non-static class that actually @@ -1216,55 +1184,22 @@ } // end if } // end while - if ( !$tif || !$tif->allInstancesPrinted() ) { - 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 ( !$tif->allowsMultiple() ) { - $template_text .= SFFormUtils::addUnhandledFields( $tif->getTemplateName() ); - } - $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( $tif->getPlaceholder() ); - if ( $tif->getPlaceholder() != null && $data_text && strpos( $data_text, $reptmp, 0 ) !== false ) { - $data_text = str_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', '}�', + 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 ) ) . - "{{{insertionpoint}}}" . $existing_page_content; - } + "\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; } } @@ -1279,13 +1214,14 @@ } else { $multipleTemplateHTML .= $this->multipleTemplateEndHTML( $tif, $form_is_disabled, $section ); } - if ( $tif->getPlaceholder() != null ) { - $multipleTemplateHTML .= self::makePlaceholderInFormHTML( $tif->getPlaceholder() ); + $placeholder = $tif->getPlaceholder(); + if ( $placeholder != null ) { + $multipleTemplateHTML .= self::makePlaceholderInFormHTML( $placeholder ); } if ( $tif->allInstancesPrinted() && $tif->getLabel() != null ) { $multipleTemplateHTML .= "</fieldset>\n"; } - if ( $tif->getPlaceholder() == null ) { + if ( $placeholder == null ) { // The normal process. $form_text .= $multipleTemplateHTML; } else { @@ -1304,7 +1240,7 @@ // 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( $tif->getPlaceholder() ), $multipleTemplateHTML, $form_text ); + $form_text = str_replace( self::makePlaceholderInFormHTML( $placeholder ), $multipleTemplateHTML, $form_text ); } if ( ! $tif->allInstancesPrinted() ) { // This will cause the section to be @@ -1321,11 +1257,6 @@ // 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 = str_replace( self::makePlaceholderInWikiText( $stringToReplace ), '', $data_text ); - // Remove the @<insertHTML>@ tags from the generated // HTML form. $form_text = str_replace( self::makePlaceholderInFormHTML( $stringToReplace ), '', $form_text ); @@ -1362,18 +1293,19 @@ } elseif ( $wgRequest->getCheck( 'sf_free_text' ) ) { $free_text = $wgRequest->getVal( 'sf_free_text' ); if ( ! $free_text_was_included ) { - $data_text .= "!free_text!"; + $wiki_page->addFreeTextSection(); } } else { $free_text = null; } - if ( $onlyinclude_free_text ) { - // modify free text and data text to insert <onlyinclude> tags + + if ( $wiki_page->freeTextOnlyInclude() ) { $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 ); } + + $page_text = ''; // The first hook here is deprecated. Use the second. // Note: Hooks::run can take a third argument which indicates @@ -1381,12 +1313,16 @@ // an extension version. Hooks::run( 'sfModifyFreeTextField', array( &$free_text, $existing_page_content ) ); Hooks::run( 'sfBeforeFreeTextSubstitution', - array( &$free_text, $existing_page_content, &$data_text ) ); + array( &$free_text, $existing_page_content, &$page_text ) ); - // now that we have it, substitute free text into the form and page + // 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 ); - $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. @@ -1425,10 +1361,10 @@ // 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 + // If doing a replace, the page text is actually the modified // original page. if ( $wgRequest->getCheck( 'partial' ) ) { - $data_text = $existing_page_content; + $page_text = $existing_page_content; } if ( !$is_embedded ) { @@ -1446,7 +1382,7 @@ // $wgParser = $oldParser; - return array( $form_text, $javascript_text, $data_text, $form_page_title, $generated_page_name ); + return array( $form_text, $javascript_text, $page_text, $form_page_title, $generated_page_name ); } /** diff --git a/includes/SF_FormUtils.php b/includes/SF_FormUtils.php index 6566b74..a93b2c3 100644 --- a/includes/SF_FormUtils.php +++ b/includes/SF_FormUtils.php @@ -50,26 +50,6 @@ return $text; } - /** - * Add unhandled fields back into the template call that the form - * generates, so that editing with a form will have no effect on them - */ - static function addUnhandledFields( $templateName ) { - global $wgRequest; - - $templateName = str_replace( ' ', '_', $templateName ); - $prefix = '_unhandled_' . $templateName . '_'; - $prefixSize = strlen( $prefix ); - $additional_template_text = ""; - foreach ( $wgRequest->getValues() as $key => $value ) { - if ( strpos( $key, $prefix ) === 0 ) { - $field_name = urldecode( substr( $key, $prefixSize ) ); - $additional_template_text .= "|$field_name=$value\n"; - } - } - return $additional_template_text; - } - static function summaryInputHTML( $is_disabled, $label = null, $attr = array(), $value = '' ) { global $sfgTabIndex; diff --git a/includes/SF_PageSection.php b/includes/SF_PageSection.php index f7773fd..f35ed88 100644 --- a/includes/SF_PageSection.php +++ b/includes/SF_PageSection.php @@ -1,6 +1,9 @@ <?php /** * Represents a page section in a user-defined form. + * This class should really be called "SFPageSectionInForm", to differentiate + * it from the SFWikiPageSection class. + * * @author Himeshi * @file * @ingroup SF diff --git a/includes/SF_TemplateInForm.php b/includes/SF_TemplateInForm.php index eab14fe..1fad687 100644 --- a/includes/SF_TemplateInForm.php +++ b/includes/SF_TemplateInForm.php @@ -14,6 +14,8 @@ private $mMinAllowed; private $mMaxAllowed; private $mFields; + private $mEmbedInTemplate; + private $mEmbedInField; private $mSearchTemplateStr; private $mPregMatchTemplateStr; @@ -284,6 +286,14 @@ return $this->mFields; } + function getEmbedInTemplate() { + return $this->mEmbedInTemplate; + } + + function getEmbedInField() { + return $this->mEmbedInField; + } + function getLabel() { return $this->mLabel; } @@ -349,7 +359,7 @@ public static function newFromFormTag( $tag_components ) { global $wgParser; - $template_name = trim( $tag_components[1] ); + $template_name = str_replace( '_', ' ', trim( $tag_components[1] ) ); $tif = SFTemplateInForm::create( $template_name ); $tif->mAddButtonText = wfMessage( 'sf_formedit_addanother' )->text(); // Cycle through the other components. @@ -376,7 +386,11 @@ // We expect something like TemplateName[fieldName], and convert it to the // TemplateName___fieldName form used internally. preg_match( '/\s*(.*)\[(.*)\]\s*/', $sub_components[1], $matches ); - $tif->mPlaceholder = ( count( $matches ) > 2 ) ? SFFormPrinter::placeholderFormat( $matches[1], $matches[2] ) : null; + if ( count( $matches ) > 2 ) { + $tif->mEmbedInTemplate = $matches[1]; + $tif->mEmbedInField = $matches[2]; + $tif->mPlaceholder = SFFormPrinter::placeholderFormat( $tif->mEmbedInTemplate, $tif->mEmbedInField ); + } } } } @@ -416,7 +430,7 @@ if ( $this->mNumInstancesFromSubmit > $this->mInstanceNum ) { $instanceKey = $valuesFromSubmitKeys[$this->mInstanceNum]; $this->mValuesFromSubmit = $allValuesFromSubmit[$instanceKey]; - } + } } else { $this->mValuesFromSubmit = $allValuesFromSubmit; } @@ -513,30 +527,30 @@ $this->mPageCallsThisTemplate = preg_match( '/{{' . $this->mPregMatchTemplateStr . '\s*[\|}]/i', str_replace( '_', ' ', $existing_page_content ) ); } - function checkIfAllInstancesPrinted( $form_submitted, $source_is_page ) { - // 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. - // @TODO - 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. - // (Also add additional, blank instances if there's a minimum - // number required in this form, and we haven't reached it yet.) - if ( !$this->mAllowMultiple ) { - return; - } - if ( $this->mInstanceNum < $this->mMinAllowed ) { - return; - } - if ( $form_submitted && $this->mInstanceNum < $this->mNumInstancesFromSubmit ) { - return; - } - if ( !$form_submitted && $source_is_page && $this->mPageCallsThisTemplate ) { - return; - } - $this->mAllInstancesPrinted = true; - } + function checkIfAllInstancesPrinted( $form_submitted, $source_is_page ) { + // 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. + // @TODO - 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. + // (Also add additional, blank instances if there's a minimum + // number required in this form, and we haven't reached it yet.) + if ( !$this->mAllowMultiple ) { + return; + } + if ( $this->mInstanceNum < $this->mMinAllowed ) { + return; + } + if ( $form_submitted && $this->mInstanceNum < $this->mNumInstancesFromSubmit ) { + return; + } + if ( !$form_submitted && $source_is_page && $this->mPageCallsThisTemplate ) { + return; + } + $this->mAllInstancesPrinted = true; + } function creationHTML( $template_num ) { $checked_attribs = ( $this->mAllowMultiple ) ? array( 'checked' => 'checked' ) : array(); diff --git a/includes/wikipage/SF_WikiPage.php b/includes/wikipage/SF_WikiPage.php new file mode 100644 index 0000000..54120cf --- /dev/null +++ b/includes/wikipage/SF_WikiPage.php @@ -0,0 +1,183 @@ +<?php +/** + * @author Yaron Koren + * @file + * @ingroup SF + */ + +/** + * Represents the structured contents of a wiki page. + */ +class SFWikiPage { + private $mComponents = array(); + private $mEmbeddedTemplateDefs = array(); + private $mEmbeddedTemplateCalls = array(); + private $mFreeTextOnlyInclude = false; + + function addTemplate( $templateInForm ) { + if ( $templateInForm->allInstancesPrinted() ) { + return; + } + + $templateName = $templateInForm->getTemplateName(); + $this->mComponents[] = new SFWikiPageTemplate( $templateName, !$templateInForm->allowsMultiple() ); + if ( $templateInForm->getInstanceNum() == 0 ) { + $embedInTemplate = $templateInForm->getEmbedInTemplate(); + $embedInParam = $templateInForm->getEmbedInField(); + if ( $embedInTemplate != null && $embedInParam != null ) { + $this->mEmbeddedTemplateDefs[] = array( $embedInTemplate, $embedInParam, $templateName ); + } + } + } + + function addTemplateParam( $templateName, $instanceNum, $paramName, $value ) { + $curInstance = 0; + foreach ( $this->mComponents as $i => $component ) { + if ( get_class( $component ) == 'SFWikiPageTemplate' && $component->getName() == $templateName ) { + if ( $curInstance++ == $instanceNum ) { + $this->mComponents[$i]->addParam( $paramName, $value ); + return; + } + } + } + } + + function getEmbeddedTemplateForParam( $templateName, $paramName ) { + foreach ( $this->mEmbeddedTemplateDefs as $etd ) { + if ( $etd[0] == $templateName && $etd[1] == $paramName ) { + return $etd[2]; + } + } + return null; + } + + function addSection( $sectionName, $headerLevel, $sectionText ) { + $this->mComponents[] = new SFWikiPageSection( $sectionName, $headerLevel, $sectionText ); + } + + function addFreeTextSection() { + $this->mComponents[] = new SFWikiPageFreeText(); + } + + function setFreeText( $text ) { + foreach ( $this->mComponents as $i => $component ) { + if ( get_class( $component ) == 'SFWikiPageFreeText' ) { + $this->mComponents[$i]->setText( $text ); + } + } + // Throw an exception here if no free text section found? + } + + function makeFreeTextOnlyInclude() { + $this->mFreeTextOnlyInclude = true; + } + + function freeTextOnlyInclude() { + return $this->mFreeTextOnlyInclude; + } + + /** + * Create an array of the template calls in the page that are embedded + * in other templates. + */ + private function findEmbeddedTemplates() { + foreach ( $this->mEmbeddedTemplateDefs as $etd ) { + $embeddedTemplateName = $etd[2]; + foreach ( $this->mComponents as $component ) { + if ( get_class( $component ) == 'SFWikiPageTemplate' ) { + if ( $embeddedTemplateName == $component->getName() ) { + if ( !array_key_exists( $embeddedTemplateName, $this->mEmbeddedTemplateCalls ) ) { + $this->mEmbeddedTemplateCalls[$embeddedTemplateName] = array(); + } + $this->mEmbeddedTemplateCalls[$embeddedTemplateName][] = $component; + } + } + } + } + } + + function createTemplateCall( $template ) { + $template->addUnhandledParams(); + + $templateCall = '{{' . $template->getName(); + foreach( $template->getParams() as $templateParam ) { + $paramName = $templateParam->getName(); + $embeddedTemplateName = $this->getEmbeddedTemplateForParam( $template->getName(), $paramName ); + $paramValue = $templateParam->getValue(); + + // If there's no value, skip this param. + if ( $embeddedTemplateName == '' && $paramValue == '' ) { + continue; + } + + // Include the field name only for non-numeric field names. + if ( is_numeric( $paramName ) ) { + $templateCall .= '|'; + } else { + $templateCall .= "\n|$paramName="; + } + if ( $embeddedTemplateName != '' ) { + foreach ( $this->mEmbeddedTemplateCalls[$embeddedTemplateName] as $embeddedTemplate ) { + $templateCall .= $this->createTemplateCall( $embeddedTemplate ); + } + } else { + $templateCall .= $paramValue; + } + } + // 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. + $templateCall = preg_replace( '/\|*$/', '', $templateCall ); + + // Add another newline before the final bracket, if this + // template call is already more than one line + if ( strpos( $templateCall, "\n" ) ) { + $templateCall .= "\n"; + } + $templateCall .= "}}"; + + return $templateCall; + } + + function createTemplateCallsForTemplateName( $templateName ) { + $text = ''; + foreach ( $this->mComponents as $component ) { + if ( get_class( $component ) == 'SFWikiPageTemplate' ) { + if ( $component->getName() == $templateName ) { + $text .= $this->createTemplateCall( $component ) . "\n"; + } + } + } + return $text; + } + + function createPageText() { + // First, go through and store the templates that are embedded, + // so that they can have special printing. + $this->findEmbeddedTemplates(); + + // Now create the text. + $pageText = ''; + foreach ( $this->mComponents as $component ) { + if ( get_class( $component ) == 'SFWikiPageTemplate' ) { + if ( !array_key_exists( $component->getName(), $this->mEmbeddedTemplateCalls ) ) { + $pageText .= $this->createTemplateCall( $component ) . "\n"; + } + } elseif ( get_class( $component ) == 'SFWikiPageSection' ) { + $sectionName = $component->getHeader(); + for ( $i = 0; $i < $component->getHeaderLevel(); $i++ ) { + $sectionName = "=$sectionName="; + } + $pageText .= "$sectionName\n"; + $pageText .= $component->getText() . "\n"; + } elseif ( get_class( $component ) == 'SFWikiPageFreeText' ) { + $freeText = $component->getText(); + if ( $this->mFreeTextOnlyInclude ) { + $freeText = "<onlyinclude>$freeText</onlyinclude>"; + } + $pageText .= "$freeText\n"; + } + } + return $pageText; + } +} diff --git a/includes/wikipage/SF_WikiPageFreeText.php b/includes/wikipage/SF_WikiPageFreeText.php new file mode 100644 index 0000000..db1c3f1 --- /dev/null +++ b/includes/wikipage/SF_WikiPageFreeText.php @@ -0,0 +1,22 @@ +<?php +/** + * @author Yaron Koren + * @file + * @ingroup SF + */ + +/** + * Represents the "free text" in a wiki page, i.e. the text not in + * pre-defined template calls and sections. + */ +class SFWikiPageFreeText { + private $mText; + + function setText( $text ) { + $this->mText = $text; + } + + function getText() { + return $this->mText; + } +} diff --git a/includes/wikipage/SF_WikiPageSection.php b/includes/wikipage/SF_WikiPageSection.php new file mode 100644 index 0000000..bef2143 --- /dev/null +++ b/includes/wikipage/SF_WikiPageSection.php @@ -0,0 +1,31 @@ +<?php +/** + * @author Yaron Koren + * @file + * @ingroup SF + */ + +/** + * Represents a section (header and contents) in a wiki page. + */ +class SFWikiPageSection { + private $mHeader, $mHeaderLevel, $mText; + + function __construct( $sectionName, $headerLevel, $sectionText ) { + $this->mHeader = $sectionName; + $this->mHeaderLevel = $headerLevel; + $this->mText = $sectionText; + } + + function getHeader() { + return $this->mHeader; + } + + function getHeaderLevel() { + return $this->mHeaderLevel; + } + + function getText() { + return $this->mText; + } +} diff --git a/includes/wikipage/SF_WikiPageTemplate.php b/includes/wikipage/SF_WikiPageTemplate.php new file mode 100644 index 0000000..c38361e --- /dev/null +++ b/includes/wikipage/SF_WikiPageTemplate.php @@ -0,0 +1,51 @@ +<?php +/** + * @author Yaron Koren + * @file + * @ingroup SF + */ + +/** + * Represents a single template call within a wiki page. + */ +class SFWikiPageTemplate { + private $mName; + private $mParams = array(); + private $mAddUnhandledParams; + + function __construct( $name, $addUnhandledParams ) { + $this->mName = $name; + $this->mAddUnhandledParams = $addUnhandledParams; + } + + function addParam( $paramName, $value ) { + $this->mParams[] = new SFWikiPageTemplateParam( $paramName, $value ); + } + + function addUnhandledParams() { + global $wgRequest; + + if ( !$this->mAddUnhandledParams ) { + return; + } + + $templateName = str_replace( ' ', '_', $this->mName ); + $prefix = '_unhandled_' . $templateName . '_'; + $prefixSize = strlen( $prefix ); + foreach ( $wgRequest->getValues() as $key => $value ) { + if ( strpos( $key, $prefix ) === 0 ) { + $paramName = urldecode( substr( $key, $prefixSize ) ); + $this->addParam( $paramName, $value ); + } + } + + } + + function getName() { + return $this->mName; + } + + function getParams() { + return $this->mParams; + } +} diff --git a/includes/wikipage/SF_WikiPageTemplateParam.php b/includes/wikipage/SF_WikiPageTemplateParam.php new file mode 100644 index 0000000..b2b58a6 --- /dev/null +++ b/includes/wikipage/SF_WikiPageTemplateParam.php @@ -0,0 +1,28 @@ +<?php +/** + * @author Yaron Koren + * @file + * @ingroup SF + */ + +/** + * Represents a single parameter (name and value) within a template call + * in a wiki page. + */ +class SFWikiPageTemplateParam { + private $mName; + private $mValue; + + function __construct( $name, $value ) { + $this->mName = $name; + $this->mValue = $value; + } + + function getName() { + return $this->mName; + } + + function getValue() { + return $this->mValue; + } +} diff --git a/tests/phpunit/includes/SF_FormPrinterTest.php b/tests/phpunit/includes/SF_FormPrinterTest.php index b759aa4..04f15a9 100644 --- a/tests/phpunit/includes/SF_FormPrinterTest.php +++ b/tests/phpunit/includes/SF_FormPrinterTest.php @@ -19,8 +19,8 @@ $wgTitle = $this->getTitle(); $wgOut->getContext()->setTitle( $wgTitle ); - list ( $form_text, $javascript_text, $data_text, $form_page_title, $generated_page_name ) = - $sfgFormPrinter->formHTML( $setup['form_definition'], null, false, null, null, 'TestStringForFormPageTitle', null ); + list ( $form_text, $javascript_text, $page_text, $form_page_title, $generated_page_name ) = + $sfgFormPrinter->formHTML( $setup['form_definition'], true, false, null, null, 'TestStringForFormPageTitle', null ); $this->assertContains( $expected['expected_form_text'], @@ -28,8 +28,8 @@ 'asserts that formHTML() returns the correct HTML text for the form for the given test input' ); $this->assertContains( - $expected['expected_data_text'], - $data_text, + $expected['expected_page_text'], + $page_text, 'assert that formHTML() returns the correct text for the page created by the form' ); @@ -49,7 +49,7 @@ {{{section|section1|level=2}}}" ), array( 'expected_form_text' => "<span class=\"inputSpan pageSection\"><textarea tabindex=\"1\" name=\"_section[section1]\" id=\"input_1\" class=\"createboxInput\" rows=\"5\" cols=\"90\" style=\"width: 100%\"></textarea></span>", - 'expected_data_text' => "==section1==" ) + 'expected_page_text' => "==section1==" ) ); // #2 'rows' and 'colums' parameters set @@ -59,7 +59,7 @@ {{{section|section 2|level=5|rows=10|cols=5}}}" ), array( 'expected_form_text' => "<span class=\"inputSpan pageSection\"><textarea tabindex=\"1\" name=\"_section[section 2]\" id=\"input_1\" class=\"createboxInput\" rows=\"10\" cols=\"5\" style=\"width: auto\"></textarea></span>", - 'expected_data_text' => "=====section 2=====" ) + 'expected_page_text' => "=====section 2=====" ) ); // #3 'mandatory' and 'autogrow' parameters set @@ -69,7 +69,7 @@ {{{section|section 3|level=2|mandatory|rows=20|cols=50|autogrow}}}" ), array( 'expected_form_text' => "<span class=\"inputSpan pageSection mandatoryFieldSpan\"><textarea tabindex=\"1\" name=\"_section[section 3]\" id=\"input_1\" class=\"mandatoryField autoGrow\" rows=\"20\" cols=\"50\" style=\"width: auto\"></textarea></span>", - 'expected_data_text' => "==section 3==" ) + 'expected_page_text' => "==section 3==" ) ); // #4 'restricted' parameter set @@ -79,7 +79,7 @@ {{{section|Section 5|level=3|restricted|class=FormTest}}}" ), array( 'expected_form_text' => "<span class=\"inputSpan pageSection\"><textarea tabindex=\"1\" name=\"_section[Section 5]\" id=\"input_1\" class=\"createboxInput FormTest\" rows=\"5\" cols=\"90\" style=\"width: 100%\" disabled=\"\"></textarea></span>", - 'expected_data_text' => "===Section 5===" ) + 'expected_page_text' => "===Section 5===" ) ); // #5 'hidden' parameter set @@ -89,7 +89,7 @@ {{{section|section 4|level=4|hidden}}}" ), array( 'expected_form_text' => "<input type=\"hidden\" name=\"_section[section 4]\" />", - 'expected_data_text' => "====section 4====" ) + 'expected_page_text' => "====section 4====" ) ); return $provider; -- To view, visit https://gerrit.wikimedia.org/r/266458 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ia643c7ee0c8692bc18f0200de270b4c317eb2603 Gerrit-PatchSet: 5 Gerrit-Project: mediawiki/extensions/SemanticForms Gerrit-Branch: master Gerrit-Owner: Yaron Koren <yaro...@gmail.com> Gerrit-Reviewer: Yaron Koren <yaro...@gmail.com> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits