/** * @dataProvider provideSpecialPages */ public function testSpecialPage($name) { $page = SpecialPageFactory::getPage($name); $title = $page->getPageTitle(); $context = RequestContext::newExtraneousContext($title); $page->setContext($context); try { $page->run(null); } catch (PermissionsError $e) { // This is okay wfDebug('Permissions error caught; expected.'); } catch (ErrorPageError $e) { // This is okay as well wfDebug('Page error caught; expected.'); } $this->assertTrue(true, "Special page {$name} was executed succesfully with anon user"); $user = new MockSuperUser(); $context->setUser($user); $page->setContext($context); // This should not throw permission errors try { $page->run(null); } catch (ErrorPageError $e) { // This is okay here wfDebug('Page error caught; expected.'); } $this->assertTrue(true, "Special page {$name} was executed succesfully with super user"); }
public function buildData() { global $wgUser, $wgTitle; $page = SpecialPageFactory::getPage($this->name); if (!is_object($page)) { $this->buildExternalData(); return; } $this->available = true; $this->enabled = $page->userCanExecute($wgUser); $this->caption = $page->getDescription(); $this->description = $page->getDescription(); $this->href = $page->getTitle()->getLocalUrl(); switch ($this->name) { case 'RecentChangesLinked': $this->href .= '/' . $wgTitle->getPartialUrl(); break; case 'Contributions': $this->href .= '/' . $wgUser->getTitleKey(); break; } $specialPageName = $page->getName(); $options = array(); wfRunHooks("UserCommand::SpecialPage::{$specialPageName}", array($this, &$options)); foreach ($options as $k => $v) { $this->{$k} = $v; } }
public function show() { $special = SpecialPageFactory::getPage('Revisiondelete'); $special->setContext($this->getContext()); $special->getContext()->setTitle($special->getPageTitle()); $special->run(''); }
public function buildData() { global $wgUser, $wgTitle; $page = SpecialPageFactory::getPage($this->name); if (!is_object($page)) { $this->buildExternalData(); // BugId:22989 - we don't want the PageLayoutBuilder to be shown if disabled. if ('LayoutBuilder' == $this->name) { // do not show PLB if it's not available on the wiki $this->available = $this->enabled; } return; } $this->available = true; $this->enabled = $page->userCanExecute($wgUser); $this->caption = $page->getDescription(); $this->description = $page->getDescription(); $this->href = $page->getTitle()->getLocalUrl(); switch ($this->name) { case 'RecentChangesLinked': $this->href .= '/' . $wgTitle->getPartialUrl(); break; case 'Contributions': $this->href .= '/' . $wgUser->getTitleKey(); break; } $specialPageName = $page->getName(); $options = array(); wfRunHooks("UserCommand::SpecialPage::{$specialPageName}", array($this, &$options)); foreach ($options as $k => $v) { $this->{$k} = $v; } }
/** * @covers SpecialPageFactory::getPage * @dataProvider specialPageProvider */ public function testGetPage($spec, $shouldReuseInstance) { $this->mergeMwGlobalArrayValue('wgSpecialPages', array('testdummy' => $spec)); SpecialPageFactory::resetList(); $page = SpecialPageFactory::getPage('testdummy'); $this->assertInstanceOf('SpecialPage', $page); $page2 = SpecialPageFactory::getPage('testdummy'); $this->assertEquals($shouldReuseInstance, $page2 === $page, "Should re-use instance:"); }
public function show() { $action = self::getName(); if ($action === 'nosuchaction') { throw new ErrorPageError($this->msg('nosuchaction'), $this->msg('nosuchactiontext')); } // map actions to (whitelisted) special pages $special = SpecialPageFactory::getPage(self::$actionToSpecialPageMapping[$action]); $special->setContext($this->getContext()); $special->getContext()->setTitle($special->getPageTitle()); $special->run(''); }
function printAltFormsList($alt_forms, $target_name) { $text = ""; $fe = SpecialPageFactory::getPage('FormEdit'); $fe_url = $fe->getTitle()->getFullURL(); $i = 0; foreach ($alt_forms as $alt_form) { if ($i++ > 0) { $text .= ', '; } $text .= "<a href=\"{$fe_url}/{$alt_form}/{$target_name}\">" . str_replace('_', ' ', $alt_form) . '</a>'; } return $text; }
function printAltFormsList($alt_forms, $target_name) { $text = ""; $fe = SpecialPageFactory::getPage('FormEdit'); $fe_url = $fe->getTitle()->getFullURL(); $i = 0; foreach ($alt_forms as $alt_form) { if ($i++ > 0) { $text .= ', '; } $altFormURL = $fe_url . '/' . rawurlencode($alt_form) . '/' . rawurlencode($target_name); $text .= Html::element('a', array('href' => $altFormURL), str_replace('_', ' ', $alt_form)); } return $text; }
public function execute($param) { $this->setHeaders(); $oOutput = new SpecialNewWikisGraphOutput(); $endDate = new DateTime(date('Y-m-d')); $endDate->sub(new DateInterval('P1D')); $startDate = clone $endDate; $startDate->sub(new DateInterval('P1M')); $oOutput->set($this->getReport($startDate, $endDate, $param)); $aAllOptions = array_merge($this->aAvailableLanguages, $this->aAvailableOtherOptions); $param = in_array($param, $aAllOptions) ? $param : ''; $oOutput->setActive($param); $sReturnChart = $oOutput->getHTML(); $oTmpl = new EasyTemplate(dirname(__FILE__) . "/templates/"); $oTmpl->set_vars(array("tabs" => $this->aAvailableLanguages, "other" => $this->aAvailableOtherOptions, "active" => $param, "path" => SpecialPageFactory::getPage(self::NEW_WIKIS_GRAPH)->getTitle()->getFullURL())); F::app()->wg->out->addHTML($oTmpl->render("metrics-menu")); F::app()->wg->out->addHTML($sReturnChart); }
/** * Compatibility helper function. * Since 1.18 SpecialPageFactory::getPage should be used. * SpecialPage::getPage is deprecated in 1.18. * * @since 2.3.3 * * @param string $pageName * * @return SpecialPage|null */ public static function getSpecialPage($pageName) { $hasFactory = class_exists('SpecialPageFactory') && method_exists('SpecialPageFactory', 'getPage'); return $hasFactory ? SpecialPageFactory::getPage($pageName) : SpecialPage::getPage($pageName); }
static function createFormLink(&$parser, $params, $parserFunctionName) { // Set defaults. $inFormName = $inLinkStr = $inExistingPageLinkStr = $inLinkType = $inTooltip = $inQueryStr = $inTargetName = ''; if ($parserFunctionName == 'queryformlink') { $inLinkStr = wfMessage('runquery')->text(); } $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') { // Change HTML-encoded ampersands directly to // URL-encoded ampersands, so that the string // doesn't get split up on the '&'. $inQueryStr = str_replace('&', '%26', $value); parse_str($inQueryStr, $arr); $inQueryArr = self::array_merge_recursive_distinct($inQueryArr, $arr); } 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 == '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 = self::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 != '') { $targetTitle = Title::newFromText($inTargetName); $targetPageExists = $targetTitle != '' && $targetTitle->exists(); } else { $targetPageExists = false; } if ($parserFunctionName == 'formredlink' && $targetPageExists) { if ($inExistingPageLinkStr == '') { return Linker::link($targetTitle); } else { return Linker::link($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); SFFormLinker::createPageWithForm($targetTitle, $inFormName); } if ($parserFunctionName == 'queryformlink') { $formSpecialPage = SpecialPageFactory::getPage('RunQuery'); } else { $formSpecialPage = SpecialPageFactory::getPage('FormEdit'); } if ($inFormName == '') { $query = array('target' => $inTargetName); $link_url = $formSpecialPage->getTitle()->getLocalURL($query); } elseif (strpos($inFormName, '/') == true) { $query = array('form' => $inFormName, 'target' => $inTargetName); $link_url = $formSpecialPage->getTitle()->getLocalURL($query); } else { $link_url = $formSpecialPage->getTitle()->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') { $formMethod = $inLinkType == 'button' ? 'get' : 'post'; $str = Html::rawElement('form', array('action' => $link_url, 'method' => $formMethod, 'class' => $classStr, 'target' => $targetWindow), '<button ' . Html::expandAttributes(array('type' => 'submit', 'value' => $inLinkStr)) . '>' . $inLinkStr . '</button>' . $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; }
/** * Performs the request. * - bad titles * - read restriction * - local interwiki redirects * - redirect loop * - special pages * - normal pages * * @throws MWException|PermissionsError|BadTitleError|HttpError * @return void */ private function performRequest() { global $wgTitle; $request = $this->context->getRequest(); $requestTitle = $title = $this->context->getTitle(); $output = $this->context->getOutput(); $user = $this->context->getUser(); if ($request->getVal('printable') === 'yes') { $output->setPrintable(); } $unused = null; // To pass it by reference Hooks::run('BeforeInitialize', array(&$title, &$unused, &$output, &$user, $request, $this)); // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty. if (is_null($title) || $title->getDBkey() == '' && !$title->isExternal() || $title->isSpecial('Badtitle')) { $this->context->setTitle(SpecialPage::getTitleFor('Badtitle')); try { $this->parseTitle(); } catch (MalformedTitleException $ex) { throw new BadTitleError($ex); } throw new BadTitleError(); } // Check user's permissions to read this page. // We have to check here to catch special pages etc. // We will check again in Article::view(). $permErrors = $title->isSpecial('RunJobs') ? array() : $title->getUserPermissionsErrors('read', $user); if (count($permErrors)) { // Bug 32276: allowing the skin to generate output with $wgTitle or // $this->context->title set to the input title would allow anonymous users to // determine whether a page exists, potentially leaking private data. In fact, the // curid and oldid request parameters would allow page titles to be enumerated even // when they are not guessable. So we reset the title to Special:Badtitle before the // permissions error is displayed. // The skin mostly uses $this->context->getTitle() these days, but some extensions // still use $wgTitle. $badTitle = SpecialPage::getTitleFor('Badtitle'); $this->context->setTitle($badTitle); $wgTitle = $badTitle; throw new PermissionsError('read', $permErrors); } // Interwiki redirects if ($title->isExternal()) { $rdfrom = $request->getVal('rdfrom'); if ($rdfrom) { $url = $title->getFullURL(array('rdfrom' => $rdfrom)); } else { $query = $request->getValues(); unset($query['title']); $url = $title->getFullURL($query); } // Check for a redirect loop if (!preg_match('/^' . preg_quote($this->config->get('Server'), '/') . '/', $url) && $title->isLocal()) { // 301 so google et al report the target as the actual url. $output->redirect($url, 301); } else { $this->context->setTitle(SpecialPage::getTitleFor('Badtitle')); try { $this->parseTitle(); } catch (MalformedTitleException $ex) { throw new BadTitleError($ex); } throw new BadTitleError(); } // Handle any other redirects. // Redirect loops, titleless URL, $wgUsePathInfo URLs, and URLs with a variant } elseif (!$this->tryNormaliseRedirect($title)) { // Prevent information leak via Special:MyPage et al (T109724) if ($title->isSpecialPage()) { $specialPage = SpecialPageFactory::getPage($title->getDBKey()); if ($specialPage instanceof RedirectSpecialPage && $this->config->get('HideIdentifiableRedirects') && $specialPage->personallyIdentifiableTarget()) { list(, $subpage) = SpecialPageFactory::resolveAlias($title->getDBKey()); $target = $specialPage->getRedirect($subpage); // target can also be true. We let that case fall through to normal processing. if ($target instanceof Title) { $query = $specialPage->getRedirectQuery() ?: array(); $request = new DerivativeRequest($this->context->getRequest(), $query); $request->setRequestURL($this->context->getRequest()->getRequestURL()); $this->context->setRequest($request); // Do not varnish cache these. May vary even for anons $this->context->getOutput()->lowerCdnMaxage(0); $this->context->setTitle($target); $wgTitle = $target; // Reset action type cache. (Special pages have only view) $this->action = null; $title = $target; $output->addJsConfigVars(array('wgInternalRedirectTargetUrl' => $target->getFullURL($query))); $output->addModules('mediawiki.action.view.redirect'); } } } // Special pages ($title may have changed since if statement above) if (NS_SPECIAL == $title->getNamespace()) { // Actions that need to be made when we have a special pages SpecialPageFactory::executePath($title, $this->context); } else { // ...otherwise treat it as an article view. The article // may still be a wikipage redirect to another article or URL. $article = $this->initializeArticle(); if (is_object($article)) { $this->performAction($article, $requestTitle); } elseif (is_string($article)) { $output->redirect($article); } else { throw new MWException("Shouldn't happen: MediaWiki::initializeArticle()" . " returned neither an object nor a URL"); } } } }
public static function uploadableHTML($input_id, $delimiter = null, $default_filename = null, $cur_value = '', $other_args = array()) { $upload_window_page = SpecialPageFactory::getPage('UploadWindow'); $query_string = "sfInputID={$input_id}"; if ($delimiter != null) { $query_string .= "&sfDelimiter={$delimiter}"; } if ($default_filename != null) { $query_string .= "&wpDestFile={$default_filename}"; } $upload_window_url = $upload_window_page->getTitle()->getFullURL($query_string); $upload_label = wfMessage('upload')->text(); // We need to set the size by default. $style = "width:650 height:500"; $cssClasses = array('sfFancyBox', 'sfUploadable'); $showPreview = array_key_exists('image preview', $other_args); if ($showPreview) { $cssClasses[] = 'sfImagePreview'; } $linkAttrs = array('href' => $upload_window_url, 'class' => implode(' ', $cssClasses), 'rev' => $style, 'data-input-id' => $input_id); $text = "\t" . Html::element('a', $linkAttrs, $upload_label) . "\n"; if ($showPreview) { $text .= Html::rawElement('div', array('id' => $input_id . '_imagepreview', 'class' => 'sfImagePreviewWrapper'), self::getPreviewImage($cur_value)); } return $text; }
/** * Show a drop-down box of special pages * @return string */ function specialPagesList() { global $wgScript; $select = new XmlSelect('title'); $pages = SpecialPageFactory::getUsablePages(); array_unshift($pages, SpecialPageFactory::getPage('SpecialPages')); foreach ($pages as $obj) { $select->addOption($obj->getDescription(), $obj->getTitle()->getPrefixedDBkey()); } return Html::rawElement('form', array('id' => 'specialpages', 'method' => 'get', 'action' => $wgScript), $select->getHTML() . Xml::submitButton(wfMessage('go')->text())); }
/** * @brief This returns the HTML output of any SpecialPage::execute function * @details * SpecialPage::capturePath will skip SpecialPages which are not "includable" * (which is all the interesting ones) So we need to force it. * * @requestParam string page the name of the Special page to invoke * @responseParam string output the HTML output of the special page */ public function GetSpecialPage() { if (!$this->wg->User->isAllowed('admindashboard')) { $this->displayRestrictionError(); return false; // skip rendering } // Construct title object from request params $pageName = $this->getVal("page"); $title = SpecialPage::getTitleFor($pageName); // Save global variables and initialize context for special page global $wgOut, $wgTitle; $oldTitle = $wgTitle; $oldOut = $wgOut; $wgOut = new OutputPage(); $wgOut->setTitle($title); $wgTitle = $title; // Construct special page object try { $basePages = array("Categories", "Recentchanges", "Specialpages"); if (in_array($pageName, $basePages)) { $sp = SpecialPageFactory::getPage($pageName); } else { $sp = new $pageName(); } } catch (Exception $e) { print_pre("Could not construct special page object"); } if ($sp instanceof SpecialPage) { $ret = $sp->execute(false); } else { print_pre("Object is not a special page."); } // TODO: check retval of special page call? $this->output = $wgOut->getHTML(); // Restore global variables $wgTitle = $oldTitle; $wgOut = $oldOut; }
function customSpecialPage($page_title) { $item = new SDItem(); $page = SpecialPageFactory::getPage($page_title); $item->link = Linker::link($page->getTitle(), $page->getDescription()); return $item; }
/** * @return SpecialPage|null */ protected function getSpecialPage() { $action = $this->getName(); if ($action === 'nosuchaction') { return null; } // map actions to (whitelisted) special pages return SpecialPageFactory::getPage(self::$actionToSpecialPageMapping[$action]); }
public function execute() { global $IP, $wgQueryPages, $wgQueryCacheLimit, $wgDisableQueryPageUpdate; $dbw = wfGetDB(DB_MASTER); $this->doSpecialPageCacheUpdates($dbw); // This is needed to initialise $wgQueryPages require_once "{$IP}/includes/QueryPage.php"; foreach ($wgQueryPages as $page) { list($class, $special) = $page; $limit = isset($page[2]) ? $page[2] : null; # --list : just show the name of pages if ($this->hasOption('list')) { $this->output("{$special} [QueryPage]\n"); continue; } if (!$this->hasOption('override') && $wgDisableQueryPageUpdate && in_array($special, $wgDisableQueryPageUpdate)) { $this->output(sprintf("%-30s [QueryPage] disabled\n", $special)); continue; } $specialObj = SpecialPageFactory::getPage($special); if (!$specialObj) { $this->output("No such special page: {$special}\n"); exit; } if ($specialObj instanceof QueryPage) { $queryPage = $specialObj; } else { if (!class_exists($class)) { $file = $specialObj->getFile(); require_once $file; } $queryPage = new $class(); } if (!$this->hasOption('only') || $this->getOption('only') == $queryPage->getName()) { $this->output(sprintf('%-30s [QueryPage] ', $special)); if ($queryPage->isExpensive()) { $t1 = explode(' ', microtime()); # Do the query $num = $queryPage->recache($limit === null ? $wgQueryCacheLimit : $limit); $t2 = explode(' ', microtime()); if ($num === false) { $this->output("FAILED: database error\n"); } else { $this->output("got {$num} rows in "); $elapsed = $t2[0] - $t1[0] + ($t2[1] - $t1[1]); $hours = intval($elapsed / 3600); $minutes = intval($elapsed % 3600 / 60); $seconds = $elapsed - $hours * 3600 - $minutes * 60; if ($hours) { $this->output($hours . 'h '); } if ($minutes) { $this->output($minutes . 'm '); } $this->output(sprintf("%.2fs\n", $seconds)); } # Reopen any connections that have closed if (!wfGetLB()->pingAll()) { $this->output("\n"); do { $this->error("Connection failed, reconnecting in 10 seconds..."); sleep(10); } while (!wfGetLB()->pingAll()); $this->output("Reconnected\n\n"); } # Wait for the slave to catch up wfWaitForSlaves(); } else { $this->output("cheap, skipped\n"); } if ($this->hasOption('only')) { break; } } } }
function createMarkup($standardInputs = array(), $freeTextLabel = null) { $title = Title::makeTitle(SF_NS_FORM, $this->mFormName); $fs = SpecialPageFactory::getPage('FormStart'); $form_start_url = SFUtils::titleURLString($fs->getTitle()) . "/" . $title->getPartialURL(); $form_description = wfMessage('sf_form_docu', $this->mFormName, $form_start_url)->inContentLanguage()->text(); $form_input = "{{#forminput:form=" . $this->mFormName; if (!is_null($this->mAssociatedCategory)) { $form_input .= "|autocomplete on category=" . $this->mAssociatedCategory; } $form_input .= "}}\n"; $text = <<<END <noinclude> {$form_description} {$form_input} </noinclude><includeonly> END; if (!empty($this->mPageNameFormula) || !empty($this->mCreateTitle) || !empty($this->mEditTitle)) { $text .= "{{{info"; if (!empty($this->mPageNameFormula)) { $text .= "|page name=" . $this->mPageNameFormula; } if (!empty($this->mCreateTitle)) { $text .= "|create title=" . $this->mCreateTitle; } if (!empty($this->mEditTitle)) { $text .= "|edit title=" . $this->mEditTitle; } $text .= "}}}\n"; } $text .= <<<END <div id="wikiPreview" style="display: none; padding-bottom: 25px; margin-bottom: 25px; border-bottom: 1px solid #AAAAAA;"></div> END; foreach ($this->mItems as $item) { if ($item['type'] == 'template') { $template = $item['item']; $text .= $template->createMarkup() . "\n"; } elseif ($item['type'] == 'section') { $section = $item['item']; $text .= $section->createMarkup() . "\n"; } } if (is_null($freeTextLabel)) { $freeTextLabel = wfMessage('sf_form_freetextlabel')->inContentLanguage()->text(); } // Add in standard inputs if they were specified. if (count($standardInputs) > 0) { if (array_key_exists('free text', $standardInputs)) { $text .= "'''{$freeTextLabel}:'''\n\n"; $text .= $standardInputs['free text'] . "\n\n\n"; } if (array_key_exists('summary', $standardInputs)) { $text .= $standardInputs['summary'] . "\n\n"; } if (array_key_exists('minor edit', $standardInputs)) { $text .= $standardInputs['minor edit'] . ' '; } if (array_key_exists('watch', $standardInputs)) { $text .= $standardInputs['watch']; } if (array_key_exists('minor edit', $standardInputs) || array_key_exists('watch', $standardInputs)) { $text .= "\n\n"; } if (array_key_exists('save', $standardInputs)) { $text .= $standardInputs['save'] . ' '; } if (array_key_exists('preview', $standardInputs)) { $text .= $standardInputs['preview'] . ' '; } if (array_key_exists('changes', $standardInputs)) { $text .= $standardInputs['changes'] . ' '; } if (array_key_exists('cancel', $standardInputs)) { $text .= $standardInputs['cancel']; } } else { $text .= <<<END '''{$freeTextLabel}:''' {{{standard input|free text|rows=10}}} {{{standard input|summary}}} {{{standard input|minor edit}}} {{{standard input|watch}}} {{{standard input|save}}} {{{standard input|preview}}} {{{standard input|changes}}} {{{standard input|cancel}}} END; } $text .= "\n</includeonly>\n"; return $text; }
/** * Get the query page associated with a special page * * @param string $special * @param string $class * @return \QueryPage * @throws \InvalidArgumentException if no special page with the given name exists */ protected function getQueryPage($special, $class) { $queryPage = \SpecialPageFactory::getPage($special); if (!$queryPage) { throw new \InvalidArgumentException("No such special page: {$special}"); } if (!$queryPage instanceof \QueryPage) { if (!class_exists($class)) { require_once $queryPage->getFile(); } $queryPage = new $class(); } return $queryPage; }
static function newFromSpecialPage($page_name) { $item = new ALItem(); $item->label = $page_name; $page = SpecialPageFactory::getPage($page_name); $item->text = Linker::linkKnown($page->getTitle(), htmlspecialchars($page->getDescription())); return $item; }
/** * Potentially open a socket and sent an HTTP request back to the server * to run a specified number of jobs. This registers a callback to cleanup * the socket once it's done. */ public function triggerJobs() { $jobRunRate = $this->config->get('JobRunRate'); if ($this->getTitle()->isSpecial('RunJobs')) { return; // recursion guard } elseif ($jobRunRate <= 0 || wfReadOnly()) { return; } if ($jobRunRate < 1) { $max = mt_getrandmax(); if (mt_rand(0, $max) > $max * $jobRunRate) { return; // the higher the job run rate, the less likely we return here } $n = 1; } else { $n = intval($jobRunRate); } $runJobsLogger = LoggerFactory::getInstance('runJobs'); // Fall back to running the job(s) while the user waits if needed if (!$this->config->get('RunJobsAsync')) { $runner = new JobRunner($runJobsLogger); $runner->run(['maxJobs' => $n]); return; } // Do not send request if there are probably no jobs try { $group = JobQueueGroup::singleton(); if (!$group->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) { return; } } catch (JobQueueError $e) { MWExceptionHandler::logException($e); return; // do not make the site unavailable } $query = ['title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5]; $query['signature'] = SpecialRunJobs::getQuerySignature($query, $this->config->get('SecretKey')); $errno = $errstr = null; $info = wfParseUrl($this->config->get('CanonicalServer')); $host = $info ? $info['host'] : null; $port = 80; if (isset($info['scheme']) && $info['scheme'] == 'https') { $host = "tls://" . $host; $port = 443; } if (isset($info['port'])) { $port = $info['port']; } MediaWiki\suppressWarnings(); $sock = $host ? fsockopen($host, $port, $errno, $errstr, 0.1) : false; MediaWiki\restoreWarnings(); $invokedWithSuccess = true; if ($sock) { $special = SpecialPageFactory::getPage('RunJobs'); $url = $special->getPageTitle()->getCanonicalURL($query); $req = "POST {$url} HTTP/1.1\r\n" . "Host: {$info['host']}\r\n" . "Connection: Close\r\n" . "Content-Length: 0\r\n\r\n"; $runJobsLogger->info("Running {$n} job(s) via '{$url}'"); // Send a cron API request to be performed in the background. // Give up if this takes too long to send (which should be rare). stream_set_timeout($sock, 2); $bytes = fwrite($sock, $req); if ($bytes !== strlen($req)) { $invokedWithSuccess = false; $runJobsLogger->error("Failed to start cron API (socket write error)"); } else { // Do not wait for the response (the script should handle client aborts). // Make sure that we don't close before that script reaches ignore_user_abort(). $start = microtime(true); $status = fgets($sock); $sec = microtime(true) - $start; if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) { $invokedWithSuccess = false; $runJobsLogger->error("Failed to start cron API: received '{$status}' ({$sec})"); } } fclose($sock); } else { $invokedWithSuccess = false; $runJobsLogger->error("Failed to start cron API (socket error {$errno}): {$errstr}"); } // Fall back to running the job(s) while the user waits if needed if (!$invokedWithSuccess) { $runJobsLogger->warning("Jobs switched to blocking; Special:RunJobs disabled"); $runner = new JobRunner($runJobsLogger); $runner->run(['maxJobs' => $n]); } }
/** * Prefix search special-case for Special: namespace. * * @param string $search Term * @param int $limit Max number of items to return * @param int $offset Number of items to offset * @return array */ protected function specialSearch($search, $limit, $offset) { global $wgContLang; $searchParts = explode('/', $search, 2); $searchKey = $searchParts[0]; $subpageSearch = isset($searchParts[1]) ? $searchParts[1] : null; // Handle subpage search separately. if ($subpageSearch !== null) { // Try matching the full search string as a page name $specialTitle = Title::makeTitleSafe(NS_SPECIAL, $searchKey); if (!$specialTitle) { return array(); } $special = SpecialPageFactory::getPage($specialTitle->getText()); if ($special) { $subpages = $special->prefixSearchSubpages($subpageSearch, $limit, $offset); return array_map(function ($sub) use($specialTitle) { return $specialTitle->getSubpage($sub); }, $subpages); } else { return array(); } } # normalize searchKey, so aliases with spaces can be found - bug 25675 $searchKey = str_replace(' ', '_', $searchKey); $searchKey = $wgContLang->caseFold($searchKey); // Unlike SpecialPage itself, we want the canonical forms of both // canonical and alias title forms... $keys = array(); foreach (SpecialPageFactory::getNames() as $page) { $keys[$wgContLang->caseFold($page)] = $page; } foreach ($wgContLang->getSpecialPageAliases() as $page => $aliases) { if (!in_array($page, SpecialPageFactory::getNames())) { # bug 20885 continue; } foreach ($aliases as $alias) { $keys[$wgContLang->caseFold($alias)] = $alias; } } ksort($keys); $srchres = array(); $skipped = 0; foreach ($keys as $pageKey => $page) { if ($searchKey === '' || strpos($pageKey, $searchKey) === 0) { // bug 27671: Don't use SpecialPage::getTitleFor() here because it // localizes its input leading to searches for e.g. Special:All // returning Spezial:MediaWiki-Systemnachrichten and returning // Spezial:Alle_Seiten twice when $wgLanguageCode == 'de' if ($offset > 0 && $skipped < $offset) { $skipped++; continue; } $srchres[] = Title::makeTitleSafe(NS_SPECIAL, $page); } if (count($srchres) >= $limit) { break; } } return $srchres; }
static function displayFormChooser($output, $title) { $output->addModules('ext.semanticforms.main'); $targetName = $title->getPrefixedText(); $output->setPageTitle(wfMessage("creating", $targetName)->text()); $output->addHTML(Html::element('p', null, wfMessage('sf-formedit-selectform')->text())); $formNames = SFUtils::getAllForms(); $fe = SpecialPageFactory::getPage('FormEdit'); $text = ''; foreach ($formNames as $i => $formName) { if ($i > 0) { $text .= " · "; } // Special handling for forms whose name contains a slash. if (strpos($formName, '/') !== false) { $url = $fe->getTitle()->getLocalURL(array('form' => $formName, 'target' => $targetName)); } else { $url = $fe->getTitle("{$formName}/{$targetName}")->getLocalURL(); } $text .= Html::element('a', array('href' => $url), $formName); } $output->addHTML(Html::rawElement('div', array('class' => 'infoMessage'), $text)); // We need to call linkKnown(), not link(), so that SF's // edit=>formedit hook won't be called on this link. $noFormLink = Linker::linkKnown($title, wfMessage('sf-formedit-donotuseform')->escaped(), array(), array('action' => 'edit', 'redlink' => true)); $output->addHTML(Html::rawElement('p', null, $noFormLink)); }
/** * Return the text of a template, after recursively * replacing any variables or templates within the template. * * @param array $piece The parts of the template * $piece['title']: the title, i.e. the part before the | * $piece['parts']: the parameter array * $piece['lineStart']: whether the brace was at the start of a line * @param PPFrame $frame The current frame, contains template arguments * @throws Exception * @return string The text of the template */ public function braceSubstitution($piece, $frame) { // Flags // $text has been filled $found = false; // wiki markup in $text should be escaped $nowiki = false; // $text is HTML, armour it against wikitext transformation $isHTML = false; // Force interwiki transclusion to be done in raw mode not rendered $forceRawInterwiki = false; // $text is a DOM node needing expansion in a child frame $isChildObj = false; // $text is a DOM node needing expansion in the current frame $isLocalObj = false; # Title object, where $text came from $title = false; # $part1 is the bit before the first |, and must contain only title characters. # Various prefixes will be stripped from it later. $titleWithSpaces = $frame->expand($piece['title']); $part1 = trim($titleWithSpaces); $titleText = false; # Original title text preserved for various purposes $originalTitle = $part1; # $args is a list of argument nodes, starting from index 0, not including $part1 # @todo FIXME: If piece['parts'] is null then the call to getLength() # below won't work b/c this $args isn't an object $args = null == $piece['parts'] ? [] : $piece['parts']; $profileSection = null; // profile templates # SUBST if (!$found) { $substMatch = $this->mSubstWords->matchStartAndRemove($part1); # Possibilities for substMatch: "subst", "safesubst" or FALSE # Decide whether to expand template or keep wikitext as-is. if ($this->ot['wiki']) { if ($substMatch === false) { $literal = true; # literal when in PST with no prefix } else { $literal = false; # expand when in PST with subst: or safesubst: } } else { if ($substMatch == 'subst') { $literal = true; # literal when not in PST with plain subst: } else { $literal = false; # expand when not in PST with safesubst: or no prefix } } if ($literal) { $text = $frame->virtualBracketedImplode('{{', '|', '}}', $titleWithSpaces, $args); $isLocalObj = true; $found = true; } } # Variables if (!$found && $args->getLength() == 0) { $id = $this->mVariables->matchStartToEnd($part1); if ($id !== false) { $text = $this->getVariableValue($id, $frame); if (MagicWord::getCacheTTL($id) > -1) { $this->mOutput->updateCacheExpiry(MagicWord::getCacheTTL($id)); } $found = true; } } # MSG, MSGNW and RAW if (!$found) { # Check for MSGNW: $mwMsgnw = MagicWord::get('msgnw'); if ($mwMsgnw->matchStartAndRemove($part1)) { $nowiki = true; } else { # Remove obsolete MSG: $mwMsg = MagicWord::get('msg'); $mwMsg->matchStartAndRemove($part1); } # Check for RAW: $mwRaw = MagicWord::get('raw'); if ($mwRaw->matchStartAndRemove($part1)) { $forceRawInterwiki = true; } } # Parser functions if (!$found) { $colonPos = strpos($part1, ':'); if ($colonPos !== false) { $func = substr($part1, 0, $colonPos); $funcArgs = [trim(substr($part1, $colonPos + 1))]; $argsLength = $args->getLength(); for ($i = 0; $i < $argsLength; $i++) { $funcArgs[] = $args->item($i); } try { $result = $this->callParserFunction($frame, $func, $funcArgs); } catch (Exception $ex) { throw $ex; } # The interface for parser functions allows for extracting # flags into the local scope. Extract any forwarded flags # here. extract($result); } } # Finish mangling title and then check for loops. # Set $title to a Title object and $titleText to the PDBK if (!$found) { $ns = NS_TEMPLATE; # Split the title into page and subpage $subpage = ''; $relative = $this->maybeDoSubpageLink($part1, $subpage); if ($part1 !== $relative) { $part1 = $relative; $ns = $this->mTitle->getNamespace(); } $title = Title::newFromText($part1, $ns); if ($title) { $titleText = $title->getPrefixedText(); # Check for language variants if the template is not found if ($this->getConverterLanguage()->hasVariants() && $title->getArticleID() == 0) { $this->getConverterLanguage()->findVariantLink($part1, $title, true); } # Do recursion depth check $limit = $this->mOptions->getMaxTemplateDepth(); if ($frame->depth >= $limit) { $found = true; $text = '<span class="error">' . wfMessage('parser-template-recursion-depth-warning')->numParams($limit)->inContentLanguage()->text() . '</span>'; } } } # Load from database if (!$found && $title) { $profileSection = $this->mProfiler->scopedProfileIn($title->getPrefixedDBkey()); if (!$title->isExternal()) { if ($title->isSpecialPage() && $this->mOptions->getAllowSpecialInclusion() && $this->ot['html']) { $specialPage = SpecialPageFactory::getPage($title->getDBkey()); // Pass the template arguments as URL parameters. // "uselang" will have no effect since the Language object // is forced to the one defined in ParserOptions. $pageArgs = []; $argsLength = $args->getLength(); for ($i = 0; $i < $argsLength; $i++) { $bits = $args->item($i)->splitArg(); if (strval($bits['index']) === '') { $name = trim($frame->expand($bits['name'], PPFrame::STRIP_COMMENTS)); $value = trim($frame->expand($bits['value'])); $pageArgs[$name] = $value; } } // Create a new context to execute the special page $context = new RequestContext(); $context->setTitle($title); $context->setRequest(new FauxRequest($pageArgs)); if ($specialPage && $specialPage->maxIncludeCacheTime() === 0) { $context->setUser($this->getUser()); } else { // If this page is cached, then we better not be per user. $context->setUser(User::newFromName('127.0.0.1', false)); } $context->setLanguage($this->mOptions->getUserLangObj()); $ret = SpecialPageFactory::capturePath($title, $context, $this->getLinkRenderer()); if ($ret) { $text = $context->getOutput()->getHTML(); $this->mOutput->addOutputPageMetadata($context->getOutput()); $found = true; $isHTML = true; if ($specialPage && $specialPage->maxIncludeCacheTime() !== false) { $this->mOutput->updateRuntimeAdaptiveExpiry($specialPage->maxIncludeCacheTime()); } } } elseif (MWNamespace::isNonincludable($title->getNamespace())) { $found = false; # access denied wfDebug(__METHOD__ . ": template inclusion denied for " . $title->getPrefixedDBkey() . "\n"); } else { list($text, $title) = $this->getTemplateDom($title); if ($text !== false) { $found = true; $isChildObj = true; } } # If the title is valid but undisplayable, make a link to it if (!$found && ($this->ot['html'] || $this->ot['pre'])) { $text = "[[:{$titleText}]]"; $found = true; } } elseif ($title->isTrans()) { # Interwiki transclusion if ($this->ot['html'] && !$forceRawInterwiki) { $text = $this->interwikiTransclude($title, 'render'); $isHTML = true; } else { $text = $this->interwikiTransclude($title, 'raw'); # Preprocess it like a template $text = $this->preprocessToDom($text, self::PTD_FOR_INCLUSION); $isChildObj = true; } $found = true; } # Do infinite loop check # This has to be done after redirect resolution to avoid infinite loops via redirects if (!$frame->loopCheck($title)) { $found = true; $text = '<span class="error">' . wfMessage('parser-template-loop-warning', $titleText)->inContentLanguage()->text() . '</span>'; wfDebug(__METHOD__ . ": template loop broken at '{$titleText}'\n"); } } # If we haven't found text to substitute by now, we're done # Recover the source wikitext and return it if (!$found) { $text = $frame->virtualBracketedImplode('{{', '|', '}}', $titleWithSpaces, $args); if ($profileSection) { $this->mProfiler->scopedProfileOut($profileSection); } return ['object' => $text]; } # Expand DOM-style return values in a child frame if ($isChildObj) { # Clean up argument array $newFrame = $frame->newChild($args, $title); if ($nowiki) { $text = $newFrame->expand($text, PPFrame::RECOVER_ORIG); } elseif ($titleText !== false && $newFrame->isEmpty()) { # Expansion is eligible for the empty-frame cache $text = $newFrame->cachedExpand($titleText, $text); } else { # Uncached expansion $text = $newFrame->expand($text); } } if ($isLocalObj && $nowiki) { $text = $frame->expand($text, PPFrame::RECOVER_ORIG); $isLocalObj = false; } if ($profileSection) { $this->mProfiler->scopedProfileOut($profileSection); } # Replace raw HTML by a placeholder if ($isHTML) { $text = $this->insertStripItem($text); } elseif ($nowiki && ($this->ot['html'] || $this->ot['pre'])) { # Escape nowiki-style return values $text = wfEscapeWikiText($text); } elseif (is_string($text) && !$piece['lineStart'] && preg_match('/^(?:{\\||:|;|#|\\*)/', $text)) { # Bug 529: if the template begins with a table or block-level # element, it should be treated as beginning a new line. # This behavior is somewhat controversial. $text = "\n" . $text; } if (is_string($text) && !$this->incrementIncludeSize('post-expand', strlen($text))) { # Error, oversize inclusion if ($titleText !== false) { # Make a working, properly escaped link if possible (bug 23588) $text = "[[:{$titleText}]]"; } else { # This will probably not be a working link, but at least it may # provide some hint of where the problem is preg_replace('/^:/', '', $originalTitle); $text = "[[:{$originalTitle}]]"; } $text .= $this->insertStripItem('<!-- WARNING: template omitted, ' . 'post-expand include size too large -->'); $this->limitationWarn('post-expand-template-inclusion'); } if ($isLocalObj) { $ret = ['object' => $text]; } else { $ret = ['text' => $text]; } return $ret; }
/** * Get a special page with a given localised name, or NULL if there * is no such special page. * * @param $alias String * @return SpecialPage object or null if the page doesn't exist * @deprecated since 1.18 call SpecialPageFactory method directly */ static function getPageByAlias($alias) { wfDeprecated(__METHOD__, '1.18'); return SpecialPageFactory::getPage($alias); }
/** * Helper function for formEditLink() - gets the 'default form' and * 'alternate form' properties for a page, and creates the * corresponding Special:FormEdit link, if any such properties are * defined */ static function getFormEditLinkForPage($target_page_title, $page_name, $page_namespace) { $default_forms = self::getFormsThatPagePointsTo($page_name, $page_namespace, self::DEFAULT_FORM); $alt_forms = self::getFormsThatPagePointsTo($page_name, $page_namespace, self::ALTERNATE_FORM); if (count($default_forms) == 0 && count($alt_forms) == 0) { return null; } $fe = SpecialPageFactory::getPage('FormEdit'); $fe_url = $fe->getTitle()->getLocalURL(); if (count($default_forms) > 0) { $form_edit_url = $fe_url . "/" . $default_forms[0] . "/" . SFUtils::titleURLString($target_page_title); } else { $form_edit_url = $fe_url; $form_edit_url .= strpos($form_edit_url, "?") ? "&" : "?"; $form_edit_url .= 'target=' . urlencode(SFUtils::titleString($target_page_title)); } foreach ($alt_forms as $i => $alt_form) { $form_edit_url .= strpos($form_edit_url, "?") ? "&" : "?"; $form_edit_url .= "alt_form[{$i}]={$alt_form}"; } // Add "redlink=1" to the query string, so that the user will // go to the actual page if it now exists. $form_edit_url .= strpos($form_edit_url, "?") ? "&" : "?"; $form_edit_url .= "redlink=1"; return $form_edit_url; }
public function onPersonalUrls(&$aPersonal_urls, &$oTitle) { $oUser = RequestContext::getMain()->getUser(); if ($oUser->isLoggedIn()) { $aPersonal_urls['userdashboard'] = array('href' => SpecialPage::getTitleFor('UserDashboard')->getLocalURL(), 'text' => SpecialPageFactory::getPage('UserDashboard')->getDescription()); } if (in_array('sysop', $oUser->getGroups())) { $aPersonal_urls['admindashboard'] = array('href' => SpecialPage::getTitleFor('AdminDashboard')->getLocalURL(), 'text' => SpecialPageFactory::getPage('AdminDashboard')->getDescription()); } return true; }
static function renderFormInput(&$parser) { global $wgHtml5; $params = func_get_args(); array_shift($params); // don't need the parser // set defaults $inFormName = $inValue = $inButtonStr = $inQueryStr = ''; $inQueryArr = array(); $positionalParameters = false; $inAutocompletionSource = ''; $inRemoteAutocompletion = false; $inSize = 25; $classStr = "sfFormInput"; $inPlaceholder = ""; // assign params - support unlabelled params, for backwards compatibility foreach ($params as $i => $param) { $elements = explode('=', $param, 2); // set param_name and value if (count($elements) > 1 && !$positionalParameters) { $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 == 'size') { $inSize = $value; } elseif ($param_name == 'default value') { $inValue = $value; } elseif ($param_name == 'button text') { $inButtonStr = $value; } elseif ($param_name == 'query string') { // Change HTML-encoded ampersands directly to // URL-encoded ampersands, so that the string // doesn't get split up on the '&'. $inQueryStr = str_replace('&', '%26', $value); // "Decode" any other HTML tags. $inQueryStr = html_entity_decode($inQueryStr, ENT_QUOTES); parse_str($inQueryStr, $arr); $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr); } 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 == 'placeholder') { $inPlaceholder = $value; } elseif ($param_name == null && $value == 'popup') { SFUtils::loadScriptsForPopupForm($parser); $classStr .= ' popupforminput'; } elseif ($param_name !== null && !$positionalParameters) { $value = urlencode($value); parse_str("{$param_name}={$value}", $arr); $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr); } elseif ($i == 0) { $inFormName = $value; $positionalParameters = true; } elseif ($i == 1) { $inSize = $value; } elseif ($i == 2) { $inValue = $value; } elseif ($i == 3) { $inButtonStr = $value; } elseif ($i == 4) { // Change HTML-encoded ampersands directly to // URL-encoded ampersands, so that the string // doesn't get split up on the '&'. $inQueryStr = str_replace('&', '%26', $value); parse_str($inQueryStr, $arr); $inQueryArr = SFUtils::array_merge_recursive_distinct($inQueryArr, $arr); } } $fs = SpecialPageFactory::getPage('FormStart'); $fs_url = $fs->getTitle()->getLocalURL(); $str = <<<END \t\t\t<form name="createbox" action="{$fs_url}" method="get" class="{$classStr}"> \t\t\t<p> END; $formInputAttrs = array('size' => $inSize); if ($wgHtml5) { $formInputAttrs['placeholder'] = $inPlaceholder; $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 { 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($parser); } $inputID = 'input_' . $input_num; $formInputAttrs['id'] = $inputID; $formInputAttrs['class'] = 'autocompleteInput createboxInput formInput'; global $sfgMaxLocalAutocompleteValues; $autocompletion_values = SFUtils::getAutocompleteValues($inAutocompletionSource, $autocompletion_type); if (count($autocompletion_values) > $sfgMaxLocalAutocompleteValues || $inRemoteAutocompletion) { $formInputAttrs['autocompletesettings'] = $inAutocompletionSource; $formInputAttrs['autocompletedatatype'] = $autocompletion_type; } else { 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 .= Html::hidden("title", urldecode(substr($fs_url, $pos + 6))); } if ($inFormName == '') { $str .= SFUtils::formDropdownHTML(); } else { $str .= Html::hidden("form", $inFormName); } // Recreate the passed-in query string as a set of hidden variables. if (!empty($inQueryArr)) { // query string has to be turned into hidden inputs. $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) { $str .= Html::hidden(urldecode($var_and_val[0]), urldecode($var_and_val[1])); } } } $button_str = $inButtonStr != '' ? $inButtonStr : wfMessage('sf_formstart_createoredit')->escaped(); $str .= <<<END \t\t\t<input type="submit" value="{$button_str}" id="input_button_{$input_num}" class="forminput_button"/></p> \t\t\t</form> END; if (!empty($inAutocompletionSource)) { $str .= "\t\t\t" . Html::element('div', array('class' => 'page_name_auto_complete', 'id' => "div_{$input_num}"), ' ') . "\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); }
/** * Adds the task-based tabs on Special:Translate and few other special pages. * Hook: SkinTemplateNavigation::SpecialPage * @since 2012-05-14 */ static function tabify(Skin $skin, array &$tabs) { $title = $skin->getTitle(); list($alias, ) = SpecialPageFactory::resolveAlias($title->getText()); $pagesInGroup = array('ManageMessageGroups' => 'namespaces', 'AggregateGroups' => 'namespaces', 'SupportedLanguages' => 'views', 'TranslationStats' => 'views'); if (!isset($pagesInGroup[$alias])) { return true; } $skin->getOutput()->addModuleStyles('ext.translate.tabgroup'); $tabs['namespaces'] = array(); foreach ($pagesInGroup as $spName => $section) { $spClass = SpecialPageFactory::getPage($spName); if ($spClass === null) { continue; // Page explicitly disabled } $spTitle = $spClass->getPageTitle(); $tabs[$section][strtolower($spName)] = array('text' => $spClass->getDescription(), 'href' => $spTitle->getLocalUrl(), 'class' => $alias === $spName ? 'selected' : ''); } return true; }