Replace wfRunHooks calls with direct Hooks::run calls
[lhc/web/wiklou.git] / includes / parser / Parser.php
index fe0c81f..91d8a81 100644 (file)
  *
  * - Parser::parse()
  *     produces HTML output
- * - Parser::preSaveTransform().
- *     produces altered wiki markup.
+ * - Parser::preSaveTransform()
+ *     produces altered wiki markup
  * - Parser::preprocess()
  *     removes HTML comments and expands templates
  * - Parser::cleanSig() and Parser::cleanSigInSig()
- *     Cleans a signature before saving it to preferences
+ *     cleans a signature before saving it to preferences
  * - Parser::getSection()
- *     Return the content of a section from an article for section editing
+ *     return the content of a section from an article for section editing
  * - Parser::replaceSection()
- *     Replaces a section by number inside an article
+ *     replaces a section by number inside an article
  * - Parser::getPreloadText()
- *     Removes <noinclude> sections, and <includeonly> tags.
+ *     removes <noinclude> sections and <includeonly> tags
  *
  * Globals used:
  *    object: $wgContLang
@@ -79,7 +79,6 @@ class Parser {
        const HALF_PARSED_VERSION = 2;
 
        # Flags for Parser::setFunctionHook
-       # Also available as global constants from Defines.php
        const SFH_NO_HASH = 1;
        const SFH_OBJECT_ARGS = 2;
 
@@ -224,6 +223,9 @@ class Parser {
         */
        public $mInParse = false;
 
+       /** @var SectionProfiler */
+       protected $mProfiler;
+
        /**
         * @param array $conf
         */
@@ -281,7 +283,7 @@ class Parser {
                        unset( $tmp );
                }
 
-               wfRunHooks( 'ParserCloned', array( $this ) );
+               Hooks::run( 'ParserCloned', array( $this ) );
        }
 
        /**
@@ -299,7 +301,7 @@ class Parser {
                CoreTagHooks::register( $this );
                $this->initialiseVariables();
 
-               wfRunHooks( 'ParserFirstCallInit', array( &$this ) );
+               Hooks::run( 'ParserFirstCallInit', array( &$this ) );
                wfProfileOut( __METHOD__ );
        }
 
@@ -365,7 +367,9 @@ class Parser {
                        $this->mPreprocessor = null;
                }
 
-               wfRunHooks( 'ParserClearState', array( &$this ) );
+               $this->mProfiler = new SectionProfiler();
+
+               Hooks::run( 'ParserClearState', array( &$this ) );
                wfProfileOut( __METHOD__ );
        }
 
@@ -389,7 +393,7 @@ class Parser {
                 * to internalParse() which does all the real work.
                 */
 
-               global $wgUseTidy, $wgAlwaysUseTidy, $wgShowHostnames;
+               global $wgShowHostnames;
                $fname = __METHOD__ . '-' . wfGetCaller();
                wfProfileIn( __METHOD__ );
                wfProfileIn( $fname );
@@ -424,46 +428,13 @@ class Parser {
                        $this->mRevisionSize = null;
                }
 
-               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
                # No more strip!
-               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->internalParse( $text );
-               wfRunHooks( 'ParserAfterParse', array( &$this, &$text, &$this->mStripState ) );
-
-               $text = $this->mStripState->unstripGeneral( $text );
-
-               # Clean up special characters, only run once, next-to-last before doBlockLevels
-               $fixtags = array(
-                       # french spaces, last one Guillemet-left
-                       # only if there is something before the space
-                       '/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1&#160;',
-                       # french spaces, Guillemet-right
-                       '/(\\302\\253) /' => '\\1&#160;',
-                       '/&#160;(!\s*important)/' => ' \\1', # Beware of CSS magic word !important, bug #11874.
-               );
-               $text = preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text );
+               Hooks::run( 'ParserAfterParse', array( &$this, &$text, &$this->mStripState ) );
 
