/** * Renrder the survey div. * * @since 0.1 * * @param Parser $parser * * @return string */ public function render(Parser $parser) { static $loadedJs = false; if (!$loadedJs) { $parser->getOutput()->addModules('ext.survey.tag'); $parser->getOutput()->addHeadItem(Skin::makeVariablesScript(array('wgSurveyDebug' => SurveySettings::get('JSDebug')))); } return Html::element('span', $this->parameters, $this->contents); }
public static function fmRender($input, array $args, Parser $parser, PPFrame $frame) { global $wgResourceModules; global $wgOut; $wgOut->addModules('ext.FinancialMathematics'); $parser->getOutput()->addModules('ext.FinancialMathematics'); $xml = simplexml_load_string($input); if (!$xml) { $_out = "<span class='fin-math-warning'>" . wfMessage('fm-error-xml')->text() . print_r($input, 1) . "</span>"; } if ($xml) { //http://stackoverflow.com/questions/834875/recursive-cast-from-simplexmlobject-to-array $x = json_decode(json_encode((array) simplexml_load_string($input)), 1); $m = new CT1_Concept_All(); $result = $m->get_controller($x); if (isset($result['warning'])) { $_out = "<span class='fin-math-warning'>" . $result['warning'] . "</span>"; } else { if (isset($result['formulae'])) { $_out = $result['formulae']; } } } if (!isset($_out)) { $_out = "<span class='fin-math-warning'>" . wfMessage('fm-error-no-output')->text() . "</span>"; } //From https://www.mediawiki.org/wiki/QINU_fix $localParser = new Parser(); $output = FinancialMathematicsHooks::renderRawHTML($localParser, $_out); return $output; }
/** * Parser hook handler for {{#articletype}} * * @param Parser $parser : Parser instance available to render * wikitext into html, or parser methods. * * @return string: HTML to insert in the page. */ public static function renderGallery($input, array $args, Parser $parser, PPFrame $frame) { $parser->getOutput()->addModules('ext.promoter.gallery'); $pageName = $parser->getTitle()->getText(); try { $renderedAds = array(); $adChooser = new AdChooser($pageName, !$parser->getUser()->isLoggedIn()); $ads = $adChooser->getAds(); foreach ($ads as $ad) { $renderedAds[] = Ad::fromName($ad['name'])->renderHtml(); } } catch (AdCampaignExistenceException $e) { wfDebugLog('Promoter', $e->getMessage()); //@todo i18n return '<span class="error">No campaign for this page</span>'; } catch (MWException $e) { wfDebugLog('Promoter', $e->getMessage()); return '<span class="error text-danger">An error occurred [' . $e->getMessage() . ']</span>'; } $html = '<div class="promotion-gallery hidden hidden-print">' . '<h5 class="sr-only">זוהי גלריה המקדמת ערכים שונים באתר.</h5>' . '<div class="gallery-controls">' . '<span class="sr-only">בכל רגע מוצגות 3 ידיעות בגלריה. ניתן להציג ידיעה נוספת או לחזור לאחור באמצעות הכפתורים הבאים, או באמצעות מקשי החיצים כאשר הפוקוס הוא על הגלריה</span>' . '<a href="#" class="owl-prev"><span class="fa fa-chevron-right fa-lg" title="הקודם"></span><span class="sr-only">הצגת הידיעה הקודמת</span></a>' . '<a href="#" class="owl-next"><span class="fa fa-chevron-left fa-lg" title="הבא"></span><span class="sr-only">הצגת הידיעה הבאה</span></a>' . '</div>'; if ($args['title']) { $html .= '<div class="header">' . $args['title'] . '</div>'; } $html .= '<div class="owl-carousel clearfix" tabindex="0">' . implode('', $renderedAds) . '</div>' . '</div>'; return $html; }
/** * @since 0.1 * * @param mixed $input * @param array $args * @param Parser $parser * @param PPFrame $frame */ public static function onSparkRender($input, array $args, Parser $parser, $frame = null) { global $wgVersion; global $wgOut; global $egSparkScriptJquery; global $egSparkScriptJquerySpark; static $loadedJs = false; if (version_compare($wgVersion, '1.17', '<')) { // We do not have resource loader if (!$loadedJs) { $wgOut->addScript('<script src="' . $egSparkScriptJquery . '" type="text/javascript"></script>'); wfDebugLog('spark', "AddScript:" . ' <script src="' . $egSparkScriptJquery . '" type="text/javascript"></script>'); //echo "AddScript:".' <script src="'.$egSparkScriptJquery.'" type="text/javascript"></script>'; $wgOut->addScript('<script src="' . $egSparkScriptJquerySpark . '" type="text/javascript"></script>'); wfDebugLog('spark', "AddScript:" . ' <script src="' . $egSparkScriptJquerySpark . '" type="text/javascript"></script>'); //echo "AddScript:".' <script src="'.$egSparkScriptJquerySpark.'" type="text/javascript"></script>'; $loadedJs = true; } } else { // We have resource loader // If we have resource loader if (!$loadedJs) { $parser->getOutput()->addModules('ext.spark'); $loadedJs = true; } } $tag = new SparkTag($args, $input); // PPFrame maybe not existing return $tag->render($parser, $frame); }
/** * @param Parser $parser * @return array */ public static function render($parser) { $html = ''; $html .= $parser->insertStripItem('<a href="#" class="custom-watchlist-wrapper" id="add-to-watchlist"></a>'); $parser->getOutput()->addModules('ext.customwatchlist.foo'); return array($html, 'markerType' => 'nowiki'); }
/** * Parses the <spoiler> tag. * * @access public * @param string User input between <spoiler> * @param array Array of arguments from the opening spoiler tag. * @param object Mediawiki Parser Object * @param object PPFrame object * @return string HTML */ public static function parseSpoilerTag($input, array $args, Parser $parser, PPFrame $frame) { $out = $parser->getOutput(); $out->addModules('ext.spoilers'); $renderedInput = $parser->recursiveTagParse($input); $output = "<div class='spoilers'>\n\t\t\t\t\t\t<div class='spoilers-button-container'>\n\t\t\t\t\t\t\t<span class='spoilers-button'>\n\t\t\t\t\t\t\t\t<span class='spoilers-show'>" . ($args['show'] ? htmlentities($args['show'], ENT_QUOTES) : wfMessage('spoilers_show_default')->text()) . "</span>\n\t\t\t\t\t\t\t\t<span class='spoilers-hide' style='display:none;'>" . ($args['hide'] ? htmlentities($args['hide'], ENT_QUOTES) : wfMessage('spoilers_hide_default')->text()) . "</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class='spoilers-body' style='display:none;'>{$renderedInput}</div>\n\t\t\t\t\t</div>"; return $output; }
/** * Clear all stored data for a given parser. * * @param Parser $parser */ public static function clearStorage(Parser $parser) { $output = $parser->getOutput(); $title = $parser->getTitle(); if (!isset($output) || !isset($title)) { return; } $output->mSMWData = new SMWSemanticData(new SMWDIWikiPage($title->getDBkey(), $title->getNamespace(), $title->getInterwiki())); }
static function renderFentt($input, array $args, Parser $parser, PPFrame $frame) { if (!self::$css_module_added) { // Tell ResourceLoader that we need our css module $parser->getOutput()->addModuleStyles('ext.FenTT'); self::$css_module_added = true; } return FenTT::renderFentt($input, $args); }
/** * Renderer for <emblem> parser tag hook * * @param $input * @param $args Array * @param $parser Parser * @param $frame */ public static function render($input, $args, Parser $parser, PPFrame $frame) { $output = $parser->getOutput(); if (!isset($output->articleEmblems)) { $output->articleEmblems = array(); } $output->articleEmblems[] = $parser->recursiveTagParse($input, $frame); return ''; }
/** * @param Parser $parser * @return string */ public static function sprintbtn($parser) { $html = ''; $title = $parser->getTitle(); $link = $title->getFullURL('printable=yes'); $link = '#'; $parser->getOutput()->addModules('ext.stools.foo'); $html .= $parser->insertStripItem('<a id="print-button" href="' . $link . '" type="button" class="btn btn-primary"><i class="fa fa-print"></i> ' . wfMessage('stools-button-print')->plain() . '</a>'); return $html; }
/** * @desc Based on parser tag arguments validation parsers an error or placeholder * * @param String $input * @param Array $args * @param Parser $parser * @param PPFrame $frame * * @return String */ public function renderPlaceholder($input, array $args, Parser $parser, PPFrame $frame) { // register resource loader module dependencies for map parser tag // done separately for CSS and JS, so CSS will go to top of the page $parser->getOutput()->addModuleStyles('ext.wikia.WikiaMaps.ParserTag'); $parser->getOutput()->addModuleScripts('ext.wikia.WikiaMaps.ParserTag'); $errorMessage = ''; $params = $this->sanitizeParserTagArguments($args); $isValid = $this->validateParseTagParams($params, $errorMessage); if ($isValid) { $params['map'] = $this->getMapObj($params['id']); if (!empty($params['map']->id)) { return $this->sendRequest('WikiaMapsParserTagController', 'mapThumbnail', $params); } else { $errorMessage = wfMessage('wikia-interactive-maps-parser-tag-error-no-map-found')->plain(); } } return $this->sendRequest('WikiaMapsParserTagController', 'parserTagError', ['errorMessage' => $errorMessage]); }
/** * Callback function for registerParserHook. * * @param string $input User-supplied input, unused * @param array $args User-supplied arguments * @param Parser $parser Instance of Parser, unused * @return string HTML */ public static function renderVote($input, $args, $parser) { global $wgOut, $wgUser; wfProfileIn(__METHOD__); // Disable parser cache (sadly we have to do this, because the caching is // messing stuff up; we want to show an up-to-date rating instead of old // or totally wrong rating, i.e. another page's rating...) $parser->disableCache(); // Add CSS & JS // In order for us to do this *here* instead of having to do this in // registerParserHook(), we must've disabled parser cache $parser->getOutput()->addModuleStyles('ext.voteNY.styles'); if ($wgUser->isAllowed('voteny')) { $parser->getOutput()->addModules('ext.voteNY.scripts'); } // Define variable - 0 means that we'll get that green voting box by default $type = 0; // Determine what kind of a voting gadget the user wants: a box or pretty stars? if (preg_match("/^\\s*type\\s*=\\s*(.*)/mi", $input, $matches)) { $type = htmlspecialchars($matches[1]); } elseif (!empty($args['type'])) { $type = intval($args['type']); } $output = null; $title = $wgOut->getTitle(); if ($title) { $articleID = $title->getArticleID(); switch ($type) { case 0: $vote = new Vote($articleID); break; case 1: $vote = new VoteStars($articleID); break; default: $vote = new Vote($articleID); } $output = $vote->display(); } wfProfileOut(__METHOD__); return $output; }
/** * Renders the necessary HTML for a <tabber> tag. * * @access public * @param string The input URL between the beginning and ending tags. * @param array Array of attribute arguments on that beginning tag. * @param object Mediawiki Parser Object * @param object Mediawiki PPFrame Object * @return string HTML */ public static function renderTabber($input, array $args, Parser $parser, PPFrame $frame) { $parser->getOutput()->addModules('ext.Tabber'); $key = md5($input); $arr = explode("|-|", $input); $htmlTabs = ''; foreach ($arr as $tab) { $htmlTabs .= self::buildTab($tab, $parser); } $HTML = '<div id="tabber-' . $key . '" class="tabber">' . $htmlTabs . "</div>"; return $HTML; }
/** * @see MapsBaseMap::addSpecificMapHTML() * */ public function addSpecificMapHTML(Parser $parser) { global $egValidatorErrorLevel; MapsGoogleMaps::addOverlayOutput($this->output, $this->mapName, $this->overlays, $this->controls); if ($egValidatorErrorLevel >= Validator_ERRORS_WARN) { $couldNotGeocodeMsg = Xml::escapeJsString(wfMsg('ukgeocoding_couldNotGeocode')); $showErrorJs = "document.getElementById( '{$this->mapName}_errors' ).innerHTML = '{$couldNotGeocodeMsg}';"; } else { $showErrorJs = ''; } $this->output .= Html::element('div', array('id' => $this->mapName, 'style' => "width: {$this->width}; height: {$this->height}; background-color: #cccccc;"), wfMsg('maps-loading-map')) . "<div id='{$this->mapName}_errors'></div>"; $parser->getOutput()->addHeadItem(Html::inlineScript(<<<EOT \$(function() { \tvar map = initializeGoogleMap('{$this->mapName}', \t\t{ \t\tlat: 0, \t\tlon: 0, \t\tzoom: {$this->zoom}, \t\ttype: {$this->type}, \t\ttypes: [{$this->types}], \t\tcontrols: [{$this->controls}], \t\tscrollWheelZoom: {$this->autozoom} \t\t}, \t\t[] \t); \tvar localSearch = new GlocalSearch(); \tfunction usePointFromPostcode( marker, callbackFunction ) { \t\tlocalSearch.setSearchCompleteCallback( null, \t\t\tfunction() { \t\t\t\tif ( localSearch.results[0] ) { \t\t\t\t\tcallbackFunction(new GLatLng(localSearch.results[0].lat, localSearch.results[0].lng), marker); \t\t\t\t} else { \t\t\t\t\t{$showErrorJs} \t\t\t\t} \t\t\t} \t\t); \t\tlocalSearch.execute(marker.location + ", UK"); \t} \tfunction updateGoogleMap(point, marker) { \t\tmap.addOverlay(createGMarker(point, marker.title, marker.label, marker.icon)); \t\tbounds.extend(point); \t\tmap.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds)); \t\tif({$this->zoom}!=null) map.setZoom({$this->zoom}); \t} \tvar markers = [{$this->markerString}]; \tvar bounds = new GLatLngBounds(); \tfor(i in markers) { \t\tusePointFromPostcode(markers[i], updateGoogleMap); \t} });\t\t\t\t EOT )); }
/** * Call controller view to render <lyricfind> parser hook * * Add an article to appriopriate category * * Example: * * <lyricfind * artist="Paradise Lost" * album="Draconian Times" * additionalAlbums="Draconian Times MMXI" * song="Forever Failure" * songwriter="Nick Holmes" * publisher="Music for Nations" * amgid=28750800> * Understand procedure, understand war * ... * </lyricfind> * * @param $content string tag content * @param array $arguments tag atribbutes * @param Parser $parser parser instance * @return string rendered content */ public static function render($content, array $arguments, Parser $parser) { wfProfileIn(__METHOD__); $data = array_merge($arguments, ['lyric' => self::encodeLyric($content)]); // RingTone URL $data['ringtoneUrl'] = 'http://www.ringtonematcher.com/co/ringtonematcher/02/noc.asp' . http_build_query(['sid' => 'WILWros', 'artist' => $data['artist'], 'song' => $data['song']]); // merge albums data $data['albums'] = array($data['album']); if (isset($data['additionalalbums']) && $data['additionalalbums'] != '') { $data['albums'] = array_merge($data['albums'], explode(',', $data['additionalalbums'])); } $html = F::app()->renderPartial('LyricFindParser', 'content', $data); // add a category + CSS and JavaScript $parser->getOutput()->addCategory(self::CATEGORY, self::CATEGORY); $parser->getOutput()->addModules('ext.lyrics.lyricbox'); // generate a marker $marker = $parser->uniqPrefix() . '-lyricfind-' . count(self::$markers) . "-"; self::$markers[$marker] = $html; wfProfileOut(__METHOD__); return $marker; }
function efSetMainImagePF(Parser $parser, $mainimage) { $parserOutput = $parser->getOutput(); if (isset($parserOutput->eHasMainImageAlready) && $parserOutput->eHasMainImageAlready) { return $mainimage; } $file = Title::newFromText($mainimage, NS_FILE); if ($file instanceof Title) { $parserOutput->addOutputHook('setmainimage', array('dbkey' => $file->getDBkey())); $parserOutput->eHasMainImageAlready = true; } return $mainimage; }
/** * @param $markup * @param Parser $parser * @param PPFrame $frame * @param array $params * * @return string * @throws UnimplementedNodeException when node used in markup does not exists * @throws XmlMarkupParseErrorException xml not well formatted * @throws InvalidInfoboxParamsException when unsupported attributes exist in params array */ public function render($markup, Parser $parser, PPFrame $frame, $params = null) { $infoboxNode = Nodes\NodeFactory::newFromXML($markup, $this->getFrameParams($frame)); $infoboxNode->setExternalParser(new Wikia\PortableInfobox\Parser\MediaWikiParserService($parser, $frame)); //get params if not overridden if (!isset($params)) { $params = $infoboxNode instanceof Nodes\NodeInfobox ? $infoboxNode->getParams() : []; } $infoboxParamsValidator = new Wikia\PortableInfobox\Helpers\InfoboParamsValidator(); $infoboxParamsValidator->validateParams($params); $data = $infoboxNode->getRenderData(); //save for later api usage $this->saveToParserOutput($parser->getOutput(), $infoboxNode); $theme = $this->getThemeWithDefault($params, $frame); $layout = $this->getLayout($params); return (new PortableInfoboxRenderService())->renderInfobox($data, $theme, $layout); }
/** * #coordinates parser function callback * * @param Parser $parser * @param PPFrame $frame * @param Array $args * @return Mixed */ public function coordinates($parser, $frame, $args) { if ($parser != $this->parser) { throw new MWException(__METHOD__ . '() called by wrong parser'); } $this->output = $parser->getOutput(); if (!isset($this->output->geoData)) { $this->output->geoData = new CoordinatesOutput(); } $this->unnamed = array(); $this->named = array(); $first = trim($frame->expand(array_shift($args))); $this->addArg($first); foreach ($args as $arg) { $bits = $arg->splitArg(); $value = trim($frame->expand($bits['value'])); if ($bits['index'] === '') { $this->named[trim($frame->expand($bits['name']))] = $value; } else { $this->addArg($value); } } $this->parseTagArgs(); $status = GeoData::parseCoordinates($this->unnamed, $this->named['globe']); if ($status->isGood()) { $coord = $status->value; $status = $this->applyTagArgs($coord); if ($status->isGood()) { $status = $this->applyCoord($coord); if ($status->isGood()) { return ''; } } } $parser->addTrackingCategory('geodata-broken-tags-category'); $errorText = $this->errorText($status); if ($errorText == '<>') { // Error that doesn't require a message, // can't think of a better way to pass this condition return ''; } return array("<span class=\"error\">{$errorText}</span>", 'noparse' => false); }
/** * @param Parser $parser * @return string */ public static function render($parser) { $user = $parser->getUser(); $title = $parser->getTitle(); if (!$title || !$title->exists()) { return ''; } $author = self::getPageAuthor($title); if (!$author) { return ''; } $html = '<span class="author-rating-wrapper">'; // Add user link $html .= $parser->insertStripItem(' <a target="_blank" href="' . $author->getUserPage()->getFullURL() . '">' . $author->getName() . '</a>'); $html .= ' <i style="display: none;" class="fa fa-thumbs-o-up author-thumbs-up" title="' . wfMessage('authorrating-rate-title')->plain() . '"></i>'; $html .= ' <span class="label label-success">?</span>'; $html .= '</span>'; $parser->getOutput()->addModules('ext.authorrating.foo'); return array($html, 'markerType' => 'nowiki'); }
function wfSampleGetProp($input, array $args, Parser $parser, PPFrame $frame) { $pageId = $parser->getTitle()->getArticleId(); if (isset($args['page'])) { $title = Title::newFromText($args['page']); if (!$title || $title->getArticleId() === 0) { // In a real extension, this would be i18n-ized. return '<span class="error">Invalid page ' . htmlspecialchars($args['page']) . ' specified.</span>'; } // Do for some page other then current one. $dbr = wfGetDB(DB_SLAVE); $propValue = $dbr->selectField('page_props', 'pp_value', array('pp_page' => $title->getArticleId(), 'pp_propname' => "SimpleSetPropExtension"), __METHOD__); if ($propValue === false) { // No prop stored for this page // In a real extension, this would be i18n-ized. return '<span class="error">No prop set for page ' . htmlspecialchars($args['page']) . ' specified.</span>'; } // We found the prop. Unserialize (First level of serialization) $prop = unserialize($propValue); if (!$parser->isValidHalfParsedText($prop)) { // Probably won't ever happen. return '<span class="error">Error retrieving prop</span>'; } else { // Everything should be good. return $parser->unserializeHalfParsedText($prop); } } else { // Second case, current page. // Can't query db, because could be set earlier in the page and not saved yet. // So have to use the parserOutput object. $prop = unserialize($parser->getOutput()->getProperty('SimpleSetPropExtension')); if (!$parser->isValidHalfParsedText($prop)) { // Probably won't ever happen. return '<span class="error">Error retrieving prop</span>'; } else { // Everything should be good. return $parser->unserializeHalfParsedText($prop); } } }
/** * Function executed by use of {{#infoboxbuilder:}} parser function. * It gets the code from InfoboxBuilder.lua and creates new module object * from it. The module is then invoked and the result is returned. * @param Parser $parser Parser object * @param PPFrame $frame PPFrame object * @param array $args Array of arguments passed from $frame object * @return string A string returned by InfoboxBuilder.lua */ public static function parserFunctionHook(\Parser $parser, $frame, $args) { wfProfileIn(__METHOD__); try { /** * Add the registered SCSS with the default theme */ $parser->getOutput()->addModuleStyles('ext.wikia.InfoboxBuilder'); $engine = \Scribunto::getParserEngine($parser); unset($args[0]); $childFrame = $frame->newChild($args, $parser->getTitle(), 1); $moduleText = file_get_contents(__DIR__ . '/includes/lua/InfoboxBuilder.lua'); $module = new \Scribunto_LuaModule($engine, $moduleText, 'InfoboxBuilder'); $result = $module->invoke('builder', $childFrame); $result = \UtfNormal::cleanUp(strval($result)); wfProfileOut(__METHOD__); return $result; } catch (\ScribuntoException $e) { $trace = $e->getScriptTraceHtml(array('msgOptions' => array('content'))); $html = \Html::element('p', array(), $e->getMessage()); if ($trace !== false) { $html .= \Html::element('p', array(), wfMessage('scribunto-common-backtrace')->inContentLanguage()->text()) . $trace; } $out = $parser->getOutput(); if (!isset($out->scribunto_errors)) { $out->addOutputHook('ScribuntoError'); $out->scribunto_errors = array(); $parser->addTrackingCategory('scribunto-common-error-category'); } $out->scribunto_errors[] = $html; $id = 'mw-scribunto-error-' . (count($out->scribunto_errors) - 1); $parserError = wfMessage('scribunto-parser-error')->inContentLanguage()->text() . $parser->insertStripItem('<!--' . htmlspecialchars($e->getMessage()) . '-->'); wfProfileOut(__METHOD__); // #iferror-compatible error element return "<strong class=\"error\"><span class=\"scribunto-error\" id=\"{$id}\">" . $parserError . "</span></strong>"; } }
/** * If a new parser process is getting started, clear collected layer data of the * previous one. * * @since 3.0 * * @param Parser $parser * * @return true */ public static function onParserClearState(Parser &$parser) { $parser->getOutput()->mExtMapsLayers = null; return true; }
/** * Create a new child frame * $args is optionally a multi-root PPNode or array containing the template arguments * * @param bool|array $args * @param Title|bool $title * @param int $indexOffset * @return PPTemplateFrame_DOM */ public function newChild($args = false, $title = false, $indexOffset = 0) { $namedArgs = array(); $numberedArgs = array(); if ($title === false) { $title = $this->title; } if ($args !== false) { $xpath = false; if ($args instanceof PPNode) { $args = $args->node; } foreach ($args as $arg) { if ($arg instanceof PPNode) { $arg = $arg->node; } if (!$xpath || $xpath->document !== $arg->ownerDocument) { $xpath = new DOMXPath($arg->ownerDocument); } $nameNodes = $xpath->query('name', $arg); $value = $xpath->query('value', $arg); if ($nameNodes->item(0)->hasAttributes()) { // Numbered parameter $index = $nameNodes->item(0)->attributes->getNamedItem('index')->textContent; $index = $index - $indexOffset; if (isset($namedArgs[$index]) || isset($numberedArgs[$index])) { $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($index))->text()); $this->parser->addTrackingCategory('duplicate-args-category'); } $numberedArgs[$index] = $value->item(0); unset($namedArgs[$index]); } else { // Named parameter $name = trim($this->expand($nameNodes->item(0), PPFrame::STRIP_COMMENTS)); if (isset($namedArgs[$name]) || isset($numberedArgs[$name])) { $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($name))->text()); $this->parser->addTrackingCategory('duplicate-args-category'); } $namedArgs[$name] = $value->item(0); unset($numberedArgs[$name]); } } } return new PPTemplateFrame_DOM($this->preprocessor, $this, $numberedArgs, $namedArgs, $title); }
/** * Fetched the current revision of the given title and return this. * Will increment the expensive function count and * add a template link to get the value refreshed on changes. * For a given title, which is equal to the current parser title, * the revision object from the parser is used, when that is the current one * * @param Parser $parser * @param Title $title * @return Revision * @since 1.23 */ private static function getCachedRevisionObject($parser, $title = null) { if (is_null($title)) { return null; } // Use the revision from the parser itself, when param is the current page // and the revision is the current one if ($title->equals($parser->getTitle())) { $parserRev = $parser->getRevisionObject(); if ($parserRev && $parserRev->isCurrent()) { // force reparse after edit with vary-revision flag $parser->getOutput()->setFlag('vary-revision'); wfDebug(__METHOD__ . ": use current revision from parser, setting vary-revision...\n"); return $parserRev; } } // Normalize name for cache $page = $title->getPrefixedDBkey(); if (!($parser->currentRevisionCache && $parser->currentRevisionCache->has($page)) && !$parser->incrementExpensiveFunctionCount()) { return null; } $rev = $parser->fetchCurrentRevisionOfTitle($title); $pageID = $rev ? $rev->getPage() : 0; $revID = $rev ? $rev->getId() : 0; // Register dependency in templatelinks $parser->getOutput()->addTemplate($title, $pageID, $revID); return $rev; }
/** * Create a new child frame * $args is optionally a multi-root PPNode or array containing the template arguments * * @param array|bool|PPNode_Hash_Array $args * @param Title|bool $title * @param int $indexOffset * @throws MWException * @return PPTemplateFrame_Hash */ public function newChild($args = false, $title = false, $indexOffset = 0) { $namedArgs = array(); $numberedArgs = array(); if ($title === false) { $title = $this->title; } if ($args !== false) { if ($args instanceof PPNode_Hash_Array) { $args = $args->value; } elseif (!is_array($args)) { throw new MWException(__METHOD__ . ': $args must be array or PPNode_Hash_Array'); } foreach ($args as $arg) { $bits = $arg->splitArg(); if ($bits['index'] !== '') { // Numbered parameter $index = $bits['index'] - $indexOffset; if (isset($namedArgs[$index]) || isset($numberedArgs[$index])) { $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($index))->text()); $this->parser->addTrackingCategory('duplicate-args-category'); } $numberedArgs[$index] = $bits['value']; unset($namedArgs[$index]); } else { // Named parameter $name = trim($this->expand($bits['name'], PPFrame::STRIP_COMMENTS)); if (isset($namedArgs[$name]) || isset($numberedArgs[$name])) { $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($name))->text()); $this->parser->addTrackingCategory('duplicate-args-category'); } $namedArgs[$name] = $bits['value']; unset($numberedArgs[$name]); } } } return new PPTemplateFrame_Hash($this->preprocessor, $this, $numberedArgs, $namedArgs, $title); }
/** * Strips the magic words added by Live Translate from the page text. * * @since 0.6 * * @param Parser &$parser * @param string &$text * * @return true */ public static function stripMagicWords(Parser &$parser, &$text) { global $egLiveTranslateMagicWords; $mw = MagicWord::get('LT_NOTRANSLATIONCONTROL'); if ($mw->matchAndRemove($text)) { $egLiveTranslateMagicWords[] = 'LT_NOTRANSLATIONCONTROL'; } $mw = MagicWord::get('LT_SHOWTRANSLATIONCONTROL'); if ($mw->matchAndRemove($text)) { $egLiveTranslateMagicWords[] = 'LT_SHOWTRANSLATIONCONTROL'; } $po = $parser->getOutput(); $po->mLTMagicWords = $egLiveTranslateMagicWords; return true; }
/** * Parser hook * * @param string $text * @param array $args * @param Parser $parser * @return string */ public static function parserHook($text, $args = array(), $parser) { global $wgUseTidy; // Don't trim leading spaces away, just the linefeeds $out = preg_replace('/^\\n+/', '', rtrim($text)); // Convert deprecated attributes if (isset($args['enclose'])) { if ($args['enclose'] === 'none') { $args['inline'] = true; } unset($args['enclose']); } $lexer = isset($args['lang']) ? $args['lang'] : ''; $result = self::highlight($out, $lexer, $args); if (!$result->isGood()) { $parser->addTrackingCategory('syntaxhighlight-error-category'); } $out = $result->getValue(); // HTML Tidy will convert tabs to spaces incorrectly (bug 30930). // But the conversion from tab to space occurs while reading the input, // before the conversion from 	 to tab, so we can armor it that way. if ($wgUseTidy) { $out = str_replace("\t", '	', $out); } // Allow certain HTML attributes $htmlAttribs = Sanitizer::validateAttributes($args, array('style', 'class', 'id', 'dir')); if (!isset($htmlAttribs['class'])) { $htmlAttribs['class'] = self::HIGHLIGHT_CSS_CLASS; } else { $htmlAttribs['class'] .= ' ' . self::HIGHLIGHT_CSS_CLASS; } if (!(isset($htmlAttribs['dir']) && $htmlAttribs['dir'] === 'rtl')) { $htmlAttribs['dir'] = 'ltr'; } if (isset($args['inline'])) { // Enforce inlineness. Stray newlines may result in unexpected list and paragraph processing // (also known as doBlockLevels()). $out = str_replace("\n", ' ', $out); $out = Html::rawElement('code', $htmlAttribs, $out); } else { // Not entirely sure what benefit this provides, but it was here already $htmlAttribs['class'] .= ' ' . 'mw-content-' . $htmlAttribs['dir']; // Unwrap Pygments output to provide our own wrapper. We can't just always use the 'nowrap' // option (pass 'inline'), since it disables other useful things like line highlighting. // Tolerate absence of quotes for Html::element() and wgWellFormedXml=false. $m = array(); if (preg_match('/^<div class="?mw-highlight"?>(.*)<\\/div>$/s', trim($out), $m)) { $out = trim($m[1]); } else { throw new MWException('Unexpected output from Pygments encountered'); } // Use 'nowiki' strip marker to prevent list processing (also known as doBlockLevels()). // However, leave the wrapping <div/> outside to prevent <p/>-wrapping. $marker = $parser->mUniqPrefix . '-syntaxhighlightinner-' . sprintf('%08X', $parser->mMarkerIndex++) . $parser::MARKER_SUFFIX; $parser->mStripState->addNoWiki($marker, $out); $out = Html::openElement('div', $htmlAttribs) . $marker . Html::closeElement('div'); } // Register CSS $parser->getOutput()->addModuleStyles('ext.pygments'); return $out; }
static function nearestRender($input, array $args, Parser $parser, PPFrame $frame) { $parser->getOutput()->addModules('ext.nearest'); return '<div id="nearestBV"></div>'; }
/** * Modify $this->internals and $colours according to language variant linking rules * @param array $colours */ protected function doVariants(&$colours) { global $wgContLang, $wgContentHandlerUseDB; $linkBatch = new LinkBatch(); $variantMap = array(); // maps $pdbkey_Variant => $keys (of link holders) $output = $this->parent->getOutput(); $linkCache = LinkCache::singleton(); $threshold = $this->parent->getOptions()->getStubThreshold(); $titlesToBeConverted = ''; $titlesAttrs = array(); // Concatenate titles to a single string, thus we only need auto convert the // single string to all variants. This would improve parser's performance // significantly. foreach ($this->internals as $ns => $entries) { if ($ns == NS_SPECIAL) { continue; } foreach ($entries as $index => $entry) { $pdbk = $entry['pdbk']; // we only deal with new links (in its first query) if (!isset($colours[$pdbk]) || $colours[$pdbk] === 'new') { $titlesAttrs[] = array($index, $entry['title']); // separate titles with \0 because it would never appears // in a valid title $titlesToBeConverted .= $entry['title']->getText() . ""; } } } // Now do the conversion and explode string to text of titles $titlesAllVariants = $wgContLang->autoConvertToAllVariants(rtrim($titlesToBeConverted, "")); $allVariantsName = array_keys($titlesAllVariants); foreach ($titlesAllVariants as &$titlesVariant) { $titlesVariant = explode("", $titlesVariant); } // Then add variants of links to link batch $parentTitle = $this->parent->getTitle(); foreach ($titlesAttrs as $i => $attrs) { /** @var Title $title */ list($index, $title) = $attrs; $ns = $title->getNamespace(); $text = $title->getText(); foreach ($allVariantsName as $variantName) { $textVariant = $titlesAllVariants[$variantName][$i]; if ($textVariant === $text) { continue; } $variantTitle = Title::makeTitle($ns, $textVariant); if (is_null($variantTitle)) { continue; } // Self-link checking for mixed/different variant titles. At this point, we // already know the exact title does not exist, so the link cannot be to a // variant of the current title that exists as a separate page. if ($variantTitle->equals($parentTitle) && !$title->hasFragment()) { $this->internals[$ns][$index]['selflink'] = true; continue 2; } $linkBatch->addObj($variantTitle); $variantMap[$variantTitle->getPrefixedDBkey()][] = "{$ns}:{$index}"; } } // process categories, check if a category exists in some variant $categoryMap = array(); // maps $category_variant => $category (dbkeys) $varCategories = array(); // category replacements oldDBkey => newDBkey foreach ($output->getCategoryLinks() as $category) { $categoryTitle = Title::makeTitleSafe(NS_CATEGORY, $category); $linkBatch->addObj($categoryTitle); $variants = $wgContLang->autoConvertToAllVariants($category); foreach ($variants as $variant) { if ($variant !== $category) { $variantTitle = Title::makeTitleSafe(NS_CATEGORY, $variant); if (is_null($variantTitle)) { continue; } $linkBatch->addObj($variantTitle); $categoryMap[$variant] = array($category, $categoryTitle); } } } if (!$linkBatch->isEmpty()) { // construct query $dbr = wfGetDB(DB_SLAVE); $fields = array('page_id', 'page_namespace', 'page_title', 'page_is_redirect', 'page_len', 'page_latest'); if ($wgContentHandlerUseDB) { $fields[] = 'page_content_model'; } $varRes = $dbr->select('page', $fields, $linkBatch->constructSet('page', $dbr), __METHOD__); $linkcolour_ids = array(); // for each found variants, figure out link holders and replace foreach ($varRes as $s) { $variantTitle = Title::makeTitle($s->page_namespace, $s->page_title); $varPdbk = $variantTitle->getPrefixedDBkey(); $vardbk = $variantTitle->getDBkey(); $holderKeys = array(); if (isset($variantMap[$varPdbk])) { $holderKeys = $variantMap[$varPdbk]; $linkCache->addGoodLinkObjFromRow($variantTitle, $s); $output->addLink($variantTitle, $s->page_id); } // loop over link holders foreach ($holderKeys as $key) { list($ns, $index) = explode(':', $key, 2); $entry =& $this->internals[$ns][$index]; $pdbk = $entry['pdbk']; if (!isset($colours[$pdbk]) || $colours[$pdbk] === 'new') { // found link in some of the variants, replace the link holder data $entry['title'] = $variantTitle; $entry['pdbk'] = $varPdbk; // set pdbk and colour # @todo FIXME: Convoluted data flow # The redirect status and length is passed to getLinkColour via the LinkCache # Use formal parameters instead $colours[$varPdbk] = Linker::getLinkColour($variantTitle, $threshold); $linkcolour_ids[$s->page_id] = $pdbk; } } // check if the object is a variant of a category if (isset($categoryMap[$vardbk])) { list($oldkey, $oldtitle) = $categoryMap[$vardbk]; if (!isset($varCategories[$oldkey]) && !$oldtitle->exists()) { $varCategories[$oldkey] = $vardbk; } } } Hooks::run('GetLinkColours', array($linkcolour_ids, &$colours)); // rebuild the categories in original order (if there are replacements) if (count($varCategories) > 0) { $newCats = array(); $originalCats = $output->getCategories(); foreach ($originalCats as $cat => $sortkey) { // make the replacement if (array_key_exists($cat, $varCategories)) { $newCats[$varCategories[$cat]] = $sortkey; } else { $newCats[$cat] = $sortkey; } } $output->setCategoryLinks($newCats); } } }
/** * XML-style tag for page status indicators: icons (or short text snippets) usually displayed in * the top-right corner of the page, outside of the main content. * * @param string $content * @param array $attributes * @param Parser $parser * @param PPFrame $frame * @return string * @since 1.25 */ public static function indicator($content, array $attributes, Parser $parser, PPFrame $frame) { if (!isset($attributes['name']) || trim($attributes['name']) === '') { return '<span class="error">' . wfMessage('invalid-indicator-name')->inContentLanguage()->parse() . '</span>'; } $parser->getOutput()->setIndicator(trim($attributes['name']), Parser::stripOuterParagraph($parser->recursiveTagParseFully($content, $frame))); return ''; }