Wikia code/includes/parser/Parser.php

--- D:\Programming\SVN\mediawiki\branches\REL1_16\phase3\includes\parser\Parser.php	2011-07-18 22:30:54.881836000 +0100
+++ D:\Programming\SVN\wikia\trunk\includes\parser\Parser.php	2011-08-17 15:28:13.331054700 +0100
@@ -340,7 +340,14 @@
 			'/(\\302\\253) /' => '\\1 ',
 			'/ (!\s*important)/' => ' \\1', #Beware of CSS magic word !important, bug #11874.
 		);
+
+		/* Wikia change begin - @author: Macbre */
+		/* RT #42007 */
+		global $wgRTEParserEnabled;
+		if (empty($wgRTEParserEnabled)) {
 		$text = preg_replace( array_keys($fixtags), array_values($fixtags), $text );
+		}
+		/* Wikia change end */
 
 		$text = $this->doBlockLevels( $text, $linestart );
 
@@ -387,7 +394,8 @@
 			if ( $convruletitle ) {
 				$this->mOutput->setTitleText( $convruletitle );
 			} else {
-				$titleText = $wgContLang->convertTitle( $title );
+				//fix problem with fake title MWException
+				$titleText = $wgContLang->convertTitle( $this->mTitle );
 				$this->mOutput->setTitleText( $titleText );
 			}
 		}
@@ -465,7 +473,7 @@
 				"Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n".
 				$PFreport;
 			wfRunHooks( 'ParserLimitReport', array( $this, &$limitReport ) );
-			$text .= "\n<!-- \n$limitReport-->\n";
+			$text .= "<!-- \n$limitReport-->";
 		}
 		$this->mOutput->setText( $text );
 
@@ -707,6 +715,11 @@
 	function doTableStuff ( $text ) {
 		wfProfileIn( __METHOD__ );
 
+		# RTE (Rich Text Editor) - begin
+		# Used to determine whether the Parser running in RTE mode or not
+		global $wgRTEParserEnabled;
+		# RTE - end
+
 		$lines = StringUtils::explode( "\n", $text );
 		$out = '';
 		$td_history = array (); // Is currently a td tag open?
@@ -719,6 +732,29 @@
 		foreach ( $lines as $outLine ) {
 			$line = trim( $outLine );
 
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+
+			# Initialize this variable regardless of the RTE mode being on/off,
+			# then it can be used in next batch of code without checking RTE mode.
+			$RTEcomment = null;
+
+			if(!empty($wgRTEParserEnabled)) {
+
+				# Check if there is a wikitext comment placholder at the beginning of given line,
+				# then cut it off - to have proper MediaWiki table processing - and store in variable for later recovery
+				$RTEdataIdx = RTEMarker::getDataIdx(RTEMarker::PLACEHOLDER, $line, false);
+				if($RTEdataIdx != null) {
+					$RTEdata = RTEData::get('placeholder', $RTEdataIdx);
+					if($RTEdata && $RTEdata['type'] == 'comment'){
+						$RTEcomment = substr($line, 0, 9);
+						$line = substr($line, 9);
+					}
+				}
+
+			}
+			# RTE - end
+
 			if( $line == '' ) { // empty line, go to next line
 				$out .= $outLine."\n";
 				continue;
@@ -731,9 +768,27 @@
 				$indent_level = strlen( $matches[1] );
 
 				$attributes = $this->mStripState->unstripBoth( $matches[2] );
+
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				if(!empty($wgRTEParserEnabled)) {
+					# Throw an RTE edgacase if there is RTR marker (\x7f) in table attributes
+					# Example: {| {{some template call}}
+					if(strpos($attributes, "\x7f") !== false) {
+						RTE::$edgeCases[] = 'COMPLEX.04';
+					}
+				}
+				# RTE - end
+
 				$attributes = Sanitizer::fixTagAttributes ( $attributes , 'table' );
 
 				$outLine = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>";
+
+				# RTE (Rich Text Editor) - begin
+				$outLine = $RTEcomment.$outLine;
+				$RTEcomment = null;
+				# RTE - end
+
 				array_push( $td_history , false );
 				array_push( $last_tag_history , '' );
 				array_push( $tr_history , false );
@@ -767,6 +822,17 @@
 
 				// Whats after the tag is now only attributes
 				$attributes = $this->mStripState->unstripBoth( $line );
+
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				if(!empty($wgRTEParserEnabled)) {
+					# Throw an RTE edgacase if there is RTR marker (\x7f) in row attributes
+					if(strpos($attributes, "\x7f") !== false) {
+						RTE::$edgeCases[] = 'COMPLEX.05';
+					}
+				}
+				# RTE - end
+
 				$attributes = Sanitizer::fixTagAttributes( $attributes, 'tr' );
 				array_pop( $tr_attributes );
 				array_push( $tr_attributes, $attributes );
@@ -862,7 +928,29 @@
 					$outLine .= $cell;
 					array_push ( $td_history , true );
 				}
+			} else {
+
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				if(!empty($wgRTEParserEnabled)) {
+					if(empty($td_history[0]) || $last_tag == 'caption') {
+						if(strpos($outLine, "\x7f-comment-") !== false) {
+							RTE::$edgeCases[] = 'COMPLEX.06';
+						}
+					}
 			}
+				# RTE - end
+
+			}
+
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			if(!empty($RTEcomment)) {
+				# Throw an edgecase if $RTEcomment did not get flushed (nulled) yet
+				RTE::$edgeCases[] = 'COMPLEX.10';
+			}
+			# RTE - end
+
 			$out .= $outLine . "\n";
 		}
 