-               $text = $this->doBlockLevels( $text, $linestart );
-
-               $this->replaceLinkHolders( $text );
-
-               /**
-                * The input doesn't get language converted if
-                * a) It's disabled
-                * b) Content isn't converted
-                * c) It's a conversion table
-                * d) it is an interface message (which is in the user language)
-                */
-               if ( !( $options->getDisableContentConversion()
-                       || isset( $this->mDoubleUnderscores['nocontentconvert'] ) )
-               ) {
-                       if ( !$this->mOptions->getInterfaceMessage() ) {
-                               # The position of the convert() call should not be changed. it
-                               # assumes that the links are all replaced and the only thing left
-                               # is the <nowiki> mark.
-                               $text = $this->getConverterLanguage()->convert( $text );
-                       }
-               }
+               $text = $this->internalParseHalfParsed( $text, true, $linestart );
 
                /**
                 * A converted title will be provided in the output object if title and
@@ -486,45 +457,6 @@ class Parser {
                        }
                }
 
-               $text = $this->mStripState->unstripNoWiki( $text );
-
-               wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) );
-
-               $text = $this->replaceTransparentTags( $text );
-               $text = $this->mStripState->unstripGeneral( $text );
-
-               $text = Sanitizer::normalizeCharReferences( $text );
-
-               if ( ( $wgUseTidy && $this->mOptions->getTidy() ) || $wgAlwaysUseTidy ) {
-                       $text = MWTidy::tidy( $text );
-               } else {
-                       # attempt to sanitize at least some nesting problems
-                       # (bug #2702 and quite a few others)
-                       $tidyregs = array(
-                               # ''Something [http://www.cool.com cool''] -->
-                               # <i>Something</i><a href="http://www.cool.com"..><i>cool></i></a>
-                               '/(<([bi])>)(<([bi])>)?([^<]*)(<\/?a[^<]*>)([^<]*)(<\/\\4>)?(<\/\\2>)/' =>
-                               '\\1\\3\\5\\8\\9\\6\\1\\3\\7\\8\\9',
-                               # fix up an anchor inside another anchor, only
-                               # at least for a single single nested link (bug 3695)
-                               '/(<a[^>]+>)([^<]*)(<a[^>]+>[^<]*)<\/a>(.*)<\/a>/' =>
-                               '\\1\\2</a>\\3</a>\\1\\4</a>',
-                               # fix div inside inline elements- doBlockLevels won't wrap a line which
-                               # contains a div, so fix it up here; replace
-                               # div with escaped text
-                               '/(<([aib]) [^>]+>)([^<]*)(<div([^>]*)>)(.*)(<\/div>)([^<]*)(<\/\\2>)/' =>
-                               '\\1\\3&lt;div\\5&gt;\\6&lt;/div&gt;\\8\\9',
-                               # remove empty italic or bold tag pairs, some
-                               # introduced by rules above
-                               '/<([bi])><\/\\1>/' => '',
-                       );
-
-                       $text = preg_replace(
-                               array_keys( $tidyregs ),
-                               array_values( $tidyregs ),
-                               $text );
-               }
-
                if ( $this->mExpensiveFunctionCount > $this->mOptions->getExpensiveParserFunctionLimit() ) {
                        $this->limitationWarn( 'expensive-parserfunction',
                                $this->mExpensiveFunctionCount,
@@ -532,8 +464,6 @@ class Parser {
                        );
                }
 
-               wfRunHooks( 'ParserAfterTidy', array( &$this, &$text ) );
-
                # Information on include size limits, for the benefit of users who try to skirt them
                if ( $this->mOptions->getEnableLimitReport() ) {
                        $max = $this->mOptions->getMaxIncludeSize();
@@ -568,14 +498,14 @@ class Parser {
                        $this->mOutput->setLimitReportData( 'limitreport-expensivefunctioncount',
                                array( $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit() )
                        );
-                       wfRunHooks( 'ParserLimitReportPrepare', array( $this, $this->mOutput ) );
+                       Hooks::run( 'ParserLimitReportPrepare', array( $this, $this->mOutput ) );
 
                        $limitReport = "NewPP limit report\n";
                        if ( $wgShowHostnames ) {
                                $limitReport .= 'Parsed by ' . wfHostname() . "\n";
                        }
                        foreach ( $this->mOutput->getLimitReportData() as $key => $value ) {
-                               if ( wfRunHooks( 'ParserLimitReportFormat',
+                               if ( Hooks::run( 'ParserLimitReportFormat',
                                        array( $key, &$value, &$limitReport, false, false )
                                ) ) {
                                        $keyMsg = wfMessage( $key )->inLanguage( 'en' )->useDatabase( false );
@@ -593,13 +523,26 @@ class Parser {
                        // Since we're not really outputting HTML, decode the entities and
                        // then re-encode the things that need hiding inside HTML comments.
                        $limitReport = htmlspecialchars_decode( $limitReport );
-                       wfRunHooks( 'ParserLimitReport', array( $this, &$limitReport ) );
+                       Hooks::run( 'ParserLimitReport', array( $this, &$limitReport ) );
 
                        // Sanitize for comment. Note '‐' in the replacement is U+2010,
                        // which looks much like the problematic '-'.
                        $limitReport = str_replace( array( '-', '&' ), array( '‐', '&amp;' ), $limitReport );
                        $text .= "\n<!-- \n$limitReport-->\n";
 
+                       // Add on template profiling data
+                       $dataByFunc = $this->mProfiler->getFunctionStats();
+                       uasort( $dataByFunc, function ( $a, $b ) {
+                               return $a['real'] < $b['real']; // descending order
+                       } );
+                       $profileReport = "Transclusion expansion time report (%,ms,calls,template)\n";
+                       foreach ( array_slice( $dataByFunc, 0, 10 ) as $item ) {
+                               $profileReport .= sprintf( "%6.2f%% %8.3f %6d - %s\n",
+                                       $item['%real'], $item['real'], $item['calls'],
+                                       htmlspecialchars( $item['name'] ) );
+                       }
+                       $text .= "\n<!-- \n$profileReport-->\n";
+
                        if ( $this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10 ) {
                                wfDebugLog( 'generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' .
                                        $this->mTitle->getPrefixedDBkey() );
@@ -621,25 +564,61 @@ class Parser {
        }
 
        /**
-        * Recursive parser entry point that can be called from an extension tag
-        * hook.
+        * Half-parse wikitext to half-parsed HTML. This recursive parser entry point
+        * can be called from an extension tag hook.
+        *
+        * The output of this function IS NOT SAFE PARSED HTML; it is "half-parsed"
+        * instead, which means that lists and links have not been fully parsed yet,
+        * and strip markers are still present.
         *
-        * If $frame is not provided, then template variables (e.g., {{{1}}}) within $text are not expanded
+        * Use recursiveTagParseFully() to fully parse wikitext to output-safe HTML.
+        *
+        * Use this function if you're a parser tag hook and you want to parse
+        * wikitext before or after applying additional transformations, and you
+        * intend to *return the result as hook output*, which will cause it to go
+        * through the rest of parsing process automatically.
+        *
+        * If $frame is not provided, then template variables (e.g., {{{1}}}) within
+        * $text are not expanded
         *
         * @param string $text Text extension wants to have parsed
         * @param bool|PPFrame $frame The frame to use for expanding any template variables
-        *
-        * @return string
+        * @return string UNSAFE half-parsed HTML
         */
        public function recursiveTagParse( $text, $frame = false ) {
                wfProfileIn( __METHOD__ );
-               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
-               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->internalParse( $text, false, $frame );
                wfProfileOut( __METHOD__ );
                return $text;
        }
 
