getTitle(); $params = func_get_args(); array_shift( $params ); // Parameters if ( count( $params ) == 0 ) { // Escape! return true; } $defaultForm = $params[0]; $parserOutput = $parser->getOutput(); $parserOutput->setProperty( 'PFDefaultForm', $defaultForm ); // Display information on the page, if this is a category. if ( $curTitle->getNamespace() == NS_CATEGORY ) { $defaultFormPage = Title::makeTitleSafe( PF_NS_FORM, $defaultForm ); if ( $defaultFormPage == null ) { return '
Error: No form found with name "' . $defaultForm . '".
'; } $defaultFormPageText = $defaultFormPage->getPrefixedText(); $defaultFormPageLink = "[[$defaultFormPageText|$defaultForm]]"; $text = wfMessage( 'pf_category_hasdefaultform', $defaultFormPageLink )->text(); return $text; } // It's not a category - display nothing. } public static function renderFormLink( &$parser ) { $params = func_get_args(); array_shift( $params ); // We don't need the parser. $str = self::createFormLink( $parser, $params, 'formlink' ); return array( $str, 'noparse' => true, 'isHTML' => true ); } public static function renderFormRedLink( &$parser ) { $params = func_get_args(); array_shift( $params ); // We don't need the parser. $str = self::createFormLink( $parser, $params, 'formredlink' ); return array( $str, 'noparse' => true, 'isHTML' => true ); } public static function renderQueryFormLink( &$parser ) { $params = func_get_args(); array_shift( $params ); // We don't need the parser. $str = self::createFormLink( $parser, $params, 'queryformlink' ); return array( $str, 'noparse' => true, 'isHTML' => true ); } private static function convertQueryString( $queryString, $inQueryArr ) { // Change HTML-encoded ampersands directly to URL-encoded // ampersands, so that the string doesn't get split up on the '&'. $queryString = str_replace( '&', '%26', $queryString ); // "Decode" any other HTML tags. $queryString = html_entity_decode( $queryString, ENT_QUOTES ); parse_str( $queryString, $arr ); return PFUtils::array_merge_recursive_distinct( $inQueryArr, $arr ); } public static function renderFormInput( &$parser ) { $params = func_get_args(); array_shift( $params ); // don't need the parser // Set defaults. $inFormName = $inValue = $inButtonStr = ''; $inQueryArr = array(); $inAutocompletionSource = ''; $inSize = 25; $classStr = "pfFormInput"; $inPlaceholder = null; $inAutofocus = true; $languageSelector = false; $namespaceSelector = false; // Assign params. foreach ( $params as $i => $param ) { $elements = explode( '=', $param, 2 ); // Set param name and value. if ( count( $elements ) > 1 ) { $paramName = trim( $elements[0] ); // Parse (and sanitize) parameter values. // We call recursivePreprocess() and not // recursiveTagParse() so that URL values will // not be turned into links. $value = trim( $parser->recursivePreprocess( $elements[1] ) ); } else { $paramName = trim( $param ); $value = null; } if ( $paramName == 'form' ) { $inFormName = $value; } elseif ( $paramName == 'size' ) { $inSize = $value; } elseif ( $paramName == 'default value' ) { $inValue = $value; } elseif ( $paramName == 'button text' ) { $inButtonStr = $value; } elseif ( $paramName == 'query string' ) { $inQueryArr = self::convertQueryString( $value, $inQueryArr ); } elseif ( $paramName == 'autocomplete on category' ) { $inAutocompletionSource = $value; $autocompletionType = 'category'; } elseif ( $paramName == 'autocomplete on namespace' ) { $inAutocompletionSource = $value; $autocompletionType = 'namespace'; } elseif ( $paramName == 'placeholder' ) { $inPlaceholder = $value; } elseif ( $paramName == 'popup' ) { self::loadScriptsForPopupForm( $parser ); $classStr .= ' popupforminput'; } elseif ( $paramName == 'reload' ) { $classStr .= ' reload'; } elseif ( $paramName == 'no autofocus' ) { $inAutofocus = false; } elseif ( $paramName == 'language selector' && defined('TRANSLATE_VERSION') ) { $languageSelector = true; } elseif ($paramName == 'namespace selector'){ $namespaceSelector = true; } else { $value = urlencode( $value ); parse_str( "$paramName=$value", $arr ); $inQueryArr = PFUtils::array_merge_recursive_distinct( $inQueryArr, $arr ); } } $formInputAttrs = array( 'size' => $inSize ); if ( $inPlaceholder != null ) { $formInputAttrs['placeholder'] = $inPlaceholder; } if ( $inAutofocus ) { $formInputAttrs['autofocus'] = 'autofocus'; } // 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 { $parser->getOutput()->addModules( 'ext.pageforms.main' ); self::$num_autocompletion_inputs++; $input_num = self::$num_autocompletion_inputs; $inputID = 'input_' . $input_num; $formInputAttrs['id'] = $inputID; $formInputAttrs['class'] = 'autocompleteInput createboxInput formInput'; // This code formerly only used remote autocompletion // when the number of autocompletion values was above // a certain limit - as happens in regular forms - // but local autocompletion didn't always work, // apparently due to page caching. $formInputAttrs['autocompletesettings'] = $inAutocompletionSource; $formInputAttrs['autocompletedatatype'] = $autocompletionType; } // The value has already been HTML-encoded as a parameter, // and it will get encoded again by Html::input() - prevent // double-encoding. $inValue = html_entity_decode( $inValue ); $formContents = Html::input( 'page_name', $inValue, 'text', $formInputAttrs ); $languageSelectorContent = ''; $namespaceSelectorContent = ''; // 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 $fs = SpecialPageFactory::getPage( 'FormStart' ); $fsURL = $fs->getPageTitle()->getLocalURL(); if ( ( $pos = strpos( $fsURL, "title=" ) ) > - 1 ) { $formContents .= Html::hidden( "title", urldecode( substr( $fsURL, $pos + 6 ) ) ); } $listOfForms = preg_split( '~(?getCode(), 'mw' ); } } else { $languages = Language::fetchLanguageNames( $wgLang->getCode(), 'mw' ); } ksort( $languages ); foreach ( $languages as $code => $name ) { if ( $wgLang->getCode() == $code ) { $optionsHtml[] = Html::element( 'option', [ 'value' => $code, 'selected' => 'selected' ], "$code - $name" ); } else { $optionsHtml[] = Html::element( 'option', [ 'value' => $code ], "$code - $name" ); } } $languageSelectorSelect = '' . Html::openElement( 'select', ['name' => "PageLang[Language]"] ) . "\n" . implode( "\n", $optionsHtml ) . "\n" . Html::closeElement( 'select' ); $languageSelectorContent .= Html::openElement( 'div', ['class' => "form-inline"] ) . $languageSelectorSelect . Html::closeElement( 'div' ); } if($namespaceSelector) { global $wgPageFormsAvailableNamespaces; if(isset($wgPageFormsAvailableNamespaces)){ foreach ($wgPageFormsAvailableNamespaces as $availableNamespace){ $optionsHtmlNamespace[] = Html::element( 'option', [ 'value' => $availableNamespace, ], $availableNamespace ); } $namespaceSelectorSelect = Html::label(wfMessage('pf_formstart_pagenamespace'), '') . Html::openElement('select', ['name' => "namespace"]) . "\n" .implode( "\n", $optionsHtmlNamespace) . "\n" . Html::closeElement('select'); $namespaceSelectorContent .= Html::openElement('div', ['class' => "form-inline"] ) .$namespaceSelectorSelect .Html::closeElement('div'); } } $buttonStr = ( $inButtonStr != '' ) ? $inButtonStr : wfMessage( 'pf_formstart_createoredit' )->escaped(); $formContents .= " " . Html::input( null, $buttonStr, 'submit', array( 'id' => "input_button_$input_num", 'class' => 'forminput_button' ) ); $str = "\t" . Html::rawElement( 'form', array( 'name' => 'createbox', 'action' => $fsURL, 'method' => 'get', 'class' => $classStr ), '

' . $formContents . '

' . $languageSelectorContent . $namespaceSelectorContent ) . "\n"; if ( ! empty( $inAutocompletionSource ) ) { $str .= "\t\t\t" . Html::element( 'div', array( 'class' => 'page_name_auto_complete', 'id' => "div_$input_num", ), // It has to be
, not //
, to work properly - stick // in a space as the content. ' ' ) . "\n"; } return array( $str, 'noparse' => true, 'isHTML' => true ); } /** * {{#arraymap:value|delimiter|var|formula|new_delimiter}} * @param Parser &$parser * @param PPFrame $frame * @param array $args * @return string */ public static function renderArrayMap( &$parser, $frame, $args ) { // Set variables. $value = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : ''; $delimiter = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ','; $var = isset( $args[2] ) ? trim( $frame->expand( $args[2], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : 'x'; $formula = isset( $args[3] ) ? $args[3] : 'x'; $new_delimiter = isset( $args[4] ) ? trim( $frame->expand( $args[4] ) ) : ', '; # Unstrip some $delimiter = $parser->mStripState->unstripNoWiki( $delimiter ); # Let '\n' represent newlines, and '\s' represent spaces. $delimiter = str_replace( array( '\n', '\s' ), array( "\n", ' ' ), $delimiter ); $new_delimiter = str_replace( array( '\n', '\s' ), array( "\n", ' ' ), $new_delimiter ); if ( $delimiter == '' ) { $values_array = preg_split( '/(.)/u', $value, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE ); } else { $values_array = explode( $delimiter, $value ); } $results_array = array(); // Add results to the results array only if the old value was // non-null, and the new, mapped value is non-null as well. foreach ( $values_array as $old_value ) { $old_value = trim( $old_value ); if ( $old_value == '' ) { continue; } $result_value = $frame->expand( $formula, PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ); $result_value = str_replace( $var, $old_value, $result_value ); $result_value = $parser->preprocessToDom( $result_value, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); $result_value = trim( $frame->expand( $result_value ) ); if ( $result_value == '' ) { continue; } $results_array[] = $result_value; } return implode( $new_delimiter, $results_array ); } /** * {{#arraymaptemplate:value|template|delimiter|new_delimiter}} * @param Parser &$parser * @param PPFrame $frame * @param array $args * @return string */ public static function renderArrayMapTemplate( &$parser, $frame, $args ) { // Set variables. $value = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : ''; $template = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ''; $delimiter = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : ','; $new_delimiter = isset( $args[3] ) ? trim( $frame->expand( $args[3] ) ) : ', '; # Unstrip some $delimiter = $parser->mStripState->unstripNoWiki( $delimiter ); # let '\n' represent newlines $delimiter = str_replace( '\n', "\n", $delimiter ); $new_delimiter = str_replace( '\n', "\n", $new_delimiter ); if ( $delimiter == '' ) { $values_array = preg_split( '/(.)/u', $value, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE ); } else { $values_array = explode( $delimiter, $value ); } $results_array = array(); foreach ( $values_array as $old_value ) { $old_value = trim( $old_value ); if ( $old_value == '' ) { continue; } $bracketed_value = $frame->virtualBracketedImplode( '{{', '|', '}}', $template, '1=' . $old_value ); // Special handling if preprocessor class is set to // 'Preprocessor_Hash'. if ( $bracketed_value instanceof PPNode_Hash_Array ) { $bracketed_value = $bracketed_value->value; } $results_array[] = $parser->replaceVariables( implode( '', $bracketed_value ), $frame ); } return implode( $new_delimiter, $results_array ); } public static function renderAutoEdit( &$parser ) { global $wgContentNamespaces; $parser->getOutput()->addModules( 'ext.pageforms.autoedit' ); $parser->getOutput()->preventClickjacking( true ); // Set defaults. $formcontent = ''; $linkString = null; $linkType = 'span'; $summary = null; $classString = 'autoedit-trigger'; $inTooltip = null; $inQueryArr = array(); $editTime = null; // Parse parameters. $params = func_get_args(); array_shift( $params ); // don't need the parser foreach ( $params as $param ) { $elements = explode( '=', $param, 2 ); $key = trim( $elements[ 0 ] ); $value = ( count( $elements ) > 1 ) ? trim( $elements[ 1 ] ) : ''; switch ( $key ) { case 'link text': $linkString = $parser->recursiveTagParse( $value ); break; case 'link type': $linkType = $parser->recursiveTagParse( $value ); break; case 'reload': $classString .= ' reload'; break; case 'summary': $summary = $parser->recursiveTagParse( $value ); break; case 'query string' : $inQueryArr = self::convertQueryString( $value, $inQueryArr ); break; case 'ok text': case 'error text': // do not parse ok text or error text yet. Will be parsed on api call $arr = array( $key => $value ); $inQueryArr = PFUtils::array_merge_recursive_distinct( $inQueryArr, $arr ); break; case 'tooltip': $inTooltip = Sanitizer::decodeCharReferences( $value ); break; case 'target': case 'title': $value = $parser->recursiveTagParse( $value ); $arr = array( $key => $value ); $inQueryArr = PFUtils::array_merge_recursive_distinct( $inQueryArr, $arr ); $targetTitle = Title::newFromText( $value ); if ( $targetTitle !== null ) { // It seems unnecessary to let // #autoedit be called for non- // content namespaces like // "Template" or "Talk". // $wgContentNamespaces mostly // fits our needs, though it's // slightly too restrictive. $allowedNamespaces = array_merge( $wgContentNamespaces, array( NS_CATEGORY ) ); if ( !in_array( $targetTitle->getNamespace(), $allowedNamespaces ) ) { return '
Error: Invalid namespace "' . $targetTitle->getNsText() . '"; only content namespaces are allowed for #autoedit.
'; } $targetArticle = new Article( $targetTitle ); $targetArticle->clear(); $editTime = $targetArticle->getTimestamp(); } default: $value = $parser->recursiveTagParse( $value ); $arr = array( $key => $value ); $inQueryArr = PFUtils::array_merge_recursive_distinct( $inQueryArr, $arr ); } } // query string has to be turned into hidden inputs. if ( !empty( $inQueryArr ) ) { $query_components = explode( '&', http_build_query( $inQueryArr, '', '&' ) ); foreach ( $query_components as $query_component ) { $var_and_val = explode( '=', $query_component, 2 ); if ( count( $var_and_val ) == 2 ) { $formcontent .= Html::hidden( urldecode( $var_and_val[0] ), urldecode( $var_and_val[1] ) ); } } } if ( $linkString == null ) { return null; } if ( $linkType == 'button' ) { $attrs = array( 'type' => 'submit', 'class' => $classString ); if ( $inTooltip != null ) { $attrs['title'] = $inTooltip; } $linkElement = Html::rawElement( 'button', $attrs, $linkString ); } elseif ( $linkType == 'link' ) { $attrs = array( 'class' => $classString, 'href' => "#" ); if ( $inTooltip != null ) { $attrs['title'] = $inTooltip; } $linkElement = Html::rawElement( 'a', $attrs, $linkString ); } else { $linkElement = Html::rawElement( 'span', array( 'class' => $classString ), $linkString ); } if ( $summary == null ) { $summary = wfMessage( 'pf_autoedit_summary', "[[{$parser->getTitle()}]]" )->text(); } $formcontent .= Html::hidden( 'wpSummary', $summary ); if ( $editTime !== null ) { $formcontent .= Html::hidden( 'wpEdittime', $editTime ); } $form = Html::rawElement( 'form', array( 'class' => 'autoedit-data' ), $formcontent ); $output = Html::rawElement( 'div', array( 'class' => 'autoedit' ), $linkElement . Html::rawElement( 'span', array( 'class' => "autoedit-result" ), null ) . $form ); // Return output HTML. return $parser->insertStripItem( $output, $parser->mStripState ); } private static function createFormLink( &$parser, $params, $parserFunctionName ) { // Set defaults. $inFormName = $inLinkStr = $inExistingPageLinkStr = $inLinkType = $inTooltip = $inTargetName = ''; if ( $parserFunctionName == 'queryformlink' ) { $inLinkStr = wfMessage( 'runquery' )->parse(); } $inCreatePage = false; $classStr = ''; $inQueryArr = array(); $targetWindow = '_self'; // assign params // - support unlabelled params, for backwards compatibility // - parse and sanitize all parameter values foreach ( $params as $i => $param ) { $elements = explode( '=', $param, 2 ); // set param_name and value if ( count( $elements ) > 1 ) { $param_name = trim( $elements[0] ); // parse (and sanitize) parameter values $value = trim( $parser->recursiveTagParse( $elements[1] ) ); } else { $param_name = null; // parse (and sanitize) parameter values $value = trim( $parser->recursiveTagParse( $param ) ); } if ( $param_name == 'form' ) { $inFormName = $value; } elseif ( $param_name == 'link text' ) { $inLinkStr = $value; } elseif ( $param_name == 'existing page link text' ) { $inExistingPageLinkStr = $value; } elseif ( $param_name == 'link type' ) { $inLinkType = $value; } elseif ( $param_name == 'query string' ) { $inQueryArr = self::convertQueryString( $value, $inQueryArr ); } elseif ( $param_name == 'tooltip' ) { $inTooltip = Sanitizer::decodeCharReferences( $value ); } elseif ( $param_name == 'target' ) { $inTargetName = $value; } elseif ( $param_name == null && $value == 'popup' ) { self::loadScriptsForPopupForm( $parser ); $classStr = 'popupformlink'; } elseif ( $param_name == null && $value == 'reload' ) { $classStr .= ' reload'; } elseif ( $param_name == null && $value == 'new window' ) { $targetWindow = '_blank'; } elseif ( $param_name == null && $value == 'create page' ) { $inCreatePage = true; } elseif ( $param_name !== null ) { $value = urlencode( $value ); parse_str( "$param_name=$value", $arr ); $inQueryArr = PFUtils::array_merge_recursive_distinct( $inQueryArr, $arr ); } } // Not the most graceful way to do this, but it is the // easiest - if this is the #formredlink function, just // ignore whatever values were passed in for these params. if ( $parserFunctionName == 'formredlink' ) { $inLinkType = $inTooltip = null; } // If "red link only" was specified, and a target page was // specified, and it exists, just link to the page. if ( $inTargetName != '' ) { // Call urldecode() on it, in case the target was // set via {{PAGENAMEE}}, and the page name contains // an apostrophe or other unusual character. $targetTitle = Title::newFromText( urldecode( $inTargetName ) ); $targetPageExists = ( $targetTitle != '' && $targetTitle->exists() ); } else { $targetPageExists = false; } if ( $parserFunctionName == 'formredlink' && $targetPageExists ) { if ( function_exists( 'MediaWiki\MediaWikiServices::getLinkRenderer' ) ) { $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); } else { $linkRenderer = null; } if ( $inExistingPageLinkStr == '' ) { return PFUtils::makeLink( $linkRenderer, $targetTitle ); } else { return PFUtils::makeLink( $linkRenderer, $targetTitle, $inExistingPageLinkStr ); } } // The page doesn't exist, so if 'create page' was // specified, create the page now. if ( $parserFunctionName == 'formredlink' && $inCreatePage && $inTargetName != '' ) { $targetTitle = Title::newFromText( $inTargetName ); PFFormLinker::createPageWithForm( $targetTitle, $inFormName ); } if ( $parserFunctionName == 'queryformlink' ) { $formSpecialPage = SpecialPageFactory::getPage( 'RunQuery' ); } else { $formSpecialPage = SpecialPageFactory::getPage( 'FormEdit' ); } $formSpecialPageTitle = $formSpecialPage->getPageTitle(); if ( $inFormName == '' ) { $query = array( 'target' => $inTargetName ); $link_url = $formSpecialPageTitle->getLocalURL( $query ); } elseif ( strpos( $inFormName, '/' ) == true ) { $query = array( 'form' => $inFormName, 'target' => $inTargetName ); $link_url = $formSpecialPageTitle->getLocalURL( $query ); } else { $link_url = $formSpecialPageTitle->getLocalURL() . "/$inFormName"; if ( ! empty( $inTargetName ) ) { $link_url .= "/$inTargetName"; } $link_url = str_replace( ' ', '_', $link_url ); } $hidden_inputs = ""; if ( ! empty( $inQueryArr ) ) { // Special handling for the buttons - query string // has to be turned into hidden inputs. if ( $inLinkType == 'button' || $inLinkType == 'post button' ) { $query_components = explode( '&', http_build_query( $inQueryArr, '', '&' ) ); foreach ( $query_components as $query_component ) { $var_and_val = explode( '=', $query_component, 2 ); if ( count( $var_and_val ) == 2 ) { $hidden_inputs .= Html::hidden( urldecode( $var_and_val[0] ), urldecode( $var_and_val[1] ) ); } } } else { $link_url .= ( strstr( $link_url, '?' ) ) ? '&' : '?'; $link_url .= str_replace( '+', '%20', http_build_query( $inQueryArr, '', '&' ) ); } } if ( $inLinkType == 'button' || $inLinkType == 'post button' ) { $buttonAttrs = array( 'type' => 'submit', 'value' => $inLinkStr, 'title' => $inTooltip ); $buttonHTML = Html::rawElement( 'button', $buttonAttrs, $inLinkStr ); $formAttrs = array( 'action' => $link_url, 'method' => ( $inLinkType == 'button' ) ? 'get' : 'post', 'class' => $classStr, 'target' => $targetWindow ); $str = Html::rawElement( 'form', $formAttrs, $buttonHTML . $hidden_inputs ); } else { // If a target page has been specified but it doesn't // exist, make it a red link. if ( ! empty( $inTargetName ) ) { if ( !$targetPageExists ) { $classStr .= " new"; } // If no link string was specified, make it // the name of the page. if ( $inLinkStr == '' ) { $inLinkStr = $inTargetName; } } $str = Html::rawElement( 'a', array( 'href' => $link_url, 'class' => $classStr, 'title' => $inTooltip, 'target' => $targetWindow ), $inLinkStr ); } return $str; } private static function loadScriptsForPopupForm( &$parser ) { $parser->getOutput()->addModules( 'ext.pageforms.popupformedit' ); return true; } }