function setUp()
 {
     parent::setUp();
     $parser = new Parser();
     $options = new ParserOptions();
     $options->setTemplateCallback(array($this, 'templateCallback'));
     $parser->startExternalParse(Title::newMainPage(), $options, Parser::OT_HTML, true);
     try {
         $engine = new Scribunto_LuaSandboxEngine(array('parser' => $parser) + $this->sandboxOpts);
         $engine->setTitle($parser->getTitle());
         $engine->getInterpreter();
         $this->engines['LuaSandbox'] = $engine;
     } catch (Scribunto_LuaInterpreterNotFoundError $e) {
         $this->markTestSkipped("LuaSandbox interpreter not available");
         return;
     }
     try {
         $engine = new Scribunto_LuaStandaloneEngine(array('parser' => $parser) + $this->standaloneOpts);
         $engine->setTitle($parser->getTitle());
         $engine->getInterpreter();
         $this->engines['LuaStandalone'] = $engine;
     } catch (Scribunto_LuaInterpreterNotFoundError $e) {
         $this->markTestSkipped("LuaStandalone interpreter not available");
         return;
     }
 }
 /**
  * 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;
 }
示例#3
0
 /**
  * Get an engine instance for the given parser, and cache it in the parser
  * so that subsequent calls to this function for the same parser will return
  * the same engine.
  *
  * @param Parser $parser
  * @return ScribuntoEngineBase
  */
 public static function getParserEngine(Parser $parser)
 {
     if (empty($parser->scribunto_engine)) {
         $parser->scribunto_engine = self::newDefaultEngine(array('parser' => $parser));
         $parser->scribunto_engine->setTitle($parser->getTitle());
     }
     return $parser->scribunto_engine;
 }
示例#4
0
 /**
  * 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()));
 }
 /**
  * Hooks into ParserAfterTidy.
  * 
  * @param Parser $parser
  * @param String $text
  * @return Boolean 
  */
 static function parse(&$parser, &$text)
 {
     global $wgexLingoUseNamespaces;
     $title = $parser->getTitle();
     // parse if
     if (!isset($parser->mDoubleUnderscores['noglossary']) && (!$title || !isset($wgexLingoUseNamespaces[$title->getNamespace()]) || $wgexLingoUseNamespaces[$title->getNamespace()])) {
         LingoParser::parse($parser, $text);
     }
     return true;
 }
示例#6
0
 /**
  * @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;
 }
 private function makeEngine($class, $opts)
 {
     $parser = new Parser();
     $options = new ParserOptions();
     $options->setTemplateCallback(array($this, 'templateCallback'));
     $parser->startExternalParse(Title::newMainPage(), $options, Parser::OT_HTML, true);
     $engine = new $class(array('parser' => $parser) + $opts);
     $parser->scribunto_engine = $engine;
     $engine->setTitle($parser->getTitle());
     $engine->getInterpreter();
     return $engine;
 }
示例#8
0
 /**
  * Method for handling the ask concept function.
  * 
  * @todo The possible use of this in an HTML or Specal page context needs to be revisited. The code mentions it, but can this actually happen?
  * @todo The escaping of symbols in concept queries needs to be revisited.
  * 
  * @since 1.5.3
  * 
  * @param Parser $parser
  */
 public static function render(Parser &$parser)
 {
     global $wgContLang, $wgTitle;
     $title = $parser->getTitle();
     $pconc = new SMWDIProperty('_CONC');
     if ($title->getNamespace() != SMW_NS_CONCEPT) {
         $result = smwfEncodeMessages(array(wfMsgForContent('smw_no_concept_namespace')));
         SMWOutputs::commitToParser($parser);
         return $result;
     } elseif (count(SMWParseData::getSMWdata($parser)->getPropertyValues($pconc)) > 0) {
         $result = smwfEncodeMessages(array(wfMsgForContent('smw_multiple_concepts')));
         SMWOutputs::commitToParser($parser);
         return $result;
     }
     // process input:
     $params = func_get_args();
     array_shift($params);
     // We already know the $parser ...
     // Use first parameter as concept (query) string.
     $concept_input = str_replace(array('&gt;', '&lt;'), array('>', '<'), array_shift($params));
     // second parameter, if any, might be a description
     $concept_docu = array_shift($params);
     // NOTE: the str_replace above is required in MediaWiki 1.11, but not in MediaWiki 1.14
     $query = SMWQueryProcessor::createQuery($concept_input, SMWQueryProcessor::getProcessedParams(array('limit' => 20, 'format' => 'list')), SMWQueryProcessor::CONCEPT_DESC);
     $concept_text = $query->getDescription()->getQueryString();
     if (!is_null(SMWParseData::getSMWData($parser))) {
         $diConcept = new SMWDIConcept($concept_text, $concept_docu, $query->getDescription()->getQueryFeatures(), $query->getDescription()->getSize(), $query->getDescription()->getDepth());
         SMWParseData::getSMWData($parser)->addPropertyObjectValue($pconc, $diConcept);
     }
     // display concept box:
     $rdflink = SMWInfolink::newInternalLink(wfMsgForContent('smw_viewasrdf'), $wgContLang->getNsText(NS_SPECIAL) . ':ExportRDF/' . $title->getPrefixedText(), 'rdflink');
     SMWOutputs::requireResource('ext.smw.style');
     // TODO: escape output, preferably via Html or Xml class.
     $result = '<div class="smwfact"><span class="smwfactboxhead">' . wfMsgForContent('smw_concept_description', $title->getText()) . (count($query->getErrors()) > 0 ? ' ' . smwfEncodeMessages($query->getErrors()) : '') . '</span>' . '<span class="smwrdflink">' . $rdflink->getWikiText() . '</span>' . '<br />' . ($concept_docu ? "<p>{$concept_docu}</p>" : '') . '<pre>' . str_replace('[', '&#x005B;', $concept_text) . "</pre>\n</div>";
     if (!is_null($wgTitle) && $wgTitle->isSpecialPage()) {
         global $wgOut;
         SMWOutputs::commitToOutputPage($wgOut);
     } else {
         SMWOutputs::commitToParser($parser);
     }
     return $result;
 }