@@ -1077,9 +1165,23 @@
 		# Is this an external image?
 		$text = $this->maybeMakeExternalImage( $url );
 		if ( $text === false ) {
+
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			$description =  $wgContLang->markNoConversion($url);
+
+			global $wgRTEParserEnabled;
+			if(!empty($wgRTEParserEnabled))  {
+				$description = RTEMarker::generate(RTEMarker::EXTERNAL_DATA, RTEData::put('data', array(
+					'type' => 'external-raw',
+					'text' => $description,
+					'link' => $url))).$description;
+			}
+
 			# Not an image, make a link
 			$text = $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free',
 				$this->getExternalLinkAttribs( $url ) );
+			# RTE - end
 			# Register it in the output object...
 			# Replace unnecessary URL escape codes with their equivalent characters
 			$pasteurized = self::replaceUnusualEscapes( $url );
@@ -1333,6 +1435,15 @@
 			# Set linktype for CSS - if URL==text, link is essentially free
 			$linktype = ($text === $url) ? 'free' : 'text';
 
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			global $wgRTEParserEnabled;
+			if(!empty($wgRTEParserEnabled)) {
+				$RTE_wikitextIdx = RTEMarker::getDataIdx(RTEMarker::EXTERNAL_WIKITEXT, $trail);
+				$wasblank = $text == '';
+			}
+			# RTE - end
+
 			# No link text, e.g. [http://domain.tld/some.link]
 			if ( $text == '' ) {
 				# Autonumber if allowed. See bug #5918
@@ -1359,6 +1470,20 @@
 			# This means that users can paste URLs directly into the text
 			# Funny characters like &ouml; aren't valid in URLs anyway
 			# This was changed in August 2004
+
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			if(!empty($wgRTEParserEnabled)) {
+				$text = RTEMarker::generate(RTEMarker::EXTERNAL_DATA, RTEData::put('data', array(
+					'type' => 'external',
+					'wikitextIdx' => $RTE_wikitextIdx,
+					'text' => $text,
+					'link' => $url,
+					'linktype' => $linktype,
+					'wasblank' => $wasblank))).$text;
+			}
+			# RTE - end
+
 			$s .= $sk->makeExternalLink( $url, $text, false, $linktype,
 				$this->getExternalLinkAttribs( $url ) ) . $dtrail . $trail;
 
@@ -1451,6 +1576,7 @@
 	 * @private
 	 */
 	function maybeMakeExternalImage( $url ) {
+		global $wgAllowExternalWhitelistImages;
 		$sk = $this->mOptions->getSkin();
 		$imagesfrom = $this->mOptions->getAllowExternalImagesFrom();
 		$imagesexception = !empty($imagesfrom);
@@ -1470,7 +1596,8 @@
 			$imagematch = false;
 		}
 		if ( $this->mOptions->getAllowExternalImages()
-		     || ( $imagesexception && $imagematch ) ) {
+		     || ( $imagesexception && $imagematch )
+		     || (!empty($wgAllowExternalWhitelistImages) && wfRunHooks('outputMakeExternalImage', array(&$url)))) {
 			if ( preg_match( self::EXT_IMAGE_REGEX, $url ) ) {
 				# Image found
 				$text = $sk->makeExternalImage( $url );
@@ -1511,7 +1638,10 @@
 	 * @private
 	 */
 	function replaceInternalLinks2( &$s ) {
-		global $wgContLang;
+		global $wgContLang, $wgEnableVideoToolExt;
+		# RTE (Rich Text Editor) - begin
+		global $wgRTEParserEnabled;
+		# RTE - end
 
 		wfProfileIn( __METHOD__ );
 
@@ -1581,6 +1711,23 @@
 				$holders->clear();
 			}
 
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			if(!empty($wgRTEParserEnabled)) {
+				$RTE_wikitextIdx = RTEMarker::getDataIdx(RTEMarker::INTERNAL_WIKITEXT, $line);
+
+				// decode entities inside links wikimarkup (RT #38844)
+				if ($pos = strpos($line, ']]')) {
+					// unmark entities inside link
+					$link = substr($line, 0, $pos);
+					$link = RTEParser::unmarkEntities($link);
+
+					// leave the rest of the line untouched
+					$line = $link . substr($line, $pos);
+				}
+ 			}
+			# RTE - end
+
 			if ( $useLinkPrefixExtension ) {
 				wfProfileIn( __METHOD__.'-prefixhandling' );
 				if ( preg_match( $e2, $s, $m ) ) {
@@ -1676,7 +1823,7 @@
 
 			if ( $might_be_img ) { # if this is actually an invalid link
 				wfProfileIn( __METHOD__."-might_be_img" );
-				if ( $ns == NS_FILE && $noforce ) { #but might be an image
+				if ( ( $ns == NS_FILE || $ns == NS_VIDEO ) && $noforce ) { #but might be an image
 					$found = false;
 					while ( true ) {
 						#look at the next 'line' to see if we can close it there
@@ -1727,7 +1874,12 @@
 
 				# Interwikis
 				wfProfileIn( __METHOD__."-interwiki" );
-				if ( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
+
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				# No interwiki handling in RTE mode
+				if ( empty($wgRTEParserEnabled) && $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
+				# RTE - end
 					$this->mOutput->addLanguageLink( $nt->getFullText() );
 					$s = rtrim($s . $prefix);
 					$s .= trim($trail, "\n") == '' ? '': $prefix . $trail;
@@ -1736,8 +1888,38 @@
 				}
 				wfProfileOut( __METHOD__."-interwiki" );
 
+				/* Wikia change begin - @author: Bartek */
+				/* Support for [[Video:...]] */
+				/* TODO: Get the hell out with this code from here */
+				if( $ns == NS_VIDEO ) {
+					if(!empty($wgEnableVideoToolExt)) {
+						wfProfileIn(__METHOD__ . "-video");
+						$text = $this->replaceExternalLinks($text);
+						$holders->merge( $this->replaceInternalLinks2( $text ) );
+						global $wgContLang;
+						$vid_tag = $wgContLang->getFormattedNsText( NS_VIDEO ) . ":Template_Placeholder";
+						( 0 === strpos( $text, $vid_tag ) ) ? $in_template = true : $in_template = false;
+
+						# RTE (Rich Text Editor) - begin
+						if (!empty($wgRTEParserEnabled)) {
+							$wikitext = RTEData::get('wikitext', $RTE_wikitextIdx);
+							$videoOut = WikiaVideo_makeVideo($nt, $text, $sk, $wikitext, false, $holders /* needed by RT #90616 */);
+						} else {
+							$videoOut = WikiaVideo_makeVideo($nt, $text, $sk, '', $in_template);
+						}
+						# RTE - end
+
+						$s .= $prefix . $this->armorLinks($videoOut).$trail;
+						$this->mOutput->addImage(':'.$nt->getDBkey());
+						wfProfileOut(__METHOD__ . "-video");
+						continue;
+					}
+				}
+				/* Wikia change end */
+
 				if ( $ns == NS_FILE ) {
 					wfProfileIn( __METHOD__."-image" );
+
 					if ( !wfIsBadImage( $nt->getDBkey(), $this->mTitle ) ) {
 						if ( $wasblank ) {
 							# if no parameters were passed, $text
@@ -1752,11 +1934,24 @@
 							$text = $this->replaceExternalLinks($text);
 							$holders->merge( $this->replaceInternalLinks2( $text ) );
 						}
-						# cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them
+						# RTE (Rich Text Editor) - begin
+						# @author: Inez Korczyński
+						if (!empty($wgRTEParserEnabled)) {
+							$text = RTEMarker::generate(RTEMarker::IMAGE_DATA, $RTE_wikitextIdx).$text;
+						}
+						# RTE - end
+
+						# cater for new placeholder-in-template namespace -  Bartek
+						# TODO: Get the hell out with this code from here this can be done in hook handler fired in makeImage function - Inez
+						if( "Template Placeholder" != $nt->getText() ) {
 						$s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text, $holders ) ) . $trail;
 					} else {
+							$s .= $prefix . $this->armorLinks( ImagePlaceholder_makeDullImage( $nt, $text, $holders ) ) . $trail;
+						}
+					} else {
 						$s .= $prefix . $trail;
 					}
+
 					$this->mOutput->addImage( $nt->getDBkey() );
 					wfProfileOut( __METHOD__."-image" );
 					continue;
@@ -1765,6 +1959,14 @@
 
 				if ( $ns == NS_CATEGORY ) {
 					wfProfileIn( __METHOD__."-category" );
+
+					# RTE (Rich Text Editor) - begin
+					# @author: Inez Korczyński
+					# Category handling
+					if(!empty($wgRTEParserEnabled)) {
+						$dataIdx = RTEData::put('placeholder', array('type' => 'category', 'wikitextIdx' => $RTE_wikitextIdx));
+						$s .= $prefix . RTEMarker::generate(RTEMarker::PLACEHOLDER, $dataIdx) . $trail;
+					} else {
 					$s = rtrim($s . "\n"); # bug 87
 
 					if ( $wasblank ) {
@@ -1781,24 +1983,62 @@
 					 * Strip the whitespace Category links produce, see bug 87
 					 * @todo We might want to use trim($tmp, "\n") here.
 					 */
+
 					$s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
+					}
+					# RTE - end
 
 					wfProfileOut( __METHOD__."-category" );
 					continue;
 				}
+
+				/* Wikia change begin - @author: Owen Davis */
+				/* Support for [[Poll:...]] */
+
+				if (defined ( "NS_WIKIA_POLL" ) && ($ns == NS_WIKIA_POLL)) {
+					$poll = WikiaPoll::newFromTitle($nt);
+					if ($poll instanceof WikiaPoll) {
+						# RTE (Rich Text Editor) - begin
+						# @author: Owen Davis
+						if (!empty($wgRTEParserEnabled)) {
+							$s .= $prefix . WikiaPollHooks::generateRTE($poll, $nt, $RTE_wikitextIdx) . $trail;
+						} else {
+							$s .= $prefix . WikiaPollHooks::generate($poll, $nt) . $trail;
+						}
+						# RTE - end
+						continue;
+					}
+				}
+				/* Wikia change end */
+
 			}
 
 			# Self-link checking
-			if( $nt->getFragment() === '' && $ns != NS_SPECIAL ) {
+
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			# No special handling for self-linking in RTE mode
+			if(empty($wgRTEParserEnabled) && $nt->getFragment() === '' && $ns != NS_SPECIAL ) {
 				if( in_array( $nt->getPrefixedText(), $selflink, true ) ) {
 					$s .= $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail );
 					continue;
 				}
 			}
+			# RTE - end
 
 			# NS_MEDIA is a pseudo-namespace for linking directly to a file
 			# FIXME: Should do batch file existence checks, see comment below
 			if( $ns == NS_MEDIA ) {
+				# RTE (Rich Text Editor) - begin
+				# @author: macbre
+				# BugId:1694 - handle [[Media:xxx]] as placeholders
+				if(!empty($wgRTEParserEnabled)) {
+					$dataIdx = RTEData::put('placeholder', array('type' => 'media', 'wikitextIdx' => $RTE_wikitextIdx));
+					$s .= $prefix . RTEMarker::generate(RTEMarker::PLACEHOLDER, $dataIdx) . $trail;
+					continue;
+				}
+				# RTE - end
+
 				wfProfileIn( __METHOD__."-media" );
 				# Give extensions a chance to select the file revision for us
 				$skip = $time = false;
@@ -1816,6 +2057,20 @@
 			}
 
 			wfProfileIn( __METHOD__."-always_known" );
+
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			if(!empty($wgRTEParserEnabled)) {
+				$text = RTEMarker::generate(RTEMarker::INTERNAL_DATA, RTEData::put('data', array(
+					'type' => 'internal',
+					'wikitextIdx' => $RTE_wikitextIdx,
+					'text' => $text,
+					'link' => $link,
+					'wasblank' => $wasblank,
+					'noforce' => $noforce))).$text;
+			}
+			# RTE - end
+
 			# Some titles, such as valid special pages or files in foreign repos, should
 			# be shown as bluelinks even though they're not included in the page table
 			#
@@ -1979,6 +2234,12 @@
 	}
 	/**#@-*/
 
+	# RTE (Rich Text Editor) - begin
+	# @author: Macbre
+	var $mCurrentPrefix = '';
+	var $mLastCommonPrefix = false;
+	# RTE - end
+
 	/**
 	 * Make lists from lines starting with ':', '*', '#', etc. (DBL)
 	 *
@@ -2000,6 +2261,8 @@
 		$prefixLength = 0;
 		$paragraphStack = false;
 
+		$comment = $prefixType = false;
+
 		foreach ( $textLines as $oLine ) {
 			# Fix up $linestart
 			if ( !$linestart ) {
@@ -2012,6 +2275,11 @@
 			// ; = dt
 			// : = dd
 
+			# RTE (Rich Text Editor) - begin
+			# @author: Macbre
+			$this->doBlockLevelsLineStart($oLine, $output);
+			# RTE - end
+
 			$lastPrefixLength = strlen( $lastPrefix );
 			$preCloseMatch = preg_match('/<\\/pre/i', $oLine );
 			$preOpenMatch = preg_match('/<pre/i', $oLine );
@@ -2035,6 +2303,11 @@
 				$t = $oLine;
 			}
 
+			# RTE (Rich Text Editor) - begin
+			# @author: Macbre
+			$this->mCurrentPrefix = $prefix;
+			# RTE - end
+
 			# List generation
 			if( $prefixLength && $lastPrefix === $prefix2 ) {
 				# Same as the last item, so no need to deal with nesting or opening stuff
@@ -2073,6 +2346,9 @@
 				// Open prefixes where appropriate.
 				while ( $prefixLength > $commonPrefixLength ) {
 					$char = substr( $prefix, $commonPrefixLength, 1 );
+					/* Wikia change begin - @author: Macbre */
+					$this->mLastCommonPrefix = ($prefixLength == $commonPrefixLength + 1);
+					/* Wikia change end */
 					$output .= $this->openList( $char );
 
 					if ( ';' === $char ) {
@@ -2095,7 +2372,13 @@
 				$openmatch = preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
 				$closematch = preg_match(
 					'/(?:<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
-					'<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );
+					'<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|'.$this->mUniqPrefix.'-bloglist|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );
+
+				# RTE (Rich Text Editor) - begin
+				# @author: Macbre
+				$this->doOpenCloseMatch($t, $openmatch, $closematch);
+				# RTE - end
+
 				if ( $openmatch or $closematch ) {
 					$paragraphStack = false;
 					# TODO bug 5718: paragraph closed
@@ -2113,7 +2396,8 @@
 						// pre
 						if ($this->mLastSection !== 'pre') {
 							$paragraphStack = false;
-							$output .= $this->closeParagraph().'<pre>';
+							$close = $this->closeParagraph();
+							$output .= $close . '<pre>';
 							$this->mLastSection = 'pre';
 						}
 						$t = substr( $t, 1 );
@@ -2141,6 +2425,17 @@
 							} else if ($this->mLastSection !== 'p') {
 								$output .= $this->closeParagraph().'<p>';
 								$this->mLastSection = 'p';
+							} else {
+								# RTE (Rich Text Editor) - begin
+								# @author: Macbre
+								global $wgRTEParserEnabled;
+								if (!empty($wgRTEParserEnabled)) {
+									// count trailing spaces
+									$text = ltrim(strrev($output), "\n");
+									$spaces = strspn($text, ' ');
+									$output .= RTEReverseParser::buildComment('LINE_BREAK', array('spaces' => $spaces));
+								}
+								# RTE - end
 							}
 						}
 					}
@@ -2154,6 +2449,12 @@
 			if ($paragraphStack === false) {
 				$output .= $t."\n";
 			}
+
+			# RTE (Rich Text Editor) - begin
+			# @author: Macbre
+			$this->doBlockLevelsLineEnd($oLine, $output);
+			# RTE - end
+
 		}
 		while ( $prefixLength ) {
 			$output .= $this->closeList( $prefix2[$prefixLength-1] );
@@ -2168,6 +2469,14 @@
 		return $output;
 	}
 
+	# RTE (Rich Text Editor) - begin
+	# @author: Macbre
+	# Add methods placeholders for RTE
+	function doBlockLevelsLineStart(&$oLine, &$output) {}
+	function doBlockLevelsLineEnd(&$oLine, &$output) {}
+	function doOpenCloseMatch($t, $openmatch, $closematch) {}
+	# RTE - end
+
 	/**
 	 * Split up a string on ':', ignoring any occurences inside tags
 	 * to prevent illegal overlapping.
@@ -2785,7 +3094,7 @@
 	 * @private
 	 */
 	function braceSubstitution( $piece, $frame ) {
-		global $wgContLang, $wgNonincludableNamespaces;
+		global $wgContLang, $wgNonincludableNamespaces, $wgRDBEnabled, $wgRDBData;
 		wfProfileIn( __METHOD__ );
 		wfProfileIn( __METHOD__.'-setup' );
 
@@ -2813,6 +3122,15 @@
 		$args = (null == $piece['parts']) ? array() : $piece['parts'];
 		wfProfileOut( __METHOD__.'-setup' );
 
+		# RTE (Rich Text Editor) - begin
+		# @author: Inez Korczyński
+		if(!empty($wgRDBEnabled)) {
+			if(!empty($wgRDBData)) {
+				$wgRDBEnabled = false;
+			}
+		}
+		# RTE - end
+
 		# SUBST
 		wfProfileIn( __METHOD__.'-modifiers' );
 		if ( !$found ) {
@@ -2835,6 +3153,10 @@
 				}
 			}
 			if ( $literal ) {
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				if(!empty($wgRDBEnabled)) $wgRDBData['type'] = 'subst';
+				# RTE - end
 				$text = $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args );
 				$isLocalObj = true;
 				$found = true;
@@ -2845,6 +3167,10 @@
 		if ( !$found && $args->getLength() == 0 ) {
 			$id = $this->mVariables->matchStartToEnd( $part1 );
 			if ( $id !== false ) {
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				if(!empty($wgRDBEnabled)) $wgRDBData['type'] = 'variable';
+				# RTE - end
 				$text = $this->getVariableValue( $id, $frame );
 				if (MagicWord::getCacheTTL($id)>-1)
 					$this->mOutput->mContainsOldMagic = true;
@@ -2918,6 +3244,10 @@
 						throw new MWException( "Tag hook for $function is not callable\n" );
 					}
 					$result = call_user_func_array( $callback, $allArgs );
+					# RTE (Rich Text Editor) - begin
+					# @author: Inez Korczyński
+					if(!empty($wgRDBEnabled)) $wgRDBData['type'] = 'pfunc';
+					# RTE - end
 					$found = true;
 					$noparse = true;
 					$preprocessFlags = 0;
@@ -2964,6 +3294,10 @@
 				$limit = $this->mOptions->getMaxTemplateDepth();
 				if ( $frame->depth >= $limit ) {
 					$found = true;
+					# RTE (Rich Text Editor) - begin
+					# @author: Inez Korczyński
+					if(!empty($wgRDBEnabled)) $wgRDBData['type'] = 'error';
+					# RTE - end
 					$text = '<span class="error">' . wfMsgForContent( 'parser-template-recursion-depth-warning', $limit ) . '</span>';
 				}
 			}
@@ -3010,9 +3344,21 @@
 				$found = true;
 			}
 
+			# RTE (Rich Text Editor) - begin
+			# @author: Inez Korczyński
+			if(!empty($wgRDBEnabled)) {
+				$wgRDBData['type'] = 'tpl';
+				$wgRDBData['title'] = &$title;
+				$wgRDBData['args'] = &$args;
+			}
+			# RTE - end
 			# Do infinite loop check
 			# This has to be done after redirect resolution to avoid infinite loops via redirects
 			if ( !$frame->loopCheck( $title ) ) {
+				# RTE (Rich Text Editor) - begin
+				# @author: Inez Korczyński
+				if(!empty($wgRDBEnabled)) $wgRDBData['type'] = 'error';
+				# RTE - end
 				$found = true;
 				$text = '<span class="error">' . wfMsgForContent( 'parser-template-loop-warning', $titleText ) . '</span>';
 				wfDebug( __METHOD__.": template loop broken at '$titleText'\n" );
@@ -3057,7 +3403,10 @@
 		# Add a blank line preceding, to prevent it from mucking up
 		# immediately preceding headings
 		if ( $isHTML ) {
-			$text = "\n\n" . $this->insertStripItem( $text );
+			/* Wikia change begin - @author: Marooned */
+			/* rt#2281 - removed "\n\n" from the beginning per request */
+			$text = $this->insertStripItem( $text );
+			/* Wikia change end */
 		}
 		# Escape nowiki-style return values
 		elseif ( $nowiki && ( $this->ot['html'] || $this->ot['pre'] ) ) {
@@ -3100,9 +3449,15 @@
 			$title = Title::makeTitle( $ns, $dbk );
 			$titleText = $title->getPrefixedDBkey();
 		}
-		if ( isset( $this->mTplDomCache[$titleText] ) ) {
+
+		# RTE (Rich Text Editor) - begin
+		# @author: Inez Korczyński
+		# Used for extracting list of available parameters in given article for transclusion
+		global $wgRTETemplateParams;
+		if (empty($wgRTETemplateParams) && isset( $this->mTplDomCache[$titleText] ) ) {
 			return array( $this->mTplDomCache[$titleText], $title );
 		}
+		# RTE - end
 
 		// Cache miss, go to the database
 		list( $text, $title ) = $this->fetchTemplateAndTitle( $title );
@@ -3136,6 +3491,9 @@
 				$this->mOutput->addTemplate( $dep['title'], $dep['page_id'], $dep['rev_id'] );
 			}
 		}
+
+		wfRunHooks( 'Parser::FetchTemplateAndTitle', array( &$text, &$finalTitle ) );
+
 		return array($text,$finalTitle);
 	}
 
@@ -3233,8 +3591,13 @@
 		}
 
 		$text = Http::get($url);
-		if (!$text)
+		if( !$text ) {
 			return wfMsg('scarytranscludefailed', $url);
+		}
+
+		if ( wfReadOnly() ) {
+			return wfReadOnlyReason();
+		}
 
 		$dbw = wfGetDB(DB_MASTER);
 		$dbw->replace('transcache', array('tc_url'), array(
@@ -3308,6 +3669,37 @@
 		$name = $frame->expand( $params['name'] );
 		$attrText = !isset( $params['attr'] ) ? null : $frame->expand( $params['attr'] );
 		$content = !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] );
+		# RTE (Rich Text Editor) - begin
+		# @author: Inez Korczyński
+		global $wgRTEParserEnabled;
+		if(!empty($wgRTEParserEnabled)) {
+
+
+			$wikitextIdx = RTEMarker::getDataIdx(RTEMarker::EXT_WIKITEXT, $content);
+
+			# Allow parser extensions to generate their own placeholders (instead of default one from RTE)
+			# @author: Macbre
+			if (wfRunHooks('RTEUseDefaultPlaceholder', array($name, $params, $frame, $wikitextIdx))) {
+				if($wikitextIdx !== null) {
+					$dataIdx = RTEData::put('placeholder', array('type' => 'ext', 'wikitextIdx' => $wikitextIdx));
+					return RTEMarker::generate(RTEMarker::PLACEHOLDER, $dataIdx);
+				}
+
+				//echo "1";
+			}
+			else {
+				//echo "2";
+				RTE::log(__METHOD__, "skipped default placeholder for <{$name}>");
+
+				// restore value of $content
+				$content = RTEData::get('wikitext', $wikitextIdx);
+
+				// keep inner content of tag
+				$content = preg_replace('#^<[^>]+>(.*)<[^>]+>$#s', '\1', $content);
+			}
+		}
+		# RTE - end
+
 		$marker = "{$this->mUniqPrefix}-$name-" . sprintf('%08X', $this->mMarkerIndex++) . self::MARKER_SUFFIX;
 
 		$isFunctionTag = isset( $this->mFunctionTagHooks[strtolower($name)] ) &&
@@ -3319,6 +3711,12 @@
 		}
 		if ( $this->ot['html'] || $isFunctionTag ) {
 			$name = strtolower( $name );
+
+			# PLB - begin
+			# @author: Tomasz Odrobny
+			$this->mCurrentTagName = $name;
+			# PLB - end
+
 			$attributes = Sanitizer::decodeTagAttributes( $attrText );
 			if ( isset( $params['attributes'] ) ) {
 				$attributes = $attributes + $params['attributes'];
@@ -3502,13 +3898,18 @@
 		global $wgMaxTocLevel, $wgContLang, $wgHtml5, $wgExperimentalHtmlIds;
 
 		$doNumberHeadings = $this->mOptions->getNumberHeadings();
-		$showEditLink = $this->mOptions->getEditSection();
+		$showEditLink = $this->mOptions->getEditSection() && wfRunHooks('EditForm::MultiEdit:Section', array($text) /* Wikia - still needed? */);
 
 		// Do not call quickUserCan unless necessary
 		if( $showEditLink && !$this->mTitle->quickUserCan( 'edit' ) ) {
 			$showEditLink = 0;
 		}
 
+		/* Wikia change begin - @author: Macbre */
+		/* Allow extensions to force section edit link (RT #79897)*/
+		wfRunHooks('Parser::showEditLink', array(&$this, &$showEditLink));
+		/* Wikia change end */
+
 		# Inhibit editsection links if requested in the page
 		if ( isset( $this->mDoubleUnderscores['noeditsection'] )  || $this->mOptions->getIsPrintable() ) {
 			$showEditLink = 0;
@@ -3795,6 +4196,7 @@
 			if( $prevtoclevel > 0 && $prevtoclevel < $wgMaxTocLevel ) {
 				$toc .= $sk->tocUnindent( $prevtoclevel - 1 );
 			}
+			wfRunHooks( 'Parser::InjectTOCitem', array( $this, $sk, &$toc, &$sublevelCount ) );
 			$toc = $sk->tocList( $toc );
 			$this->mOutput->setTOCHTML( $toc );
 		}
@@ -4114,6 +4516,7 @@
 		if ( !$parsing ) {
 			global $wgTitle;
 			$this->clearState();
+			$this->clearTagHooks();
 			$this->setTitle( $wgTitle );
 			$this->mOptions = new ParserOptions;
 			$this->setOutputType = self::OT_PREPROCESS;
@@ -4158,7 +4561,7 @@
 	 * so that an external function can call some class members with confidence
 	 * @public
 	 */
-	function startExternalParse( &$title, $options, $outputType, $clearState = true ) {
+	function startExternalParse( Title $title = null, ParserOptions $options, $outputType, $clearState = true ) {
 		$this->setTitle( $title );
 		$this->mOptions = $options;
 		$this->setOutputType( $outputType );
@@ -4212,7 +4615,7 @@
 		$tag = strtolower( $tag );
 		$oldVal = isset( $this->mTagHooks[$tag] ) ? $this->mTagHooks[$tag] : null;
 		$this->mTagHooks[$tag] = $callback;
-		if( !in_array( $tag, $this->mStripList ) ) {
+		if( is_array($this->mStripList) && !in_array( $tag, $this->mStripList ) ) {
 			$this->mStripList[] = $tag;
 		}
 
@@ -4369,6 +4772,12 @@
 	 */
 	function renderImageGallery( $text, $params ) {
 		$ig = new ImageGallery();
+
+		/* Wikia change begin - @author: Macbre */
+		/* Allow extensions to use different class to render image gallery */
+		wfRunHooks('renderImageGallerySetup', array(&$ig, &$text, &$params));
+		/* Wikia change end */
+
 		$ig->setContextTitle( $this->mTitle );
 		$ig->setShowBytes( false );
 		$ig->setShowFilename( false );
@@ -4394,7 +4803,12 @@
 			$ig->setHeights( $params['heights'] );
 		}
 
-		wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
+		/* Wikia change begin */
+		/* Allow extensions to use their own "parser" for <gallery> tag content */
+		if ( !wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) ) ) {
+			return $ig->toHTML();
+		}
+		/* Wikia change end */
 
 		$lines = StringUtils::explode( "\n", $text );
 		foreach ( $lines as $line ) {
@@ -4409,7 +4823,9 @@
 
 			if ( strpos( $matches[0], '%' ) !== false )
 				$matches[1] = urldecode( $matches[1] );
-			$tp = Title::newFromText( $matches[1]/*, NS_FILE*/ );
+
+			# Allow <gallery> to accept image names without an Image: prefix
+			$tp = Title::newFromText( $matches[1], NS_FILE );
 			$nt =& $tp;
 			if( is_null( $nt ) ) {
 				# Bogus title. Ignore these so we don't bomb out later.
@@ -4528,6 +4944,13 @@
 		$caption = '';
 		$params = array( 'frame' => array(), 'handler' => array(),
 			'horizAlign' => array(), 'vertAlign' => array() );
+
+		// please consider adding a hook providing options next time
+		if (!wfRunHooks( 'BeforeParserMakeImageLinkObjOptions', array( &$this, &$title, &$parts, &$params, &$time, &$descQuery, $options ) ) ) {
+			$ret = $sk->makeImageLink2( $title, $file, $params['frame'], $params['handler'], $time, $descQuery );
+			return $ret;
+		}
+
 		foreach( $parts as $part ) {
 			$part = trim( $part );
 			list( $magicName, $value ) = $mwArray->matchVariableStartToEnd( $part );