function reportLimitData(ParserOutput $output)
 {
     try {
         $this->load();
     } catch (Exception $e) {
         return;
     }
     if ($this->initialStatus) {
         $status = $this->interpreter->getStatus();
         $output->setLimitReportData('scribunto-limitreport-timeusage', array(sprintf("%.3f", $status['time'] / $this->getClockTick()), sprintf("%.3f", $this->options['cpuLimit'])));
         $output->setLimitReportData('scribunto-limitreport-virtmemusage', array($status['vsize'], $this->options['memoryLimit']));
         $output->setLimitReportData('scribunto-limitreport-estmemusage', $status['vsize'] - $this->initialStatus['vsize']);
     }
     $logs = $this->getLogBuffer();
     if ($logs !== '') {
         $output->addModules('ext.scribunto.logs');
         $output->setLimitReportData('scribunto-limitreport-logs', $logs);
     }
 }
示例#2
0
 /**
  * This function accomplishes several tasks:
  * 1) Auto-number headings if that option is enabled
  * 2) Add an [edit] link to sections for users who have enabled the option and can edit the page
  * 3) Add a Table of contents on the top for users who have enabled the option
  * 4) Auto-anchor headings
  *
  * It loops through all headlines, collects the necessary data, then splits up the
  * string and re-inserts the newly formatted headlines.
  *
  * @param string $text
  * @param string $origText Original, untouched wikitext
  * @param bool $isMain
  * @return mixed|string
  * @private
  */
 public function formatHeadings($text, $origText, $isMain = true)
 {
     global $wgMaxTocLevel, $wgExperimentalHtmlIds;
     # Inhibit editsection links if requested in the page
     if (isset($this->mDoubleUnderscores['noeditsection'])) {
         $maybeShowEditLink = $showEditLink = false;
     } else {
         $maybeShowEditLink = true;
         /* Actual presence will depend on ParserOptions option */
         $showEditLink = $this->mOptions->getEditSection();
     }
     if ($showEditLink) {
         $this->mOutput->setEditSectionTokens(true);
     }
     # Get all headlines for numbering them and adding funky stuff like [edit]
     # links - this is for later, but we need the number of headlines right now
     $matches = array();
     $numMatches = preg_match_all('/<H(?P<level>[1-6])(?P<attrib>.*?>)\\s*(?P<header>[\\s\\S]*?)\\s*<\\/H[1-6] *>/i', $text, $matches);
     # if there are fewer than 4 headlines in the article, do not show TOC
     # unless it's been explicitly enabled.
     $enoughToc = $this->mShowToc && ($numMatches >= 4 || $this->mForceTocPosition);
     # Allow user to stipulate that a page should have a "new section"
     # link added via __NEWSECTIONLINK__
     if (isset($this->mDoubleUnderscores['newsectionlink'])) {
         $this->mOutput->setNewSection(true);
     }
     # Allow user to remove the "new section"
     # link via __NONEWSECTIONLINK__
     if (isset($this->mDoubleUnderscores['nonewsectionlink'])) {
         $this->mOutput->hideNewSection(true);
     }
     # if the string __FORCETOC__ (not case-sensitive) occurs in the HTML,
     # override above conditions and always show TOC above first header
     if (isset($this->mDoubleUnderscores['forcetoc'])) {
         $this->mShowToc = true;
         $enoughToc = true;
     }
     # headline counter
     $headlineCount = 0;
     $numVisible = 0;
     # Ugh .. the TOC should have neat indentation levels which can be
     # passed to the skin functions. These are determined here
     $toc = '';
     $full = '';
     $head = array();
     $sublevelCount = array();
     $levelCount = array();
     $level = 0;
     $prevlevel = 0;
     $toclevel = 0;
     $prevtoclevel = 0;
     $markerRegex = self::MARKER_PREFIX . "-h-(\\d+)-" . self::MARKER_SUFFIX;
     $baseTitleText = $this->mTitle->getPrefixedDBkey();
     $oldType = $this->mOutputType;
     $this->setOutputType(self::OT_WIKI);
     $frame = $this->getPreprocessor()->newFrame();
     $root = $this->preprocessToDom($origText);
     $node = $root->getFirstChild();
     $byteOffset = 0;
     $tocraw = array();
     $refers = array();
     $headlines = $numMatches !== false ? $matches[3] : array();
     foreach ($headlines as $headline) {
         $isTemplate = false;
         $titleText = false;
         $sectionIndex = false;
         $numbering = '';
         $markerMatches = array();
         if (preg_match("/^{$markerRegex}/", $headline, $markerMatches)) {
             $serial = $markerMatches[1];
             list($titleText, $sectionIndex) = $this->mHeadings[$serial];
             $isTemplate = $titleText != $baseTitleText;
             $headline = preg_replace("/^{$markerRegex}\\s*/", "", $headline);
         }
         if ($toclevel) {
             $prevlevel = $level;
         }
         $level = $matches[1][$headlineCount];
         if ($level > $prevlevel) {
             # Increase TOC level
             $toclevel++;
             $sublevelCount[$toclevel] = 0;
             if ($toclevel < $wgMaxTocLevel) {
                 $prevtoclevel = $toclevel;
                 $toc .= Linker::tocIndent();
                 $numVisible++;
             }
         } elseif ($level < $prevlevel && $toclevel > 1) {
             # Decrease TOC level, find level to jump to
             for ($i = $toclevel; $i > 0; $i--) {
                 if ($levelCount[$i] == $level) {
                     # Found last matching level
                     $toclevel = $i;
                     break;
                 } elseif ($levelCount[$i] < $level) {
                     # Found first matching level below current level
                     $toclevel = $i + 1;
                     break;
                 }
             }
             if ($i == 0) {
                 $toclevel = 1;
             }
             if ($toclevel < $wgMaxTocLevel) {
                 if ($prevtoclevel < $wgMaxTocLevel) {
                     # Unindent only if the previous toc level was shown :p
                     $toc .= Linker::tocUnindent($prevtoclevel - $toclevel);
                     $prevtoclevel = $toclevel;
                 } else {
                     $toc .= Linker::tocLineEnd();
                 }
             }
         } else {
             # No change in level, end TOC line
             if ($toclevel < $wgMaxTocLevel) {
                 $toc .= Linker::tocLineEnd();
             }
         }
         $levelCount[$toclevel] = $level;
         # count number of headlines for each level
         $sublevelCount[$toclevel]++;
         $dot = 0;
         for ($i = 1; $i <= $toclevel; $i++) {
             if (!empty($sublevelCount[$i])) {
                 if ($dot) {
                     $numbering .= '.';
                 }
                 $numbering .= $this->getTargetLanguage()->formatNum($sublevelCount[$i]);
                 $dot = 1;
             }
         }
         # The safe header is a version of the header text safe to use for links
         # Remove link placeholders by the link text.
         #     <!--LINK number-->
         # turns into
         #     link text with suffix
         # Do this before unstrip since link text can contain strip markers
         $safeHeadline = $this->replaceLinkHoldersText($headline);
         # Avoid insertion of weird stuff like <math> by expanding the relevant sections
         $safeHeadline = $this->mStripState->unstripBoth($safeHeadline);
         # Strip out HTML (first regex removes any tag not allowed)
         # Allowed tags are:
         # * <sup> and <sub> (bug 8393)
         # * <i> (bug 26375)
         # * <b> (r105284)
         # * <bdi> (bug 72884)
         # * <span dir="rtl"> and <span dir="ltr"> (bug 35167)
         #
         # We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from <span>,
         # to allow setting directionality in toc items.
         $tocline = preg_replace(array('#<(?!/?(span|sup|sub|bdi|i|b)(?: [^>]*)?>).*?>#', '#<(/?(?:span(?: dir="(?:rtl|ltr)")?|sup|sub|bdi|i|b))(?: .*?)?>#'), array('', '<$1>'), $safeHeadline);
         # Strip '<span></span>', which is the result from the above if
         # <span id="foo"></span> is used to produce an additional anchor
         # for a section.
         $tocline = str_replace('<span></span>', '', $tocline);
         $tocline = trim($tocline);
         # For the anchor, strip out HTML-y stuff period
         $safeHeadline = preg_replace('/<.*?>/', '', $safeHeadline);
         $safeHeadline = Sanitizer::normalizeSectionNameWhitespace($safeHeadline);
         # Save headline for section edit hint before it's escaped
         $headlineHint = $safeHeadline;
         if ($wgExperimentalHtmlIds) {
             # For reverse compatibility, provide an id that's
             # HTML4-compatible, like we used to.
             #
             # It may be worth noting, academically, that it's possible for
             # the legacy anchor to conflict with a non-legacy headline
             # anchor on the page.  In this case likely the "correct" thing
             # would be to either drop the legacy anchors or make sure
             # they're numbered first.  However, this would require people
             # to type in section names like "abc_.D7.93.D7.90.D7.A4"
             # manually, so let's not bother worrying about it.
             $legacyHeadline = Sanitizer::escapeId($safeHeadline, array('noninitial', 'legacy'));
             $safeHeadline = Sanitizer::escapeId($safeHeadline);
             if ($legacyHeadline == $safeHeadline) {
                 # No reason to have both (in fact, we can't)
                 $legacyHeadline = false;
             }
         } else {
             $legacyHeadline = false;
             $safeHeadline = Sanitizer::escapeId($safeHeadline, 'noninitial');
         }
         # HTML names must be case-insensitively unique (bug 10721).
         # This does not apply to Unicode characters per
         # http://www.w3.org/TR/html5/infrastructure.html#case-sensitivity-and-string-comparison
         # @todo FIXME: We may be changing them depending on the current locale.
         $arrayKey = strtolower($safeHeadline);
         if ($legacyHeadline === false) {
             $legacyArrayKey = false;
         } else {
             $legacyArrayKey = strtolower($legacyHeadline);
         }
         # Create the anchor for linking from the TOC to the section
         $anchor = $safeHeadline;
         $legacyAnchor = $legacyHeadline;
         if (isset($refers[$arrayKey])) {
             for ($i = 2; isset($refers["{$arrayKey}_{$i}"]); ++$i) {
             }
             $anchor .= "_{$i}";
             $refers["{$arrayKey}_{$i}"] = true;
         } else {
             $refers[$arrayKey] = true;
         }
         if ($legacyHeadline !== false && isset($refers[$legacyArrayKey])) {
             for ($i = 2; isset($refers["{$legacyArrayKey}_{$i}"]); ++$i) {
             }
             $legacyAnchor .= "_{$i}";
             $refers["{$legacyArrayKey}_{$i}"] = true;
         } else {
             $refers[$legacyArrayKey] = true;
         }
         # Don't number the heading if it is the only one (looks silly)
         if (count($matches[3]) > 1 && $this->mOptions->getNumberHeadings()) {
             # the two are different if the line contains a link
             $headline = Html::element('span', array('class' => 'mw-headline-number'), $numbering) . ' ' . $headline;
         }
         if ($enoughToc && (!isset($wgMaxTocLevel) || $toclevel < $wgMaxTocLevel)) {
             $toc .= Linker::tocLine($anchor, $tocline, $numbering, $toclevel, $isTemplate ? false : $sectionIndex);
         }
         # Add the section to the section tree
         # Find the DOM node for this header
         $noOffset = $isTemplate || $sectionIndex === false;
         while ($node && !$noOffset) {
             if ($node->getName() === 'h') {
                 $bits = $node->splitHeading();
                 if ($bits['i'] == $sectionIndex) {
                     break;
                 }
             }
             $byteOffset += mb_strlen($this->mStripState->unstripBoth($frame->expand($node, PPFrame::RECOVER_ORIG)));
             $node = $node->getNextSibling();
         }
         $tocraw[] = array('toclevel' => $toclevel, 'level' => $level, 'line' => $tocline, 'number' => $numbering, 'index' => ($isTemplate ? 'T-' : '') . $sectionIndex, 'fromtitle' => $titleText, 'byteoffset' => $noOffset ? null : $byteOffset, 'anchor' => $anchor);
         # give headline the correct <h#> tag
         if ($maybeShowEditLink && $sectionIndex !== false) {
             // Output edit section links as markers with styles that can be customized by skins
             if ($isTemplate) {
                 # Put a T flag in the section identifier, to indicate to extractSections()
                 # that sections inside <includeonly> should be counted.
                 $editsectionPage = $titleText;
                 $editsectionSection = "T-{$sectionIndex}";
                 $editsectionContent = null;
             } else {
                 $editsectionPage = $this->mTitle->getPrefixedText();
                 $editsectionSection = $sectionIndex;
                 $editsectionContent = $headlineHint;
             }
             // We use a bit of pesudo-xml for editsection markers. The
             // language converter is run later on. Using a UNIQ style marker
             // leads to the converter screwing up the tokens when it
             // converts stuff. And trying to insert strip tags fails too. At
             // this point all real inputted tags have already been escaped,
             // so we don't have to worry about a user trying to input one of
             // these markers directly. We use a page and section attribute
             // to stop the language converter from converting these
             // important bits of data, but put the headline hint inside a
             // content block because the language converter is supposed to
             // be able to convert that piece of data.
             // Gets replaced with html in ParserOutput::getText
             $editlink = '<mw:editsection page="' . htmlspecialchars($editsectionPage);
             $editlink .= '" section="' . htmlspecialchars($editsectionSection) . '"';
             if ($editsectionContent !== null) {
                 $editlink .= '>' . $editsectionContent . '</mw:editsection>';
             } else {
                 $editlink .= '/>';
             }
         } else {
             $editlink = '';
         }
         $head[$headlineCount] = Linker::makeHeadline($level, $matches['attrib'][$headlineCount], $anchor, $headline, $editlink, $legacyAnchor);
         $headlineCount++;
     }
     $this->setOutputType($oldType);
     # Never ever show TOC if no headers
     if ($numVisible < 1) {
         $enoughToc = false;
     }
     if ($enoughToc) {
         if ($prevtoclevel > 0 && $prevtoclevel < $wgMaxTocLevel) {
             $toc .= Linker::tocUnindent($prevtoclevel - 1);
         }
         $toc = Linker::tocList($toc, $this->mOptions->getUserLangObj());
         $this->mOutput->setTOCHTML($toc);
         $toc = self::TOC_START . $toc . self::TOC_END;
         $this->mOutput->addModules('mediawiki.toc');
     }
     if ($isMain) {
         $this->mOutput->setSections($tocraw);
     }
     # split up and insert constructed headlines
     $blocks = preg_split('/<H[1-6].*?>[\\s\\S]*?<\\/H[1-6]>/i', $text);
     $i = 0;
     // build an array of document sections
     $sections = array();
     foreach ($blocks as $block) {
         // $head is zero-based, sections aren't.
         if (empty($head[$i - 1])) {
             $sections[$i] = $block;
         } else {
             $sections[$i] = $head[$i - 1] . $block;
         }
         /**
          * Send a hook, one per section.
          * The idea here is to be able to make section-level DIVs, but to do so in a
          * lower-impact, more correct way than r50769
          *
          * $this : caller
          * $section : the section number
          * &$sectionContent : ref to the content of the section
          * $showEditLinks : boolean describing whether this section has an edit link
          */
         Hooks::run('ParserSectionCreate', array($this, $i, &$sections[$i], $showEditLink));
         $i++;
     }
     if ($enoughToc && $isMain && !$this->mForceTocPosition) {
         // append the TOC at the beginning
         // Top anchor now in skin
         $sections[0] = $sections[0] . $toc . "\n";
     }
     $full .= join('', $sections);
     if ($this->mForceTocPosition) {
         return str_replace('<!--MWTOC-->', $toc, $full);
     } else {
         return $full;
     }
 }
示例#3
0
 /**
  * Similar to SMWOutputs::commitToParser() but acting on a ParserOutput object.
  *
  * @param ParserOutput $parserOutput
  */
 public static function commitToParserOutput(ParserOutput $parserOutput)
 {
     foreach (self::$scripts as $key => $script) {
         $parserOutput->addHeadItem($script . "\n", $key);
     }
     foreach (self::$headItems as $key => $item) {
         $parserOutput->addHeadItem("\t\t" . $item . "\n", $key);
     }
     $parserOutput->addModules(array_values(self::$resourceModules));
     self::$resourceModules = array();
     self::$headItems = array();
 }
示例#4
0
 public function reportLimitData(ParserOutput $output)
 {
     $data = $this->getLimitReportData();
     foreach ($data as $k => $v) {
         $output->setLimitReportData($k, $v);
     }
     if (isset($data['scribunto-limitreport-logs'])) {
         $output->addModules('ext.scribunto.logs');
     }
 }