示例#9
0
 /**
  * Renders the #serieslink parser function.
  * 
  * @param Parser $parser
  * @return string the unique tag which must be inserted into the stripped text 
  */
 public static function renderSeriesLink(&$parser)
 {
     global $wgTitle;
     $params = func_get_args();
     array_shift($params);
     // We don't need the parser.
     // remove the target parameter should it be present
     foreach ($params as $key => $value) {
         $elements = explode('=', $value, 2);
         if ($elements[0] === 'target') {
             unset($params[$key]);
         }
     }
     // set the origin parameter
     // This will block it from use as iterator parameter. Oh well.
     $params[] = "origin=" . $parser->getTitle()->getArticleId();
     // 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(SFUtils::createFormLink($parser, 'SeriesEdit', $params), $parser->mStripState);
 }
 /**
  * @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);
        }
    }
}
示例#12
0
 function renderHeadCount(Parser &$parser, $page = '', $level = '')
 {
     if (empty($page)) {
         $title = $parser->getTitle();
     } else {
         $title = Title::newFromText($page);
         if (!$title->exists()) {
             return "'''{$title} does not exist.'''";
         }
     }
     $rev = Revision::newFromTitle($title);
     if ($rev === null) {
         return "'''Could not retrieve revision from {$title}.'''";
     }
     $content = $rev->getContent(Revision::RAW);
     if ($content === null) {
         return "'''Could not extract text from {$title}.'''";
     }
     $level = empty($level) ? 2 : intval($level);
     $header = str_repeat('=', $level);
     $serialized = $content->serialize();
     $count = preg_match_all("/^{$header}" . "[^=]+" . "{$header}\$/m", $serialized);
     return $count == false ? 0 : $count;
 }
示例#13
0
 function getEngine()
 {
     if (!$this->engine) {
         $parser = new Parser();
         $options = new ParserOptions();
         $options->setTemplateCallback(array($this, 'templateCallback'));
         $parser->startExternalParse(Title::newMainPage(), $options, Parser::OT_HTML, true);
         $class = "Scribunto_{$this->engineName}Engine";
         $this->engine = new $class(self::$engineConfigurations[$this->engineName] + array('parser' => $parser));
         $this->engine->setTitle($parser->getTitle());
     }
     return $this->engine;
 }
示例#14
0
 /**
  * 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);
         }
     }
 }
示例#15
0
function BugzillaRender($input, array $args, Parser $parser, $frame = null)
{
    global $wgBugzillaRESTURL;
    // We don't want the page to be cached
    // TODO: Not sure if we need this
    $parser->disableCache();
    // TODO: Figure out to have the parser not do anything to our output
    // mediawiki docs are wrong :-(
    // error_log(print_r($parser->mStripState, true));
    // $parser->mStripState->addItem( 'nowiki', 'NOWIKI', true);
    // 'noparse' => true, 'isHTML' => true, 'markerType' => 'nowiki' );
    $input = $parser->recursiveTagParse($input, $frame);
    // Create a new bugzilla object
    $bz = Bugzilla::create($args, $input, $parser->getTitle());
    // Show the desired output (or an error if there was one)
    return $bz->render();
}
 /**
  * Handles the Parser Hook for TagExtensions
  * @param string $sInput Content of $lt;pagesvisited /&gt; from MediaWiki Framework
  * @param array $aAttributes Attributes of &lt;pagesvisited /&gt; from MediaWiki Framework
  * @param Parser $oParser Parser object from MediaWiki Framework
  * @return string HTML list of recently visited pages
  */
 public function onPagesVisitedTag($sInput, $aAttributes, $oParser)
 {
     $oParser->disableCache();
     $oErrorListView = new ViewTagErrorList($this);
     $iCount = BsCore::sanitizeArrayEntry($aAttributes, 'count', 5, BsPARAMTYPE::INT);
     $iMaxTitleLength = BsCore::sanitizeArrayEntry($aAttributes, 'maxtitlelength', 20, BsPARAMTYPE::INT);
     $sNamespaces = BsCore::sanitizeArrayEntry($aAttributes, 'namespaces', 'all', BsPARAMTYPE::STRING | BsPARAMOPTION::CLEANUP_STRING);
     $sSortOrder = BsCore::sanitizeArrayEntry($aAttributes, 'order', 'time', BsPARAMTYPE::STRING | BsPARAMOPTION::CLEANUP_STRING);
     //Validation
     $oValidationICount = BsValidator::isValid('IntegerRange', $iCount, array('fullResponse' => true, 'lowerBoundary' => 1, 'upperBoundary' => 30));
     if ($oValidationICount->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError('count: ' . $oValidationICount->getI18N()));
     }
     $oValidationIMaxTitleLength = BsValidator::isValid('IntegerRange', $iMaxTitleLength, array('fullResponse' => true, 'lowerBoundary' => 5, 'upperBoundary' => 50));
     if ($oValidationIMaxTitleLength->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError('maxtitlelength: ' . $oValidationIMaxTitleLength->getI18N()));
     }
     if ($oErrorListView->hasItems()) {
         return $oErrorListView->execute();
     }
     $iCurrentNamespaceId = $oParser->getTitle()->getNamespace();
     $oListView = $this->makePagesVisitedWikiList($iCount, $sNamespaces, $iCurrentNamespaceId, $iMaxTitleLength, $sSortOrder);
     $sOut = $oListView->execute();
     if ($oListView instanceof ViewTagErrorList) {
         return $sOut;
     } else {
         return $this->mCore->parseWikiText($sOut, $this->getTitle());
     }
 }
 protected function handleShapeData(array &$params, Parser $parserClone)
 {
     $textContainers = array(&$params['lines'], &$params['polygons'], &$params['circles'], &$params['rectangles'], &$params['imageoverlays']);
     foreach ($textContainers as &$textContainer) {
         if (is_array($textContainer)) {
             foreach ($textContainer as &$obj) {
                 if ($obj instanceof Element) {
                     $obj = $obj->getArrayValue();
                 }
                 $obj['title'] = $parserClone->parse($obj['title'], $parserClone->getTitle(), new ParserOptions())->getText();
                 $obj['text'] = $parserClone->parse($obj['text'], $parserClone->getTitle(), new ParserOptions())->getText();
                 $hasTitleAndtext = $obj['title'] !== '' && $obj['text'] !== '';
                 $obj['text'] = ($hasTitleAndtext ? '<b>' . $obj['title'] . '</b><hr />' : $obj['title']) . $obj['text'];
                 $obj['title'] = strip_tags($obj['title']);
             }
         }
     }
 }
