Show a warning in edit preview when a template loop is detected
[lhc/web/wiklou.git] / includes / parser / Parser.php
index 19f368a..c0a648c 100644 (file)
@@ -245,7 +245,7 @@ class Parser {
        public $currentRevisionCache;
 
        /**
-        * @var bool Recursive call protection.
+        * @var bool|string Recursive call protection.
         * This variable should be treated as if it were private.
         */
        public $mInParse = false;
@@ -589,6 +589,14 @@ class Parser {
                                        $this->mTitle->getPrefixedDBkey() );
                        }
                }
+
+               # Wrap non-interface parser output in a <div> so it can be targeted
+               # with CSS (T37247)
+               $class = $this->mOptions->getWrapOutputClass();
+               if ( $class !== false && !$this->mOptions->getInterfaceMessage() ) {
+                       $text = Html::rawElement( 'div', [ 'class' => $class ], $text );
+               }
+
                $this->mOutput->setText( $text );
 
                $this->mRevisionId = $oldRevisionId;
@@ -3253,6 +3261,8 @@ class Parser {
                                        . wfMessage( 'parser-template-loop-warning', $titleText )->inContentLanguage()->text()
                                        . '</span>';
                                $this->addTrackingCategory( 'template-loop-category' );
+                               $this->mOutput->addWarning( wfMessage( 'template-loop-warning',
+                                       wfEscapeWikiText( $titleText ) )->text() );
                                wfDebug( __METHOD__ . ": template loop broken at '$titleText'\n" );
                        }
                }
@@ -3476,7 +3486,7 @@ class Parser {
 
                if ( !$title->equals( $cacheTitle ) ) {
                        $this->mTplRedirCache[$cacheTitle->getPrefixedDBkey()] =
-                               [ $title->getNamespace(), $cdb = $title->getDBkey() ];
+                               [ $title->getNamespace(), $title->getDBkey() ];
                }
 
                return [ $dom, $title ];
@@ -4392,7 +4402,6 @@ class Parser {
                        $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 ) {
@@ -4967,6 +4976,7 @@ class Parser {
 
                $ig->setContextTitle( $this->mTitle );
                $ig->setShowBytes( false );
+               $ig->setShowDimensions( false );
                $ig->setShowFilename( false );
                $ig->setParser( $this );
                $ig->setHideBadImages();
@@ -6065,9 +6075,13 @@ class Parser {
        protected function lock() {
                if ( $this->mInParse ) {
                        throw new MWException( "Parser state cleared while parsing. "
-                               . "Did you call Parser::parse recursively?" );
+                               . "Did you call Parser::parse recursively? Lock is held by: " . $this->mInParse );
                }
-               $this->mInParse = true;
+
+               // Save the backtrace when locking, so that if some code tries locking again,
+               // we can print the lock owner's backtrace for easier debugging
+               $e = new Exception;
+               $this->mInParse = $e->getTraceAsString();
 
                $recursiveCheck = new ScopedCallback( function() {
                        $this->mInParse = false;