Index: trunk/phase3/maintenance/parserTests.inc |
— | — | @@ -26,7 +26,7 @@ |
27 | 27 | |
28 | 28 | /** */ |
29 | 29 | $options = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record' ); |
30 | | -$optionsWithArgs = array( 'regex', 'seed' ); |
| 30 | +$optionsWithArgs = array( 'regex' ); |
31 | 31 | |
32 | 32 | require_once( 'commandLine.inc' ); |
33 | 33 | require_once( "$IP/maintenance/parserTestsParserHook.php" ); |
— | — | @@ -62,11 +62,6 @@ |
63 | 63 | */ |
64 | 64 | private $oldTablePrefix; |
65 | 65 | |
66 | | - private $maxFuzzHairLength = 20; |
67 | | - private $maxFuzzTestLength = 1000; |
68 | | - private $fuzzSeed = 0; |
69 | | - private $memoryLimit = 50; |
70 | | - |
71 | 66 | /** |
72 | 67 | * Sets terminal colorization and diff/quick modes depending on OS and |
73 | 68 | * command-line options (--color and --quick). |
— | — | @@ -122,10 +117,6 @@ |
123 | 118 | } |
124 | 119 | $this->keepUploads = isset( $options['keep-uploads'] ); |
125 | 120 | |
126 | | - if ( isset( $options['seed'] ) ) { |
127 | | - $this->fuzzSeed = intval( $options['seed'] ) - 1; |
128 | | - } |
129 | | - |
130 | 121 | $this->hooks = array(); |
131 | 122 | $this->functionHooks = array(); |
132 | 123 | } |
— | — | @@ -143,116 +134,6 @@ |
144 | 135 | } |
145 | 136 | |
146 | 137 | /** |
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 | | - /** |
257 | 138 | * Run a series of tests listed in the given text files. |
258 | 139 | * Each test consists of a brief description, wikitext input, |
259 | 140 | * and the expected HTML output. |
— | — | @@ -386,24 +267,6 @@ |
387 | 268 | } |
388 | 269 | |
389 | 270 | /** |
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 | | - /** |
408 | 271 | * Run a given wikitext input through a freshly-constructed wiki parser, |
409 | 272 | * and compare the output against the expected results. |
410 | 273 | * Prints status and explanatory messages to stdout. |
— | — | @@ -413,6 +276,7 @@ |
414 | 277 | * @return bool |
415 | 278 | */ |
416 | 279 | private function runTest( $desc, $input, $result, $opts ) { |
| 280 | + global $wgParserConf; |
417 | 281 | if( $this->showProgress ) { |
418 | 282 | $this->showTesting( $desc ); |
419 | 283 | } |
— | — | @@ -436,7 +300,18 @@ |
437 | 301 | } |
438 | 302 | |
439 | 303 | $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 | + |
441 | 316 | $title =& Title::makeTitle( NS_MAIN, $titleText ); |
442 | 317 | |
443 | 318 | $matches = array(); |
— | — | @@ -566,7 +441,6 @@ |
567 | 442 | $langObj = Language::factory( $lang ); |
568 | 443 | $GLOBALS['wgLang'] = $langObj; |
569 | 444 | $GLOBALS['wgContLang'] = $langObj; |
570 | | - $GLOBALS['wgMemc'] = new FakeMemCachedClient; |
571 | 445 | |
572 | 446 | //$GLOBALS['wgMessageCache'] = new MessageCache( new BagOStuff(), false, 0, $GLOBALS['wgDBname'] ); |
573 | 447 | |
— | — | @@ -677,10 +551,10 @@ |
678 | 552 | # Hack: insert a few Wikipedia in-project interwiki prefixes, |
679 | 553 | # for testing inter-language links |
680 | 554 | $db->insert( 'interwiki', array( |
681 | | - array( 'iw_prefix' => 'wikipedia', |
| 555 | + array( 'iw_prefix' => 'Wikipedia', |
682 | 556 | 'iw_url' => 'http://en.wikipedia.org/wiki/$1', |
683 | 557 | 'iw_local' => 0 ), |
684 | | - array( 'iw_prefix' => 'meatball', |
| 558 | + array( 'iw_prefix' => 'MeatBall', |
685 | 559 | 'iw_url' => 'http://www.usemod.com/cgi-bin/mb.pl?$1', |
686 | 560 | 'iw_local' => 0 ), |
687 | 561 | array( 'iw_prefix' => 'zh', |
— | — | @@ -747,12 +621,11 @@ |
748 | 622 | return; |
749 | 623 | } |
750 | 624 | |
751 | | - /* |
752 | 625 | $tables = $this->listTables(); |
753 | 626 | $db = wfGetDB( DB_MASTER ); |
754 | 627 | foreach ( $tables as $table ) { |
755 | 628 | $db->query( "DROP TABLE `parsertest_$table`" ); |
756 | | - }*/ |
| 629 | + } |
757 | 630 | } |
758 | 631 | |
759 | 632 | /** |
— | — | @@ -772,10 +645,6 @@ |
773 | 646 | } |
774 | 647 | |
775 | 648 | wfDebug( "Creating upload directory $dir\n" ); |
776 | | - if ( file_exists( $dir ) ) { |
777 | | - wfDebug( "Already exists!\n" ); |
778 | | - return $dir; |
779 | | - } |
780 | 649 | mkdir( $dir ); |
781 | 650 | mkdir( $dir . '/3' ); |
782 | 651 | mkdir( $dir . '/3/3a' ); |
— | — | @@ -789,8 +658,6 @@ |
790 | 659 | */ |
791 | 660 | private function teardownGlobals() { |
792 | 661 | RepoGroup::destroySingleton(); |
793 | | - LinkCache::singleton()->clear(); |
794 | | - $GLOBALS['wgLang']->__destruct(); |
795 | 662 | foreach( $this->savedGlobals as $var => $val ) { |
796 | 663 | $GLOBALS[$var] = $val; |
797 | 664 | } |
Index: trunk/phase3/maintenance/parserTests.php |
— | — | @@ -28,21 +28,22 @@ |
29 | 29 | if( isset( $options['help'] ) ) { |
30 | 30 | echo <<<ENDS |
31 | 31 | 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] |
34 | 37 | Options: |
35 | 38 | --quick Suppress diff output of failed tests |
36 | 39 | --quiet Suppress notification of passed tests (shows only failed tests) |
37 | 40 | --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 |
39 | 42 | use wgCommandLineDarkBg = true; if your term is dark |
40 | 43 | --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 |
42 | 45 | --record Record tests in database |
43 | 46 | --compare Compare with recorded results, without updating the database. |
44 | 47 | --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 |
47 | 48 | --help Show this help message |
48 | 49 | |
49 | 50 | |
— | — | @@ -66,10 +67,7 @@ |
67 | 68 | # Print out software version to assist with locating regressions |
68 | 69 | $version = SpecialVersion::getVersion(); |
69 | 70 | echo( "This is MediaWiki version {$version}.\n\n" ); |
| 71 | +$ok = $tester->runTestsFromFiles( $files ); |
70 | 72 | |
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 @@ |
28 | 28 | if ( ! count( $argv ) ) { |
29 | 29 | $buf = $in; |
30 | 30 | 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 ) { |
34 | 32 | // Clear the buffer, we probably don't need to |
35 | 33 | $tmp = $buf; |
36 | 34 | $buf = null; |
37 | 35 | return $tmp; |
38 | 36 | } else |
39 | 37 | // wtf? |
40 | | - return |
| 38 | + die( |
41 | 39 | "\nCall this extension as <statictag>string</statictag> or as" . |
42 | 40 | " <statictag action=flush/>, not in any other way.\n" . |
43 | 41 | "text: " . var_export( $in, true ) . "\n" . |
44 | | - "argv: " . var_export( $argv, true ) . "\n"; |
| 42 | + "argv: " . var_export( $argv, true ) . "\n" |
| 43 | + ); |
45 | 44 | } |
46 | 45 | |
Index: trunk/phase3/includes/parser/LinkHolderArray.php |
— | — | @@ -12,15 +12,6 @@ |
13 | 13 | } |
14 | 14 | |
15 | 15 | /** |
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 | | - /** |
25 | 16 | * Merge another LinkHolderArray into this one |
26 | 17 | */ |
27 | 18 | function merge( $other ) { |
Index: trunk/phase3/includes/parser/Parser.php |
— | — | @@ -98,7 +98,7 @@ |
99 | 99 | # Cleared with clearState(): |
100 | 100 | var $mOutput, $mAutonumber, $mDTopen, $mStripState; |
101 | 101 | var $mIncludeCount, $mArgStack, $mLastSection, $mInPre; |
102 | | - var $mLinkHolders, $mLinkID; |
| 102 | + var $mInterwikiLinkHolders, $mLinkHolders; |
103 | 103 | var $mIncludeSizes, $mPPNodeCount, $mDefaultSort; |
104 | 104 | var $mTplExpandCache; // empty-frame expansion cache |
105 | 105 | var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores; |
— | — | @@ -143,18 +143,6 @@ |
144 | 144 | } |
145 | 145 | |
146 | 146 | /** |
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 | | - /** |
159 | 147 | * Do various kinds of initialisation on the first call of the parser |
160 | 148 | */ |
161 | 149 | function firstCallInit() { |
— | — | @@ -191,8 +179,17 @@ |
192 | 180 | $this->mStripState = new StripState; |
193 | 181 | $this->mArgStack = false; |
194 | 182 | $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 | + ); |
197 | 194 | $this->mRevisionTimestamp = $this->mRevisionId = null; |
198 | 195 | |
199 | 196 | /** |
— | — | @@ -207,7 +204,7 @@ |
208 | 205 | */ |
209 | 206 | #$this->mUniqPrefix = "\x07UNIQ" . Parser::getRandomString(); |
210 | 207 | # Changed to \x7f to allow XML double-parsing -- TS |
211 | | - $this->mUniqPrefix = "\x7fUNIQ" . self::getRandomString(); |
| 208 | + $this->mUniqPrefix = "\x7fUNIQ" . Parser::getRandomString(); |
212 | 209 | |
213 | 210 | |
214 | 211 | # Clear these on every parse, bug 4549 |
— | — | @@ -297,7 +294,7 @@ |
298 | 295 | */ |
299 | 296 | |
300 | 297 | global $wgUseTidy, $wgAlwaysUseTidy, $wgContLang; |
301 | | - $fname = __METHOD__.'-' . wfGetCaller(); |
| 298 | + $fname = 'Parser::parse-' . wfGetCaller(); |
302 | 299 | wfProfileIn( __METHOD__ ); |
303 | 300 | wfProfileIn( $fname ); |
304 | 301 | |
— | — | @@ -331,6 +328,7 @@ |
332 | 329 | ); |
333 | 330 | $text = preg_replace( array_keys($fixtags), array_values($fixtags), $text ); |
334 | 331 | |
| 332 | + # only once and last |
335 | 333 | $text = $this->doBlockLevels( $text, $linestart ); |
336 | 334 | |
337 | 335 | $this->replaceLinkHolders( $text ); |
— | — | @@ -350,7 +348,7 @@ |
351 | 349 | $uniq_prefix = $this->mUniqPrefix; |
352 | 350 | $matches = array(); |
353 | 351 | $elements = array_keys( $this->mTransparentTagHooks ); |
354 | | - $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix ); |
| 352 | + $text = Parser::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix ); |
355 | 353 | |
356 | 354 | foreach( $matches as $marker => $data ) { |
357 | 355 | list( $element, $content, $params, $tag ) = $data; |
— | — | @@ -368,7 +366,7 @@ |
369 | 367 | $text = Sanitizer::normalizeCharReferences( $text ); |
370 | 368 | |
371 | 369 | if (($wgUseTidy and $this->mOptions->mTidy) or $wgAlwaysUseTidy) { |
372 | | - $text = self::tidy($text); |
| 370 | + $text = Parser::tidy($text); |
373 | 371 | } else { |
374 | 372 | # attempt to sanitize at least some nesting problems |
375 | 373 | # (bug #2702 and quite a few others) |
— | — | @@ -473,8 +471,6 @@ |
474 | 472 | function &getTitle() { return $this->mTitle; } |
475 | 473 | function getOptions() { return $this->mOptions; } |
476 | 474 | function getRevisionId() { return $this->mRevisionId; } |
477 | | - function getOutput() { return $this->mOutput; } |
478 | | - function nextLinkID() { return $this->mLinkID++; } |
479 | 475 | |
480 | 476 | function getFunctionLang() { |
481 | 477 | global $wgLang, $wgContLang; |
— | — | @@ -553,7 +549,7 @@ |
554 | 550 | $text = $inside; |
555 | 551 | $tail = null; |
556 | 552 | } else { |
557 | | - if( $element === '!--' ) { |
| 553 | + if( $element == '!--' ) { |
558 | 554 | $end = '/(-->)/'; |
559 | 555 | } else { |
560 | 556 | $end = "/(<\\/$element\\s*>)/i"; |
— | — | @@ -662,9 +658,9 @@ |
663 | 659 | ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>'. |
664 | 660 | '<head><title>test</title></head><body>'.$text.'</body></html>'; |
665 | 661 | if( $wgTidyInternal ) { |
666 | | - $correctedtext = self::internalTidy( $wrappedtext ); |
| 662 | + $correctedtext = Parser::internalTidy( $wrappedtext ); |
667 | 663 | } else { |
668 | | - $correctedtext = self::externalTidy( $wrappedtext ); |
| 664 | + $correctedtext = Parser::externalTidy( $wrappedtext ); |
669 | 665 | } |
670 | 666 | if( is_null( $correctedtext ) ) { |
671 | 667 | wfDebug( "Tidy error detected!\n" ); |
— | — | @@ -681,7 +677,8 @@ |
682 | 678 | */ |
683 | 679 | function externalTidy( $text ) { |
684 | 680 | global $wgTidyConf, $wgTidyBin, $wgTidyOpts; |
685 | | - wfProfileIn( __METHOD__ ); |
| 681 | + $fname = 'Parser::externalTidy'; |
| 682 | + wfProfileIn( $fname ); |
686 | 683 | |
687 | 684 | $cleansource = ''; |
688 | 685 | $opts = ' -utf8'; |
— | — | @@ -710,7 +707,7 @@ |
711 | 708 | } |
712 | 709 | } |
713 | 710 | |
714 | | - wfProfileOut( __METHOD__ ); |
| 711 | + wfProfileOut( $fname ); |
715 | 712 | |
716 | 713 | if( $cleansource == '' && $text != '') { |
717 | 714 | // Some kind of error happened, so we couldn't get the corrected text. |
— | — | @@ -732,7 +729,8 @@ |
733 | 730 | */ |
734 | 731 | function internalTidy( $text ) { |
735 | 732 | global $wgTidyConf, $IP, $wgDebugTidy; |
736 | | - wfProfileIn( __METHOD__ ); |
| 733 | + $fname = 'Parser::internalTidy'; |
| 734 | + wfProfileIn( $fname ); |
737 | 735 | |
738 | 736 | $tidy = new tidy; |
739 | 737 | $tidy->parseString( $text, $wgTidyConf, 'utf8' ); |
— | — | @@ -750,7 +748,7 @@ |
751 | 749 | "\n-->"; |
752 | 750 | } |
753 | 751 | |
754 | | - wfProfileOut( __METHOD__ ); |
| 752 | + wfProfileOut( $fname ); |
755 | 753 | return $cleansource; |
756 | 754 | } |
757 | 755 | |
— | — | @@ -760,35 +758,34 @@ |
761 | 759 | * @private |
762 | 760 | */ |
763 | 761 | function doTableStuff ( $text ) { |
764 | | - wfProfileIn( __METHOD__ ); |
| 762 | + $fname = 'Parser::doTableStuff'; |
| 763 | + wfProfileIn( $fname ); |
765 | 764 | |
766 | | - $lines = StringUtils::explode( "\n", $text ); |
767 | | - $out = ''; |
| 765 | + $lines = explode ( "\n" , $text ); |
768 | 766 | $td_history = array (); // Is currently a td tag open? |
769 | 767 | $last_tag_history = array (); // Save history of last lag activated (td, th or caption) |
770 | 768 | $tr_history = array (); // Is currently a tr tag open? |
771 | 769 | $tr_attributes = array (); // history of tr attributes |
772 | 770 | $has_opened_tr = array(); // Did this table open a <tr> element? |
773 | 771 | $indent_level = 0; // indent level of the table |
| 772 | + foreach ( $lines as $key => $line ) |
| 773 | + { |
| 774 | + $line = trim ( $line ); |
774 | 775 | |
775 | | - foreach ( $lines as $outLine ) { |
776 | | - $line = trim( $outLine ); |
777 | | - |
778 | 776 | if( $line == '' ) { // empty line, go to next line |
779 | | - $out .= $outLine."\n"; |
780 | 777 | continue; |
781 | 778 | } |
782 | | - $first_character = $line[0]; |
| 779 | + $first_character = $line{0}; |
783 | 780 | $matches = array(); |
784 | 781 | |
785 | | - if ( preg_match( '/^(:*)\{\|(.*)$/', $line , $matches ) ) { |
| 782 | + if ( preg_match( '/^(:*)\{\|(.*)$/' , $line , $matches ) ) { |
786 | 783 | // First check if we are starting a new table |
787 | 784 | $indent_level = strlen( $matches[1] ); |
788 | 785 | |
789 | 786 | $attributes = $this->mStripState->unstripBoth( $matches[2] ); |
790 | 787 | $attributes = Sanitizer::fixTagAttributes ( $attributes , 'table' ); |
791 | 788 | |
792 | | - $outLine = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>"; |
| 789 | + $lines[$key] = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>"; |
793 | 790 | array_push ( $td_history , false ); |
794 | 791 | array_push ( $last_tag_history , '' ); |
795 | 792 | array_push ( $tr_history , false ); |
— | — | @@ -796,9 +793,8 @@ |
797 | 794 | array_push ( $has_opened_tr , false ); |
798 | 795 | } else if ( count ( $td_history ) == 0 ) { |
799 | 796 | // Don't do any of the following |
800 | | - $out .= $outLine."\n"; |
801 | 797 | continue; |
802 | | - } else if ( substr ( $line , 0 , 2 ) === '|}' ) { |
| 798 | + } else if ( substr ( $line , 0 , 2 ) == '|}' ) { |
803 | 799 | // We are ending a table |
804 | 800 | $line = '</table>' . substr ( $line , 2 ); |
805 | 801 | $last_tag = array_pop ( $last_tag_history ); |
— | — | @@ -815,8 +811,8 @@ |
816 | 812 | $line = "</{$last_tag}>{$line}"; |
817 | 813 | } |
818 | 814 | 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 ) == '|-' ) { |
821 | 817 | // Now we have a table row |
822 | 818 | $line = preg_replace( '#^\|-+#', '', $line ); |
823 | 819 | |
— | — | @@ -839,21 +835,21 @@ |
840 | 836 | $line = "</{$last_tag}>{$line}"; |
841 | 837 | } |
842 | 838 | |
843 | | - $outLine = $line; |
| 839 | + $lines[$key] = $line; |
844 | 840 | array_push ( $tr_history , false ); |
845 | 841 | array_push ( $td_history , false ); |
846 | 842 | array_push ( $last_tag_history , '' ); |
847 | 843 | } |
848 | | - else if ( $first_character === '|' || $first_character === '!' || substr ( $line , 0 , 2 ) === '|+' ) { |
| 844 | + else if ( $first_character == '|' || $first_character == '!' || substr ( $line , 0 , 2 ) == '|+' ) { |
849 | 845 | // This might be cell elements, td, th or captions |
850 | | - if ( substr ( $line , 0 , 2 ) === '|+' ) { |
| 846 | + if ( substr ( $line , 0 , 2 ) == '|+' ) { |
851 | 847 | $first_character = '+'; |
852 | 848 | $line = substr ( $line , 1 ); |
853 | 849 | } |
854 | 850 | |
855 | 851 | $line = substr ( $line , 1 ); |
856 | 852 | |
857 | | - if ( $first_character === '!' ) { |
| 853 | + if ( $first_character == '!' ) { |
858 | 854 | $line = str_replace ( '!!' , '||' , $line ); |
859 | 855 | } |
860 | 856 | |
— | — | @@ -863,13 +859,13 @@ |
864 | 860 | // attribute values containing literal "||". |
865 | 861 | $cells = StringUtils::explodeMarkup( '||' , $line ); |
866 | 862 | |
867 | | - $outLine = ''; |
| 863 | + $lines[$key] = ''; |
868 | 864 | |
869 | 865 | // Loop through each table cell |
870 | 866 | foreach ( $cells as $cell ) |
871 | 867 | { |
872 | 868 | $previous = ''; |
873 | | - if ( $first_character !== '+' ) |
| 869 | + if ( $first_character != '+' ) |
874 | 870 | { |
875 | 871 | $tr_after = array_pop ( $tr_attributes ); |
876 | 872 | if ( !array_pop ( $tr_history ) ) { |
— | — | @@ -887,11 +883,11 @@ |
888 | 884 | $previous = "</{$last_tag}>{$previous}"; |
889 | 885 | } |
890 | 886 | |
891 | | - if ( $first_character === '|' ) { |
| 887 | + if ( $first_character == '|' ) { |
892 | 888 | $last_tag = 'td'; |
893 | | - } else if ( $first_character === '!' ) { |
| 889 | + } else if ( $first_character == '!' ) { |
894 | 890 | $last_tag = 'th'; |
895 | | - } else if ( $first_character === '+' ) { |
| 891 | + } else if ( $first_character == '+' ) { |
896 | 892 | $last_tag = 'caption'; |
897 | 893 | } else { |
898 | 894 | $last_tag = ''; |
— | — | @@ -914,42 +910,38 @@ |
915 | 911 | $cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}"; |
916 | 912 | } |
917 | 913 | |
918 | | - $outLine .= $cell; |
| 914 | + $lines[$key] .= $cell; |
919 | 915 | array_push ( $td_history , true ); |
920 | 916 | } |
921 | 917 | } |
922 | | - $out .= $outLine . "\n"; |
923 | 918 | } |
924 | 919 | |
925 | 920 | // Closing open td, tr && table |
926 | 921 | while ( count ( $td_history ) > 0 ) |
927 | 922 | { |
928 | 923 | if ( array_pop ( $td_history ) ) { |
929 | | - $out .= "</td>\n"; |
| 924 | + $lines[] = '</td>' ; |
930 | 925 | } |
931 | 926 | if ( array_pop ( $tr_history ) ) { |
932 | | - $out .= "</tr>\n"; |
| 927 | + $lines[] = '</tr>' ; |
933 | 928 | } |
934 | 929 | if ( !array_pop ( $has_opened_tr ) ) { |
935 | | - $out .= "<tr><td></td></tr>\n" ; |
| 930 | + $lines[] = "<tr><td></td></tr>" ; |
936 | 931 | } |
937 | 932 | |
938 | | - $out .= "</table>\n"; |
| 933 | + $lines[] = '</table>' ; |
939 | 934 | } |
940 | 935 | |
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 ) ; |
945 | 937 | |
946 | 938 | // 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 = ''; |
949 | 941 | } |
950 | 942 | |
951 | | - wfProfileOut( __METHOD__ ); |
| 943 | + wfProfileOut( $fname ); |
952 | 944 | |
953 | | - return $out; |
| 945 | + return $output; |
954 | 946 | } |
955 | 947 | |
956 | 948 | /** |
— | — | @@ -960,11 +952,12 @@ |
961 | 953 | */ |
962 | 954 | function internalParse( $text ) { |
963 | 955 | $isMain = true; |
964 | | - wfProfileIn( __METHOD__ ); |
| 956 | + $fname = 'Parser::internalParse'; |
| 957 | + wfProfileIn( $fname ); |
965 | 958 | |
966 | 959 | # Hook to suspend the parser in this state |
967 | 960 | if ( !wfRunHooks( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) { |
968 | | - wfProfileOut( __METHOD__ ); |
| 961 | + wfProfileOut( $fname ); |
969 | 962 | return $text ; |
970 | 963 | } |
971 | 964 | |
— | — | @@ -997,15 +990,14 @@ |
998 | 991 | $text = $this->doMagicLinks( $text ); |
999 | 992 | $text = $this->formatHeadings( $text, $isMain ); |
1000 | 993 | |
1001 | | - wfProfileOut( __METHOD__ ); |
| 994 | + wfProfileOut( $fname ); |
1002 | 995 | return $text; |
1003 | 996 | } |
1004 | 997 | |
1005 | 998 | /** |
1006 | 999 | * Replace special strings like "ISBN xxx" and "RFC xxx" with |
1007 | 1000 | * magic external links. |
1008 | | - * |
1009 | | - * DML |
| 1001 | + * |
1010 | 1002 | * @private |
1011 | 1003 | */ |
1012 | 1004 | function doMagicLinks( $text ) { |
— | — | @@ -1026,10 +1018,10 @@ |
1027 | 1019 | } |
1028 | 1020 | |
1029 | 1021 | function magicLinkCallback( $m ) { |
1030 | | - if ( substr( $m[0], 0, 1 ) === '<' ) { |
| 1022 | + if ( substr( $m[0], 0, 1 ) == '<' ) { |
1031 | 1023 | # Skip HTML element |
1032 | 1024 | return $m[0]; |
1033 | | - } elseif ( substr( $m[0], 0, 4 ) === 'ISBN' ) { |
| 1025 | + } elseif ( substr( $m[0], 0, 4 ) == 'ISBN' ) { |
1034 | 1026 | $isbn = $m[2]; |
1035 | 1027 | $num = strtr( $isbn, array( |
1036 | 1028 | '-' => '', |
— | — | @@ -1041,11 +1033,11 @@ |
1042 | 1034 | $titleObj->escapeLocalUrl() . |
1043 | 1035 | "\" class=\"internal\">ISBN $isbn</a>"; |
1044 | 1036 | } else { |
1045 | | - if ( substr( $m[0], 0, 3 ) === 'RFC' ) { |
| 1037 | + if ( substr( $m[0], 0, 3 ) == 'RFC' ) { |
1046 | 1038 | $keyword = 'RFC'; |
1047 | 1039 | $urlmsg = 'rfcurl'; |
1048 | 1040 | $id = $m[1]; |
1049 | | - } elseif ( substr( $m[0], 0, 4 ) === 'PMID' ) { |
| 1041 | + } elseif ( substr( $m[0], 0, 4 ) == 'PMID' ) { |
1050 | 1042 | $keyword = 'PMID'; |
1051 | 1043 | $urlmsg = 'pubmedurl'; |
1052 | 1044 | $id = $m[1]; |
— | — | @@ -1068,13 +1060,14 @@ |
1069 | 1061 | * @private |
1070 | 1062 | */ |
1071 | 1063 | function doHeadings( $text ) { |
1072 | | - wfProfileIn( __METHOD__ ); |
| 1064 | + $fname = 'Parser::doHeadings'; |
| 1065 | + wfProfileIn( $fname ); |
1073 | 1066 | for ( $i = 6; $i >= 1; --$i ) { |
1074 | 1067 | $h = str_repeat( '=', $i ); |
1075 | 1068 | $text = preg_replace( "/^$h(.+)$h\\s*$/m", |
1076 | 1069 | "<h$i>\\1</h$i>", $text ); |
1077 | 1070 | } |
1078 | | - wfProfileOut( __METHOD__ ); |
| 1071 | + wfProfileOut( $fname ); |
1079 | 1072 | return $text; |
1080 | 1073 | } |
1081 | 1074 | |
— | — | @@ -1084,14 +1077,15 @@ |
1085 | 1078 | * @return string the altered text |
1086 | 1079 | */ |
1087 | 1080 | function doAllQuotes( $text ) { |
1088 | | - wfProfileIn( __METHOD__ ); |
| 1081 | + $fname = 'Parser::doAllQuotes'; |
| 1082 | + wfProfileIn( $fname ); |
1089 | 1083 | $outtext = ''; |
1090 | | - $lines = StringUtils::explode( "\n", $text ); |
| 1084 | + $lines = explode( "\n", $text ); |
1091 | 1085 | foreach ( $lines as $line ) { |
1092 | | - $outtext .= $this->doQuotes( $line ) . "\n"; |
| 1086 | + $outtext .= $this->doQuotes ( $line ) . "\n"; |
1093 | 1087 | } |
1094 | 1088 | $outtext = substr($outtext, 0,-1); |
1095 | | - wfProfileOut( __METHOD__ ); |
| 1089 | + wfProfileOut( $fname ); |
1096 | 1090 | return $outtext; |
1097 | 1091 | } |
1098 | 1092 | |
— | — | @@ -1153,9 +1147,9 @@ |
1154 | 1148 | { |
1155 | 1149 | $x1 = substr ($arr[$i-1], -1); |
1156 | 1150 | $x2 = substr ($arr[$i-1], -2, 1); |
1157 | | - if ($x1 === ' ') { |
| 1151 | + if ($x1 == ' ') { |
1158 | 1152 | if ($firstspace == -1) $firstspace = $i; |
1159 | | - } else if ($x2 === ' ') { |
| 1153 | + } else if ($x2 == ' ') { |
1160 | 1154 | if ($firstsingleletterword == -1) $firstsingleletterword = $i; |
1161 | 1155 | } else { |
1162 | 1156 | if ($firstmultiletterword == -1) $firstmultiletterword = $i; |
— | — | @@ -1195,7 +1189,7 @@ |
1196 | 1190 | { |
1197 | 1191 | if (($i % 2) == 0) |
1198 | 1192 | { |
1199 | | - if ($state === 'both') |
| 1193 | + if ($state == 'both') |
1200 | 1194 | $buffer .= $r; |
1201 | 1195 | else |
1202 | 1196 | $output .= $r; |
— | — | @@ -1204,41 +1198,41 @@ |
1205 | 1199 | { |
1206 | 1200 | if (strlen ($r) == 2) |
1207 | 1201 | { |
1208 | | - if ($state === 'i') |
| 1202 | + if ($state == 'i') |
1209 | 1203 | { $output .= '</i>'; $state = ''; } |
1210 | | - else if ($state === 'bi') |
| 1204 | + else if ($state == 'bi') |
1211 | 1205 | { $output .= '</i>'; $state = 'b'; } |
1212 | | - else if ($state === 'ib') |
| 1206 | + else if ($state == 'ib') |
1213 | 1207 | { $output .= '</b></i><b>'; $state = 'b'; } |
1214 | | - else if ($state === 'both') |
| 1208 | + else if ($state == 'both') |
1215 | 1209 | { $output .= '<b><i>'.$buffer.'</i>'; $state = 'b'; } |
1216 | 1210 | else # $state can be 'b' or '' |
1217 | 1211 | { $output .= '<i>'; $state .= 'i'; } |
1218 | 1212 | } |
1219 | 1213 | else if (strlen ($r) == 3) |
1220 | 1214 | { |
1221 | | - if ($state === 'b') |
| 1215 | + if ($state == 'b') |
1222 | 1216 | { $output .= '</b>'; $state = ''; } |
1223 | | - else if ($state === 'bi') |
| 1217 | + else if ($state == 'bi') |
1224 | 1218 | { $output .= '</i></b><i>'; $state = 'i'; } |
1225 | | - else if ($state === 'ib') |
| 1219 | + else if ($state == 'ib') |
1226 | 1220 | { $output .= '</b>'; $state = 'i'; } |
1227 | | - else if ($state === 'both') |
| 1221 | + else if ($state == 'both') |
1228 | 1222 | { $output .= '<i><b>'.$buffer.'</b>'; $state = 'i'; } |
1229 | 1223 | else # $state can be 'i' or '' |
1230 | 1224 | { $output .= '<b>'; $state .= 'b'; } |
1231 | 1225 | } |
1232 | 1226 | else if (strlen ($r) == 5) |
1233 | 1227 | { |
1234 | | - if ($state === 'b') |
| 1228 | + if ($state == 'b') |
1235 | 1229 | { $output .= '</b><i>'; $state = 'i'; } |
1236 | | - else if ($state === 'i') |
| 1230 | + else if ($state == 'i') |
1237 | 1231 | { $output .= '</i><b>'; $state = 'b'; } |
1238 | | - else if ($state === 'bi') |
| 1232 | + else if ($state == 'bi') |
1239 | 1233 | { $output .= '</i></b>'; $state = ''; } |
1240 | | - else if ($state === 'ib') |
| 1234 | + else if ($state == 'ib') |
1241 | 1235 | { $output .= '</b></i>'; $state = ''; } |
1242 | | - else if ($state === 'both') |
| 1236 | + else if ($state == 'both') |
1243 | 1237 | { $output .= '<i><b>'.$buffer.'</b></i>'; $state = ''; } |
1244 | 1238 | else # ($state == '') |
1245 | 1239 | { $buffer = ''; $state = 'both'; } |
— | — | @@ -1247,21 +1241,21 @@ |
1248 | 1242 | $i++; |
1249 | 1243 | } |
1250 | 1244 | # Now close all remaining tags. Notice that the order is important. |
1251 | | - if ($state === 'b' || $state === 'ib') |
| 1245 | + if ($state == 'b' || $state == 'ib') |
1252 | 1246 | $output .= '</b>'; |
1253 | | - if ($state === 'i' || $state === 'bi' || $state === 'ib') |
| 1247 | + if ($state == 'i' || $state == 'bi' || $state == 'ib') |
1254 | 1248 | $output .= '</i>'; |
1255 | | - if ($state === 'bi') |
| 1249 | + if ($state == 'bi') |
1256 | 1250 | $output .= '</b>'; |
1257 | 1251 | # There might be lonely ''''', so make sure we have a buffer |
1258 | | - if ($state === 'both' && $buffer) |
| 1252 | + if ($state == 'both' && $buffer) |
1259 | 1253 | $output .= '<b><i>'.$buffer.'</i></b>'; |
1260 | 1254 | return $output; |
1261 | 1255 | } |
1262 | 1256 | } |
1263 | 1257 | |
1264 | 1258 | /** |
1265 | | - * Replace external links (REL) |
| 1259 | + * Replace external links |
1266 | 1260 | * |
1267 | 1261 | * Note: this is all very hackish and the order of execution matters a lot. |
1268 | 1262 | * Make sure to run maintenance/parserTests.php if you change this code. |
— | — | @@ -1270,7 +1264,8 @@ |
1271 | 1265 | */ |
1272 | 1266 | function replaceExternalLinks( $text ) { |
1273 | 1267 | global $wgContLang; |
1274 | | - wfProfileIn( __METHOD__ ); |
| 1268 | + $fname = 'Parser::replaceExternalLinks'; |
| 1269 | + wfProfileIn( $fname ); |
1275 | 1270 | |
1276 | 1271 | $sk = $this->mOptions->getSkin(); |
1277 | 1272 | |
— | — | @@ -1304,7 +1299,7 @@ |
1305 | 1300 | $dtrail = ''; |
1306 | 1301 | |
1307 | 1302 | # Set linktype for CSS - if URL==text, link is essentially free |
1308 | | - $linktype = ($text === $url) ? 'free' : 'text'; |
| 1303 | + $linktype = ($text == $url) ? 'free' : 'text'; |
1309 | 1304 | |
1310 | 1305 | # No link text, e.g. [http://domain.tld/some.link] |
1311 | 1306 | if ( $text == '' ) { |
— | — | @@ -1340,11 +1335,11 @@ |
1341 | 1336 | # Register link in the output object. |
1342 | 1337 | # Replace unnecessary URL escape codes with the referenced character |
1343 | 1338 | # This prevents spammers from hiding links from the filters |
1344 | | - $pasteurized = self::replaceUnusualEscapes( $url ); |
| 1339 | + $pasteurized = Parser::replaceUnusualEscapes( $url ); |
1345 | 1340 | $this->mOutput->addExternalLink( $pasteurized ); |
1346 | 1341 | } |
1347 | 1342 | |
1348 | | - wfProfileOut( __METHOD__ ); |
| 1343 | + wfProfileOut( $fname ); |
1349 | 1344 | return $s; |
1350 | 1345 | } |
1351 | 1346 | |
— | — | @@ -1354,7 +1349,8 @@ |
1355 | 1350 | */ |
1356 | 1351 | function replaceFreeExternalLinks( $text ) { |
1357 | 1352 | global $wgContLang; |
1358 | | - wfProfileIn( __METHOD__ ); |
| 1353 | + $fname = 'Parser::replaceFreeExternalLinks'; |
| 1354 | + wfProfileIn( $fname ); |
1359 | 1355 | |
1360 | 1356 | $bits = preg_split( '/(\b(?:' . wfUrlProtocols() . '))/S', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); |
1361 | 1357 | $s = array_shift( $bits ); |
— | — | @@ -1416,7 +1412,7 @@ |
1417 | 1413 | $text = $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free', $this->mTitle->getNamespace() ); |
1418 | 1414 | # Register it in the output object... |
1419 | 1415 | # Replace unnecessary URL escape codes with their equivalent characters |
1420 | | - $pasteurized = self::replaceUnusualEscapes( $url ); |
| 1416 | + $pasteurized = Parser::replaceUnusualEscapes( $url ); |
1421 | 1417 | $this->mOutput->addExternalLink( $pasteurized ); |
1422 | 1418 | } |
1423 | 1419 | $s .= $text . $trail; |
— | — | @@ -1424,7 +1420,7 @@ |
1425 | 1421 | $s .= $protocol . $remainder; |
1426 | 1422 | } |
1427 | 1423 | } |
1428 | | - wfProfileOut( __METHOD__ ); |
| 1424 | + wfProfileOut( $fname ); |
1429 | 1425 | return $s; |
1430 | 1426 | } |
1431 | 1427 | |
— | — | @@ -1440,7 +1436,7 @@ |
1441 | 1437 | */ |
1442 | 1438 | static function replaceUnusualEscapes( $url ) { |
1443 | 1439 | return preg_replace_callback( '/%[0-9A-Fa-f]{2}/', |
1444 | | - array( __CLASS__, 'replaceUnusualEscapesCallback' ), $url ); |
| 1440 | + array( 'Parser', 'replaceUnusualEscapesCallback' ), $url ); |
1445 | 1441 | } |
1446 | 1442 | |
1447 | 1443 | /** |
— | — | @@ -1484,48 +1480,35 @@ |
1485 | 1481 | |
1486 | 1482 | /** |
1487 | 1483 | * Process [[ ]] wikilinks |
1488 | | - * @return processed text |
1489 | 1484 | * |
1490 | 1485 | * @private |
1491 | 1486 | */ |
1492 | 1487 | 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 ) { |
1504 | 1488 | global $wgContLang; |
| 1489 | + static $fname = 'Parser::replaceInternalLinks' ; |
1505 | 1490 | |
1506 | | - wfProfileIn( __METHOD__ ); |
| 1491 | + wfProfileIn( $fname ); |
1507 | 1492 | |
1508 | | - wfProfileIn( __METHOD__.'-setup' ); |
1509 | | - static $tc = FALSE, $e1, $e1_img; |
| 1493 | + wfProfileIn( $fname.'-setup' ); |
| 1494 | + static $tc = FALSE; |
1510 | 1495 | # 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() . '#%'; } |
1518 | 1497 | |
1519 | 1498 | $sk = $this->mOptions->getSkin(); |
1520 | | - $holders = new LinkHolderArray( $this ); |
1521 | 1499 | |
1522 | 1500 | #split the entire text string on occurences of [[ |
1523 | | - $a = StringUtils::explode( '[[', ' ' . $s ); |
| 1501 | + $a = explode( '[[', ' ' . $s ); |
1524 | 1502 | #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 ); |
1528 | 1504 | $s = substr( $s, 1 ); |
1529 | 1505 | |
| 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 | + |
1530 | 1513 | $useLinkPrefixExtension = $wgContLang->linkPrefixExtension(); |
1531 | 1514 | $e2 = null; |
1532 | 1515 | if ( $useLinkPrefixExtension ) { |
— | — | @@ -1535,8 +1518,8 @@ |
1536 | 1519 | } |
1537 | 1520 | |
1538 | 1521 | if( is_null( $this->mTitle ) ) { |
1539 | | - wfProfileOut( __METHOD__.'-setup' ); |
1540 | | - wfProfileOut( __METHOD__ ); |
| 1522 | + wfProfileOut( $fname ); |
| 1523 | + wfProfileOut( $fname.'-setup' ); |
1541 | 1524 | throw new MWException( __METHOD__.": \$this->mTitle is null\n" ); |
1542 | 1525 | } |
1543 | 1526 | $nottalk = !$this->mTitle->isTalkPage(); |
— | — | @@ -1558,20 +1541,13 @@ |
1559 | 1542 | $selflink = array($this->mTitle->getPrefixedText()); |
1560 | 1543 | } |
1561 | 1544 | $useSubpages = $this->areSubpagesAllowed(); |
1562 | | - wfProfileOut( __METHOD__.'-setup' ); |
| 1545 | + wfProfileOut( $fname.'-setup' ); |
1563 | 1546 | |
1564 | 1547 | # 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]; |
1574 | 1550 | if ( $useLinkPrefixExtension ) { |
1575 | | - wfProfileIn( __METHOD__.'-prefixhandling' ); |
| 1551 | + wfProfileIn( $fname.'-prefixhandling' ); |
1576 | 1552 | if ( preg_match( $e2, $s, $m ) ) { |
1577 | 1553 | $prefix = $m[2]; |
1578 | 1554 | $s = $m[1]; |
— | — | @@ -1583,12 +1559,12 @@ |
1584 | 1560 | $prefix = $first_prefix; |
1585 | 1561 | $first_prefix = false; |
1586 | 1562 | } |
1587 | | - wfProfileOut( __METHOD__.'-prefixhandling' ); |
| 1563 | + wfProfileOut( $fname.'-prefixhandling' ); |
1588 | 1564 | } |
1589 | 1565 | |
1590 | 1566 | $might_be_img = false; |
1591 | 1567 | |
1592 | | - wfProfileIn( __METHOD__."-e1" ); |
| 1568 | + wfProfileIn( "$fname-e1" ); |
1593 | 1569 | if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt |
1594 | 1570 | $text = $m[2]; |
1595 | 1571 | # If we get a ] at the beginning of $m[3] that means we have a link that's something like: |
— | — | @@ -1622,18 +1598,18 @@ |
1623 | 1599 | $trail = ""; |
1624 | 1600 | } else { # Invalid form; output directly |
1625 | 1601 | $s .= $prefix . '[[' . $line ; |
1626 | | - wfProfileOut( __METHOD__."-e1" ); |
| 1602 | + wfProfileOut( "$fname-e1" ); |
1627 | 1603 | continue; |
1628 | 1604 | } |
1629 | | - wfProfileOut( __METHOD__."-e1" ); |
1630 | | - wfProfileIn( __METHOD__."-misc" ); |
| 1605 | + wfProfileOut( "$fname-e1" ); |
| 1606 | + wfProfileIn( "$fname-misc" ); |
1631 | 1607 | |
1632 | 1608 | # Don't allow internal links to pages containing |
1633 | 1609 | # PROTO: where PROTO is a valid URL protocol; these |
1634 | 1610 | # should be external links. |
1635 | 1611 | if (preg_match('/^\b(?:' . wfUrlProtocols() . ')/', $m[1])) { |
1636 | 1612 | $s .= $prefix . '[[' . $line ; |
1637 | | - wfProfileOut( __METHOD__."-misc" ); |
| 1613 | + wfProfileOut( "$fname-misc" ); |
1638 | 1614 | continue; |
1639 | 1615 | } |
1640 | 1616 | |
— | — | @@ -1644,36 +1620,33 @@ |
1645 | 1621 | $link = $m[1]; |
1646 | 1622 | } |
1647 | 1623 | |
1648 | | - $noforce = (substr($m[1], 0, 1) !== ':'); |
| 1624 | + $noforce = (substr($m[1], 0, 1) != ':'); |
1649 | 1625 | if (!$noforce) { |
1650 | 1626 | # Strip off leading ':' |
1651 | 1627 | $link = substr($link, 1); |
1652 | 1628 | } |
1653 | 1629 | |
1654 | | - wfProfileOut( __METHOD__."-misc" ); |
1655 | | - wfProfileIn( __METHOD__."-title" ); |
| 1630 | + wfProfileOut( "$fname-misc" ); |
| 1631 | + wfProfileIn( "$fname-title" ); |
1656 | 1632 | $nt = Title::newFromText( $this->mStripState->unstripNoWiki($link) ); |
1657 | 1633 | if( !$nt ) { |
1658 | 1634 | $s .= $prefix . '[[' . $line; |
1659 | | - wfProfileOut( __METHOD__."-title" ); |
| 1635 | + wfProfileOut( "$fname-title" ); |
1660 | 1636 | continue; |
1661 | 1637 | } |
1662 | 1638 | |
1663 | 1639 | $ns = $nt->getNamespace(); |
1664 | 1640 | $iw = $nt->getInterWiki(); |
1665 | | - wfProfileOut( __METHOD__."-title" ); |
| 1641 | + wfProfileOut( "$fname-title" ); |
1666 | 1642 | |
1667 | 1643 | if ($might_be_img) { # if this is actually an invalid link |
1668 | | - wfProfileIn( __METHOD__."-might_be_img" ); |
| 1644 | + wfProfileIn( "$fname-might_be_img" ); |
1669 | 1645 | if ($ns == NS_IMAGE && $noforce) { #but might be an image |
1670 | 1646 | $found = false; |
1671 | | - while ( true ) { |
| 1647 | + while (isset ($a[$k+1]) ) { |
1672 | 1648 | #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 ); |
1678 | 1651 | $m = explode( ']]', $next_line, 3 ); |
1679 | 1652 | if ( count( $m ) == 3 ) { |
1680 | 1653 | # the first ]] closes the inner link, the second the image |
— | — | @@ -1693,19 +1666,19 @@ |
1694 | 1667 | if ( !$found ) { |
1695 | 1668 | # we couldn't find the end of this imageLink, so output it raw |
1696 | 1669 | #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); |
1698 | 1671 | $s .= "{$prefix}[[$link|$text"; |
1699 | 1672 | # note: no $trail, because without an end, there *is* no trail |
1700 | | - wfProfileOut( __METHOD__."-might_be_img" ); |
| 1673 | + wfProfileOut( "$fname-might_be_img" ); |
1701 | 1674 | continue; |
1702 | 1675 | } |
1703 | 1676 | } else { #it's not an image, so output it raw |
1704 | 1677 | $s .= "{$prefix}[[$link|$text"; |
1705 | 1678 | # note: no $trail, because without an end, there *is* no trail |
1706 | | - wfProfileOut( __METHOD__."-might_be_img" ); |
| 1679 | + wfProfileOut( "$fname-might_be_img" ); |
1707 | 1680 | continue; |
1708 | 1681 | } |
1709 | | - wfProfileOut( __METHOD__."-might_be_img" ); |
| 1682 | + wfProfileOut( "$fname-might_be_img" ); |
1710 | 1683 | } |
1711 | 1684 | |
1712 | 1685 | $wasblank = ( '' == $text ); |
— | — | @@ -1715,36 +1688,41 @@ |
1716 | 1689 | if( $noforce ) { |
1717 | 1690 | |
1718 | 1691 | # Interwikis |
1719 | | - wfProfileIn( __METHOD__."-interwiki" ); |
| 1692 | + wfProfileIn( "$fname-interwiki" ); |
1720 | 1693 | if( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) { |
1721 | 1694 | $this->mOutput->addLanguageLink( $nt->getFullText() ); |
1722 | 1695 | $s = rtrim($s . $prefix); |
1723 | 1696 | $s .= trim($trail, "\n") == '' ? '': $prefix . $trail; |
1724 | | - wfProfileOut( __METHOD__."-interwiki" ); |
| 1697 | + wfProfileOut( "$fname-interwiki" ); |
1725 | 1698 | continue; |
1726 | 1699 | } |
1727 | | - wfProfileOut( __METHOD__."-interwiki" ); |
| 1700 | + wfProfileOut( "$fname-interwiki" ); |
1728 | 1701 | |
1729 | 1702 | if ( $ns == NS_IMAGE ) { |
1730 | | - wfProfileIn( __METHOD__."-image" ); |
| 1703 | + wfProfileIn( "$fname-image" ); |
1731 | 1704 | if ( !wfIsBadImage( $nt->getDBkey(), $this->mTitle ) ) { |
1732 | 1705 | # recursively parse links inside the image caption |
1733 | 1706 | # actually, this will parse them in any other parameters, too, |
1734 | 1707 | # but it might be hard to fix that, and it doesn't matter ATM |
1735 | 1708 | $text = $this->replaceExternalLinks($text); |
1736 | | - $holders->merge( $this->replaceInternalLinks2( $text ) ); |
| 1709 | + $text = $this->replaceInternalLinks($text); |
1737 | 1710 | |
1738 | 1711 | # 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() ); |
1740 | 1720 | } |
1741 | | - $this->mOutput->addImage( $nt->getDBkey() ); |
1742 | | - wfProfileOut( __METHOD__."-image" ); |
1743 | | - continue; |
| 1721 | + wfProfileOut( "$fname-image" ); |
1744 | 1722 | |
1745 | 1723 | } |
1746 | 1724 | |
1747 | 1725 | if ( $ns == NS_CATEGORY ) { |
1748 | | - wfProfileIn( __METHOD__."-category" ); |
| 1726 | + wfProfileIn( "$fname-category" ); |
1749 | 1727 | $s = rtrim($s . "\n"); # bug 87 |
1750 | 1728 | |
1751 | 1729 | if ( $wasblank ) { |
— | — | @@ -1763,7 +1741,7 @@ |
1764 | 1742 | */ |
1765 | 1743 | $s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail; |
1766 | 1744 | |
1767 | | - wfProfileOut( __METHOD__."-category" ); |
| 1745 | + wfProfileOut( "$fname-category" ); |
1768 | 1746 | continue; |
1769 | 1747 | } |
1770 | 1748 | } |
— | — | @@ -1794,7 +1772,7 @@ |
1795 | 1773 | if( SpecialPage::exists( $nt->getDBkey() ) ) { |
1796 | 1774 | $s .= $this->makeKnownLinkHolder( $nt, $text, '', $trail, $prefix ); |
1797 | 1775 | } else { |
1798 | | - $s .= $holders->makeHolder( $nt, $text, '', $trail, $prefix ); |
| 1776 | + $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix ); |
1799 | 1777 | } |
1800 | 1778 | continue; |
1801 | 1779 | } elseif( $ns == NS_IMAGE ) { |
— | — | @@ -1808,10 +1786,10 @@ |
1809 | 1787 | continue; |
1810 | 1788 | } |
1811 | 1789 | } |
1812 | | - $s .= $holders->makeHolder( $nt, $text, '', $trail, $prefix ); |
| 1790 | + $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix ); |
1813 | 1791 | } |
1814 | | - wfProfileOut( __METHOD__ ); |
1815 | | - return $holders; |
| 1792 | + wfProfileOut( $fname ); |
| 1793 | + return $s; |
1816 | 1794 | } |
1817 | 1795 | |
1818 | 1796 | /** |
— | — | @@ -1820,10 +1798,32 @@ |
1821 | 1799 | * parsing of interwiki links, and secondly to allow all existence checks and |
1822 | 1800 | * article length checks (for stub links) to be bundled into a single query. |
1823 | 1801 | * |
1824 | | - * @deprecated |
1825 | 1802 | */ |
1826 | 1803 | 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; |
1828 | 1828 | } |
1829 | 1829 | |
1830 | 1830 | /** |
— | — | @@ -1889,7 +1889,8 @@ |
1890 | 1890 | # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage |
1891 | 1891 | # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage |
1892 | 1892 | |
1893 | | - wfProfileIn( __METHOD__ ); |
| 1893 | + $fname = 'Parser::maybeDoSubpageLink'; |
| 1894 | + wfProfileIn( $fname ); |
1894 | 1895 | $ret = $target; # default return value is no change |
1895 | 1896 | |
1896 | 1897 | # Some namespaces don't allow subpages, |
— | — | @@ -1905,7 +1906,7 @@ |
1906 | 1907 | # bug 7425 |
1907 | 1908 | $target = trim( $target ); |
1908 | 1909 | # Look at the first character |
1909 | | - if( $target != '' && $target{0} === '/' ) { |
| 1910 | + if( $target != '' && $target{0} == '/' ) { |
1910 | 1911 | # / at end means we don't want the slash to be shown |
1911 | 1912 | $m = array(); |
1912 | 1913 | $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m ); |
— | — | @@ -1932,7 +1933,7 @@ |
1933 | 1934 | if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page |
1934 | 1935 | $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) ); |
1935 | 1936 | # / at the end means don't show full path |
1936 | | - if( substr( $nodotdot, -1, 1 ) === '/' ) { |
| 1937 | + if( substr( $nodotdot, -1, 1 ) == '/' ) { |
1937 | 1938 | $nodotdot = substr( $nodotdot, 0, -1 ); |
1938 | 1939 | if( '' === $text ) { |
1939 | 1940 | $text = $nodotdot . $suffix; |
— | — | @@ -1948,7 +1949,7 @@ |
1949 | 1950 | } |
1950 | 1951 | } |
1951 | 1952 | |
1952 | | - wfProfileOut( __METHOD__ ); |
| 1953 | + wfProfileOut( $fname ); |
1953 | 1954 | return $ret; |
1954 | 1955 | } |
1955 | 1956 | |
— | — | @@ -1984,10 +1985,10 @@ |
1985 | 1986 | /* private */ function openList( $char ) { |
1986 | 1987 | $result = $this->closeParagraph(); |
1987 | 1988 | |
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 ) { |
1992 | 1993 | $result .= '<dl><dt>'; |
1993 | 1994 | $this->mDTopen = true; |
1994 | 1995 | } |
— | — | @@ -1997,11 +1998,11 @@ |
1998 | 1999 | } |
1999 | 2000 | |
2000 | 2001 | /* 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 ) { |
2003 | 2004 | $close = '</dd>'; |
2004 | 2005 | if ( $this->mDTopen ) { $close = '</dt>'; } |
2005 | | - if ( ';' === $char ) { |
| 2006 | + if ( ';' == $char ) { |
2006 | 2007 | $this->mDTopen = true; |
2007 | 2008 | return $close . '<dt>'; |
2008 | 2009 | } else { |
— | — | @@ -2013,9 +2014,9 @@ |
2014 | 2015 | } |
2015 | 2016 | |
2016 | 2017 | /* 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 ) { |
2020 | 2021 | if ( $this->mDTopen ) { |
2021 | 2022 | $this->mDTopen = false; |
2022 | 2023 | $text = '</dt></dl>'; |
— | — | @@ -2029,59 +2030,56 @@ |
2030 | 2031 | /**#@-*/ |
2031 | 2032 | |
2032 | 2033 | /** |
2033 | | - * Make lists from lines starting with ':', '*', '#', etc. (DBL) |
| 2034 | + * Make lists from lines starting with ':', '*', '#', etc. |
2034 | 2035 | * |
2035 | 2036 | * @private |
2036 | 2037 | * @return string the lists rendered as HTML |
2037 | 2038 | */ |
2038 | 2039 | function doBlockLevels( $text, $linestart ) { |
2039 | | - wfProfileIn( __METHOD__ ); |
| 2040 | + $fname = 'Parser::doBlockLevels'; |
| 2041 | + wfProfileIn( $fname ); |
2040 | 2042 | |
2041 | 2043 | # Parsing through the text line by line. The main thing |
2042 | 2044 | # happening here is handling of block-level elements p, pre, |
2043 | 2045 | # and making lists from lines starting with * # : etc. |
2044 | 2046 | # |
2045 | | - $textLines = StringUtils::explode( "\n", $text ); |
| 2047 | + $textLines = explode( "\n", $text ); |
2046 | 2048 | |
2047 | 2049 | $lastPrefix = $output = ''; |
2048 | 2050 | $this->mDTopen = $inBlockElem = false; |
2049 | 2051 | $prefixLength = 0; |
2050 | 2052 | $paragraphStack = false; |
2051 | 2053 | |
| 2054 | + if ( !$linestart ) { |
| 2055 | + $output .= array_shift( $textLines ); |
| 2056 | + } |
2052 | 2057 | foreach ( $textLines as $oLine ) { |
2053 | | - # Fix up $linestart |
2054 | | - if ( !$linestart ) { |
2055 | | - $output .= $oLine; |
2056 | | - $linestart = true; |
2057 | | - continue; |
2058 | | - } |
2059 | | - |
2060 | 2058 | $lastPrefixLength = strlen( $lastPrefix ); |
2061 | 2059 | $preCloseMatch = preg_match('/<\\/pre/i', $oLine ); |
2062 | 2060 | $preOpenMatch = preg_match('/<pre/i', $oLine ); |
2063 | 2061 | if ( !$this->mInPre ) { |
2064 | 2062 | # Multiple prefixes may abut each other for nested lists. |
2065 | 2063 | $prefixLength = strspn( $oLine, '*#:;' ); |
2066 | | - $prefix = substr( $oLine, 0, $prefixLength ); |
| 2064 | + $pref = substr( $oLine, 0, $prefixLength ); |
2067 | 2065 | |
2068 | 2066 | # eh? |
2069 | | - $prefix2 = str_replace( ';', ':', $prefix ); |
| 2067 | + $pref2 = str_replace( ';', ':', $pref ); |
2070 | 2068 | $t = substr( $oLine, $prefixLength ); |
2071 | | - $this->mInPre = (bool)$preOpenMatch; |
| 2069 | + $this->mInPre = !empty($preOpenMatch); |
2072 | 2070 | } else { |
2073 | 2071 | # Don't interpret any other prefixes in preformatted text |
2074 | 2072 | $prefixLength = 0; |
2075 | | - $prefix = $prefix2 = ''; |
| 2073 | + $pref = $pref2 = ''; |
2076 | 2074 | $t = $oLine; |
2077 | 2075 | } |
2078 | 2076 | |
2079 | 2077 | # List generation |
2080 | | - if( $prefixLength && $lastPrefix === $prefix2 ) { |
| 2078 | + if( $prefixLength && 0 == strcmp( $lastPrefix, $pref2 ) ) { |
2081 | 2079 | # 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 ) ); |
2083 | 2081 | $paragraphStack = false; |
2084 | 2082 | |
2085 | | - if ( substr( $prefix, -1 ) === ';') { |
| 2083 | + if ( substr( $pref, -1 ) == ';') { |
2086 | 2084 | # The one nasty exception: definition lists work like this: |
2087 | 2085 | # ; title : definition text |
2088 | 2086 | # So we check for : in the remainder text to split up the |
— | — | @@ -2094,21 +2092,21 @@ |
2095 | 2093 | } |
2096 | 2094 | } elseif( $prefixLength || $lastPrefixLength ) { |
2097 | 2095 | # Either open or close a level... |
2098 | | - $commonPrefixLength = $this->getCommon( $prefix, $lastPrefix ); |
| 2096 | + $commonPrefixLength = $this->getCommon( $pref, $lastPrefix ); |
2099 | 2097 | $paragraphStack = false; |
2100 | 2098 | |
2101 | 2099 | while( $commonPrefixLength < $lastPrefixLength ) { |
2102 | | - $output .= $this->closeList( $lastPrefix[$lastPrefixLength-1] ); |
| 2100 | + $output .= $this->closeList( $lastPrefix{$lastPrefixLength-1} ); |
2103 | 2101 | --$lastPrefixLength; |
2104 | 2102 | } |
2105 | 2103 | if ( $prefixLength <= $commonPrefixLength && $commonPrefixLength > 0 ) { |
2106 | | - $output .= $this->nextItem( $prefix[$commonPrefixLength-1] ); |
| 2104 | + $output .= $this->nextItem( $pref{$commonPrefixLength-1} ); |
2107 | 2105 | } |
2108 | 2106 | while ( $prefixLength > $commonPrefixLength ) { |
2109 | | - $char = substr( $prefix, $commonPrefixLength, 1 ); |
| 2107 | + $char = substr( $pref, $commonPrefixLength, 1 ); |
2110 | 2108 | $output .= $this->openList( $char ); |
2111 | 2109 | |
2112 | | - if ( ';' === $char ) { |
| 2110 | + if ( ';' == $char ) { |
2113 | 2111 | # FIXME: This is dupe of code above |
2114 | 2112 | if ($this->findColonNoLinks($t, $term, $t2) !== false) { |
2115 | 2113 | $t = $t2; |
— | — | @@ -2117,10 +2115,10 @@ |
2118 | 2116 | } |
2119 | 2117 | ++$commonPrefixLength; |
2120 | 2118 | } |
2121 | | - $lastPrefix = $prefix2; |
| 2119 | + $lastPrefix = $pref2; |
2122 | 2120 | } |
2123 | 2121 | if( 0 == $prefixLength ) { |
2124 | | - wfProfileIn( __METHOD__."-paragraph" ); |
| 2122 | + wfProfileIn( "$fname-paragraph" ); |
2125 | 2123 | # No prefix (not in list)--go to paragraph mode |
2126 | 2124 | // XXX: use a stack for nestable elements like span, table and div |
2127 | 2125 | $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 @@ |
2141 | 2139 | $inBlockElem = true; |
2142 | 2140 | } |
2143 | 2141 | } 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) != '' ) ) { |
2145 | 2143 | // pre |
2146 | | - if ($this->mLastSection !== 'pre') { |
| 2144 | + if ($this->mLastSection != 'pre') { |
2147 | 2145 | $paragraphStack = false; |
2148 | 2146 | $output .= $this->closeParagraph().'<pre>'; |
2149 | 2147 | $this->mLastSection = 'pre'; |
— | — | @@ -2156,7 +2154,7 @@ |
2157 | 2155 | $paragraphStack = false; |
2158 | 2156 | $this->mLastSection = 'p'; |
2159 | 2157 | } else { |
2160 | | - if ($this->mLastSection !== 'p' ) { |
| 2158 | + if ($this->mLastSection != 'p' ) { |
2161 | 2159 | $output .= $this->closeParagraph(); |
2162 | 2160 | $this->mLastSection = ''; |
2163 | 2161 | $paragraphStack = '<p>'; |
— | — | @@ -2169,14 +2167,14 @@ |
2170 | 2168 | $output .= $paragraphStack; |
2171 | 2169 | $paragraphStack = false; |
2172 | 2170 | $this->mLastSection = 'p'; |
2173 | | - } else if ($this->mLastSection !== 'p') { |
| 2171 | + } else if ($this->mLastSection != 'p') { |
2174 | 2172 | $output .= $this->closeParagraph().'<p>'; |
2175 | 2173 | $this->mLastSection = 'p'; |
2176 | 2174 | } |
2177 | 2175 | } |
2178 | 2176 | } |
2179 | 2177 | } |
2180 | | - wfProfileOut( __METHOD__."-paragraph" ); |
| 2178 | + wfProfileOut( "$fname-paragraph" ); |
2181 | 2179 | } |
2182 | 2180 | // somewhere above we forget to get out of pre block (bug 785) |
2183 | 2181 | if($preCloseMatch && $this->mInPre) { |
— | — | @@ -2187,7 +2185,7 @@ |
2188 | 2186 | } |
2189 | 2187 | } |
2190 | 2188 | while ( $prefixLength ) { |
2191 | | - $output .= $this->closeList( $prefix2[$prefixLength-1] ); |
| 2189 | + $output .= $this->closeList( $pref2{$prefixLength-1} ); |
2192 | 2190 | --$prefixLength; |
2193 | 2191 | } |
2194 | 2192 | if ( '' != $this->mLastSection ) { |
— | — | @@ -2195,7 +2193,7 @@ |
2196 | 2194 | $this->mLastSection = ''; |
2197 | 2195 | } |
2198 | 2196 | |
2199 | | - wfProfileOut( __METHOD__ ); |
| 2197 | + wfProfileOut( $fname ); |
2200 | 2198 | return $output; |
2201 | 2199 | } |
2202 | 2200 | |
— | — | @@ -2208,12 +2206,13 @@ |
2209 | 2207 | * return string the position of the ':', or false if none found |
2210 | 2208 | */ |
2211 | 2209 | function findColonNoLinks($str, &$before, &$after) { |
2212 | | - wfProfileIn( __METHOD__ ); |
| 2210 | + $fname = 'Parser::findColonNoLinks'; |
| 2211 | + wfProfileIn( $fname ); |
2213 | 2212 | |
2214 | 2213 | $pos = strpos( $str, ':' ); |
2215 | 2214 | if( $pos === false ) { |
2216 | 2215 | // Nothing to find! |
2217 | | - wfProfileOut( __METHOD__ ); |
| 2216 | + wfProfileOut( $fname ); |
2218 | 2217 | return false; |
2219 | 2218 | } |
2220 | 2219 | |
— | — | @@ -2222,7 +2221,7 @@ |
2223 | 2222 | // Easy; no tag nesting to worry about |
2224 | 2223 | $before = substr( $str, 0, $pos ); |
2225 | 2224 | $after = substr( $str, $pos+1 ); |
2226 | | - wfProfileOut( __METHOD__ ); |
| 2225 | + wfProfileOut( $fname ); |
2227 | 2226 | return $pos; |
2228 | 2227 | } |
2229 | 2228 | |
— | — | @@ -2246,7 +2245,7 @@ |
2247 | 2246 | // We found it! |
2248 | 2247 | $before = substr( $str, 0, $i ); |
2249 | 2248 | $after = substr( $str, $i + 1 ); |
2250 | | - wfProfileOut( __METHOD__ ); |
| 2249 | + wfProfileOut( $fname ); |
2251 | 2250 | return $i; |
2252 | 2251 | } |
2253 | 2252 | // Embedded in a tag; don't break it. |
— | — | @@ -2256,7 +2255,7 @@ |
2257 | 2256 | $colon = strpos( $str, ':', $i ); |
2258 | 2257 | if( $colon === false ) { |
2259 | 2258 | // Nothing else interesting |
2260 | | - wfProfileOut( __METHOD__ ); |
| 2259 | + wfProfileOut( $fname ); |
2261 | 2260 | return false; |
2262 | 2261 | } |
2263 | 2262 | $lt = strpos( $str, '<', $i ); |
— | — | @@ -2265,7 +2264,7 @@ |
2266 | 2265 | // We found it! |
2267 | 2266 | $before = substr( $str, 0, $colon ); |
2268 | 2267 | $after = substr( $str, $colon + 1 ); |
2269 | | - wfProfileOut( __METHOD__ ); |
| 2268 | + wfProfileOut( $fname ); |
2270 | 2269 | return $i; |
2271 | 2270 | } |
2272 | 2271 | } |
— | — | @@ -2312,18 +2311,18 @@ |
2313 | 2312 | break; |
2314 | 2313 | case 3: // self::COLON_STATE_CLOSETAG: |
2315 | 2314 | // In a </tag> |
2316 | | - if( $c === ">" ) { |
| 2315 | + if( $c == ">" ) { |
2317 | 2316 | $stack--; |
2318 | 2317 | 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 ); |
2321 | 2320 | return false; |
2322 | 2321 | } |
2323 | 2322 | $state = self::COLON_STATE_TEXT; |
2324 | 2323 | } |
2325 | 2324 | break; |
2326 | 2325 | case self::COLON_STATE_TAGSLASH: |
2327 | | - if( $c === ">" ) { |
| 2326 | + if( $c == ">" ) { |
2328 | 2327 | // Yes, a self-closed tag <blah/> |
2329 | 2328 | $state = self::COLON_STATE_TEXT; |
2330 | 2329 | } else { |
— | — | @@ -2332,33 +2331,33 @@ |
2333 | 2332 | } |
2334 | 2333 | break; |
2335 | 2334 | case 5: // self::COLON_STATE_COMMENT: |
2336 | | - if( $c === "-" ) { |
| 2335 | + if( $c == "-" ) { |
2337 | 2336 | $state = self::COLON_STATE_COMMENTDASH; |
2338 | 2337 | } |
2339 | 2338 | break; |
2340 | 2339 | case self::COLON_STATE_COMMENTDASH: |
2341 | | - if( $c === "-" ) { |
| 2340 | + if( $c == "-" ) { |
2342 | 2341 | $state = self::COLON_STATE_COMMENTDASHDASH; |
2343 | 2342 | } else { |
2344 | 2343 | $state = self::COLON_STATE_COMMENT; |
2345 | 2344 | } |
2346 | 2345 | break; |
2347 | 2346 | case self::COLON_STATE_COMMENTDASHDASH: |
2348 | | - if( $c === ">" ) { |
| 2347 | + if( $c == ">" ) { |
2349 | 2348 | $state = self::COLON_STATE_TEXT; |
2350 | 2349 | } else { |
2351 | 2350 | $state = self::COLON_STATE_COMMENT; |
2352 | 2351 | } |
2353 | 2352 | break; |
2354 | 2353 | default: |
2355 | | - throw new MWException( "State machine error in " . __METHOD__ ); |
| 2354 | + throw new MWException( "State machine error in $fname" ); |
2356 | 2355 | } |
2357 | 2356 | } |
2358 | 2357 | 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" ); |
2360 | 2359 | return false; |
2361 | 2360 | } |
2362 | | - wfProfileOut( __METHOD__ ); |
| 2361 | + wfProfileOut( $fname ); |
2363 | 2362 | return false; |
2364 | 2363 | } |
2365 | 2364 | |
— | — | @@ -2588,11 +2587,12 @@ |
2589 | 2588 | * @private |
2590 | 2589 | */ |
2591 | 2590 | function initialiseVariables() { |
2592 | | - wfProfileIn( __METHOD__ ); |
| 2591 | + $fname = 'Parser::initialiseVariables'; |
| 2592 | + wfProfileIn( $fname ); |
2593 | 2593 | $variableIDs = MagicWord::getVariableIDs(); |
2594 | 2594 | |
2595 | 2595 | $this->mVariables = new MagicWordArray( $variableIDs ); |
2596 | | - wfProfileOut( __METHOD__ ); |
| 2596 | + wfProfileOut( $fname ); |
2597 | 2597 | } |
2598 | 2598 | |
2599 | 2599 | /** |
— | — | @@ -2661,7 +2661,8 @@ |
2662 | 2662 | return $text; |
2663 | 2663 | } |
2664 | 2664 | |
2665 | | - wfProfileIn( __METHOD__ ); |
| 2665 | + $fname = __METHOD__; |
| 2666 | + wfProfileIn( $fname ); |
2666 | 2667 | |
2667 | 2668 | if ( $frame === false ) { |
2668 | 2669 | $frame = $this->getPreprocessor()->newFrame(); |
— | — | @@ -2674,7 +2675,7 @@ |
2675 | 2676 | $flags = $argsOnly ? PPFrame::NO_TEMPLATES : 0; |
2676 | 2677 | $text = $frame->expand( $dom, $flags ); |
2677 | 2678 | |
2678 | | - wfProfileOut( __METHOD__ ); |
| 2679 | + wfProfileOut( $fname ); |
2679 | 2680 | return $text; |
2680 | 2681 | } |
2681 | 2682 | |
— | — | @@ -2737,7 +2738,8 @@ |
2738 | 2739 | */ |
2739 | 2740 | function braceSubstitution( $piece, $frame ) { |
2740 | 2741 | global $wgContLang, $wgLang, $wgAllowDisplayTitle, $wgNonincludableNamespaces; |
2741 | | - wfProfileIn( __METHOD__ ); |
| 2742 | + $fname = __METHOD__; |
| 2743 | + wfProfileIn( $fname ); |
2742 | 2744 | wfProfileIn( __METHOD__.'-setup' ); |
2743 | 2745 | |
2744 | 2746 | # Flags |
— | — | @@ -2924,7 +2926,7 @@ |
2925 | 2927 | } |
2926 | 2928 | } else if ( $wgNonincludableNamespaces && in_array( $title->getNamespace(), $wgNonincludableNamespaces ) ) { |
2927 | 2929 | $found = false; //access denied |
2928 | | - wfDebug( __METHOD__.": template inclusion denied for " . $title->getPrefixedDBkey() ); |
| 2930 | + wfDebug( "$fname: template inclusion denied for " . $title->getPrefixedDBkey() ); |
2929 | 2931 | } else { |
2930 | 2932 | list( $text, $title ) = $this->getTemplateDom( $title ); |
2931 | 2933 | if ( $text !== false ) { |
— | — | @@ -2958,7 +2960,7 @@ |
2959 | 2961 | # Recover the source wikitext and return it |
2960 | 2962 | if ( !$found ) { |
2961 | 2963 | $text = $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args ); |
2962 | | - wfProfileOut( __METHOD__ ); |
| 2964 | + wfProfileOut( $fname ); |
2963 | 2965 | return array( 'object' => $text ); |
2964 | 2966 | } |
2965 | 2967 | |
— | — | @@ -3017,7 +3019,7 @@ |
3018 | 3020 | $ret = array( 'text' => $text ); |
3019 | 3021 | } |
3020 | 3022 | |
3021 | | - wfProfileOut( __METHOD__ ); |
| 3023 | + wfProfileOut( $fname ); |
3022 | 3024 | return $ret; |
3023 | 3025 | } |
3024 | 3026 | |
— | — | @@ -3304,7 +3306,7 @@ |
3305 | 3307 | } |
3306 | 3308 | } |
3307 | 3309 | |
3308 | | - if ( $name === 'html' || $name === 'nowiki' ) { |
| 3310 | + if ( $name == 'html' || $name == 'nowiki' ) { |
3309 | 3311 | $this->mStripState->nowiki->setPair( $marker, $output ); |
3310 | 3312 | } else { |
3311 | 3313 | $this->mStripState->general->setPair( $marker, $output ); |
— | — | @@ -3560,7 +3562,12 @@ |
3561 | 3563 | # <!--LINK number--> |
3562 | 3564 | # turns into |
3563 | 3565 | # 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 ); |
3565 | 3572 | |
3566 | 3573 | # Strip out HTML (other than plain <sup> and <sub>: bug 8393) |
3567 | 3574 | $tocline = preg_replace( |
— | — | @@ -3636,7 +3643,7 @@ |
3637 | 3644 | $i = 0; |
3638 | 3645 | |
3639 | 3646 | foreach( $blocks as $block ) { |
3640 | | - if( $showEditLink && $headlineCount > 0 && $i == 0 && $block !== "\n" ) { |
| 3647 | + if( $showEditLink && $headlineCount > 0 && $i == 0 && $block != "\n" ) { |
3641 | 3648 | # This is the [edit] link that appears for the top block of text when |
3642 | 3649 | # section editing is enabled |
3643 | 3650 | |
— | — | @@ -3788,7 +3795,7 @@ |
3789 | 3796 | } else { |
3790 | 3797 | # Failed to validate; fall back to the default |
3791 | 3798 | $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" ); |
3793 | 3800 | } |
3794 | 3801 | } |
3795 | 3802 | |
— | — | @@ -3894,17 +3901,19 @@ |
3895 | 3902 | global $wgTitle; |
3896 | 3903 | static $executing = false; |
3897 | 3904 | |
| 3905 | + $fname = "Parser::transformMsg"; |
| 3906 | + |
3898 | 3907 | # Guard against infinite recursion |
3899 | 3908 | if ( $executing ) { |
3900 | 3909 | return $text; |
3901 | 3910 | } |
3902 | 3911 | $executing = true; |
3903 | 3912 | |
3904 | | - wfProfileIn(__METHOD__); |
| 3913 | + wfProfileIn($fname); |
3905 | 3914 | $text = $this->preprocess( $text, $wgTitle, $options ); |
3906 | 3915 | |
3907 | 3916 | $executing = false; |
3908 | | - wfProfileOut(__METHOD__); |
| 3917 | + wfProfileOut($fname); |
3909 | 3918 | return $text; |
3910 | 3919 | } |
3911 | 3920 | |
— | — | @@ -4001,7 +4010,7 @@ |
4002 | 4011 | # Add to function cache |
4003 | 4012 | $mw = MagicWord::get( $id ); |
4004 | 4013 | if( !$mw ) |
4005 | | - throw new MWException( __METHOD__.'() expecting a magic word identifier.' ); |
| 4014 | + throw new MWException( 'Parser::setFunctionHook() expecting a magic word identifier.' ); |
4006 | 4015 | |
4007 | 4016 | $synonyms = $mw->getSynonyms(); |
4008 | 4017 | $sensitive = intval( $mw->isCaseSensitive() ); |
— | — | @@ -4016,7 +4025,7 @@ |
4017 | 4026 | $syn = '#' . $syn; |
4018 | 4027 | } |
4019 | 4028 | # Remove trailing colon |
4020 | | - if ( substr( $syn, -1, 1 ) === ':' ) { |
| 4029 | + if ( substr( $syn, -1, 1 ) == ':' ) { |
4021 | 4030 | $syn = substr( $syn, 0, -1 ); |
4022 | 4031 | } |
4023 | 4032 | $this->mFunctionSynonyms[$sensitive][$syn] = $id; |
— | — | @@ -4037,9 +4046,266 @@ |
4038 | 4047 | * Replace <!--LINK--> link placeholders with actual links, in the buffer |
4039 | 4048 | * Placeholders created in Skin::makeLinkObj() |
4040 | 4049 | * Returns an array of link CSS classes, indexed by PDBK. |
| 4050 | + * $options is a bit field, RLH_FOR_UPDATE to select for update |
4041 | 4051 | */ |
4042 | 4052 | 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; |
4044 | 4310 | } |
4045 | 4311 | |
4046 | 4312 | /** |
— | — | @@ -4049,10 +4315,39 @@ |
4050 | 4316 | * @return string |
4051 | 4317 | */ |
4052 | 4318 | 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; |
4054 | 4329 | } |
4055 | 4330 | |
4056 | 4331 | /** |
| 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 | + /** |
4057 | 4352 | * Tag hook handler for 'pre'. |
4058 | 4353 | */ |
4059 | 4354 | function renderPreTag( $text, $attribs ) { |
— | — | @@ -4103,7 +4398,7 @@ |
4104 | 4399 | |
4105 | 4400 | wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) ); |
4106 | 4401 | |
4107 | | - $lines = StringUtils::explode( "\n", $text ); |
| 4402 | + $lines = explode( "\n", $text ); |
4108 | 4403 | foreach ( $lines as $line ) { |
4109 | 4404 | # match lines like these: |
4110 | 4405 | # Image:someimage.jpg|This is some image |
— | — | @@ -4116,7 +4411,7 @@ |
4117 | 4412 | |
4118 | 4413 | if ( strpos( $matches[0], '%' ) !== false ) |
4119 | 4414 | $matches[1] = urldecode( $matches[1] ); |
4120 | | - $tp = Title::newFromText( $matches[1], NS_IMAGE ); |
| 4415 | + $tp = Title::newFromText( $matches[1] ); |
4121 | 4416 | $nt =& $tp; |
4122 | 4417 | if( is_null( $nt ) ) { |
4123 | 4418 | # Bogus title. Ignore these so we don't bomb out later. |
— | — | @@ -4182,11 +4477,8 @@ |
4183 | 4478 | |
4184 | 4479 | /** |
4185 | 4480 | * Parse image options text and use it to make an image |
4186 | | - * @param Title $title |
4187 | | - * @param string $options |
4188 | | - * @param LinkHolderArray $holders |
4189 | 4481 | */ |
4190 | | - function makeImage( $title, $options, $holders = false ) { |
| 4482 | + function makeImage( $title, $options ) { |
4191 | 4483 | # Check if the options text is of the form "options|alt text" |
4192 | 4484 | # Options are: |
4193 | 4485 | # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang |
— | — | @@ -4209,7 +4501,7 @@ |
4210 | 4502 | # * bottom |
4211 | 4503 | # * text-bottom |
4212 | 4504 | |
4213 | | - $parts = StringUtils::explode( "|", $options ); |
| 4505 | + $parts = array_map( 'trim', explode( '|', $options) ); |
4214 | 4506 | $sk = $this->mOptions->getSkin(); |
4215 | 4507 | |
4216 | 4508 | # Give extensions a chance to select the file revision for us |
— | — | @@ -4231,14 +4523,13 @@ |
4232 | 4524 | $params = array( 'frame' => array(), 'handler' => array(), |
4233 | 4525 | 'horizAlign' => array(), 'vertAlign' => array() ); |
4234 | 4526 | foreach( $parts as $part ) { |
4235 | | - $part = trim( $part ); |
4236 | 4527 | list( $magicName, $value ) = $mwArray->matchVariableStartToEnd( $part ); |
4237 | 4528 | $validated = false; |
4238 | 4529 | if( isset( $paramMap[$magicName] ) ) { |
4239 | 4530 | list( $type, $paramName ) = $paramMap[$magicName]; |
4240 | 4531 | |
4241 | 4532 | // Special case; width and height come in one variable together |
4242 | | - if( $type === 'handler' && $paramName === 'width' ) { |
| 4533 | + if( $type == 'handler' && $paramName == 'width' ) { |
4243 | 4534 | $m = array(); |
4244 | 4535 | # (bug 13500) In both cases (width/height and width only), |
4245 | 4536 | # permit trailing "px" for backward compatibility. |
— | — | @@ -4261,7 +4552,7 @@ |
4262 | 4553 | } |
4263 | 4554 | } // else no validation -- bug 13436 |
4264 | 4555 | } else { |
4265 | | - if ( $type === 'handler' ) { |
| 4556 | + if ( $type == 'handler' ) { |
4266 | 4557 | # Validate handler parameter |
4267 | 4558 | $validated = $handler->validateParam( $paramName, $value ); |
4268 | 4559 | } else { |
— | — | @@ -4297,13 +4588,7 @@ |
4298 | 4589 | } |
4299 | 4590 | |
4300 | 4591 | # 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 ); |
4308 | 4593 | |
4309 | 4594 | # make sure there are no placeholders in thumbnail attributes |
4310 | 4595 | # that are later expanded to html- so expand them now and |
— | — | @@ -4406,7 +4691,7 @@ |
4407 | 4692 | $sectionParts = explode( '-', $section ); |
4408 | 4693 | $sectionIndex = array_pop( $sectionParts ); |
4409 | 4694 | foreach ( $sectionParts as $part ) { |
4410 | | - if ( $part === 'T' ) { |
| 4695 | + if ( $part == 'T' ) { |
4411 | 4696 | $flags |= self::PTD_FOR_INCLUSION; |
4412 | 4697 | } |
4413 | 4698 | } |
— | — | @@ -4423,14 +4708,14 @@ |
4424 | 4709 | $targetLevel = 1000; |
4425 | 4710 | } else { |
4426 | 4711 | while ( $node ) { |
4427 | | - if ( $node->getName() === 'h' ) { |
| 4712 | + if ( $node->getName() == 'h' ) { |
4428 | 4713 | $bits = $node->splitHeading(); |
4429 | 4714 | if ( $bits['i'] == $sectionIndex ) { |
4430 | 4715 | $targetLevel = $bits['level']; |
4431 | 4716 | break; |
4432 | 4717 | } |
4433 | 4718 | } |
4434 | | - if ( $mode === 'replace' ) { |
| 4719 | + if ( $mode == 'replace' ) { |
4435 | 4720 | $outText .= $frame->expand( $node, PPFrame::RECOVER_ORIG ); |
4436 | 4721 | } |
4437 | 4722 | $node = $node->getNextSibling(); |
— | — | @@ -4439,7 +4724,7 @@ |
4440 | 4725 | |
4441 | 4726 | if ( !$node ) { |
4442 | 4727 | // Not found |
4443 | | - if ( $mode === 'get' ) { |
| 4728 | + if ( $mode == 'get' ) { |
4444 | 4729 | return $newText; |
4445 | 4730 | } else { |
4446 | 4731 | return $text; |
— | — | @@ -4448,21 +4733,21 @@ |
4449 | 4734 | |
4450 | 4735 | // Find the end of the section, including nested sections |
4451 | 4736 | do { |
4452 | | - if ( $node->getName() === 'h' ) { |
| 4737 | + if ( $node->getName() == 'h' ) { |
4453 | 4738 | $bits = $node->splitHeading(); |
4454 | 4739 | $curLevel = $bits['level']; |
4455 | 4740 | if ( $bits['i'] != $sectionIndex && $curLevel <= $targetLevel ) { |
4456 | 4741 | break; |
4457 | 4742 | } |
4458 | 4743 | } |
4459 | | - if ( $mode === 'get' ) { |
| 4744 | + if ( $mode == 'get' ) { |
4460 | 4745 | $outText .= $frame->expand( $node, PPFrame::RECOVER_ORIG ); |
4461 | 4746 | } |
4462 | 4747 | $node = $node->getNextSibling(); |
4463 | 4748 | } while ( $node ); |
4464 | 4749 | |
4465 | 4750 | // Write out the remainder (in replace mode only) |
4466 | | - if ( $mode === 'replace' ) { |
| 4751 | + if ( $mode == 'replace' ) { |
4467 | 4752 | // Output the replacement text |
4468 | 4753 | // Add two newlines on -- trailing whitespace in $newText is conventionally |
4469 | 4754 | // stripped by the editor, so we need both newlines to restore the paragraph gap |
— | — | @@ -4692,7 +4977,7 @@ |
4693 | 4978 | do { |
4694 | 4979 | $oldText = $text; |
4695 | 4980 | $text = $this->general->replace( $text ); |
4696 | | - } while ( $text !== $oldText ); |
| 4981 | + } while ( $text != $oldText ); |
4697 | 4982 | wfProfileOut( __METHOD__ ); |
4698 | 4983 | return $text; |
4699 | 4984 | } |
— | — | @@ -4702,7 +4987,7 @@ |
4703 | 4988 | do { |
4704 | 4989 | $oldText = $text; |
4705 | 4990 | $text = $this->nowiki->replace( $text ); |
4706 | | - } while ( $text !== $oldText ); |
| 4991 | + } while ( $text != $oldText ); |
4707 | 4992 | wfProfileOut( __METHOD__ ); |
4708 | 4993 | return $text; |
4709 | 4994 | } |
— | — | @@ -4713,7 +4998,7 @@ |
4714 | 4999 | $oldText = $text; |
4715 | 5000 | $text = $this->general->replace( $text ); |
4716 | 5001 | $text = $this->nowiki->replace( $text ); |
4717 | | - } while ( $text !== $oldText ); |
| 5002 | + } while ( $text != $oldText ); |
4718 | 5003 | wfProfileOut( __METHOD__ ); |
4719 | 5004 | return $text; |
4720 | 5005 | } |
— | — | @@ -4727,7 +5012,7 @@ |
4728 | 5013 | var $output = ''; |
4729 | 5014 | |
4730 | 5015 | function replace( $matches ) { |
4731 | | - if ( substr( $matches[1], -1 ) === "\n" ) { |
| 5016 | + if ( substr( $matches[1], -1 ) == "\n" ) { |
4732 | 5017 | $this->output .= substr( $matches[1], 0, -1 ); |
4733 | 5018 | } else { |
4734 | 5019 | $this->output .= $matches[1]; |
Index: trunk/phase3/includes/parser/Parser_DiffTest.php |
— | — | @@ -69,17 +69,9 @@ |
70 | 70 | $lastResult = $currentResult; |
71 | 71 | } |
72 | 72 | 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 | | - } |
79 | 73 | throw new MWException( "Parser_DiffTest: results mismatch on call to $name\n" . |
80 | 74 | 'Arguments: ' . $this->formatArray( $args ) . "\n" . |
81 | | - 'Results: ' . $this->formatArray( $results ) . "\n" . |
82 | | - "Diff: $diff\n" |
83 | | - ); |
| 75 | + 'Results: ' . $this->formatArray( $results ) . "\n" ); |
84 | 76 | } |
85 | 77 | return $lastResult; |
86 | 78 | } |
Index: trunk/phase3/includes/Title.php |
— | — | @@ -410,12 +410,6 @@ |
411 | 411 | global $wgInterwikiCache, $wgContLang; |
412 | 412 | $fname = 'Title::getInterwikiLink'; |
413 | 413 | |
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 | | - |
420 | 414 | $key = $wgContLang->lc( $key ); |
421 | 415 | |
422 | 416 | $k = wfMemcKey( 'interwiki', $key ); |
Index: trunk/phase3/languages/LanguageConverter.php |
— | — | @@ -435,9 +435,8 @@ |
436 | 436 | if ($isTitle) return $this->convertTitle($text); |
437 | 437 | |
438 | 438 | $plang = $this->getPreferredVariant(); |
439 | | - $tarray = StringUtils::explode($this->mMarkup['end'], $text); |
| 439 | + $tarray = explode($this->mMarkup['end'], $text); |
440 | 440 | $text = ''; |
441 | | - $lastDelim = false; |
442 | 441 | foreach($tarray as $txt) { |
443 | 442 | $marked = explode($this->mMarkup['begin'], $txt, 2); |
444 | 443 | |
— | — | @@ -453,17 +452,8 @@ |
454 | 453 | |
455 | 454 | $text .= $crule->getDisplay(); |
456 | 455 | $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; |
462 | 456 | } |
463 | 457 | } |
464 | | - if ( $lastDelim ) { |
465 | | - // Remove the last delimiter (wasn't real) |
466 | | - $text = substr( $text, 0, -strlen( $this->mMarkup['end'] ) ); |
467 | | - } |
468 | 458 | |
469 | 459 | return $text; |
470 | 460 | } |
Index: trunk/phase3/languages/Language.php |
— | — | @@ -177,15 +177,6 @@ |
178 | 178 | } |
179 | 179 | |
180 | 180 | /** |
181 | | - * Reduce memory usage |
182 | | - */ |
183 | | - function __destruct() { |
184 | | - foreach ( $this as $name => $value ) { |
185 | | - unset( $this->$name ); |
186 | | - } |
187 | | - } |
188 | | - |
189 | | - /** |
190 | 181 | * Hook which will be called if this is the content language. |
191 | 182 | * Descendants can use this to register hook functions or modify globals |
192 | 183 | */ |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -94,7 +94,6 @@ |
95 | 95 | * HTML entities like now work (are not escaped) in edit summaries. |
96 | 96 | * (bug 13815) In the comment for page moves, use the colon-separator message |
97 | 97 | instead of a hardcoded colon. |
98 | | -* Allow <gallery> to accept image names without an Image: prefix |
99 | 98 | |
100 | 99 | === Bug fixes in 1.14 === |
101 | 100 | |