示例#18
0
 /**
  * Clear all stored data for a given parser.
  *
  * @param Parser $parser
  */
 public static function clearStorage(Parser $parser)
 {
     $title = $parser->getTitle();
     if (!isset($title)) {
         return;
     }
     self::setSMWData($parser->getOutput(), new SMWSemanticData(SMWDIWikiPage::newFromTitle($title)));
 }
 /**
  * Do not convert content on talk pages
  *
  * @param string $text
  * @param Parser $parser
  * @return string
  */
 function parserConvert($text, &$parser)
 {
     $this->mDoContentConvert = !(is_object($parser->getTitle()) && $parser->getTitle()->isTalkPage());
     return parent::parserConvert($text, $parser);
 }
 static function parse_label($input, array $args, Parser $parser, PPFrame $frame)
 {
     $ThisPageName = (string) $parser->getTitle();
     $ID = $args['label'];
     // return a id-ed span of the parsed input
     return Html::rawElement('span', array('id' => $ID), $parser->recursiveTagParse($input, $frame));
 }
示例#21
0
 /**
  * Hook for parser function {{NUMBEROFVOTESPAGE:<page>}}
  *
  * @param Parser $parser
  * @param string $pagename Page name
  * @return int Amount of votes for the given page
  */
 static function getNumberOfVotesPageParser($parser, $pagename)
 {
     $title = Title::newFromText($pagename);
     if (!$title instanceof Title) {
         $title = $parser->getTitle();
     }
     return VoteHooks::getNumberOfVotesPage($title);
 }
 /**
  * Renders the blog. Called by parser function for bs:blog tag and also from Blog::onUnknownAction.
  * @param string $input Inner HTML of bs:blog tag. Not used.
  * @param array $args List of tag attributes.
  * @param Parser $parser MediaWiki parser object
  * @return string HTML output that is to be displayed.
  */
 public function onBlog($input, $args, $parser)
 {
     $oTitle = null;
     if ($parser instanceof Parser) {
         $oTitle = $parser->getTitle();
         $parser->disableCache();
     } else {
         $oTitle = $this->getTitle();
     }
     $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'Blog', $oTitle->getArticleID());
     $aData = BsCacheHelper::get($sKey);
     if ($aData !== false) {
         return $aData;
     }
     // initialize local variables
     $oErrorListView = new ViewTagErrorList($this);
     BsExtensionManager::setContext('MW::Blog::ShowBlog');
     // get all config options
     $iShowLimit = BsConfig::get('MW::Blog::ShowLimit');
     //$blogShowTrackback    = BsConfig::get('MW::Blog::ShowTrackback');  // see comment below
     $bShowPermalink = BsConfig::get('MW::Blog::ShowPermalink');
     $bShowInfo = BsConfig::get('MW::Blog::ShowInfo');
     $sSortBy = BsConfig::get('MW::Blog::SortBy');
     $bMoreInNewWindow = BsConfig::get('MW::Blog::MoreInNewWindow');
     $bShowAll = BsConfig::get('MW::Blog::ShowAll');
     $bMoreAtEndOfEntry = BsConfig::get('MW::Blog::MoreAtEndOfEntry');
     $bShowNewEntryField = BsConfig::get('MW::Blog::ShowNewEntryField');
     $bNewEntryFieldPosition = BsConfig::get('MW::Blog::NewEntryFieldPosition');
     $sImageRenderMode = BsConfig::get('MW::Blog::ImageRenderMode');
     $sImageFloatDirection = BsConfig::get('MW::Blog::ThumbFloatDirection');
     $iMaxEntryCharacters = BsConfig::get('MW::Blog::MaxEntryCharacters');
     // Trackbacks are not supported the way we intend it to be. From http://www.mediawiki.org/wiki/Manual:$wgUseTrackbacks
     // When MediaWiki receives a trackback ping, a box will show up at the bottom of the article containing a link to the originating page
     //if (!$wgUseTrackbacks)
     $bShowTrackback = false;
     // get tag attributes
     $argsIShowLimit = BsCore::sanitizeArrayEntry($args, 'count', $iShowLimit, BsPARAMTYPE::NUMERIC | BsPARAMOPTION::DEFAULT_ON_ERROR);
     $argsSCategory = BsCore::sanitizeArrayEntry($args, 'cat', false, BsPARAMTYPE::STRING);
     $argsINamespace = BsNamespaceHelper::getNamespaceIndex(BsCore::sanitizeArrayEntry($args, 'ns', NS_BLOG, BsPARAMTYPE::STRING));
     $argsBNewEntryField = BsCore::sanitizeArrayEntry($args, 'newentryfield', $bShowNewEntryField, BsPARAMTYPE::BOOL);
     $argsSNewEntryFieldPosition = BsCore::sanitizeArrayEntry($args, 'newentryfieldposition', $bNewEntryFieldPosition, BsPARAMTYPE::STRING);
     $argsSImageRenderMode = BsCore::sanitizeArrayEntry($args, 'imagerendermode', $sImageRenderMode, BsPARAMTYPE::STRING);
     $argsSImageFloatDirection = BsCore::sanitizeArrayEntry($args, 'imagefloatdirection', $sImageFloatDirection, BsPARAMTYPE::STRING);
     $argsIMaxEntryCharacters = BsCore::sanitizeArrayEntry($args, 'maxchars', $iMaxEntryCharacters, BsPARAMTYPE::INT);
     $argsSSortBy = BsCore::sanitizeArrayEntry($args, 'sort', $sSortBy, BsPARAMTYPE::STRING);
     $argsBShowInfo = BsCore::sanitizeArrayEntry($args, 'showinfo', $bShowInfo, BsPARAMTYPE::BOOL);
     $argsBMoreInNewWindow = BsCore::sanitizeArrayEntry($args, 'moreinnewwindow', $bMoreInNewWindow, BsPARAMTYPE::BOOL);
     $argsBShowPermalink = BsCore::sanitizeArrayEntry($args, 'showpermalink', $bShowPermalink, BsPARAMTYPE::BOOL);
     $argsModeNamespace = BsCore::sanitizeArrayEntry($args, 'mode', null, BsPARAMTYPE::STRING);
     if ($argsModeNamespace === 'ns' && is_object($oTitle)) {
         $argsINamespace = $oTitle->getNamespace();
     }
     // validate tag attributes
     $validateIShowLimit = BsValidator::isValid('ArgCount', $argsIShowLimit, array('fullResponse' => true));
     if ($validateIShowLimit->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($validateIShowLimit->getI18N()));
     }
     if ($argsSCategory) {
         $validateSCategory = BsValidator::isValid('Category', $argsSCategory, array('fullResponse' => true));
         if ($validateSCategory->getErrorCode()) {
             $oErrorListView->addItem(new ViewTagError($validateSCategory->getI18N()));
         }
     }
     $oValidationResult = BsValidator::isValid('SetItem', $argsSImageRenderMode, array('fullResponse' => true, 'setname' => 'imagerendermode', 'set' => array('full', 'thumb', 'none')));
     if ($oValidationResult->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($oValidationResult->getI18N()));
     }
     $oValidationResult = BsValidator::isValid('SetItem', $argsSImageFloatDirection, array('fullResponse' => true, 'setname' => 'imagefloatdirection', 'set' => array('left', 'right', 'none')));
     if ($oValidationResult->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($oValidationResult->getI18N()));
     }
     $oValidationResult = BsValidator::isValid('SetItem', $argsSSortBy, array('fullResponse' => true, 'setname' => 'sort', 'set' => array('title', 'creation')));
     if ($oValidationResult->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($oValidationResult->getI18N()));
     }
     // if there are errors, abort with a message
     if ($oErrorListView->hasEntries()) {
         return $oErrorListView->execute();
     }
     if (BsConfig::get('MW::Blog::ShowTagFormWhenNotLoggedIn') != true) {
         $oPermissionTest = Title::newFromText('PermissionTest', $argsINamespace);
         if (!$oPermissionTest->userCan('edit')) {
             $argsBNewEntryField = false;
         }
     }
     // get array of article ids from Blog/subpages
     $oBlogTitle = Title::makeTitleSafe($oTitle->getNamespace(), 'Blog');
     $aSubpages = $oBlogTitle->getSubpages();
     $iLimit = 0;
     // for later use
     $aArticleIds = array();
     foreach ($aSubpages as $oSubpage) {
         $aArticleIds[] = $oSubpage->getArticleID();
         $iLimit++;
         // for later use
     }
     if (count($aArticleIds) < 1) {
         $aArticleIds = 0;
     }
     $aTables = array('page');
     $aFields = array('entry_page_id' => 'page_id');
     $aConditions = array();
     $aOptions = array();
     $aJoins = array();
     $dbr = wfGetDB(DB_SLAVE);
     // get blog entries
     if ($argsSSortBy == 'title') {
         $aOptions['ORDER BY'] = 'page_title ASC';
     } else {
         //Creation: Also fetch possible custom timestamps from page_props table
         $aOptions['ORDER BY'] = 'entry_timestamp DESC';
         $aOptions['GROUP BY'] = 'page_id';
         global $wgDBtype;
         switch ($wgDBtype) {
             case 'oracle':
                 $aFields['entry_timestamp'] = "NVL( pp_value, rev_timestamp )";
                 $aConditions[] = "NVL( pp_value, rev_timestamp ) < " . wfTimestampNow();
                 break;
             case 'mssql':
                 $aFields['entry_timestamp'] = "ISNULL( pp_value, rev_timestamp )";
                 $aConditions[] = "ISNULL( pp_value, rev_timestamp ) < " . wfTimestampNow();
                 break;
             case 'postgres':
                 $aFields['entry_timestamp'] = "NULLIF( pp_value, rev_timestamp )";
                 $aConditions[] = "NULLIF( pp_value, rev_timestamp ) < " . wfTimestampNow();
                 break;
             default:
                 //MySQL, SQLite
                 //use pp_value if exists
                 $aFields['entry_timestamp'] = "IFNULL( pp_value, rev_timestamp )";
                 //also do not list future entries
                 $aConditions[] = "IFNULL( pp_value, rev_timestamp ) < " . wfTimestampNow();
         }
         $aTables[] = 'revision';
         $aTables[] = 'page_props';
         $aConditions[] = 'rev_page = page_id';
         $aJoins['page_props'] = array('LEFT JOIN', "pp_page = rev_page AND pp_propname = 'blogtime'");
     }
     if ($argsSCategory) {
         $aTables[] = 'categorylinks';
         $aConditions['cl_to'] = $argsSCategory;
         $aConditions[] = 'cl_from = page_id';
     } else {
         if ($argsModeNamespace === 'ns') {
             $aConditions['page_id'] = $aArticleIds;
         }
         $aConditions['page_namespace'] = $argsINamespace;
     }
     $res = $dbr->select($aTables, $aFields, $aConditions, __METHOD__, $aOptions, $aJoins);
     $iNumberOfEntries = $dbr->numRows($res);
     $iLimit = $iNumberOfEntries;
     //All
     // Sole importance is the existence of param 'showall'
     $paramBShowAll = $this->getRequest()->getFuzzyBool('showall', false);
     if ($paramBShowAll == false) {
         $iLimit = $argsIShowLimit;
     }
     // abort if there are no entries
     if ($iNumberOfEntries < 1) {
         $oBlogView = new ViewBlog();
         $oBlogView->setOption('shownewentryfield', $argsBNewEntryField);
         $oBlogView->setOption('newentryfieldposition', $argsSNewEntryFieldPosition);
         $oBlogView->setOption('namespace', BsNamespaceHelper::getNamespaceName($argsINamespace));
         if ($argsSCategory) {
             $oBlogView->setOption('blogcat', $argsSCategory);
         }
         // actually create blog output
         $sOut = $oBlogView->execute();
         $sOut .= wfMessage('bs-blog-no-entries')->plain();
         return $sOut;
     }
     $oBlogView = new ViewBlog();
     // prepare views per blog item
     $iLoop = 0;
     foreach ($res as $row) {
         // prepare data for view class
         $oEntryTitle = Title::newFromID($row->entry_page_id);
         if (!$oEntryTitle->userCan('read')) {
             $iNumberOfEntries--;
             continue;
         }
         $bMore = false;
         $aContent = preg_split('#<(bs:blog:)?more */>#', BsPageContentProvider::getInstance()->getContentFromTitle($oEntryTitle));
         if (sizeof($aContent) > 1) {
             $bMore = true;
         }
         $aContent = trim($aContent[0]);
         // Prevent recursive rendering of blog tag
         $aContent = preg_replace('/<(bs:)blog[^>]*?>/', '', $aContent);
         // Thumbnail images
         $sNamespaceRegEx = implode('|', BsNamespaceHelper::getNamespaceNamesAndAliases(NS_IMAGE));
         switch ($argsSImageRenderMode) {
             case 'none':
                 $aContent = preg_replace('/(\\[\\[(' . $sNamespaceRegEx . '):[^\\|\\]]*)(\\|)?(.*?)(\\]\\])/', '', $aContent);
                 break;
             case 'full':
                 // do nothing
                 break;
             case 'thumb':
             default:
                 $aContent = preg_replace('/(\\[\\[(' . $sNamespaceRegEx . '):[^\\|\\]]*)(\\|)?(.*?)(\\]\\])/', "\$1|thumb|{$argsSImageFloatDirection}\$3\$4|150px\$5", $aContent);
                 break;
         }
         if (strlen($aContent) > $argsIMaxEntryCharacters) {
             $bMore = true;
         }
         $aContent = BsStringHelper::shorten($aContent, array('max-length' => $argsIMaxEntryCharacters, 'ignore-word-borders' => false, 'position' => 'end'));
         $resComment = $dbr->selectRow('revision', 'COUNT( rev_id ) AS cnt', array('rev_page' => $oEntryTitle->getTalkPage()->getArticleID()));
         $iCount = $resComment->cnt;
         // set data for view class
         $oBlogItemView = new ViewBlogItem();
         // use magic set
         $oBlogItemView->setOption('showInfo', $argsBShowInfo);
         $oBlogItemView->setOption('showLimit', $argsIShowLimit);
         $oBlogItemView->setOption('showTrackback', $bShowTrackback);
         $oBlogItemView->setOption('showPermalink', $argsBShowPermalink);
         $oBlogItemView->setOption('moreInNewWindow', $argsBMoreInNewWindow);
         $oBlogItemView->setOption('showAll', $bShowAll);
         $oBlogItemView->setOption('moreAtEndOfEntry', $bMoreAtEndOfEntry);
         $oBlogItemView->setOption('more', $bMore);
         //TODO: magic_call?
         if ($argsModeNamespace === 'ns') {
             $sTitle = substr($oEntryTitle->getText(), 5);
         } else {
             $sTitle = $oEntryTitle->getText();
         }
         $aTalkParams = array();
         if (!$oEntryTitle->getTalkPage()->exists()) {
             $aTalkParams = array('action' => 'edit');
         }
         $oRevision = Revision::newFromTitle($oEntryTitle);
         $oBlogItemView->setTitle($sTitle);
         $oBlogItemView->setRevId($oRevision->getId());
         $oBlogItemView->setURL($oEntryTitle->getLocalURL());
         $oBlogItemView->setTalkURL($oEntryTitle->getTalkPage()->getLocalURL($aTalkParams));
         $oBlogItemView->setTalkCount($iCount);
         $oBlogItemView->setTrackbackUrl($oEntryTitle->getLocalURL());
         if ($bShowInfo) {
             $oFirstRevision = $oEntryTitle->getFirstRevision();
             $sTimestamp = $oFirstRevision->getTimestamp();
             $sLocalDateTimeString = BsFormatConverter::timestampToAgeString(wfTimestamp(TS_UNIX, $sTimestamp));
             $oBlogItemView->setEntryDate($sLocalDateTimeString);
             $iUserId = $oFirstRevision->getUser();
             if ($iUserId != 0) {
                 $oAuthorUser = User::newFromId($iUserId);
                 $oBlogItemView->setAuthorPage($oAuthorUser->getUserPage()->getPrefixedText());
                 $oBlogItemView->setAuthorName($this->mCore->getUserDisplayName($oAuthorUser));
             } else {
                 $oBlogItemView->setAuthorName($oFirstRevision->getUserText());
             }
         }
         $oBlogItemView->setContent($aContent);
         $oBlogView->addItem($oBlogItemView);
         $iLoop++;
         if ($iLoop >= $iLimit) {
             break;
         }
     }
     $dbr->freeResult($res);
     // prepare complete blog output
     if ($bShowAll && !$paramBShowAll && $iNumberOfEntries > $argsIShowLimit) {
         $oBlogView->setOption('showall', true);
     }
     $oBlogView->setOption('shownewentryfield', $argsBNewEntryField);
     $oBlogView->setOption('newentryfieldposition', $argsSNewEntryFieldPosition);
     $oBlogView->setOption('namespace', BsNamespaceHelper::getNamespaceName($argsINamespace, false));
     $oBlogView->setOption('blogcat', $argsSCategory);
     if ($argsModeNamespace === 'ns') {
         $oBlogView->setOption('parentpage', 'Blog/');
     }
     // actually create blog output
     $sOut = $oBlogView->execute();
     //Use cache only in NS_BLOG - there is curently no functionality to
     //figure out in what type of blog tag a entry is showen and why
     //(coditions). Possible blog by categories or subpages...
     //Needs rework.
     if (in_array($oTitle->getNamespace(), array(NS_BLOG, NS_BLOG_TALK))) {
         $aKey = array($sKey);
         $sTagsKey = BsCacheHelper::getCacheKey('BlueSpice', 'Blog', 'Tags');
         $aTagsData = BsCacheHelper::get($sTagsKey);
         if ($aTagsData !== false) {
             if (!in_array($sKey, $aTagsData)) {
                 $aTagsData = array_merge($aTagsData, $aKey);
             }
         } else {
             $aTagsData = $aKey;
         }
         BsCacheHelper::set($sTagsKey, $aTagsData, 60 * 1440);
         // one day
         BsCacheHelper::set($sKey, $sOut, 60 * 1440);
         // one day
     }
     return $sOut;
 }