+       /**
+        * Fully parse wikitext to fully parsed HTML. This recursive parser entry
+        * point can be called from an extension tag hook.
+        *
+        * The output of this function is fully-parsed HTML that is safe for output.
+        * If you're a parser tag hook, you might want to use recursiveTagParse()
+        * instead.
+        *
+        * If $frame is not provided, then template variables (e.g., {{{1}}}) within
+        * $text are not expanded
+        *
+        * @since 1.25
+        *
+        * @param string $text Text extension wants to have parsed
+        * @param bool|PPFrame $frame The frame to use for expanding any template variables
+        * @return string Fully parsed HTML
+        */
+       public function recursiveTagParseFully( $text, $frame = false ) {
+               wfProfileIn( __METHOD__ );
+               $text = $this->recursiveTagParse( $text, $frame );
+               $text = $this->internalParseHalfParsed( $text, false );
+               wfProfileOut( __METHOD__ );
+               return $text;
+       }
+
        /**
         * Expand templates and variables in the text, producing valid, static wikitext.
         * Also removes comments.
@@ -658,8 +637,8 @@ class Parser {
                if ( $revid !== null ) {
                        $this->mRevisionId = $revid;
                }
-               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
-               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->replaceVariables( $text, $frame );
                $text = $this->mStripState->unstripBoth( $text );
                wfProfileOut( __METHOD__ );
@@ -1227,7 +1206,7 @@ class Parser {
        }
 
        /**
-        * Helper function for parse() that transforms wiki markup into
+        * Helper function for parse() that transforms wiki markup into half-parsed
         * HTML. Only called for $mOutputType == self::OT_HTML.
         *
         * @private
@@ -1244,7 +1223,7 @@ class Parser {
                $origText = $text;
 
                # Hook to suspend the parser in this state
-               if ( !wfRunHooks( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
+               if ( !Hooks::run( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
                        wfProfileOut( __METHOD__ );
                        return $text;
                }
@@ -1265,14 +1244,14 @@ class Parser {
                        $text = $this->replaceVariables( $text );
                }
 
-               wfRunHooks( 'InternalParseBeforeSanitize', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'InternalParseBeforeSanitize', array( &$this, &$text, &$this->mStripState ) );
                $text = Sanitizer::removeHTMLtags(
                        $text,
                        array( &$this, 'attributeStripCallback' ),
                        false,
                        array_keys( $this->mTransparentTagHooks )
                );
-               wfRunHooks( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
+               Hooks::run( 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState ) );
 
                # Tables need to come after variable replacement for things to work
                # properly; putting them before other transformations should keep
@@ -1300,6 +1279,101 @@ class Parser {
                return $text;
        }
 
+       /**
+        * Helper function for parse() that transforms half-parsed HTML into fully
+        * parsed HTML.
+        *
+        * @param string $text
+        * @param bool $isMain
+        * @param bool $linestart
+        * @return string
+        */
+       private function internalParseHalfParsed( $text, $isMain = true, $linestart = true ) {
+               global $wgUseTidy, $wgAlwaysUseTidy;
+
+               $text = $this->mStripState->unstripGeneral( $text );
+
+               # Clean up special characters, only run once, next-to-last before doBlockLevels
+               $fixtags = array(
+                       # french spaces, last one Guillemet-left
+                       # only if there is something before the space
+                       '/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1&#160;',
+                       # french spaces, Guillemet-right
+                       '/(\\302\\253) /' => '\\1&#160;',
+                       '/&#160;(!\s*important)/' => ' \\1', # Beware of CSS magic word !important, bug #11874.
+               );
+               $text = preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text );
+
+               $text = $this->doBlockLevels( $text, $linestart );
+
+               $this->replaceLinkHolders( $text );
+
+               /**
+                * The input doesn't get language converted if
+                * a) It's disabled
+                * b) Content isn't converted
+                * c) It's a conversion table
+                * d) it is an interface message (which is in the user language)
+                */
+               if ( !( $this->mOptions->getDisableContentConversion()
+                       || isset( $this->mDoubleUnderscores['nocontentconvert'] ) )
+               ) {
+                       if ( !$this->mOptions->getInterfaceMessage() ) {
+                               # The position of the convert() call should not be changed. it
+                               # assumes that the links are all replaced and the only thing left
+                               # is the <nowiki> mark.
+                               $text = $this->getConverterLanguage()->convert( $text );
+                       }
+               }
+
+               $text = $this->mStripState->unstripNoWiki( $text );
+
+               if ( $isMain ) {
+                       Hooks::run( 'ParserBeforeTidy', array( &$this, &$text ) );
+               }
+
+               $text = $this->replaceTransparentTags( $text );
+               $text = $this->mStripState->unstripGeneral( $text );
+
+               $text = Sanitizer::normalizeCharReferences( $text );
+
+               if ( ( $wgUseTidy && $this->mOptions->getTidy() ) || $wgAlwaysUseTidy ) {
+                       $text = MWTidy::tidy( $text );
+               } else {
+                       # attempt to sanitize at least some nesting problems
+                       # (bug #2702 and quite a few others)
+                       $tidyregs = array(
+                               # ''Something [http://www.cool.com cool''] -->
+                               # <i>Something</i><a href="http://www.cool.com"..><i>cool></i></a>
+                               '/(<([bi])>)(<([bi])>)?([^<]*)(<\/?a[^<]*>)([^<]*)(<\/\\4>)?(<\/\\2>)/' =>
+                               '\\1\\3\\5\\8\\9\\6\\1\\3\\7\\8\\9',
+                               # fix up an anchor inside another anchor, only
+                               # at least for a single single nested link (bug 3695)
+                               '/(<a[^>]+>)([^<]*)(<a[^>]+>[^<]*)<\/a>(.*)<\/a>/' =>
+                               '\\1\\2</a>\\3</a>\\1\\4</a>',
+                               # fix div inside inline elements- doBlockLevels won't wrap a line which
+                               # contains a div, so fix it up here; replace
+                               # div with escaped text
+                               '/(<([aib]) [^>]+>)([^<]*)(<div([^>]*)>)(.*)(<\/div>)([^<]*)(<\/\\2>)/' =>
+                               '\\1\\3&lt;div\\5&gt;\\6&lt;/div&gt;\\8\\9',
+                               # remove empty italic or bold tag pairs, some
+                               # introduced by rules above
+                               '/<([bi])><\/\\1>/' => '',
+                       );
+
+                       $text = preg_replace(
+                               array_keys( $tidyregs ),
+                               array_values( $tidyregs ),
+                               $text );
+               }
+
+               if ( $isMain ) {
+                       Hooks::run( 'ParserAfterTidy', array( &$this, &$text ) );
+               }
+
+               return $text;
+       }
+
        /**
         * Replace special strings like "ISBN xxx" and "RFC xxx" with
         * magic external links.
@@ -2244,7 +2318,7 @@ class Parser {
                                # Give extensions a chance to select the file revision for us
                                $options = array();
                                $descQuery = false;
-                               wfRunHooks( 'BeforeParserFetchFileAndTitle',
+                               Hooks::run( 'BeforeParserFetchFileAndTitle',
                                        array( $this, $nt, &$options, &$descQuery ) );
                                # Fetch and register the file (file title may be different via hooks)
                                list( $file, $nt ) = $this->fetchFileAndTitle( $nt, $options );
@@ -2871,14 +2945,14 @@ class Parser {
                 * Some of these require message or data lookups and can be
                 * expensive to check many times.
                 */
