r39980 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r39979‎ | r39980 | r39981 >
Date:22:19, 25 August 2008
Author:brion
Status:old
Tags:
Comment:
Revert r39949 "* Revert revert r39662 of my parser changes."
Causes weird regressions on http://meta.wikimedia.org/wiki/Talk:Spam_blacklist
Couldn't isolate to a parser test in a few minutes; some kind of template interaction perhaps.

Sample bad HTML like:
The associated page is used by the Mediawiki <a href="&lt;a href=" class="external free" title="http://www.mediawiki.org/wiki/Extension:SpamBlacklist&quot; rel="nofollow">http://www.mediawiki.org/wiki/Extension:SpamBlacklist&lt;/a&gt;&quot; class="extiw" title="mw:Extension:SpamBlacklist"&gt;Spam Blacklist extension, and lists strings of text that may not be used in URLs in any page in Wikimedia Foundation projects (as well as many external wikis). Any meta <a href="/wiki/Administrator" title="Administrator">administrator</a> can edit the spam blacklist. There is also a more aggressive way to block spamming through direct use of <a href="/wiki/Anti-spam_features#.24wgSpamRegex" title="Anti-spam features">$wgSpamRegex</a>. Only <a href="/wiki/Developers" title="Developers" class="mw-redirect">developers</a> can make changes to $wgSpamRegex, and its use is to be avoided whenever possible.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/includes/parser/LinkHolderArray.php (modified) (history)
  • /trunk/phase3/includes/parser/Parser.php (modified) (history)
  • /trunk/phase3/includes/parser/Parser_DiffTest.php (modified) (history)
  • /trunk/phase3/languages/Language.php (modified) (history)
  • /trunk/phase3/languages/LanguageConverter.php (modified) (history)
  • /trunk/phase3/maintenance/parserTests.inc (modified) (history)
  • /trunk/phase3/maintenance/parserTests.php (modified) (history)
  • /trunk/phase3/maintenance/parserTestsStaticParserHook.php (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/parserTests.inc
@@ -26,7 +26,7 @@
2727
2828 /** */
2929 $options = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record' );
30 -$optionsWithArgs = array( 'regex', 'seed' );
 30+$optionsWithArgs = array( 'regex' );
3131
3232 require_once( 'commandLine.inc' );
3333 require_once( "$IP/maintenance/parserTestsParserHook.php" );
@@ -62,11 +62,6 @@
6363 */
6464 private $oldTablePrefix;
6565
66 - private $maxFuzzHairLength = 20;
67 - private $maxFuzzTestLength = 1000;
68 - private $fuzzSeed = 0;
69 - private $memoryLimit = 50;
70 -
7166 /**
7267 * Sets terminal colorization and diff/quick modes depending on OS and
7368 * command-line options (--color and --quick).
@@ -122,10 +117,6 @@
123118 }
124119 $this->keepUploads = isset( $options['keep-uploads'] );
125120
126 - if ( isset( $options['seed'] ) ) {
127 - $this->fuzzSeed = intval( $options['seed'] ) - 1;
128 - }
129 -
130121 $this->hooks = array();
131122 $this->functionHooks = array();
132123 }
@@ -143,116 +134,6 @@
144135 }
145136
146137 /**
147 - * Run a fuzz test series
148 - * Draw input from a set of test files
149 - */
150 - function fuzzTest( $filenames ) {
151 - $dict = $this->getFuzzInput( $filenames );
152 - $this->setupDatabase();
153 - ini_set( 'memory_limit', $this->memoryLimit * 1048576 );
154 -
155 - $numTotal = 0;
156 - $numSuccess = 0;
157 - $user = new User;
158 - $opts = ParserOptions::newFromUser( $user );
159 - $title = Title::makeTitle( NS_MAIN, 'Parser_test' );
160 -
161 - while ( true ) {
162 - // Generate test input
163 - mt_srand( ++$this->fuzzSeed );
164 - $totalLength = mt_rand( 1, $this->maxFuzzTestLength );
165 - $input = '';
166 - while ( strlen( $input ) < $totalLength ) {
167 - $hairLength = mt_rand( 1, $this->maxFuzzHairLength );
168 - $offset = mt_rand( 0, strlen( $dict ) - $hairLength );
169 - $input .= substr( $dict, $offset, $hairLength );
170 - }
171 -
172 - $this->setupGlobals();
173 - $parser = $this->getParser();
174 - // Run the test
175 - try {
176 - $parser->parse( $input, $title, $opts );
177 - $fail = false;
178 - } catch ( Exception $exception ) {
179 - $fail = true;
180 - }
181 -
182 - if ( $fail ) {
183 - echo "Test failed with seed {$this->fuzzSeed}\n";
184 - echo "Input:\n";
185 - var_dump( $input );
186 - echo "\n\n";
187 - echo "$exception\n";
188 - } else {
189 - $numSuccess++;
190 - }
191 - $numTotal++;
192 - $this->teardownGlobals();
193 - $parser->__destruct();
194 -
195 - if ( $numTotal % 100 == 0 ) {
196 - $usage = intval( memory_get_usage( true ) / $this->memoryLimit / 1048576 * 100 );
197 - echo "{$this->fuzzSeed}: $numSuccess/$numTotal (mem: $usage%)\n";
198 - if ( $usage > 90 ) {
199 - echo "Out of memory:\n";
200 - $memStats = $this->getMemoryBreakdown();
201 - foreach ( $memStats as $name => $usage ) {
202 - echo "$name: $usage\n";
203 - }
204 - $this->abort();
205 - }
206 - }
207 - }
208 - }
209 -
210 - /**
211 - * Get an input dictionary from a set of parser test files
212 - */
213 - function getFuzzInput( $filenames ) {
214 - $dict = '';
215 - foreach( $filenames as $filename ) {
216 - $contents = file_get_contents( $filename );
217 - preg_match_all( '/!!\s*input\n(.*?)\n!!\s*result/s', $contents, $matches );
218 - foreach ( $matches[1] as $match ) {
219 - $dict .= $match . "\n";
220 - }
221 - }
222 - return $dict;
223 - }
224 -
225 - /**
226 - * Get a memory usage breakdown
227 - */
228 - function getMemoryBreakdown() {
229 - $memStats = array();
230 - foreach ( $GLOBALS as $name => $value ) {
231 - $memStats['$'.$name] = strlen( serialize( $value ) );
232 - }
233 - $classes = get_declared_classes();
234 - foreach ( $classes as $class ) {
235 - $rc = new ReflectionClass( $class );
236 - $props = $rc->getStaticProperties();
237 - $memStats[$class] = strlen( serialize( $props ) );
238 - $methods = $rc->getMethods();
239 - foreach ( $methods as $method ) {
240 - $memStats[$class] += strlen( serialize( $method->getStaticVariables() ) );
241 - }
242 - }
243 - $functions = get_defined_functions();
244 - foreach ( $functions['user'] as $function ) {
245 - $rf = new ReflectionFunction( $function );
246 - $memStats["$function()"] = strlen( serialize( $rf->getStaticVariables() ) );
247 - }
248 - asort( $memStats );
249 - return $memStats;
250 - }
251 -
252 - function abort() {
253 - $this->abort();
254 - }
255 -
256 - /**
257138 * Run a series of tests listed in the given text files.
258139 * Each test consists of a brief description, wikitext input,
259140 * and the expected HTML output.
@@ -386,24 +267,6 @@
387268 }
388269
389270 /**
390 - * Get a Parser object
391 - */
392 - function getParser() {
393 - global $wgParserConf;
394 - $class = $wgParserConf['class'];
395 - $parser = new $class( $wgParserConf );
396 - foreach( $this->hooks as $tag => $callback ) {
397 - $parser->setHook( $tag, $callback );
398 - }
399 - foreach( $this->functionHooks as $tag => $bits ) {
400 - list( $callback, $flags ) = $bits;
401 - $parser->setFunctionHook( $tag, $callback, $flags );
402 - }
403 - wfRunHooks( 'ParserTestParser', array( &$parser ) );
404 - return $parser;
405 - }
406 -
407 - /**
408271 * Run a given wikitext input through a freshly-constructed wiki parser,
409272 * and compare the output against the expected results.
410273 * Prints status and explanatory messages to stdout.
@@ -413,6 +276,7 @@
414277 * @return bool
415278 */
416279 private function runTest( $desc, $input, $result, $opts ) {
 280+ global $wgParserConf;
417281 if( $this->showProgress ) {
418282 $this->showTesting( $desc );
419283 }
@@ -436,7 +300,18 @@
437301 }
438302
439303 $noxml = (bool)preg_match( '~\\b noxml \\b~x', $opts );
440 - $parser = $this->getParser();
 304+
 305+ $class = $wgParserConf['class'];
 306+ $parser = new $class( $wgParserConf );
 307+ foreach( $this->hooks as $tag => $callback ) {
 308+ $parser->setHook( $tag, $callback );
 309+ }
 310+ foreach( $this->functionHooks as $tag => $bits ) {
 311+ list( $callback, $flags ) = $bits;
 312+ $parser->setFunctionHook( $tag, $callback, $flags );
 313+ }
 314+ wfRunHooks( 'ParserTestParser', array( &$parser ) );
 315+
441316 $title =& Title::makeTitle( NS_MAIN, $titleText );
442317
443318 $matches = array();
@@ -566,7 +441,6 @@
567442 $langObj = Language::factory( $lang );
568443 $GLOBALS['wgLang'] = $langObj;
569444 $GLOBALS['wgContLang'] = $langObj;
570 - $GLOBALS['wgMemc'] = new FakeMemCachedClient;
571445
572446 //$GLOBALS['wgMessageCache'] = new MessageCache( new BagOStuff(), false, 0, $GLOBALS['wgDBname'] );
573447
@@ -677,10 +551,10 @@
678552 # Hack: insert a few Wikipedia in-project interwiki prefixes,
679553 # for testing inter-language links
680554 $db->insert( 'interwiki', array(
681 - array( 'iw_prefix' => 'wikipedia',
 555+ array( 'iw_prefix' => 'Wikipedia',
682556 'iw_url' => 'http://en.wikipedia.org/wiki/$1',
683557 'iw_local' => 0 ),
684 - array( 'iw_prefix' => 'meatball',
 558+ array( 'iw_prefix' => 'MeatBall',
685559 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1',
686560 'iw_local' => 0 ),
687561 array( 'iw_prefix' => 'zh',
@@ -747,12 +621,11 @@
748622 return;
749623 }
750624
751 - /*
752625 $tables = $this->listTables();
753626 $db = wfGetDB( DB_MASTER );
754627 foreach ( $tables as $table ) {
755628 $db->query( "DROP TABLE `parsertest_$table`" );
756 - }*/
 629+ }
757630 }
758631
759632 /**
@@ -772,10 +645,6 @@
773646 }
774647
775648 wfDebug( "Creating upload directory $dir\n" );
776 - if ( file_exists( $dir ) ) {
777 - wfDebug( "Already exists!\n" );
778 - return $dir;
779 - }
780649 mkdir( $dir );
781650 mkdir( $dir . '/3' );
782651 mkdir( $dir . '/3/3a' );
@@ -789,8 +658,6 @@
790659 */
791660 private function teardownGlobals() {
792661 RepoGroup::destroySingleton();
793 - LinkCache::singleton()->clear();
794 - $GLOBALS['wgLang']->__destruct();
795662 foreach( $this->savedGlobals as $var => $val ) {
796663 $GLOBALS[$var] = $val;
797664 }
Index: trunk/phase3/maintenance/parserTests.php
@@ -28,21 +28,22 @@
2929 if( isset( $options['help'] ) ) {
3030 echo <<<ENDS
3131 MediaWiki $wgVersion parser test suite
32 -Usage: php parserTests.php [options...]
33 -
 32+Usage: php parserTests.php [--quick] [--quiet] [--show-output]
 33+ [--color[=(yes|no)]]
 34+ [--regex=<expression>] [--file=<testfile>]
 35+ [--record] [--compare]
 36+ [--help]
3437 Options:
3538 --quick Suppress diff output of failed tests
3639 --quiet Suppress notification of passed tests (shows only failed tests)
3740 --show-output Show expected and actual output
38 - --color[=yes|no] Override terminal detection and force color output on or off
 41+ --color Override terminal detection and force color output on or off
3942 use wgCommandLineDarkBg = true; if your term is dark
4043 --regex Only run tests whose descriptions which match given regex
41 - --file=<testfile> Run test cases from a custom file instead of parserTests.txt
 44+ --file Run test cases from a custom file instead of parserTests.txt
4245 --record Record tests in database
4346 --compare Compare with recorded results, without updating the database.
4447 --keep-uploads Re-use the same upload directory for each test, don't delete it
45 - --fuzz Do a fuzz test instead of a normal test
46 - --seed <n> Start the fuzz test from the specified seed
4748 --help Show this help message
4849
4950
@@ -66,10 +67,7 @@
6768 # Print out software version to assist with locating regressions
6869 $version = SpecialVersion::getVersion();
6970 echo( "This is MediaWiki version {$version}.\n\n" );
 71+$ok = $tester->runTestsFromFiles( $files );
7072
71 -if ( isset( $options['fuzz'] ) ) {
72 - $tester->fuzzTest( $files );
73 -} else {
74 - $ok = $tester->runTestsFromFiles( $files );
75 - exit ($ok ? 0 : -1);
76 -}
 73+exit ($ok ? 0 : -1);
 74+
Index: trunk/phase3/maintenance/parserTestsStaticParserHook.php
@@ -27,19 +27,18 @@
2828 if ( ! count( $argv ) ) {
2929 $buf = $in;
3030 return '';
31 - } else if ( count( $argv ) === 1 && isset( $argv['action'] )
32 - && $argv['action'] === 'flush' && $in === null )
33 - {
 31+ } else if ( count( $argv ) === 1 && $argv['action'] === 'flush' && $in === null ) {
3432 // Clear the buffer, we probably don't need to
3533 $tmp = $buf;
3634 $buf = null;
3735 return $tmp;
3836 } else
3937 // wtf?
40 - return
 38+ die(
4139 "\nCall this extension as <statictag>string</statictag> or as" .
4240 " <statictag action=flush/>, not in any other way.\n" .
4341 "text: " . var_export( $in, true ) . "\n" .
44 - "argv: " . var_export( $argv, true ) . "\n";
 42+ "argv: " . var_export( $argv, true ) . "\n"
 43+ );
4544 }
4645
Index: trunk/phase3/includes/parser/LinkHolderArray.php
@@ -12,15 +12,6 @@
1313 }
1414
1515 /**
16 - * Reduce memory usage to reduce the impact of circular references
17 - */
18 - function __destruct() {
19 - foreach ( $this as $name => $value ) {
20 - unset( $this->$name );
21 - }
22 - }
23 -
24 - /**
2516 * Merge another LinkHolderArray into this one
2617 */
2718 function merge( $other ) {
Index: trunk/phase3/includes/parser/Parser.php
@@ -98,7 +98,7 @@
9999 # Cleared with clearState():
100100 var $mOutput, $mAutonumber, $mDTopen, $mStripState;
101101 var $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
102 - var $mLinkHolders, $mLinkID;
 102+ var $mInterwikiLinkHolders, $mLinkHolders;
103103 var $mIncludeSizes, $mPPNodeCount, $mDefaultSort;
104104 var $mTplExpandCache; // empty-frame expansion cache
105105 var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
@@ -143,18 +143,6 @@
144144 }
145145
146146 /**
147 - * Reduce memory usage to reduce the impact of circular references
148 - */
149 - function __destruct() {
150 - if ( isset( $this->mLinkHolders ) ) {
151 - $this->mLinkHolders->__destruct();
152 - }
153 - foreach ( $this as $name => $value ) {
154 - unset( $this->$name );
155 - }
156 - }
157 -
158 - /**
159147 * Do various kinds of initialisation on the first call of the parser
160148 */
161149 function firstCallInit() {
@@ -191,8 +179,17 @@
192180 $this->mStripState = new StripState;
193181 $this->mArgStack = false;
194182 $this->mInPre = false;
195 - $this->mLinkHolders = new LinkHolderArray( $this );
196 - $this->mLinkID = 0;
 183+ $this->mInterwikiLinkHolders = array(
 184+ 'texts' => array(),
 185+ 'titles' => array()
 186+ );
 187+ $this->mLinkHolders = array(
 188+ 'namespaces' => array(),
 189+ 'dbkeys' => array(),
 190+ 'queries' => array(),
 191+ 'texts' => array(),
 192+ 'titles' => array()
 193+ );
197194 $this->mRevisionTimestamp = $this->mRevisionId = null;
198195
199196 /**
@@ -207,7 +204,7 @@
208205 */
209206 #$this->mUniqPrefix = "\x07UNIQ" . Parser::getRandomString();
210207 # Changed to \x7f to allow XML double-parsing -- TS
211 - $this->mUniqPrefix = "\x7fUNIQ" . self::getRandomString();
 208+ $this->mUniqPrefix = "\x7fUNIQ" . Parser::getRandomString();
212209
213210
214211 # Clear these on every parse, bug 4549
@@ -297,7 +294,7 @@
298295 */
299296
300297 global $wgUseTidy, $wgAlwaysUseTidy, $wgContLang;
301 - $fname = __METHOD__.'-' . wfGetCaller();
 298+ $fname = 'Parser::parse-' . wfGetCaller();
302299 wfProfileIn( __METHOD__ );
303300 wfProfileIn( $fname );
304301
@@ -331,6 +328,7 @@
332329 );
333330 $text = preg_replace( array_keys($fixtags), array_values($fixtags), $text );
334331
 332+ # only once and last
335333 $text = $this->doBlockLevels( $text, $linestart );
336334
337335 $this->replaceLinkHolders( $text );
@@ -350,7 +348,7 @@
351349 $uniq_prefix = $this->mUniqPrefix;
352350 $matches = array();
353351 $elements = array_keys( $this->mTransparentTagHooks );
354 - $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
 352+ $text = Parser::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
355353
356354 foreach( $matches as $marker => $data ) {
357355 list( $element, $content, $params, $tag ) = $data;
@@ -368,7 +366,7 @@
369367 $text = Sanitizer::normalizeCharReferences( $text );
370368
371369 if (($wgUseTidy and $this->mOptions->mTidy) or $wgAlwaysUseTidy) {
372 - $text = self::tidy($text);
 370+ $text = Parser::tidy($text);
373371 } else {
374372 # attempt to sanitize at least some nesting problems
375373 # (bug #2702 and quite a few others)
@@ -473,8 +471,6 @@
474472 function &getTitle() { return $this->mTitle; }
475473 function getOptions() { return $this->mOptions; }
476474 function getRevisionId() { return $this->mRevisionId; }
477 - function getOutput() { return $this->mOutput; }
478 - function nextLinkID() { return $this->mLinkID++; }
479475
480476 function getFunctionLang() {
481477 global $wgLang, $wgContLang;
@@ -553,7 +549,7 @@
554550 $text = $inside;
555551 $tail = null;
556552 } else {
557 - if( $element === '!--' ) {
 553+ if( $element == '!--' ) {
558554 $end = '/(-->)/';
559555 } else {
560556 $end = "/(<\\/$element\\s*>)/i";
@@ -662,9 +658,9 @@
663659 ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>'.
664660 '<head><title>test</title></head><body>'.$text.'</body></html>';
665661 if( $wgTidyInternal ) {
666 - $correctedtext = self::internalTidy( $wrappedtext );
 662+ $correctedtext = Parser::internalTidy( $wrappedtext );
667663 } else {
668 - $correctedtext = self::externalTidy( $wrappedtext );
 664+ $correctedtext = Parser::externalTidy( $wrappedtext );
669665 }
670666 if( is_null( $correctedtext ) ) {
671667 wfDebug( "Tidy error detected!\n" );
@@ -681,7 +677,8 @@
682678 */
683679 function externalTidy( $text ) {
684680 global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
685 - wfProfileIn( __METHOD__ );
 681+ $fname = 'Parser::externalTidy';
 682+ wfProfileIn( $fname );
686683
687684 $cleansource = '';
688685 $opts = ' -utf8';
@@ -710,7 +707,7 @@
711708 }
712709 }
713710
714 - wfProfileOut( __METHOD__ );
 711+ wfProfileOut( $fname );
715712
716713 if( $cleansource == '' && $text != '') {
717714 // Some kind of error happened, so we couldn't get the corrected text.
@@ -732,7 +729,8 @@
733730 */
734731 function internalTidy( $text ) {
735732 global $wgTidyConf, $IP, $wgDebugTidy;
736 - wfProfileIn( __METHOD__ );
 733+ $fname = 'Parser::internalTidy';
 734+ wfProfileIn( $fname );
737735
738736 $tidy = new tidy;
739737 $tidy->parseString( $text, $wgTidyConf, 'utf8' );
@@ -750,7 +748,7 @@
751749 "\n-->";
752750 }
753751
754 - wfProfileOut( __METHOD__ );
 752+ wfProfileOut( $fname );
755753 return $cleansource;
756754 }
757755
@@ -760,35 +758,34 @@
761759 * @private
762760 */
763761 function doTableStuff ( $text ) {
764 - wfProfileIn( __METHOD__ );
 762+ $fname = 'Parser::doTableStuff';
 763+ wfProfileIn( $fname );
765764
766 - $lines = StringUtils::explode( "\n", $text );
767 - $out = '';
 765+ $lines = explode ( "\n" , $text );
768766 $td_history = array (); // Is currently a td tag open?
769767 $last_tag_history = array (); // Save history of last lag activated (td, th or caption)
770768 $tr_history = array (); // Is currently a tr tag open?
771769 $tr_attributes = array (); // history of tr attributes
772770 $has_opened_tr = array(); // Did this table open a <tr> element?
773771 $indent_level = 0; // indent level of the table
 772+ foreach ( $lines as $key => $line )
 773+ {
 774+ $line = trim ( $line );
774775
775 - foreach ( $lines as $outLine ) {
776 - $line = trim( $outLine );
777 -
778776 if( $line == '' ) { // empty line, go to next line
779 - $out .= $outLine."\n";
780777 continue;
781778 }
782 - $first_character = $line[0];
 779+ $first_character = $line{0};
783780 $matches = array();
784781
785 - if ( preg_match( '/^(:*)\{\|(.*)$/', $line , $matches ) ) {
 782+ if ( preg_match( '/^(:*)\{\|(.*)$/' , $line , $matches ) ) {
786783 // First check if we are starting a new table
787784 $indent_level = strlen( $matches[1] );
788785
789786 $attributes = $this->mStripState->unstripBoth( $matches[2] );
790787 $attributes = Sanitizer::fixTagAttributes ( $attributes , 'table' );
791788
792 - $outLine = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>";
 789+ $lines[$key] = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>";
793790 array_push ( $td_history , false );
794791 array_push ( $last_tag_history , '' );
795792 array_push ( $tr_history , false );
@@ -796,9 +793,8 @@
797794 array_push ( $has_opened_tr , false );
798795 } else if ( count ( $td_history ) == 0 ) {
799796 // Don't do any of the following
800 - $out .= $outLine."\n";
801797 continue;
802 - } else if ( substr ( $line , 0 , 2 ) === '|}' ) {
 798+ } else if ( substr ( $line , 0 , 2 ) == '|}' ) {
803799 // We are ending a table
804800 $line = '</table>' . substr ( $line , 2 );
805801 $last_tag = array_pop ( $last_tag_history );
@@ -815,8 +811,8 @@
816812 $line = "</{$last_tag}>{$line}";
817813 }
818814 array_pop ( $tr_attributes );
819 - $outLine = $line . str_repeat( '</dd></dl>' , $indent_level );
820 - } else if ( substr ( $line , 0 , 2 ) === '|-' ) {
 815+ $lines[$key] = $line . str_repeat( '</dd></dl>' , $indent_level );
 816+ } else if ( substr ( $line , 0 , 2 ) == '|-' ) {
821817 // Now we have a table row
822818 $line = preg_replace( '#^\|-+#', '', $line );
823819
@@ -839,21 +835,21 @@
840836 $line = "</{$last_tag}>{$line}";
841837 }
842838
843 - $outLine = $line;
 839+ $lines[$key] = $line;
844840 array_push ( $tr_history , false );
845841 array_push ( $td_history , false );
846842 array_push ( $last_tag_history , '' );
847843 }
848 - else if ( $first_character === '|' || $first_character === '!' || substr ( $line , 0 , 2 ) === '|+' ) {
 844+ else if ( $first_character == '|' || $first_character == '!' || substr ( $line , 0 , 2 ) == '|+' ) {
849845 // This might be cell elements, td, th or captions
850 - if ( substr ( $line , 0 , 2 ) === '|+' ) {
 846+ if ( substr ( $line , 0 , 2 ) == '|+' ) {
851847 $first_character = '+';
852848 $line = substr ( $line , 1 );
853849 }
854850
855851 $line = substr ( $line , 1 );
856852
857 - if ( $first_character === '!' ) {
 853+ if ( $first_character == '!' ) {
858854 $line = str_replace ( '!!' , '||' , $line );
859855 }
860856
@@ -863,13 +859,13 @@
864860 // attribute values containing literal "||".
865861 $cells = StringUtils::explodeMarkup( '||' , $line );
866862
867 - $outLine = '';
 863+ $lines[$key] = '';
868864
869865 // Loop through each table cell
870866 foreach ( $cells as $cell )
871867 {
872868 $previous = '';
873 - if ( $first_character !== '+' )
 869+ if ( $first_character != '+' )
874870 {
875871 $tr_after = array_pop ( $tr_attributes );
876872 if ( !array_pop ( $tr_history ) ) {
@@ -887,11 +883,11 @@
888884 $previous = "</{$last_tag}>{$previous}";
889885 }
890886
891 - if ( $first_character === '|' ) {
 887+ if ( $first_character == '|' ) {
892888 $last_tag = 'td';
893 - } else if ( $first_character === '!' ) {
 889+ } else if ( $first_character == '!' ) {
894890 $last_tag = 'th';
895 - } else if ( $first_character === '+' ) {
 891+ } else if ( $first_character == '+' ) {
896892 $last_tag = 'caption';
897893 } else {
898894 $last_tag = '';
@@ -914,42 +910,38 @@
915911 $cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}";
916912 }
917913
918 - $outLine .= $cell;
 914+ $lines[$key] .= $cell;
919915 array_push ( $td_history , true );
920916 }
921917 }
922 - $out .= $outLine . "\n";
923918 }
924919
925920 // Closing open td, tr && table
926921 while ( count ( $td_history ) > 0 )
927922 {
928923 if ( array_pop ( $td_history ) ) {
929 - $out .= "</td>\n";
 924+ $lines[] = '</td>' ;
930925 }
931926 if ( array_pop ( $tr_history ) ) {
932 - $out .= "</tr>\n";
 927+ $lines[] = '</tr>' ;
933928 }
934929 if ( !array_pop ( $has_opened_tr ) ) {
935 - $out .= "<tr><td></td></tr>\n" ;
 930+ $lines[] = "<tr><td></td></tr>" ;
936931 }
937932
938 - $out .= "</table>\n";
 933+ $lines[] = '</table>' ;
939934 }
940935
941 - // Remove trailing line-ending (b/c)
942 - if ( substr( $out, -1 ) === "\n" ) {
943 - $out = substr( $out, 0, -1 );
944 - }
 936+ $output = implode ( "\n" , $lines ) ;
945937
946938 // special case: don't return empty table
947 - if( $out === "<table>\n<tr><td></td></tr>\n</table>" ) {
948 - $out = '';
 939+ if( $output == "<table>\n<tr><td></td></tr>\n</table>" ) {
 940+ $output = '';
949941 }
950942
951 - wfProfileOut( __METHOD__ );
 943+ wfProfileOut( $fname );
952944
953 - return $out;
 945+ return $output;
954946 }
955947
956948 /**
@@ -960,11 +952,12 @@
961953 */
962954 function internalParse( $text ) {
963955 $isMain = true;
964 - wfProfileIn( __METHOD__ );
 956+ $fname = 'Parser::internalParse';
 957+ wfProfileIn( $fname );
965958
966959 # Hook to suspend the parser in this state
967960 if ( !wfRunHooks( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
968 - wfProfileOut( __METHOD__ );
 961+ wfProfileOut( $fname );
969962 return $text ;
970963 }
971964
@@ -997,15 +990,14 @@
998991 $text = $this->doMagicLinks( $text );
999992 $text = $this->formatHeadings( $text, $isMain );
1000993
1001 - wfProfileOut( __METHOD__ );
 994+ wfProfileOut( $fname );
1002995 return $text;
1003996 }
1004997
1005998 /**
1006999 * Replace special strings like "ISBN xxx" and "RFC xxx" with
10071000 * magic external links.
1008 - *
1009 - * DML
 1001+ *
10101002 * @private
10111003 */
10121004 function doMagicLinks( $text ) {
@@ -1026,10 +1018,10 @@
10271019 }
10281020
10291021 function magicLinkCallback( $m ) {
1030 - if ( substr( $m[0], 0, 1 ) === '<' ) {
 1022+ if ( substr( $m[0], 0, 1 ) == '<' ) {
10311023 # Skip HTML element
10321024 return $m[0];
1033 - } elseif ( substr( $m[0], 0, 4 ) === 'ISBN' ) {
 1025+ } elseif ( substr( $m[0], 0, 4 ) == 'ISBN' ) {
10341026 $isbn = $m[2];
10351027 $num = strtr( $isbn, array(
10361028 '-' => '',
@@ -1041,11 +1033,11 @@
10421034 $titleObj->escapeLocalUrl() .
10431035 "\" class=\"internal\">ISBN $isbn</a>";
10441036 } else {
1045 - if ( substr( $m[0], 0, 3 ) === 'RFC' ) {
 1037+ if ( substr( $m[0], 0, 3 ) == 'RFC' ) {
10461038 $keyword = 'RFC';
10471039 $urlmsg = 'rfcurl';
10481040 $id = $m[1];
1049 - } elseif ( substr( $m[0], 0, 4 ) === 'PMID' ) {
 1041+ } elseif ( substr( $m[0], 0, 4 ) == 'PMID' ) {
10501042 $keyword = 'PMID';
10511043 $urlmsg = 'pubmedurl';
10521044 $id = $m[1];
@@ -1068,13 +1060,14 @@
10691061 * @private
10701062 */
10711063 function doHeadings( $text ) {
1072 - wfProfileIn( __METHOD__ );
 1064+ $fname = 'Parser::doHeadings';
 1065+ wfProfileIn( $fname );
10731066 for ( $i = 6; $i >= 1; --$i ) {
10741067 $h = str_repeat( '=', $i );
10751068 $text = preg_replace( "/^$h(.+)$h\\s*$/m",
10761069 "<h$i>\\1</h$i>", $text );
10771070 }
1078 - wfProfileOut( __METHOD__ );
 1071+ wfProfileOut( $fname );
10791072 return $text;
10801073 }
10811074
@@ -1084,14 +1077,15 @@
10851078 * @return string the altered text
10861079 */
10871080 function doAllQuotes( $text ) {
1088 - wfProfileIn( __METHOD__ );
 1081+ $fname = 'Parser::doAllQuotes';
 1082+ wfProfileIn( $fname );
10891083 $outtext = '';
1090 - $lines = StringUtils::explode( "\n", $text );
 1084+ $lines = explode( "\n", $text );
10911085 foreach ( $lines as $line ) {
1092 - $outtext .= $this->doQuotes( $line ) . "\n";
 1086+ $outtext .= $this->doQuotes ( $line ) . "\n";
10931087 }
10941088 $outtext = substr($outtext, 0,-1);
1095 - wfProfileOut( __METHOD__ );
 1089+ wfProfileOut( $fname );
10961090 return $outtext;
10971091 }
10981092
@@ -1153,9 +1147,9 @@
11541148 {
11551149 $x1 = substr ($arr[$i-1], -1);
11561150 $x2 = substr ($arr[$i-1], -2, 1);
1157 - if ($x1 === ' ') {
 1151+ if ($x1 == ' ') {
11581152 if ($firstspace == -1) $firstspace = $i;
1159 - } else if ($x2 === ' ') {
 1153+ } else if ($x2 == ' ') {
11601154 if ($firstsingleletterword == -1) $firstsingleletterword = $i;
11611155 } else {
11621156 if ($firstmultiletterword == -1) $firstmultiletterword = $i;
@@ -1195,7 +1189,7 @@
11961190 {
11971191 if (($i % 2) == 0)
11981192 {
1199 - if ($state === 'both')
 1193+ if ($state == 'both')
12001194 $buffer .= $r;
12011195 else
12021196 $output .= $r;
@@ -1204,41 +1198,41 @@
12051199 {
12061200 if (strlen ($r) == 2)
12071201 {
1208 - if ($state === 'i')
 1202+ if ($state == 'i')
12091203 { $output .= '</i>'; $state = ''; }
1210 - else if ($state === 'bi')
 1204+ else if ($state == 'bi')
12111205 { $output .= '</i>'; $state = 'b'; }
1212 - else if ($state === 'ib')
 1206+ else if ($state == 'ib')
12131207 { $output .= '</b></i><b>'; $state = 'b'; }
1214 - else if ($state === 'both')
 1208+ else if ($state == 'both')
12151209 { $output .= '<b><i>'.$buffer.'</i>'; $state = 'b'; }
12161210 else # $state can be 'b' or ''
12171211 { $output .= '<i>'; $state .= 'i'; }
12181212 }
12191213 else if (strlen ($r) == 3)
12201214 {
1221 - if ($state === 'b')
 1215+ if ($state == 'b')
12221216 { $output .= '</b>'; $state = ''; }
1223 - else if ($state === 'bi')
 1217+ else if ($state == 'bi')
12241218 { $output .= '</i></b><i>'; $state = 'i'; }
1225 - else if ($state === 'ib')
 1219+ else if ($state == 'ib')
12261220 { $output .= '</b>'; $state = 'i'; }
1227 - else if ($state === 'both')
 1221+ else if ($state == 'both')
12281222 { $output .= '<i><b>'.$buffer.'</b>'; $state = 'i'; }
12291223 else # $state can be 'i' or ''
12301224 { $output .= '<b>'; $state .= 'b'; }
12311225 }
12321226 else if (strlen ($r) == 5)
12331227 {
1234 - if ($state === 'b')
 1228+ if ($state == 'b')
12351229 { $output .= '</b><i>'; $state = 'i'; }
1236 - else if ($state === 'i')
 1230+ else if ($state == 'i')
12371231 { $output .= '</i><b>'; $state = 'b'; }
1238 - else if ($state === 'bi')
 1232+ else if ($state == 'bi')
12391233 { $output .= '</i></b>'; $state = ''; }
1240 - else if ($state === 'ib')
 1234+ else if ($state == 'ib')
12411235 { $output .= '</b></i>'; $state = ''; }
1242 - else if ($state === 'both')
 1236+ else if ($state == 'both')
12431237 { $output .= '<i><b>'.$buffer.'</b></i>'; $state = ''; }
12441238 else # ($state == '')
12451239 { $buffer = ''; $state = 'both'; }
@@ -1247,21 +1241,21 @@
12481242 $i++;
12491243 }
12501244 # Now close all remaining tags. Notice that the order is important.
1251 - if ($state === 'b' || $state === 'ib')
 1245+ if ($state == 'b' || $state == 'ib')
12521246 $output .= '</b>';
1253 - if ($state === 'i' || $state === 'bi' || $state === 'ib')
 1247+ if ($state == 'i' || $state == 'bi' || $state == 'ib')
12541248 $output .= '</i>';
1255 - if ($state === 'bi')
 1249+ if ($state == 'bi')
12561250 $output .= '</b>';
12571251 # There might be lonely ''''', so make sure we have a buffer
1258 - if ($state === 'both' && $buffer)
 1252+ if ($state == 'both' && $buffer)
12591253 $output .= '<b><i>'.$buffer.'</i></b>';
12601254 return $output;
12611255 }
12621256 }
12631257
12641258 /**
1265 - * Replace external links (REL)
 1259+ * Replace external links
12661260 *
12671261 * Note: this is all very hackish and the order of execution matters a lot.
12681262 * Make sure to run maintenance/parserTests.php if you change this code.
@@ -1270,7 +1264,8 @@
12711265 */
12721266 function replaceExternalLinks( $text ) {
12731267 global $wgContLang;
1274 - wfProfileIn( __METHOD__ );
 1268+ $fname = 'Parser::replaceExternalLinks';
 1269+ wfProfileIn( $fname );
12751270
12761271 $sk = $this->mOptions->getSkin();
12771272
@@ -1304,7 +1299,7 @@
13051300 $dtrail = '';
13061301
13071302 # Set linktype for CSS - if URL==text, link is essentially free
1308 - $linktype = ($text === $url) ? 'free' : 'text';
 1303+ $linktype = ($text == $url) ? 'free' : 'text';
13091304
13101305 # No link text, e.g. [http://domain.tld/some.link]
13111306 if ( $text == '' ) {
@@ -1340,11 +1335,11 @@
13411336 # Register link in the output object.
13421337 # Replace unnecessary URL escape codes with the referenced character
13431338 # This prevents spammers from hiding links from the filters
1344 - $pasteurized = self::replaceUnusualEscapes( $url );
 1339+ $pasteurized = Parser::replaceUnusualEscapes( $url );
13451340 $this->mOutput->addExternalLink( $pasteurized );
13461341 }
13471342
1348 - wfProfileOut( __METHOD__ );
 1343+ wfProfileOut( $fname );
13491344 return $s;
13501345 }
13511346
@@ -1354,7 +1349,8 @@
13551350 */
13561351 function replaceFreeExternalLinks( $text ) {
13571352 global $wgContLang;
1358 - wfProfileIn( __METHOD__ );
 1353+ $fname = 'Parser::replaceFreeExternalLinks';
 1354+ wfProfileIn( $fname );
13591355
13601356 $bits = preg_split( '/(\b(?:' . wfUrlProtocols() . '))/S', $text, -1, PREG_SPLIT_DELIM_CAPTURE );
13611357 $s = array_shift( $bits );
@@ -1416,7 +1412,7 @@
14171413 $text = $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free', $this->mTitle->getNamespace() );
14181414 # Register it in the output object...
14191415 # Replace unnecessary URL escape codes with their equivalent characters
1420 - $pasteurized = self::replaceUnusualEscapes( $url );
 1416+ $pasteurized = Parser::replaceUnusualEscapes( $url );
14211417 $this->mOutput->addExternalLink( $pasteurized );
14221418 }
14231419 $s .= $text . $trail;
@@ -1424,7 +1420,7 @@
14251421 $s .= $protocol . $remainder;
14261422 }
14271423 }
1428 - wfProfileOut( __METHOD__ );
 1424+ wfProfileOut( $fname );
14291425 return $s;
14301426 }
14311427
@@ -1440,7 +1436,7 @@
14411437 */
14421438 static function replaceUnusualEscapes( $url ) {
14431439 return preg_replace_callback( '/%[0-9A-Fa-f]{2}/',
1444 - array( __CLASS__, 'replaceUnusualEscapesCallback' ), $url );
 1440+ array( 'Parser', 'replaceUnusualEscapesCallback' ), $url );
14451441 }
14461442
14471443 /**
@@ -1484,48 +1480,35 @@
14851481
14861482 /**
14871483 * Process [[ ]] wikilinks
1488 - * @return processed text
14891484 *
14901485 * @private
14911486 */
14921487 function replaceInternalLinks( $s ) {
1493 - $this->mLinkHolders->merge( $this->replaceInternalLinks2( $s ) );
1494 - return $s;
1495 - }
1496 -
1497 - /**
1498 - * Process [[ ]] wikilinks (RIL)
1499 - * @return LinkHolderArray
1500 - *
1501 - * @private
1502 - */
1503 - function replaceInternalLinks2( &$s ) {
15041488 global $wgContLang;
 1489+ static $fname = 'Parser::replaceInternalLinks' ;
15051490
1506 - wfProfileIn( __METHOD__ );
 1491+ wfProfileIn( $fname );
15071492
1508 - wfProfileIn( __METHOD__.'-setup' );
1509 - static $tc = FALSE, $e1, $e1_img;
 1493+ wfProfileIn( $fname.'-setup' );
 1494+ static $tc = FALSE;
15101495 # the % is needed to support urlencoded titles as well
1511 - if ( !$tc ) {
1512 - $tc = Title::legalChars() . '#%';
1513 - # Match a link having the form [[namespace:link|alternate]]trail
1514 - $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD";
1515 - # Match cases where there is no "]]", which might still be images
1516 - $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD";
1517 - }
 1496+ if ( !$tc ) { $tc = Title::legalChars() . '#%'; }
15181497
15191498 $sk = $this->mOptions->getSkin();
1520 - $holders = new LinkHolderArray( $this );
15211499
15221500 #split the entire text string on occurences of [[
1523 - $a = StringUtils::explode( '[[', ' ' . $s );
 1501+ $a = explode( '[[', ' ' . $s );
15241502 #get the first element (all text up to first [[), and remove the space we added
1525 - $s = $a->current();
1526 - $a->next();
1527 - $line = $a->current(); # Workaround for broken ArrayIterator::next() that returns "void"
 1503+ $s = array_shift( $a );
15281504 $s = substr( $s, 1 );
15291505
 1506+ # Match a link having the form [[namespace:link|alternate]]trail
 1507+ static $e1 = FALSE;
 1508+ if ( !$e1 ) { $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; }
 1509+ # Match cases where there is no "]]", which might still be images
 1510+ static $e1_img = FALSE;
 1511+ if ( !$e1_img ) { $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; }
 1512+
15301513 $useLinkPrefixExtension = $wgContLang->linkPrefixExtension();
15311514 $e2 = null;
15321515 if ( $useLinkPrefixExtension ) {
@@ -1535,8 +1518,8 @@
15361519 }
15371520
15381521 if( is_null( $this->mTitle ) ) {
1539 - wfProfileOut( __METHOD__.'-setup' );
1540 - wfProfileOut( __METHOD__ );
 1522+ wfProfileOut( $fname );
 1523+ wfProfileOut( $fname.'-setup' );
15411524 throw new MWException( __METHOD__.": \$this->mTitle is null\n" );
15421525 }
15431526 $nottalk = !$this->mTitle->isTalkPage();
@@ -1558,20 +1541,13 @@
15591542 $selflink = array($this->mTitle->getPrefixedText());
15601543 }
15611544 $useSubpages = $this->areSubpagesAllowed();
1562 - wfProfileOut( __METHOD__.'-setup' );
 1545+ wfProfileOut( $fname.'-setup' );
15631546
15641547 # Loop for each link
1565 - for ( ; $line !== false && $line !== null ; $a->next(), $line = $a->current() ) {
1566 - # Check for excessive memory usage
1567 - if ( $holders->isBig() ) {
1568 - # Too big
1569 - # Do the existence check, replace the link holders and clear the array
1570 - $holders->replace( $s );
1571 - $holders->clear();
1572 - }
1573 -
 1548+ for ($k = 0; isset( $a[$k] ); $k++) {
 1549+ $line = $a[$k];
15741550 if ( $useLinkPrefixExtension ) {
1575 - wfProfileIn( __METHOD__.'-prefixhandling' );
 1551+ wfProfileIn( $fname.'-prefixhandling' );
15761552 if ( preg_match( $e2, $s, $m ) ) {
15771553 $prefix = $m[2];
15781554 $s = $m[1];
@@ -1583,12 +1559,12 @@
15841560 $prefix = $first_prefix;
15851561 $first_prefix = false;
15861562 }
1587 - wfProfileOut( __METHOD__.'-prefixhandling' );
 1563+ wfProfileOut( $fname.'-prefixhandling' );
15881564 }
15891565
15901566 $might_be_img = false;
15911567
1592 - wfProfileIn( __METHOD__."-e1" );
 1568+ wfProfileIn( "$fname-e1" );
15931569 if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt
15941570 $text = $m[2];
15951571 # If we get a ] at the beginning of $m[3] that means we have a link that's something like:
@@ -1622,18 +1598,18 @@
16231599 $trail = "";
16241600 } else { # Invalid form; output directly
16251601 $s .= $prefix . '[[' . $line ;
1626 - wfProfileOut( __METHOD__."-e1" );
 1602+ wfProfileOut( "$fname-e1" );
16271603 continue;
16281604 }
1629 - wfProfileOut( __METHOD__."-e1" );
1630 - wfProfileIn( __METHOD__."-misc" );
 1605+ wfProfileOut( "$fname-e1" );
 1606+ wfProfileIn( "$fname-misc" );
16311607
16321608 # Don't allow internal links to pages containing
16331609 # PROTO: where PROTO is a valid URL protocol; these
16341610 # should be external links.
16351611 if (preg_match('/^\b(?:' . wfUrlProtocols() . ')/', $m[1])) {
16361612 $s .= $prefix . '[[' . $line ;
1637 - wfProfileOut( __METHOD__."-misc" );
 1613+ wfProfileOut( "$fname-misc" );
16381614 continue;
16391615 }
16401616
@@ -1644,36 +1620,33 @@
16451621 $link = $m[1];
16461622 }
16471623
1648 - $noforce = (substr($m[1], 0, 1) !== ':');
 1624+ $noforce = (substr($m[1], 0, 1) != ':');
16491625 if (!$noforce) {
16501626 # Strip off leading ':'
16511627 $link = substr($link, 1);
16521628 }
16531629
1654 - wfProfileOut( __METHOD__."-misc" );
1655 - wfProfileIn( __METHOD__."-title" );
 1630+ wfProfileOut( "$fname-misc" );
 1631+ wfProfileIn( "$fname-title" );
16561632 $nt = Title::newFromText( $this->mStripState->unstripNoWiki($link) );
16571633 if( !$nt ) {
16581634 $s .= $prefix . '[[' . $line;
1659 - wfProfileOut( __METHOD__."-title" );
 1635+ wfProfileOut( "$fname-title" );
16601636 continue;
16611637 }
16621638
16631639 $ns = $nt->getNamespace();
16641640 $iw = $nt->getInterWiki();
1665 - wfProfileOut( __METHOD__."-title" );
 1641+ wfProfileOut( "$fname-title" );
16661642
16671643 if ($might_be_img) { # if this is actually an invalid link
1668 - wfProfileIn( __METHOD__."-might_be_img" );
 1644+ wfProfileIn( "$fname-might_be_img" );
16691645 if ($ns == NS_IMAGE && $noforce) { #but might be an image
16701646 $found = false;
1671 - while ( true ) {
 1647+ while (isset ($a[$k+1]) ) {
16721648 #look at the next 'line' to see if we can close it there
1673 - $a->next();
1674 - $next_line = $a->current();
1675 - if ( $next_line === false || $next_line === null ) {
1676 - break;
1677 - }
 1649+ $spliced = array_splice( $a, $k + 1, 1 );
 1650+ $next_line = array_shift( $spliced );
16781651 $m = explode( ']]', $next_line, 3 );
16791652 if ( count( $m ) == 3 ) {
16801653 # the first ]] closes the inner link, the second the image
@@ -1693,19 +1666,19 @@
16941667 if ( !$found ) {
16951668 # we couldn't find the end of this imageLink, so output it raw
16961669 #but don't ignore what might be perfectly normal links in the text we've examined
1697 - $holders->merge( $this->replaceInternalLinks2( $text ) );
 1670+ $text = $this->replaceInternalLinks($text);
16981671 $s .= "{$prefix}[[$link|$text";
16991672 # note: no $trail, because without an end, there *is* no trail
1700 - wfProfileOut( __METHOD__."-might_be_img" );
 1673+ wfProfileOut( "$fname-might_be_img" );
17011674 continue;
17021675 }
17031676 } else { #it's not an image, so output it raw
17041677 $s .= "{$prefix}[[$link|$text";
17051678 # note: no $trail, because without an end, there *is* no trail
1706 - wfProfileOut( __METHOD__."-might_be_img" );
 1679+ wfProfileOut( "$fname-might_be_img" );
17071680 continue;
17081681 }
1709 - wfProfileOut( __METHOD__."-might_be_img" );
 1682+ wfProfileOut( "$fname-might_be_img" );
17101683 }
17111684
17121685 $wasblank = ( '' == $text );
@@ -1715,36 +1688,41 @@
17161689 if( $noforce ) {
17171690
17181691 # Interwikis
1719 - wfProfileIn( __METHOD__."-interwiki" );
 1692+ wfProfileIn( "$fname-interwiki" );
17201693 if( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
17211694 $this->mOutput->addLanguageLink( $nt->getFullText() );
17221695 $s = rtrim($s . $prefix);
17231696 $s .= trim($trail, "\n") == '' ? '': $prefix . $trail;
1724 - wfProfileOut( __METHOD__."-interwiki" );
 1697+ wfProfileOut( "$fname-interwiki" );
17251698 continue;
17261699 }
1727 - wfProfileOut( __METHOD__."-interwiki" );
 1700+ wfProfileOut( "$fname-interwiki" );
17281701
17291702 if ( $ns == NS_IMAGE ) {
1730 - wfProfileIn( __METHOD__."-image" );
 1703+ wfProfileIn( "$fname-image" );
17311704 if ( !wfIsBadImage( $nt->getDBkey(), $this->mTitle ) ) {
17321705 # recursively parse links inside the image caption
17331706 # actually, this will parse them in any other parameters, too,
17341707 # but it might be hard to fix that, and it doesn't matter ATM
17351708 $text = $this->replaceExternalLinks($text);
1736 - $holders->merge( $this->replaceInternalLinks2( $text ) );
 1709+ $text = $this->replaceInternalLinks($text);
17371710
17381711 # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them
1739 - $s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text, $holders ) ) . $trail;
 1712+ $s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text ) ) . $trail;
 1713+ $this->mOutput->addImage( $nt->getDBkey() );
 1714+
 1715+ wfProfileOut( "$fname-image" );
 1716+ continue;
 1717+ } else {
 1718+ # We still need to record the image's presence on the page
 1719+ $this->mOutput->addImage( $nt->getDBkey() );
17401720 }
1741 - $this->mOutput->addImage( $nt->getDBkey() );
1742 - wfProfileOut( __METHOD__."-image" );
1743 - continue;
 1721+ wfProfileOut( "$fname-image" );
17441722
17451723 }
17461724
17471725 if ( $ns == NS_CATEGORY ) {
1748 - wfProfileIn( __METHOD__."-category" );
 1726+ wfProfileIn( "$fname-category" );
17491727 $s = rtrim($s . "\n"); # bug 87
17501728
17511729 if ( $wasblank ) {
@@ -1763,7 +1741,7 @@
17641742 */
17651743 $s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
17661744
1767 - wfProfileOut( __METHOD__."-category" );
 1745+ wfProfileOut( "$fname-category" );
17681746 continue;
17691747 }
17701748 }
@@ -1794,7 +1772,7 @@
17951773 if( SpecialPage::exists( $nt->getDBkey() ) ) {
17961774 $s .= $this->makeKnownLinkHolder( $nt, $text, '', $trail, $prefix );
17971775 } else {
1798 - $s .= $holders->makeHolder( $nt, $text, '', $trail, $prefix );
 1776+ $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix );
17991777 }
18001778 continue;
18011779 } elseif( $ns == NS_IMAGE ) {
@@ -1808,10 +1786,10 @@
18091787 continue;
18101788 }
18111789 }
1812 - $s .= $holders->makeHolder( $nt, $text, '', $trail, $prefix );
 1790+ $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix );
18131791 }
1814 - wfProfileOut( __METHOD__ );
1815 - return $holders;
 1792+ wfProfileOut( $fname );
 1793+ return $s;
18161794 }
18171795
18181796 /**
@@ -1820,10 +1798,32 @@
18211799 * parsing of interwiki links, and secondly to allow all existence checks and
18221800 * article length checks (for stub links) to be bundled into a single query.
18231801 *
1824 - * @deprecated
18251802 */
18261803 function makeLinkHolder( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1827 - return $this->mLinkHolders->makeHolder( $nt, $text, $query, $trail, $prefix );
 1804+ wfProfileIn( __METHOD__ );
 1805+ if ( ! is_object($nt) ) {
 1806+ # Fail gracefully
 1807+ $retVal = "<!-- ERROR -->{$prefix}{$text}{$trail}";
 1808+ } else {
 1809+ # Separate the link trail from the rest of the link
 1810+ list( $inside, $trail ) = Linker::splitTrail( $trail );
 1811+
 1812+ if ( $nt->isExternal() ) {
 1813+ $nr = array_push( $this->mInterwikiLinkHolders['texts'], $prefix.$text.$inside );
 1814+ $this->mInterwikiLinkHolders['titles'][] = $nt;
 1815+ $retVal = '<!--IWLINK '. ($nr-1) ."-->{$trail}";
 1816+ } else {
 1817+ $nr = array_push( $this->mLinkHolders['namespaces'], $nt->getNamespace() );
 1818+ $this->mLinkHolders['dbkeys'][] = $nt->getDBkey();
 1819+ $this->mLinkHolders['queries'][] = $query;
 1820+ $this->mLinkHolders['texts'][] = $prefix.$text.$inside;
 1821+ $this->mLinkHolders['titles'][] = $nt;
 1822+
 1823+ $retVal = '<!--LINK '. ($nr-1) ."-->{$trail}";
 1824+ }
 1825+ }
 1826+ wfProfileOut( __METHOD__ );
 1827+ return $retVal;
18281828 }
18291829
18301830 /**
@@ -1889,7 +1889,8 @@
18901890 # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage
18911891 # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage
18921892
1893 - wfProfileIn( __METHOD__ );
 1893+ $fname = 'Parser::maybeDoSubpageLink';
 1894+ wfProfileIn( $fname );
18941895 $ret = $target; # default return value is no change
18951896
18961897 # Some namespaces don't allow subpages,
@@ -1905,7 +1906,7 @@
19061907 # bug 7425
19071908 $target = trim( $target );
19081909 # Look at the first character
1909 - if( $target != '' && $target{0} === '/' ) {
 1910+ if( $target != '' && $target{0} == '/' ) {
19101911 # / at end means we don't want the slash to be shown
19111912 $m = array();
19121913 $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m );
@@ -1932,7 +1933,7 @@
19331934 if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page
19341935 $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) );
19351936 # / at the end means don't show full path
1936 - if( substr( $nodotdot, -1, 1 ) === '/' ) {
 1937+ if( substr( $nodotdot, -1, 1 ) == '/' ) {
19371938 $nodotdot = substr( $nodotdot, 0, -1 );
19381939 if( '' === $text ) {
19391940 $text = $nodotdot . $suffix;
@@ -1948,7 +1949,7 @@
19491950 }
19501951 }
19511952
1952 - wfProfileOut( __METHOD__ );
 1953+ wfProfileOut( $fname );
19531954 return $ret;
19541955 }
19551956
@@ -1984,10 +1985,10 @@
19851986 /* private */ function openList( $char ) {
19861987 $result = $this->closeParagraph();
19871988
1988 - if ( '*' === $char ) { $result .= '<ul><li>'; }
1989 - else if ( '#' === $char ) { $result .= '<ol><li>'; }
1990 - else if ( ':' === $char ) { $result .= '<dl><dd>'; }
1991 - else if ( ';' === $char ) {
 1989+ if ( '*' == $char ) { $result .= '<ul><li>'; }
 1990+ else if ( '#' == $char ) { $result .= '<ol><li>'; }
 1991+ else if ( ':' == $char ) { $result .= '<dl><dd>'; }
 1992+ else if ( ';' == $char ) {
19921993 $result .= '<dl><dt>';
19931994 $this->mDTopen = true;
19941995 }
@@ -1997,11 +1998,11 @@
19981999 }
19992000
20002001 /* private */ function nextItem( $char ) {
2001 - if ( '*' === $char || '#' === $char ) { return '</li><li>'; }
2002 - else if ( ':' === $char || ';' === $char ) {
 2002+ if ( '*' == $char || '#' == $char ) { return '</li><li>'; }
 2003+ else if ( ':' == $char || ';' == $char ) {
20032004 $close = '</dd>';
20042005 if ( $this->mDTopen ) { $close = '</dt>'; }
2005 - if ( ';' === $char ) {
 2006+ if ( ';' == $char ) {
20062007 $this->mDTopen = true;
20072008 return $close . '<dt>';
20082009 } else {
@@ -2013,9 +2014,9 @@
20142015 }
20152016
20162017 /* private */ function closeList( $char ) {
2017 - if ( '*' === $char ) { $text = '</li></ul>'; }
2018 - else if ( '#' === $char ) { $text = '</li></ol>'; }
2019 - else if ( ':' === $char ) {
 2018+ if ( '*' == $char ) { $text = '</li></ul>'; }
 2019+ else if ( '#' == $char ) { $text = '</li></ol>'; }
 2020+ else if ( ':' == $char ) {
20202021 if ( $this->mDTopen ) {
20212022 $this->mDTopen = false;
20222023 $text = '</dt></dl>';
@@ -2029,59 +2030,56 @@
20302031 /**#@-*/
20312032
20322033 /**
2033 - * Make lists from lines starting with ':', '*', '#', etc. (DBL)
 2034+ * Make lists from lines starting with ':', '*', '#', etc.
20342035 *
20352036 * @private
20362037 * @return string the lists rendered as HTML
20372038 */
20382039 function doBlockLevels( $text, $linestart ) {
2039 - wfProfileIn( __METHOD__ );
 2040+ $fname = 'Parser::doBlockLevels';
 2041+ wfProfileIn( $fname );
20402042
20412043 # Parsing through the text line by line. The main thing
20422044 # happening here is handling of block-level elements p, pre,
20432045 # and making lists from lines starting with * # : etc.
20442046 #
2045 - $textLines = StringUtils::explode( "\n", $text );
 2047+ $textLines = explode( "\n", $text );
20462048
20472049 $lastPrefix = $output = '';
20482050 $this->mDTopen = $inBlockElem = false;
20492051 $prefixLength = 0;
20502052 $paragraphStack = false;
20512053
 2054+ if ( !$linestart ) {
 2055+ $output .= array_shift( $textLines );
 2056+ }
20522057 foreach ( $textLines as $oLine ) {
2053 - # Fix up $linestart
2054 - if ( !$linestart ) {
2055 - $output .= $oLine;
2056 - $linestart = true;
2057 - continue;
2058 - }
2059 -
20602058 $lastPrefixLength = strlen( $lastPrefix );
20612059 $preCloseMatch = preg_match('/<\\/pre/i', $oLine );
20622060 $preOpenMatch = preg_match('/<pre/i', $oLine );
20632061 if ( !$this->mInPre ) {
20642062 # Multiple prefixes may abut each other for nested lists.
20652063 $prefixLength = strspn( $oLine, '*#:;' );
2066 - $prefix = substr( $oLine, 0, $prefixLength );
 2064+ $pref = substr( $oLine, 0, $prefixLength );
20672065
20682066 # eh?
2069 - $prefix2 = str_replace( ';', ':', $prefix );
 2067+ $pref2 = str_replace( ';', ':', $pref );
20702068 $t = substr( $oLine, $prefixLength );
2071 - $this->mInPre = (bool)$preOpenMatch;
 2069+ $this->mInPre = !empty($preOpenMatch);
20722070 } else {
20732071 # Don't interpret any other prefixes in preformatted text
20742072 $prefixLength = 0;
2075 - $prefix = $prefix2 = '';
 2073+ $pref = $pref2 = '';
20762074 $t = $oLine;
20772075 }
20782076
20792077 # List generation
2080 - if( $prefixLength && $lastPrefix === $prefix2 ) {
 2078+ if( $prefixLength && 0 == strcmp( $lastPrefix, $pref2 ) ) {
20812079 # Same as the last item, so no need to deal with nesting or opening stuff
2082 - $output .= $this->nextItem( substr( $prefix, -1 ) );
 2080+ $output .= $this->nextItem( substr( $pref, -1 ) );
20832081 $paragraphStack = false;
20842082
2085 - if ( substr( $prefix, -1 ) === ';') {
 2083+ if ( substr( $pref, -1 ) == ';') {
20862084 # The one nasty exception: definition lists work like this:
20872085 # ; title : definition text
20882086 # So we check for : in the remainder text to split up the
@@ -2094,21 +2092,21 @@
20952093 }
20962094 } elseif( $prefixLength || $lastPrefixLength ) {
20972095 # Either open or close a level...
2098 - $commonPrefixLength = $this->getCommon( $prefix, $lastPrefix );
 2096+ $commonPrefixLength = $this->getCommon( $pref, $lastPrefix );
20992097 $paragraphStack = false;
21002098
21012099 while( $commonPrefixLength < $lastPrefixLength ) {
2102 - $output .= $this->closeList( $lastPrefix[$lastPrefixLength-1] );
 2100+ $output .= $this->closeList( $lastPrefix{$lastPrefixLength-1} );
21032101 --$lastPrefixLength;
21042102 }
21052103 if ( $prefixLength <= $commonPrefixLength && $commonPrefixLength > 0 ) {
2106 - $output .= $this->nextItem( $prefix[$commonPrefixLength-1] );
 2104+ $output .= $this->nextItem( $pref{$commonPrefixLength-1} );
21072105 }
21082106 while ( $prefixLength > $commonPrefixLength ) {
2109 - $char = substr( $prefix, $commonPrefixLength, 1 );
 2107+ $char = substr( $pref, $commonPrefixLength, 1 );
21102108 $output .= $this->openList( $char );
21112109
2112 - if ( ';' === $char ) {
 2110+ if ( ';' == $char ) {
21132111 # FIXME: This is dupe of code above
21142112 if ($this->findColonNoLinks($t, $term, $t2) !== false) {
21152113 $t = $t2;
@@ -2117,10 +2115,10 @@
21182116 }
21192117 ++$commonPrefixLength;
21202118 }
2121 - $lastPrefix = $prefix2;
 2119+ $lastPrefix = $pref2;
21222120 }
21232121 if( 0 == $prefixLength ) {
2124 - wfProfileIn( __METHOD__."-paragraph" );
 2122+ wfProfileIn( "$fname-paragraph" );
21252123 # No prefix (not in list)--go to paragraph mode
21262124 // XXX: use a stack for nestable elements like span, table and div
21272125 $openmatch = preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
@@ -2140,9 +2138,9 @@
21412139 $inBlockElem = true;
21422140 }
21432141 } else if ( !$inBlockElem && !$this->mInPre ) {
2144 - if ( ' ' == $t{0} and ( $this->mLastSection === 'pre' or trim($t) != '' ) ) {
 2142+ if ( ' ' == $t{0} and ( $this->mLastSection == 'pre' or trim($t) != '' ) ) {
21452143 // pre
2146 - if ($this->mLastSection !== 'pre') {
 2144+ if ($this->mLastSection != 'pre') {
21472145 $paragraphStack = false;
21482146 $output .= $this->closeParagraph().'<pre>';
21492147 $this->mLastSection = 'pre';
@@ -2156,7 +2154,7 @@
21572155 $paragraphStack = false;
21582156 $this->mLastSection = 'p';
21592157 } else {
2160 - if ($this->mLastSection !== 'p' ) {
 2158+ if ($this->mLastSection != 'p' ) {
21612159 $output .= $this->closeParagraph();
21622160 $this->mLastSection = '';
21632161 $paragraphStack = '<p>';
@@ -2169,14 +2167,14 @@
21702168 $output .= $paragraphStack;
21712169 $paragraphStack = false;
21722170 $this->mLastSection = 'p';
2173 - } else if ($this->mLastSection !== 'p') {
 2171+ } else if ($this->mLastSection != 'p') {
21742172 $output .= $this->closeParagraph().'<p>';
21752173 $this->mLastSection = 'p';
21762174 }
21772175 }
21782176 }
21792177 }
2180 - wfProfileOut( __METHOD__."-paragraph" );
 2178+ wfProfileOut( "$fname-paragraph" );
21812179 }
21822180 // somewhere above we forget to get out of pre block (bug 785)
21832181 if($preCloseMatch && $this->mInPre) {
@@ -2187,7 +2185,7 @@
21882186 }
21892187 }
21902188 while ( $prefixLength ) {
2191 - $output .= $this->closeList( $prefix2[$prefixLength-1] );
 2189+ $output .= $this->closeList( $pref2{$prefixLength-1} );
21922190 --$prefixLength;
21932191 }
21942192 if ( '' != $this->mLastSection ) {
@@ -2195,7 +2193,7 @@
21962194 $this->mLastSection = '';
21972195 }
21982196
2199 - wfProfileOut( __METHOD__ );
 2197+ wfProfileOut( $fname );
22002198 return $output;
22012199 }
22022200
@@ -2208,12 +2206,13 @@
22092207 * return string the position of the ':', or false if none found
22102208 */
22112209 function findColonNoLinks($str, &$before, &$after) {
2212 - wfProfileIn( __METHOD__ );
 2210+ $fname = 'Parser::findColonNoLinks';
 2211+ wfProfileIn( $fname );
22132212
22142213 $pos = strpos( $str, ':' );
22152214 if( $pos === false ) {
22162215 // Nothing to find!
2217 - wfProfileOut( __METHOD__ );
 2216+ wfProfileOut( $fname );
22182217 return false;
22192218 }
22202219
@@ -2222,7 +2221,7 @@
22232222 // Easy; no tag nesting to worry about
22242223 $before = substr( $str, 0, $pos );
22252224 $after = substr( $str, $pos+1 );
2226 - wfProfileOut( __METHOD__ );
 2225+ wfProfileOut( $fname );
22272226 return $pos;
22282227 }
22292228
@@ -2246,7 +2245,7 @@
22472246 // We found it!
22482247 $before = substr( $str, 0, $i );
22492248 $after = substr( $str, $i + 1 );
2250 - wfProfileOut( __METHOD__ );
 2249+ wfProfileOut( $fname );
22512250 return $i;
22522251 }
22532252 // Embedded in a tag; don't break it.
@@ -2256,7 +2255,7 @@
22572256 $colon = strpos( $str, ':', $i );
22582257 if( $colon === false ) {
22592258 // Nothing else interesting
2260 - wfProfileOut( __METHOD__ );
 2259+ wfProfileOut( $fname );
22612260 return false;
22622261 }
22632262 $lt = strpos( $str, '<', $i );
@@ -2265,7 +2264,7 @@
22662265 // We found it!
22672266 $before = substr( $str, 0, $colon );
22682267 $after = substr( $str, $colon + 1 );
2269 - wfProfileOut( __METHOD__ );
 2268+ wfProfileOut( $fname );
22702269 return $i;
22712270 }
22722271 }
@@ -2312,18 +2311,18 @@
23132312 break;
23142313 case 3: // self::COLON_STATE_CLOSETAG:
23152314 // In a </tag>
2316 - if( $c === ">" ) {
 2315+ if( $c == ">" ) {
23172316 $stack--;
23182317 if( $stack < 0 ) {
2319 - wfDebug( __METHOD__.": Invalid input; too many close tags\n" );
2320 - wfProfileOut( __METHOD__ );
 2318+ wfDebug( "Invalid input in $fname; too many close tags\n" );
 2319+ wfProfileOut( $fname );
23212320 return false;
23222321 }
23232322 $state = self::COLON_STATE_TEXT;
23242323 }
23252324 break;
23262325 case self::COLON_STATE_TAGSLASH:
2327 - if( $c === ">" ) {
 2326+ if( $c == ">" ) {
23282327 // Yes, a self-closed tag <blah/>
23292328 $state = self::COLON_STATE_TEXT;
23302329 } else {
@@ -2332,33 +2331,33 @@
23332332 }
23342333 break;
23352334 case 5: // self::COLON_STATE_COMMENT:
2336 - if( $c === "-" ) {
 2335+ if( $c == "-" ) {
23372336 $state = self::COLON_STATE_COMMENTDASH;
23382337 }
23392338 break;
23402339 case self::COLON_STATE_COMMENTDASH:
2341 - if( $c === "-" ) {
 2340+ if( $c == "-" ) {
23422341 $state = self::COLON_STATE_COMMENTDASHDASH;
23432342 } else {
23442343 $state = self::COLON_STATE_COMMENT;
23452344 }
23462345 break;
23472346 case self::COLON_STATE_COMMENTDASHDASH:
2348 - if( $c === ">" ) {
 2347+ if( $c == ">" ) {
23492348 $state = self::COLON_STATE_TEXT;
23502349 } else {
23512350 $state = self::COLON_STATE_COMMENT;
23522351 }
23532352 break;
23542353 default:
2355 - throw new MWException( "State machine error in " . __METHOD__ );
 2354+ throw new MWException( "State machine error in $fname" );
23562355 }
23572356 }
23582357 if( $stack > 0 ) {
2359 - wfDebug( __METHOD__.": Invalid input; not enough close tags (stack $stack, state $state)\n" );
 2358+ wfDebug( "Invalid input in $fname; not enough close tags (stack $stack, state $state)\n" );
23602359 return false;
23612360 }
2362 - wfProfileOut( __METHOD__ );
 2361+ wfProfileOut( $fname );
23632362 return false;
23642363 }
23652364
@@ -2588,11 +2587,12 @@
25892588 * @private
25902589 */
25912590 function initialiseVariables() {
2592 - wfProfileIn( __METHOD__ );
 2591+ $fname = 'Parser::initialiseVariables';
 2592+ wfProfileIn( $fname );
25932593 $variableIDs = MagicWord::getVariableIDs();
25942594
25952595 $this->mVariables = new MagicWordArray( $variableIDs );
2596 - wfProfileOut( __METHOD__ );
 2596+ wfProfileOut( $fname );
25972597 }
25982598
25992599 /**
@@ -2661,7 +2661,8 @@
26622662 return $text;
26632663 }
26642664
2665 - wfProfileIn( __METHOD__ );
 2665+ $fname = __METHOD__;
 2666+ wfProfileIn( $fname );
26662667
26672668 if ( $frame === false ) {
26682669 $frame = $this->getPreprocessor()->newFrame();
@@ -2674,7 +2675,7 @@
26752676 $flags = $argsOnly ? PPFrame::NO_TEMPLATES : 0;
26762677 $text = $frame->expand( $dom, $flags );
26772678
2678 - wfProfileOut( __METHOD__ );
 2679+ wfProfileOut( $fname );
26792680 return $text;
26802681 }
26812682
@@ -2737,7 +2738,8 @@
27382739 */
27392740 function braceSubstitution( $piece, $frame ) {
27402741 global $wgContLang, $wgLang, $wgAllowDisplayTitle, $wgNonincludableNamespaces;
2741 - wfProfileIn( __METHOD__ );
 2742+ $fname = __METHOD__;
 2743+ wfProfileIn( $fname );
27422744 wfProfileIn( __METHOD__.'-setup' );
27432745
27442746 # Flags
@@ -2924,7 +2926,7 @@
29252927 }
29262928 } else if ( $wgNonincludableNamespaces && in_array( $title->getNamespace(), $wgNonincludableNamespaces ) ) {
29272929 $found = false; //access denied
2928 - wfDebug( __METHOD__.": template inclusion denied for " . $title->getPrefixedDBkey() );
 2930+ wfDebug( "$fname: template inclusion denied for " . $title->getPrefixedDBkey() );
29292931 } else {
29302932 list( $text, $title ) = $this->getTemplateDom( $title );
29312933 if ( $text !== false ) {
@@ -2958,7 +2960,7 @@
29592961 # Recover the source wikitext and return it
29602962 if ( !$found ) {
29612963 $text = $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args );
2962 - wfProfileOut( __METHOD__ );
 2964+ wfProfileOut( $fname );
29632965 return array( 'object' => $text );
29642966 }
29652967
@@ -3017,7 +3019,7 @@
30183020 $ret = array( 'text' => $text );
30193021 }
30203022
3021 - wfProfileOut( __METHOD__ );
 3023+ wfProfileOut( $fname );
30223024 return $ret;
30233025 }
30243026
@@ -3304,7 +3306,7 @@
33053307 }
33063308 }
33073309
3308 - if ( $name === 'html' || $name === 'nowiki' ) {
 3310+ if ( $name == 'html' || $name == 'nowiki' ) {
33093311 $this->mStripState->nowiki->setPair( $marker, $output );
33103312 } else {
33113313 $this->mStripState->general->setPair( $marker, $output );
@@ -3560,7 +3562,12 @@
35613563 # <!--LINK number-->
35623564 # turns into
35633565 # link text with suffix
3564 - $safeHeadline = $this->replaceLinkHoldersText( $safeHeadline );
 3566+ $safeHeadline = preg_replace( '/<!--LINK ([0-9]*)-->/e',
 3567+ "\$this->mLinkHolders['texts'][\$1]",
 3568+ $safeHeadline );
 3569+ $safeHeadline = preg_replace( '/<!--IWLINK ([0-9]*)-->/e',
 3570+ "\$this->mInterwikiLinkHolders['texts'][\$1]",
 3571+ $safeHeadline );
35653572
35663573 # Strip out HTML (other than plain <sup> and <sub>: bug 8393)
35673574 $tocline = preg_replace(
@@ -3636,7 +3643,7 @@
36373644 $i = 0;
36383645
36393646 foreach( $blocks as $block ) {
3640 - if( $showEditLink && $headlineCount > 0 && $i == 0 && $block !== "\n" ) {
 3647+ if( $showEditLink && $headlineCount > 0 && $i == 0 && $block != "\n" ) {
36413648 # This is the [edit] link that appears for the top block of text when
36423649 # section editing is enabled
36433650
@@ -3788,7 +3795,7 @@
37893796 } else {
37903797 # Failed to validate; fall back to the default
37913798 $nickname = $username;
3792 - wfDebug( __METHOD__.": $username has bad XML tags in signature.\n" );
 3799+ wfDebug( "Parser::getUserSig: $username has bad XML tags in signature.\n" );
37933800 }
37943801 }
37953802
@@ -3894,17 +3901,19 @@
38953902 global $wgTitle;
38963903 static $executing = false;
38973904
 3905+ $fname = "Parser::transformMsg";
 3906+
38983907 # Guard against infinite recursion
38993908 if ( $executing ) {
39003909 return $text;
39013910 }
39023911 $executing = true;
39033912
3904 - wfProfileIn(__METHOD__);
 3913+ wfProfileIn($fname);
39053914 $text = $this->preprocess( $text, $wgTitle, $options );
39063915
39073916 $executing = false;
3908 - wfProfileOut(__METHOD__);
 3917+ wfProfileOut($fname);
39093918 return $text;
39103919 }
39113920
@@ -4001,7 +4010,7 @@
40024011 # Add to function cache
40034012 $mw = MagicWord::get( $id );
40044013 if( !$mw )
4005 - throw new MWException( __METHOD__.'() expecting a magic word identifier.' );
 4014+ throw new MWException( 'Parser::setFunctionHook() expecting a magic word identifier.' );
40064015
40074016 $synonyms = $mw->getSynonyms();
40084017 $sensitive = intval( $mw->isCaseSensitive() );
@@ -4016,7 +4025,7 @@
40174026 $syn = '#' . $syn;
40184027 }
40194028 # Remove trailing colon
4020 - if ( substr( $syn, -1, 1 ) === ':' ) {
 4029+ if ( substr( $syn, -1, 1 ) == ':' ) {
40214030 $syn = substr( $syn, 0, -1 );
40224031 }
40234032 $this->mFunctionSynonyms[$sensitive][$syn] = $id;
@@ -4037,9 +4046,266 @@
40384047 * Replace <!--LINK--> link placeholders with actual links, in the buffer
40394048 * Placeholders created in Skin::makeLinkObj()
40404049 * Returns an array of link CSS classes, indexed by PDBK.
 4050+ * $options is a bit field, RLH_FOR_UPDATE to select for update
40414051 */
40424052 function replaceLinkHolders( &$text, $options = 0 ) {
4043 - return $this->mLinkHolders->replace( $text );
 4053+ global $wgUser;
 4054+ global $wgContLang;
 4055+
 4056+ $fname = 'Parser::replaceLinkHolders';
 4057+ wfProfileIn( $fname );
 4058+
 4059+ $pdbks = array();
 4060+ $colours = array();
 4061+ $linkcolour_ids = array();
 4062+ $sk = $this->mOptions->getSkin();
 4063+ $linkCache = LinkCache::singleton();
 4064+
 4065+ if ( !empty( $this->mLinkHolders['namespaces'] ) ) {
 4066+ wfProfileIn( $fname.'-check' );
 4067+ $dbr = wfGetDB( DB_SLAVE );
 4068+ $page = $dbr->tableName( 'page' );
 4069+ $threshold = $wgUser->getOption('stubthreshold');
 4070+
 4071+ # Sort by namespace
 4072+ asort( $this->mLinkHolders['namespaces'] );
 4073+
 4074+ # Generate query
 4075+ $query = false;
 4076+ $current = null;
 4077+ foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) {
 4078+ # Make title object
 4079+ $title = $this->mLinkHolders['titles'][$key];
 4080+
 4081+ # Skip invalid entries.
 4082+ # Result will be ugly, but prevents crash.
 4083+ if ( is_null( $title ) ) {
 4084+ continue;
 4085+ }
 4086+ $pdbk = $pdbks[$key] = $title->getPrefixedDBkey();
 4087+
 4088+ # Check if it's a static known link, e.g. interwiki
 4089+ if ( $title->isAlwaysKnown() ) {
 4090+ $colours[$pdbk] = '';
 4091+ } elseif ( ( $id = $linkCache->getGoodLinkID( $pdbk ) ) != 0 ) {
 4092+ $colours[$pdbk] = '';
 4093+ $this->mOutput->addLink( $title, $id );
 4094+ } elseif ( $linkCache->isBadLink( $pdbk ) ) {
 4095+ $colours[$pdbk] = 'new';
 4096+ } elseif ( $title->getNamespace() == NS_SPECIAL && !SpecialPage::exists( $pdbk ) ) {
 4097+ $colours[$pdbk] = 'new';
 4098+ } else {
 4099+ # Not in the link cache, add it to the query
 4100+ if ( !isset( $current ) ) {
 4101+ $current = $ns;
 4102+ $query = "SELECT page_id, page_namespace, page_title, page_is_redirect, page_len";
 4103+ $query .= " FROM $page WHERE (page_namespace=$ns AND page_title IN(";
 4104+ } elseif ( $current != $ns ) {
 4105+ $current = $ns;
 4106+ $query .= ")) OR (page_namespace=$ns AND page_title IN(";
 4107+ } else {
 4108+ $query .= ', ';
 4109+ }
 4110+
 4111+ $query .= $dbr->addQuotes( $this->mLinkHolders['dbkeys'][$key] );
 4112+ }
 4113+ }
 4114+ if ( $query ) {
 4115+ $query .= '))';
 4116+ if ( $options & RLH_FOR_UPDATE ) {
 4117+ $query .= ' FOR UPDATE';
 4118+ }
 4119+
 4120+ $res = $dbr->query( $query, $fname );
 4121+
 4122+ # Fetch data and form into an associative array
 4123+ # non-existent = broken
 4124+ while ( $s = $dbr->fetchObject($res) ) {
 4125+ $title = Title::makeTitle( $s->page_namespace, $s->page_title );
 4126+ $pdbk = $title->getPrefixedDBkey();
 4127+ $linkCache->addGoodLinkObj( $s->page_id, $title, $s->page_len, $s->page_is_redirect );
 4128+ $this->mOutput->addLink( $title, $s->page_id );
 4129+ $colours[$pdbk] = $sk->getLinkColour( $title, $threshold );
 4130+ //add id to the extension todolist
 4131+ $linkcolour_ids[$s->page_id] = $pdbk;
 4132+ }
 4133+ //pass an array of page_ids to an extension
 4134+ wfRunHooks( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
 4135+ }
 4136+ wfProfileOut( $fname.'-check' );
 4137+
 4138+ # Do a second query for different language variants of links and categories
 4139+ if($wgContLang->hasVariants()){
 4140+ $linkBatch = new LinkBatch();
 4141+ $variantMap = array(); // maps $pdbkey_Variant => $keys (of link holders)
 4142+ $categoryMap = array(); // maps $category_variant => $category (dbkeys)
 4143+ $varCategories = array(); // category replacements oldDBkey => newDBkey
 4144+
 4145+ $categories = $this->mOutput->getCategoryLinks();
 4146+
 4147+ // Add variants of links to link batch
 4148+ foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) {
 4149+ $title = $this->mLinkHolders['titles'][$key];
 4150+ if ( is_null( $title ) )
 4151+ continue;
 4152+
 4153+ $pdbk = $title->getPrefixedDBkey();
 4154+ $titleText = $title->getText();
 4155+
 4156+ // generate all variants of the link title text
 4157+ $allTextVariants = $wgContLang->convertLinkToAllVariants($titleText);
 4158+
 4159+ // if link was not found (in first query), add all variants to query
 4160+ if ( !isset($colours[$pdbk]) ){
 4161+ foreach($allTextVariants as $textVariant){
 4162+ if($textVariant != $titleText){
 4163+ $variantTitle = Title::makeTitle( $ns, $textVariant );
 4164+ if(is_null($variantTitle)) continue;
 4165+ $linkBatch->addObj( $variantTitle );
 4166+ $variantMap[$variantTitle->getPrefixedDBkey()][] = $key;
 4167+ }
 4168+ }
 4169+ }
 4170+ }
 4171+
 4172+ // process categories, check if a category exists in some variant
 4173+ foreach( $categories as $category ){
 4174+ $variants = $wgContLang->convertLinkToAllVariants($category);
 4175+ foreach($variants as $variant){
 4176+ if($variant != $category){
 4177+ $variantTitle = Title::newFromDBkey( Title::makeName(NS_CATEGORY,$variant) );
 4178+ if(is_null($variantTitle)) continue;
 4179+ $linkBatch->addObj( $variantTitle );
 4180+ $categoryMap[$variant] = $category;
 4181+ }
 4182+ }
 4183+ }
 4184+
 4185+
 4186+ if(!$linkBatch->isEmpty()){
 4187+ // construct query
 4188+ $titleClause = $linkBatch->constructSet('page', $dbr);
 4189+
 4190+ $variantQuery = "SELECT page_id, page_namespace, page_title, page_is_redirect, page_len";
 4191+
 4192+ $variantQuery .= " FROM $page WHERE $titleClause";
 4193+ if ( $options & RLH_FOR_UPDATE ) {
 4194+ $variantQuery .= ' FOR UPDATE';
 4195+ }
 4196+
 4197+ $varRes = $dbr->query( $variantQuery, $fname );
 4198+
 4199+ // for each found variants, figure out link holders and replace
 4200+ while ( $s = $dbr->fetchObject($varRes) ) {
 4201+
 4202+ $variantTitle = Title::makeTitle( $s->page_namespace, $s->page_title );
 4203+ $varPdbk = $variantTitle->getPrefixedDBkey();
 4204+ $vardbk = $variantTitle->getDBkey();
 4205+
 4206+ $holderKeys = array();
 4207+ if(isset($variantMap[$varPdbk])){
 4208+ $holderKeys = $variantMap[$varPdbk];
 4209+ $linkCache->addGoodLinkObj( $s->page_id, $variantTitle, $s->page_len, $s->page_is_redirect );
 4210+ $this->mOutput->addLink( $variantTitle, $s->page_id );
 4211+ }
 4212+
 4213+ // loop over link holders
 4214+ foreach($holderKeys as $key){
 4215+ $title = $this->mLinkHolders['titles'][$key];
 4216+ if ( is_null( $title ) ) continue;
 4217+
 4218+ $pdbk = $title->getPrefixedDBkey();
 4219+
 4220+ if(!isset($colours[$pdbk])){
 4221+ // found link in some of the variants, replace the link holder data
 4222+ $this->mLinkHolders['titles'][$key] = $variantTitle;
 4223+ $this->mLinkHolders['dbkeys'][$key] = $variantTitle->getDBkey();
 4224+
 4225+ // set pdbk and colour
 4226+ $pdbks[$key] = $varPdbk;
 4227+ $colours[$varPdbk] = $sk->getLinkColour( $variantTitle, $threshold );
 4228+ $linkcolour_ids[$s->page_id] = $pdbk;
 4229+ }
 4230+ wfRunHooks( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
 4231+ }
 4232+
 4233+ // check if the object is a variant of a category
 4234+ if(isset($categoryMap[$vardbk])){
 4235+ $oldkey = $categoryMap[$vardbk];
 4236+ if($oldkey != $vardbk)
 4237+ $varCategories[$oldkey]=$vardbk;
 4238+ }
 4239+ }
 4240+
 4241+ // rebuild the categories in original order (if there are replacements)
 4242+ if(count($varCategories)>0){
 4243+ $newCats = array();
 4244+ $originalCats = $this->mOutput->getCategories();
 4245+ foreach($originalCats as $cat => $sortkey){
 4246+ // make the replacement
 4247+ if( array_key_exists($cat,$varCategories) )
 4248+ $newCats[$varCategories[$cat]] = $sortkey;
 4249+ else $newCats[$cat] = $sortkey;
 4250+ }
 4251+ $this->mOutput->setCategoryLinks($newCats);
 4252+ }
 4253+ }
 4254+ }
 4255+
 4256+ # Construct search and replace arrays
 4257+ wfProfileIn( $fname.'-construct' );
 4258+ $replacePairs = array();
 4259+ foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) {
 4260+ $pdbk = $pdbks[$key];
 4261+ $searchkey = "<!--LINK $key-->";
 4262+ $title = $this->mLinkHolders['titles'][$key];
 4263+ if ( !isset( $colours[$pdbk] ) || $colours[$pdbk] == 'new' ) {
 4264+ $linkCache->addBadLinkObj( $title );
 4265+ $colours[$pdbk] = 'new';
 4266+ $this->mOutput->addLink( $title, 0 );
 4267+ $replacePairs[$searchkey] = $sk->makeBrokenLinkObj( $title,
 4268+ $this->mLinkHolders['texts'][$key],
 4269+ $this->mLinkHolders['queries'][$key] );
 4270+ } else {
 4271+ $replacePairs[$searchkey] = $sk->makeColouredLinkObj( $title, $colours[$pdbk],
 4272+ $this->mLinkHolders['texts'][$key],
 4273+ $this->mLinkHolders['queries'][$key] );
 4274+ }
 4275+ }
 4276+ $replacer = new HashtableReplacer( $replacePairs, 1 );
 4277+ wfProfileOut( $fname.'-construct' );
 4278+
 4279+ # Do the thing
 4280+ wfProfileIn( $fname.'-replace' );
 4281+ $text = preg_replace_callback(
 4282+ '/(<!--LINK .*?-->)/',
 4283+ $replacer->cb(),
 4284+ $text);
 4285+
 4286+ wfProfileOut( $fname.'-replace' );
 4287+ }
 4288+
 4289+ # Now process interwiki link holders
 4290+ # This is quite a bit simpler than internal links
 4291+ if ( !empty( $this->mInterwikiLinkHolders['texts'] ) ) {
 4292+ wfProfileIn( $fname.'-interwiki' );
 4293+ # Make interwiki link HTML
 4294+ $replacePairs = array();
 4295+ foreach( $this->mInterwikiLinkHolders['texts'] as $key => $link ) {
 4296+ $title = $this->mInterwikiLinkHolders['titles'][$key];
 4297+ $replacePairs[$key] = $sk->link( $title, $link );
 4298+ }
 4299+ $replacer = new HashtableReplacer( $replacePairs, 1 );
 4300+
 4301+ $text = preg_replace_callback(
 4302+ '/<!--IWLINK (.*?)-->/',
 4303+ $replacer->cb(),
 4304+ $text );
 4305+ wfProfileOut( $fname.'-interwiki' );
 4306+ }
 4307+
 4308+ wfProfileOut( $fname );
 4309+ return $colours;
40444310 }
40454311
40464312 /**
@@ -4049,10 +4315,39 @@
40504316 * @return string
40514317 */
40524318 function replaceLinkHoldersText( $text ) {
4053 - return $this->mLinkHolders->replaceText( $text );
 4319+ $fname = 'Parser::replaceLinkHoldersText';
 4320+ wfProfileIn( $fname );
 4321+
 4322+ $text = preg_replace_callback(
 4323+ '/<!--(LINK|IWLINK) (.*?)-->/',
 4324+ array( &$this, 'replaceLinkHoldersTextCallback' ),
 4325+ $text );
 4326+
 4327+ wfProfileOut( $fname );
 4328+ return $text;
40544329 }
40554330
40564331 /**
 4332+ * @param array $matches
 4333+ * @return string
 4334+ * @private
 4335+ */
 4336+ function replaceLinkHoldersTextCallback( $matches ) {
 4337+ $type = $matches[1];
 4338+ $key = $matches[2];
 4339+ if( $type == 'LINK' ) {
 4340+ if( isset( $this->mLinkHolders['texts'][$key] ) ) {
 4341+ return $this->mLinkHolders['texts'][$key];
 4342+ }
 4343+ } elseif( $type == 'IWLINK' ) {
 4344+ if( isset( $this->mInterwikiLinkHolders['texts'][$key] ) ) {
 4345+ return $this->mInterwikiLinkHolders['texts'][$key];
 4346+ }
 4347+ }
 4348+ return $matches[0];
 4349+ }
 4350+
 4351+ /**
40574352 * Tag hook handler for 'pre'.
40584353 */
40594354 function renderPreTag( $text, $attribs ) {
@@ -4103,7 +4398,7 @@
41044399
41054400 wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) );
41064401
4107 - $lines = StringUtils::explode( "\n", $text );
 4402+ $lines = explode( "\n", $text );
41084403 foreach ( $lines as $line ) {
41094404 # match lines like these:
41104405 # Image:someimage.jpg|This is some image
@@ -4116,7 +4411,7 @@
41174412
41184413 if ( strpos( $matches[0], '%' ) !== false )
41194414 $matches[1] = urldecode( $matches[1] );
4120 - $tp = Title::newFromText( $matches[1], NS_IMAGE );
 4415+ $tp = Title::newFromText( $matches[1] );
41214416 $nt =& $tp;
41224417 if( is_null( $nt ) ) {
41234418 # Bogus title. Ignore these so we don't bomb out later.
@@ -4182,11 +4477,8 @@
41834478
41844479 /**
41854480 * Parse image options text and use it to make an image
4186 - * @param Title $title
4187 - * @param string $options
4188 - * @param LinkHolderArray $holders
41894481 */
4190 - function makeImage( $title, $options, $holders = false ) {
 4482+ function makeImage( $title, $options ) {
41914483 # Check if the options text is of the form "options|alt text"
41924484 # Options are:
41934485 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
@@ -4209,7 +4501,7 @@
42104502 # * bottom
42114503 # * text-bottom
42124504
4213 - $parts = StringUtils::explode( "|", $options );
 4505+ $parts = array_map( 'trim', explode( '|', $options) );
42144506 $sk = $this->mOptions->getSkin();
42154507
42164508 # Give extensions a chance to select the file revision for us
@@ -4231,14 +4523,13 @@
42324524 $params = array( 'frame' => array(), 'handler' => array(),
42334525 'horizAlign' => array(), 'vertAlign' => array() );
42344526 foreach( $parts as $part ) {
4235 - $part = trim( $part );
42364527 list( $magicName, $value ) = $mwArray->matchVariableStartToEnd( $part );
42374528 $validated = false;
42384529 if( isset( $paramMap[$magicName] ) ) {
42394530 list( $type, $paramName ) = $paramMap[$magicName];
42404531
42414532 // Special case; width and height come in one variable together
4242 - if( $type === 'handler' && $paramName === 'width' ) {
 4533+ if( $type == 'handler' && $paramName == 'width' ) {
42434534 $m = array();
42444535 # (bug 13500) In both cases (width/height and width only),
42454536 # permit trailing "px" for backward compatibility.
@@ -4261,7 +4552,7 @@
42624553 }
42634554 } // else no validation -- bug 13436
42644555 } else {
4265 - if ( $type === 'handler' ) {
 4556+ if ( $type == 'handler' ) {
42664557 # Validate handler parameter
42674558 $validated = $handler->validateParam( $paramName, $value );
42684559 } else {
@@ -4297,13 +4588,7 @@
42984589 }
42994590
43004591 # Strip bad stuff out of the alt text
4301 - # We can't just use replaceLinkHoldersText() here, because if this function
4302 - # is called from replaceInternalLinks2(), mLinkHolders won't be up to date.
4303 - if ( $holders ) {
4304 - $alt = $holders->replaceText( $caption );
4305 - } else {
4306 - $alt = $this->replaceLinkHoldersText( $caption );
4307 - }
 4592+ $alt = $this->replaceLinkHoldersText( $caption );
43084593
43094594 # make sure there are no placeholders in thumbnail attributes
43104595 # that are later expanded to html- so expand them now and
@@ -4406,7 +4691,7 @@
44074692 $sectionParts = explode( '-', $section );
44084693 $sectionIndex = array_pop( $sectionParts );
44094694 foreach ( $sectionParts as $part ) {
4410 - if ( $part === 'T' ) {
 4695+ if ( $part == 'T' ) {
44114696 $flags |= self::PTD_FOR_INCLUSION;
44124697 }
44134698 }
@@ -4423,14 +4708,14 @@
44244709 $targetLevel = 1000;
44254710 } else {
44264711 while ( $node ) {
4427 - if ( $node->getName() === 'h' ) {
 4712+ if ( $node->getName() == 'h' ) {
44284713 $bits = $node->splitHeading();
44294714 if ( $bits['i'] == $sectionIndex ) {
44304715 $targetLevel = $bits['level'];
44314716 break;
44324717 }
44334718 }
4434 - if ( $mode === 'replace' ) {
 4719+ if ( $mode == 'replace' ) {
44354720 $outText .= $frame->expand( $node, PPFrame::RECOVER_ORIG );
44364721 }
44374722 $node = $node->getNextSibling();
@@ -4439,7 +4724,7 @@
44404725
44414726 if ( !$node ) {
44424727 // Not found
4443 - if ( $mode === 'get' ) {
 4728+ if ( $mode == 'get' ) {
44444729 return $newText;
44454730 } else {
44464731 return $text;
@@ -4448,21 +4733,21 @@
44494734
44504735 // Find the end of the section, including nested sections
44514736 do {
4452 - if ( $node->getName() === 'h' ) {
 4737+ if ( $node->getName() == 'h' ) {
44534738 $bits = $node->splitHeading();
44544739 $curLevel = $bits['level'];
44554740 if ( $bits['i'] != $sectionIndex && $curLevel <= $targetLevel ) {
44564741 break;
44574742 }
44584743 }
4459 - if ( $mode === 'get' ) {
 4744+ if ( $mode == 'get' ) {
44604745 $outText .= $frame->expand( $node, PPFrame::RECOVER_ORIG );
44614746 }
44624747 $node = $node->getNextSibling();
44634748 } while ( $node );
44644749
44654750 // Write out the remainder (in replace mode only)
4466 - if ( $mode === 'replace' ) {
 4751+ if ( $mode == 'replace' ) {
44674752 // Output the replacement text
44684753 // Add two newlines on -- trailing whitespace in $newText is conventionally
44694754 // stripped by the editor, so we need both newlines to restore the paragraph gap
@@ -4692,7 +4977,7 @@
46934978 do {
46944979 $oldText = $text;
46954980 $text = $this->general->replace( $text );
4696 - } while ( $text !== $oldText );
 4981+ } while ( $text != $oldText );
46974982 wfProfileOut( __METHOD__ );
46984983 return $text;
46994984 }
@@ -4702,7 +4987,7 @@
47034988 do {
47044989 $oldText = $text;
47054990 $text = $this->nowiki->replace( $text );
4706 - } while ( $text !== $oldText );
 4991+ } while ( $text != $oldText );
47074992 wfProfileOut( __METHOD__ );
47084993 return $text;
47094994 }
@@ -4713,7 +4998,7 @@
47144999 $oldText = $text;
47155000 $text = $this->general->replace( $text );
47165001 $text = $this->nowiki->replace( $text );
4717 - } while ( $text !== $oldText );
 5002+ } while ( $text != $oldText );
47185003 wfProfileOut( __METHOD__ );
47195004 return $text;
47205005 }
@@ -4727,7 +5012,7 @@
47285013 var $output = '';
47295014
47305015 function replace( $matches ) {
4731 - if ( substr( $matches[1], -1 ) === "\n" ) {
 5016+ if ( substr( $matches[1], -1 ) == "\n" ) {
47325017 $this->output .= substr( $matches[1], 0, -1 );
47335018 } else {
47345019 $this->output .= $matches[1];
Index: trunk/phase3/includes/parser/Parser_DiffTest.php
@@ -69,17 +69,9 @@
7070 $lastResult = $currentResult;
7171 }
7272 if ( $mismatch ) {
73 - if ( count( $results ) == 2 ) {
74 - $results2 = array_values( $results );
75 - $diff = wfDiff( var_export( $results2[0], true ), var_export( $results2[1], true ) );
76 - } else {
77 - $diff = '[too many parsers]';
78 - }
7973 throw new MWException( "Parser_DiffTest: results mismatch on call to $name\n" .
8074 'Arguments: ' . $this->formatArray( $args ) . "\n" .
81 - 'Results: ' . $this->formatArray( $results ) . "\n" .
82 - "Diff: $diff\n"
83 - );
 75+ 'Results: ' . $this->formatArray( $results ) . "\n" );
8476 }
8577 return $lastResult;
8678 }
Index: trunk/phase3/includes/Title.php
@@ -410,12 +410,6 @@
411411 global $wgInterwikiCache, $wgContLang;
412412 $fname = 'Title::getInterwikiLink';
413413
414 - if ( count( Title::$interwikiCache ) >= self::CACHE_MAX ) {
415 - // Don't use infinite memory
416 - reset( Title::$interwikiCache );
417 - unset( Title::$interwikiCache[ key( Title::$interwikiCache ) ] );
418 - }
419 -
420414 $key = $wgContLang->lc( $key );
421415
422416 $k = wfMemcKey( 'interwiki', $key );
Index: trunk/phase3/languages/LanguageConverter.php
@@ -435,9 +435,8 @@
436436 if ($isTitle) return $this->convertTitle($text);
437437
438438 $plang = $this->getPreferredVariant();
439 - $tarray = StringUtils::explode($this->mMarkup['end'], $text);
 439+ $tarray = explode($this->mMarkup['end'], $text);
440440 $text = '';
441 - $lastDelim = false;
442441 foreach($tarray as $txt) {
443442 $marked = explode($this->mMarkup['begin'], $txt, 2);
444443
@@ -453,17 +452,8 @@
454453
455454 $text .= $crule->getDisplay();
456455 $this->applyManualConv($crule);
457 - $lastDelim = false;
458 - } else {
459 - // Reinsert the }- which wasn't part of anything
460 - $text .= $this->mMarkup['end'];
461 - $lastDelim = true;
462456 }
463457 }
464 - if ( $lastDelim ) {
465 - // Remove the last delimiter (wasn't real)
466 - $text = substr( $text, 0, -strlen( $this->mMarkup['end'] ) );
467 - }
468458
469459 return $text;
470460 }
Index: trunk/phase3/languages/Language.php
@@ -177,15 +177,6 @@
178178 }
179179
180180 /**
181 - * Reduce memory usage
182 - */
183 - function __destruct() {
184 - foreach ( $this as $name => $value ) {
185 - unset( $this->$name );
186 - }
187 - }
188 -
189 - /**
190181 * Hook which will be called if this is the content language.
191182 * Descendants can use this to register hook functions or modify globals
192183 */
Index: trunk/phase3/RELEASE-NOTES
@@ -94,7 +94,6 @@
9595 * HTML entities like &nbsp; now work (are not escaped) in edit summaries.
9696 * (bug 13815) In the comment for page moves, use the colon-separator message
9797 instead of a hardcoded colon.
98 -* Allow <gallery> to accept image names without an Image: prefix
9998
10099 === Bug fixes in 1.14 ===
101100

Follow-up revisions

RevisionCommit summaryAuthorDate
r40020* Revert back to my parser pseudo-branch again. Note: if you feel like revert...tstarling14:37, 26 August 2008

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r39662Revert Parser.php to r39295 good state....brion20:59, 19 August 2008
r39949* Revert revert r39662 of my parser changes....tstarling16:08, 25 August 2008

Status & tagging log