示例#23
0
 /**
  * If this song is on takedown list... replace the lyrics content with a message about why
  * it is gone. This will replace the content of all <lyrics> tags on the page (also <lyricfind>
  * and <gracenotelyrics> tags for support of legacy pages).
  *
  * @param Parser $parser
  * @param $text a string containing the wikitext (this is _not_ a Text object).
  * @param strip_state (undocumented)
  */
 public static function onParserBeforeStrip(Parser $parser, &$text, &$strip_state)
 {
     $removedProp = wfGetWikiaPageProp(WPP_LYRICFIND_MARKED_FOR_REMOVAL, $parser->getTitle()->getArticleID());
     $isMarkedAsRemoved = !empty($removedProp);
     if ($isMarkedAsRemoved) {
         // Replace just the lyrics boxes if any are found. If none are found, hide the whole page.
         $NO_LIMIT = -1;
         $numReplacements = 0;
         $text = preg_replace("/<(lyrics|lyricfind|gracenotelyrics)>(.*?)<\\/(lyrics|lyricfind|gracenotelyrics)>/is", "<lyrics>{{lyricfind_takedown}}</lyrics>", $text, $NO_LIMIT, $numReplacements);
     }
     return true;
 }
 /**
  *
  * @param type $input
  * @param string $args
  * @param Parser $parser
  * @return string
  */
 public function onTagBsPageAccess($input, $args, $parser)
 {
     //ignore access tag on mainpage or it will break all ajax calls without title param
     if ($parser->getTitle()->equals(Title::newMainPage()) === true) {
         return '';
     }
     $parser->disableCache();
     if (!isset($args['groups'])) {
         $oErrorView = new ViewTagError(wfMessage('bs-pageaccess-error-no-groups-given')->escaped());
         return $oErrorView->execute();
     }
     $sOldAccessGroups = $parser->getOutput()->getProperty('bs-page-access');
     if ($sOldAccessGroups) {
         $args['groups'] = $sOldAccessGroups . "," . $args['groups'];
     }
     $parser->getOutput()->setProperty('bs-page-access', $args['groups']);
     return '';
 }