-               if ( wfRunHooks( 'ParserGetVariableValueVarCache', array( &$this, &$this->mVarCache ) ) ) {
+               if ( Hooks::run( 'ParserGetVariableValueVarCache', array( &$this, &$this->mVarCache ) ) ) {
                        if ( isset( $this->mVarCache[$index] ) ) {
                                return $this->mVarCache[$index];
                        }
                }
 
                $ts = wfTimestamp( TS_UNIX, $this->mOptions->getTimestamp() );
-               wfRunHooks( 'ParserGetVariableValueTs', array( &$this, &$ts ) );
+               Hooks::run( 'ParserGetVariableValueTs', array( &$this, &$ts ) );
 
                $pageLang = $this->getFunctionLang();
 
@@ -3186,7 +3260,7 @@ class Parser {
                                break;
                        default:
                                $ret = null;
-                               wfRunHooks(
+                               Hooks::run(
                                        'ParserGetVariableValueSwitch',
                                        array( &$this, &$this->mVarCache, &$index, &$ret, &$frame )
                                );
@@ -3416,7 +3490,7 @@ class Parser {
                $args = ( null == $piece['parts'] ) ? array() : $piece['parts'];
                wfProfileOut( __METHOD__ . '-setup' );
 
-               $titleProfileIn = null; // profile templates
+               $profileSection = null; // profile templates
 
                # SUBST
                wfProfileIn( __METHOD__ . '-modifiers' );
@@ -3537,11 +3611,7 @@ class Parser {
 
                # Load from database
                if ( !$found && $title ) {
-                       if ( !Profiler::instance()->isPersistent() ) {
-                               # Too many unique items can kill profiling DBs/collectors
-                               $titleProfileIn = __METHOD__ . "-title-" . $title->getPrefixedDBkey();
-                               wfProfileIn( $titleProfileIn ); // template in
-                       }
+                       $profileSection = $this->mProfiler->scopedProfileIn( $title->getPrefixedDBkey() );
                        wfProfileIn( __METHOD__ . '-loadtpl' );
                        if ( !$title->isExternal() ) {
                                if ( $title->isSpecialPage()
@@ -3623,8 +3693,8 @@ class Parser {
                # Recover the source wikitext and return it
                if ( !$found ) {
                        $text = $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args );
-                       if ( $titleProfileIn ) {
-                               wfProfileOut( $titleProfileIn ); // template out
+                       if ( $profileSection ) {
+                               $this->mProfiler->scopedProfileOut( $profileSection );
                        }
                        wfProfileOut( __METHOD__ );
                        return array( 'object' => $text );
@@ -3650,8 +3720,8 @@ class Parser {
                        $isLocalObj = false;
                }
 
-               if ( $titleProfileIn ) {
-                       wfProfileOut( $titleProfileIn ); // template out
+               if ( $profileSection ) {
+                       $this->mProfiler->scopedProfileOut( $profileSection );
                }
 
                # Replace raw HTML by a placeholder
@@ -3745,7 +3815,7 @@ class Parser {
                }
 
                $allArgs = array( &$this );
-               if ( $flags & SFH_OBJECT_ARGS ) {
+               if ( $flags & self::SFH_OBJECT_ARGS ) {
                        # Convert arguments to PPNodes and collect for appending to $allArgs
                        $funcArgs = array();
                        foreach ( $args as $k => $v ) {
@@ -3941,7 +4011,7 @@ class Parser {
                for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) {
                        # Give extensions a chance to select the revision instead
                        $id = false; # Assume current
-                       wfRunHooks( 'BeforeParserFetchTemplateAndtitle',
+                       Hooks::run( 'BeforeParserFetchTemplateAndtitle',
                                array( $parser, $title, &$skip, &$id ) );
 
                        if ( $skip ) {
@@ -4750,7 +4820,7 @@ class Parser {
                         * &$sectionContent : ref to the content of the section
                         * $showEditLinks : boolean describing whether this section has an edit link
                         */
-                       wfRunHooks( 'ParserSectionCreate', array( $this, $i, &$sections[$i], $showEditLink ) );
+                       Hooks::run( 'ParserSectionCreate', array( $this, $i, &$sections[$i], $showEditLink ) );
 
                        $i++;
                }
@@ -4772,7 +4842,7 @@ class Parser {
 
        /**
         * Transform wiki markup when saving a page by doing "\r\n" -> "\n"
-        * conversion, substitting signatures, {{subst:}} templates, etc.
+        * conversion, substituting signatures, {{subst:}} templates, etc.
         *
         * @param string $text The text to transform
         * @param Title $title The Title object for the current article
@@ -5147,7 +5217,7 @@ class Parser {
         * The callback function should have the form:
         *    function myParserFunction( &$parser, $arg1, $arg2, $arg3 ) { ... }
         *
-        * Or with SFH_OBJECT_ARGS:
+        * Or with Parser::SFH_OBJECT_ARGS:
         *    function myParserFunction( $parser, $frame, $args ) { ... }
         *
         * The callback may either return the text result of the function, or an array with the text
@@ -5161,10 +5231,10 @@ class Parser {
         * @param string $id The magic word ID
         * @param callable $callback The callback function (and object) to use
         * @param int $flags A combination of the following flags:
-        *     SFH_NO_HASH   No leading hash, i.e. {{plural:...}} instead of {{#if:...}}
+        *     Parser::SFH_NO_HASH      No leading hash, i.e. {{plural:...}} instead of {{#if:...}}
         *
-        *     SFH_OBJECT_ARGS   Pass the template arguments as PPNode objects instead of text. This
-        *     allows for conditional expansion of the parse tree, allowing you to eliminate dead
+        *     Parser::SFH_OBJECT_ARGS  Pass the template arguments as PPNode objects instead of text.
+        *     This allows for conditional expansion of the parse tree, allowing you to eliminate dead
         *     branches and thus speed up parsing. It is also possible to analyse the parse tree of
         *     the arguments, and to control the way they are expanded.
         *
@@ -5206,7 +5276,7 @@ class Parser {
                                $syn = $wgContLang->lc( $syn );
                        }
                        # Add leading hash
-                       if ( !( $flags & SFH_NO_HASH ) ) {
+                       if ( !( $flags & self::SFH_NO_HASH ) ) {
                                $syn = '#' . $syn;
                        }
                        # Remove trailing colon
@@ -5260,11 +5330,9 @@ class Parser {
         *
         * @param string $text
         * @param int $options
-        *
-        * @return array Array of link CSS classes, indexed by PDBK.
         */
        public function replaceLinkHolders( &$text, $options = 0 ) {
-               return $this->mLinkHolders->replace( $text );
+               $this->mLinkHolders->replace( $text );
        }
 
        /**
@@ -5335,7 +5403,7 @@ class Parser {
                }
                $ig->setAdditionalOptions( $params );
 
-               wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
+               Hooks::run( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
 
                $lines = StringUtils::explode( "\n", $text );
                foreach ( $lines as $line ) {
@@ -5362,7 +5430,7 @@ class Parser {
                        # file (which potentially could be of a different type and have different handler).
                        $options = array();
                        $descQuery = false;
-                       wfRunHooks( 'BeforeParserFetchFileAndTitle',
+                       Hooks::run( 'BeforeParserFetchFileAndTitle',
                                array( $this, $title, &$options, &$descQuery ) );
                        # Don't register it now, as ImageGallery does that later.
                        $file = $this->fetchFileNoRegister( $title, $options );
@@ -5443,7 +5511,7 @@ class Parser {
                        $ig->add( $title, $label, $alt, $link, $handlerOptions );
                }
                $html = $ig->toHTML();
-               wfRunHooks( 'AfterParserFetchFileAndTitle', array( $this, $ig, &$html ) );
+               Hooks::run( 'AfterParserFetchFileAndTitle', array( $this, $ig, &$html ) );
                wfProfileOut( __METHOD__ );
                return $html;
        }
@@ -5532,7 +5600,7 @@ class Parser {
                # Give extensions a chance to select the file revision for us
                $options = array();
                $descQuery = false;
-               wfRunHooks( 'BeforeParserFetchFileAndTitle',
+               Hooks::run( 'BeforeParserFetchFileAndTitle',
                        array( $this, $title, &$options, &$descQuery ) );
                # Fetch and register the file (file title may be different via hooks)
                list( $file, $title ) = $this->fetchFileAndTitle( $title, $options );
@@ -5696,7 +5764,7 @@ class Parser {
                        $params['frame']['title'] = $this->stripAltText( $caption, $holders );
                }
 
-               wfRunHooks( 'ParserMakeImageParams', array( $title, $file, &$params, $this ) );
+               Hooks::run( 'ParserMakeImageParams', array( $title, $file, &$params, $this ) );
 
                # Linker does the rest
                $time = isset( $options['time'] ) ? $options['time'] : false;