示例#25
0
	/**
	 * Helper to get a new title from user input. Returns null if invalid title is given.
	 * 
	 * @param Parser $parser
	 * @param string $title
	 * 
	 * @return Title|null
	 */
	private static function newTitleObject ( Parser &$parser, $title = null ) {
		
		if( is_array( $title ) ) {
			/*
			 * Instead of one Title, all arguments given to the parser function are given.
			 * This is because it makes things more generic to deal with extension 'Parser Fun' support
			 * especially for functions only requiring an option title.
			 */
			// get all possible arguments:
			$args = ExtSubpageFun::getFunctionArgsArray( $title );
			$title = isset( $args[1] ) ? $args[1] : null;	
		}
		
		if( $title !== null && $title !== '' ) {
			return Title::newFromText( $title );
		}
		//returns object of current page if nothing else is requested:
		return $parser->getTitle();
	}
示例#26
0
 /**
  * At the end of article parsing, in case of layer page, save layers to database
  *
  * @since 3.0
  *
  * @param Parser &$parser
  * @param string &$text
  *
  * @return true
  */
 public static function onParserAfterTidy(Parser &$parser, &$text)
 {
     $title = $parser->getTitle();
     if ($title === null || self::$purgedBeforeStore !== true) {
         // just preprocessing some stuff or no purge
         return true;
     }
     self::processLayersStoreCandidate($parser->getOutput(), $title);
     // Set helper to false immediately so we won't run into job-processing weirdness:
     self::$purgedBeforeStore = false;
     return true;
 }
 /**
  * Get the pageid of a specified page
  * @param Parser $parser
  * @param string $title Title to get the pageid from
  * @return int|null|string
  * @since 1.23
  */
 public static function pageid($parser, $title = null)
 {
     $t = Title::newFromText($title);
     if (is_null($t)) {
         return '';
     }
     // Use title from parser to have correct pageid after edit
     if ($t->equals($parser->getTitle())) {
         $t = $parser->getTitle();
         return $t->getArticleID();
     }
     // These can't have ids
     if (!$t->canExist() || $t->isExternal()) {
         return 0;
     }
     // Check the link cache, maybe something already looked it up.
     $linkCache = LinkCache::singleton();
     $pdbk = $t->getPrefixedDBkey();
     $id = $linkCache->getGoodLinkID($pdbk);
     if ($id != 0) {
         $parser->mOutput->addLink($t, $id);
         return $id;
     }
     if ($linkCache->isBadLink($pdbk)) {
         $parser->mOutput->addLink($t, 0);
         return $id;
     }
     // We need to load it from the DB, so mark expensive
     if ($parser->incrementExpensiveFunctionCount()) {
         $id = $t->getArticleID();
         $parser->mOutput->addLink($t, $id);
         return $id;
     }
     return null;
 }
示例#28
0
 protected function getJsonForStaticLocation(Location $location, array $params, $iconUrl, $visitedIconUrl, Parser $parser)
 {
     $jsonObj = $location->getJSONObject($params['title'], $params['label'], $iconUrl, '', '', $visitedIconUrl);
     $jsonObj['title'] = $parser->parse($jsonObj['title'], $parser->getTitle(), new ParserOptions())->getText();
     $jsonObj['text'] = $parser->parse($jsonObj['text'], $parser->getTitle(), new ParserOptions())->getText();
     $hasTitleAndtext = $jsonObj['title'] !== '' && $jsonObj['text'] !== '';
     $jsonObj['text'] = ($hasTitleAndtext ? '<b>' . $jsonObj['title'] . '</b><hr />' : $jsonObj['title']) . $jsonObj['text'];
     $jsonObj['title'] = strip_tags($jsonObj['title']);
     if ($params['pagelabel']) {
         $jsonObj['inlineLabel'] = Linker::link(Title::newFromText($jsonObj['title']));
     }
     return $jsonObj;
 }
示例#29
0
 protected function parse($wikitext, $params, $newline = false)
 {
     $withVars = $this->parser->replaceVariables($wikitext, $this->parser->getPreprocessor()->newCustomFrame($params));
     $parserOutput = $this->parser->parse($withVars, $this->parser->getTitle(), $this->parser->getOptions(), $newline);
     return preg_replace('|{{{.*}}}|Us', '', preg_replace('|[\\n\\r]|Us', '', $parserOutput->getText()));
 }
 /**
  * Parser hook for the <opengraph> tag.
  * 
  * This tag is dual-purpose. By specifying the "type" attribute, the type
  * of Open Graph object represented by the wiki page can be set. The
  * additional attributes set the <meta> properties for the object. Even
  * if "type" isn't specified, the other attributes can still be used to
  * override the default properties.
  * 
  * If the "action" attribute is given, this tag will render a link that,
  * when clicked, adds an action to the Facebook user's Timeline with the
  * wiki page as the target object. If no action is given, $innertext is
  * discarded.
  */
 public static function parserHook($innertext, array $args, Parser $parser, PPFrame $frame)
 {
     global $wgFbOpenGraph, $wgFbOpenGraphCustomObjects;
     if (empty($wgFbOpenGraph) || empty($wgFbOpenGraphCustomObjects)) {
         return '';
         // Open Graph is disabled for this wiki
     }
     if (isset($args['action'])) {
         $action = $args['action'];
         unset($args['action']);
     } else {
         $action = '';
     }
     if (count($args)) {
         foreach ($args as $key => $value) {
             // Expand template arguments
             $value = trim($parser->replaceVariables($value, $frame));
             // Check if $value is a wiki link
             if (substr($value, 0, 2) == '[[') {
                 $resolved = $parser->replaceInternalLinks($value);
                 $parser->replaceLinkHolders($resolved);
                 preg_match('/^<a\\b[^<>]*?\\bhref=("[^"]*"|\'[^\']*\')/', $resolved, $matches);
                 if (count($matches) >= 2) {
                     global $wgServer;
                     // strip quotes
                     $matches[1] = substr($matches[1], 1, strlen($matches[1]) - 2);
                     $url = $wgServer . $matches[1];
                 }
             }
             $value = !empty($url) ? $url : $parser->recursiveTagParse($value, $frame);
             $args[$key] = htmlspecialchars($value);
         }
         self::registerProperties($parser->getTitle(), $args);
     }
     // TODO: Insert a placeholder so that actions can be placed above type definitions on the page
     if ($action != '') {
         // See if the action is available for the object type
         $object = self::newObjectFromTitle($parser->getTitle());
         $actions = $object->getCustomActions();
         if (count($actions) && in_array($action, $actions)) {
             // Let the page know it should load the actions module
             global $wgVersion;
             if (version_compare($wgVersion, '1.17', '>=')) {
                 global $wgOut;
                 $wgOut->addModules('ext.facebook.actions');
             }
             $innertext = htmlspecialchars($parser->replaceVariables($innertext, $frame));
             return '<a href="#" class="mw-facebook-logo opengraph-action opengraph-action-' . $action . '">' . $innertext . '</a>';
         }
     }
     return '';
 }