Index: trunk/phase3/languages/LanguageConverter.php |
— | — | @@ -12,9 +12,7 @@ |
13 | 13 | var $mMainLanguageCode; |
14 | 14 | var $mVariants, $mVariantFallbacks; |
15 | 15 | var $mTablesLoaded = false; |
16 | | - var $mUseFss = false; |
17 | 16 | var $mTables; |
18 | | - var $mFssObjects; |
19 | 17 | var $mTitleDisplay=''; |
20 | 18 | var $mDoTitleConvert=true, $mDoContentConvert=true; |
21 | 19 | var $mCacheKey; |
— | — | @@ -49,9 +47,6 @@ |
50 | 48 | $this->mMarkup = array_merge($m, $markup); |
51 | 49 | $f = array('A'=>'A', 'T'=>'T'); |
52 | 50 | $this->mFlags = array_merge($f, $flags); |
53 | | - if ( function_exists( 'fss_prep_replace' ) ) { |
54 | | - $this->mUseFss = true; |
55 | | - } |
56 | 51 | } |
57 | 52 | |
58 | 53 | /** |
— | — | @@ -194,19 +189,12 @@ |
195 | 190 | * @return string Translated text |
196 | 191 | */ |
197 | 192 | function translate( $text, $variant ) { |
| 193 | + wfProfileIn( __METHOD__ ); |
198 | 194 | if( !$this->mTablesLoaded ) |
199 | 195 | $this->loadTables(); |
200 | | - if ( $this->mUseFss ) { |
201 | | - wfProfileIn( __METHOD__.'-fss' ); |
202 | | - $text = fss_exec_replace( $this->mFssObjects[$variant], $text ); |
203 | | - wfProfileOut( __METHOD__.'-fss' ); |
204 | | - return $text; |
205 | | - } else { |
206 | | - wfProfileIn( __METHOD__.'-strtr' ); |
207 | | - $text = strtr( $text, $this->mTables[$variant] ); |
208 | | - wfProfileOut( __METHOD__.'-strtr' ); |
209 | | - return $text; |
210 | | - } |
| 196 | + $text = $this->mTables[$variant]->replace( $text ); |
| 197 | + wfProfileOut( __METHOD__ ); |
| 198 | + return $text; |
211 | 199 | } |
212 | 200 | |
213 | 201 | /** |
— | — | @@ -407,13 +395,9 @@ |
408 | 396 | continue; |
409 | 397 | if(!array_key_exists($vto, $carray)) |
410 | 398 | continue; |
411 | | - $this->mTables[$vto][$carray[$vfrom]] = $carray[$vto]; |
412 | | - |
| 399 | + $this->mTables[$vto]->setPair($carray[$vfrom], $carray[$vto]); |
413 | 400 | } |
414 | 401 | } |
415 | | - if ( $this->mUseFss ) { |
416 | | - $this->generateFssObjects(); |
417 | | - } |
418 | 402 | } |
419 | 403 | } |
420 | 404 | else { |
— | — | @@ -557,8 +541,8 @@ |
558 | 542 | $this->mTables = $wgMemc->get( $this->mCacheKey ); |
559 | 543 | wfProfileOut( __METHOD__.'-cache' ); |
560 | 544 | } |
561 | | - if ( !$this->mTables ) { |
562 | | - wfProfileOut( __METHOD__.'-recache' ); |
| 545 | + if ( !$this->mTables || !isset( $this->mTables['VERSION 2'] ) ) { |
| 546 | + wfProfileIn( __METHOD__.'-recache' ); |
563 | 547 | // not in cache, or we need a fresh reload. |
564 | 548 | // we will first load the default tables |
565 | 549 | // then update them using things in MediaWiki:Zhconversiontable/* |
— | — | @@ -566,10 +550,11 @@ |
567 | 551 | $this->loadDefaultTables(); |
568 | 552 | foreach($this->mVariants as $var) { |
569 | 553 | $cached = $this->parseCachedTable($var); |
570 | | - $this->mTables[$var] = array_merge($this->mTables[$var], $cached); |
| 554 | + $this->mTables[$var]->mergeArray($cached); |
571 | 555 | } |
572 | 556 | |
573 | 557 | $this->postLoadTables(); |
| 558 | + $this->mTables['VERSION 2'] = true; |
574 | 559 | |
575 | 560 | if($this->lockCache()) { |
576 | 561 | $wgMemc->set($this->mCacheKey, $this->mTables, 43200); |
— | — | @@ -577,23 +562,9 @@ |
578 | 563 | } |
579 | 564 | wfProfileOut( __METHOD__.'-recache' ); |
580 | 565 | } |
581 | | - if ( $this->mUseFss ) { |
582 | | - wfProfileIn( __METHOD__.'-fss' ); |
583 | | - $this->generateFssObjects(); |
584 | | - wfProfileOut( __METHOD__.'-fss' ); |
585 | | - } |
586 | 566 | wfProfileOut( __METHOD__ ); |
587 | 567 | } |
588 | 568 | |
589 | | - /** |
590 | | - * Generate FSS objects. The FSS extension must be available. |
591 | | - */ |
592 | | - function generateFssObjects() { |
593 | | - foreach ( $this->mTables as $variant => $table ) { |
594 | | - $this->mFssObjects[$variant] = fss_prep_replace( $table ); |
595 | | - } |
596 | | - } |
597 | | - |
598 | 569 | /** |
599 | 570 | * Hook for post processig after conversion tables are loaded |
600 | 571 | * |
Index: trunk/phase3/languages/classes/LanguageSr.php |
— | — | @@ -53,12 +53,13 @@ |
54 | 54 | ); |
55 | 55 | |
56 | 56 | function loadDefaultTables() { |
57 | | - $this->mTables = array(); |
58 | | - $this->mTables['sr-ec'] = $this->mToCyrillics; |
59 | | - $this->mTables['sr-jc'] = $this->mToCyrillics; |
60 | | - $this->mTables['sr-el'] = $this->mToLatin; |
61 | | - $this->mTables['sr-jl'] = $this->mToLatin; |
62 | | - $this->mTables['sr'] = array(); |
| 57 | + $this->mTables = array( |
| 58 | + 'sr-ec' => new ReplacementArray( $this->mToCyrillics ), |
| 59 | + 'sr-jc' => new ReplacementArray( $this->mToCyrillics), |
| 60 | + 'sr-el' => new ReplacementArray( $this->mToLatin), |
| 61 | + 'sr-jl' => new ReplacementArray( $this->mToLatin), |
| 62 | + 'sr' => new ReplacementArray() |
| 63 | + ); |
63 | 64 | } |
64 | 65 | |
65 | 66 | /* rules should be defined as -{ekavian | iyekavian-} -or- |
— | — | @@ -139,7 +140,7 @@ |
140 | 141 | $matches = preg_split($reg, $text, -1, PREG_SPLIT_OFFSET_CAPTURE); |
141 | 142 | |
142 | 143 | $m = array_shift($matches); |
143 | | - $ret = strtr($m[0], $this->mTables[$toVariant]); |
| 144 | + $ret = $this->mTables[$toVariant]->replace( $m[0] ); |
144 | 145 | $mstart = $m[1]+strlen($m[0]); |
145 | 146 | foreach($matches as $m) { |
146 | 147 | $ret .= substr($text, $mstart, $m[1]-$mstart); |
— | — | @@ -149,8 +150,6 @@ |
150 | 151 | |
151 | 152 | return $ret; |
152 | 153 | } |
153 | | - |
154 | | - |
155 | 154 | } |
156 | 155 | |
157 | 156 | class LanguageSr extends LanguageSr_ec { |
Index: trunk/phase3/languages/classes/LanguageZh.php |
— | — | @@ -9,17 +9,18 @@ |
10 | 10 | class ZhConverter extends LanguageConverter { |
11 | 11 | function loadDefaultTables() { |
12 | 12 | require( "includes/ZhConversion.php" ); |
13 | | - $this->mTables = array(); |
14 | | - $this->mTables['zh-cn'] = $zh2CN; |
15 | | - $this->mTables['zh-tw'] = $zh2TW; |
16 | | - $this->mTables['zh-sg'] = array_merge($zh2CN, $zh2SG); |
17 | | - $this->mTables['zh-hk'] = array_merge($zh2TW, $zh2HK); |
18 | | - $this->mTables['zh'] = array(); |
| 13 | + $this->mTables = array( |
| 14 | + 'zh-cn' => new ReplacementArray( $zh2CN ), |
| 15 | + 'zh-tw' => new ReplacementArray( $zh2TW ), |
| 16 | + 'zh-sg' => new ReplacementArray( array_merge($zh2CN, $zh2SG) ), |
| 17 | + 'zh-hk' => new ReplacementArray( array_merge($zh2TW, $zh2HK) ), |
| 18 | + 'zh' => new ReplacementArray |
| 19 | + ); |
19 | 20 | } |
20 | 21 | |
21 | 22 | function postLoadTables() { |
22 | | - $this->mTables['zh-sg'] = array_merge($this->mTables['zh-cn'], $this->mTables['zh-sg']); |
23 | | - $this->mTables['zh-hk'] = array_merge($this->mTables['zh-tw'], $this->mTables['zh-hk']); |
| 23 | + $this->mTables['zh-sg']->merge( $this->mTables['zh-cn'] ); |
| 24 | + $this->mTables['zh-hk']->merge( $this->mTables['zh-tw'] ); |
24 | 25 | } |
25 | 26 | |
26 | 27 | /* there shouldn't be any latin text in Chinese conversion, so no need |
Index: trunk/phase3/languages/classes/LanguageKk.php |
— | — | @@ -89,11 +89,12 @@ |
90 | 90 | ); |
91 | 91 | |
92 | 92 | function loadDefaultTables() { |
93 | | - $this->mTables = array(); |
94 | | - $this->mTables['kk-kz'] = $this->mLatinToCyrillic; |
95 | | - $this->mTables['kk-tr'] = $this->mCyrillicToLatin; |
96 | | - $this->mTables['kk-cn'] = $this->mCyrillicToArabic; |
97 | | - $this->mTables['kk'] = array(); |
| 93 | + $this->mTables = array( |
| 94 | + 'kk-kz' => new ReplacementArray( $this->mLatinToCyrillic ), |
| 95 | + 'kk-tr' => new ReplacementArray( $this->mCyrillicToLatin ), |
| 96 | + 'kk-cn' => new ReplacementArray( $this->mCyrillicToArabic ), |
| 97 | + 'kk' => new ReplacementArray() |
| 98 | + ); |
98 | 99 | } |
99 | 100 | |
100 | 101 | /* |
Index: trunk/phase3/maintenance/namespace2sql.php |
— | — | @@ -6,8 +6,8 @@ |
7 | 7 | require_once( "commandLine.inc" ); |
8 | 8 | |
9 | 9 | for ($i = -2; $i < 16; ++$i) { |
10 | | - $nsname = wfStrencode( $wgLang->getNsText( $i ) ); |
11 | | - $dbname = wfStrencode( $wgDBname ); |
| 10 | + $nsname = mysql_escape_string( $wgLang->getNsText( $i ) ); |
| 11 | + $dbname = mysql_escape_string( $wgDBname ); |
12 | 12 | print "INSERT INTO ns_name(ns_db, ns_num, ns_name) VALUES('$dbname', $i, '$nsname');\n"; |
13 | 13 | } |
14 | 14 | |
Index: trunk/phase3/includes/SiteStatsUpdate.php |
— | — | @@ -1,92 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * See deferred.txt |
5 | | - * |
6 | | - * @package MediaWiki |
7 | | - */ |
8 | | - |
9 | | -/** |
10 | | - * |
11 | | - * @package MediaWiki |
12 | | - */ |
13 | | -class SiteStatsUpdate { |
14 | | - |
15 | | - var $mViews, $mEdits, $mGood, $mPages, $mUsers; |
16 | | - |
17 | | - function SiteStatsUpdate( $views, $edits, $good, $pages = 0, $users = 0 ) { |
18 | | - $this->mViews = $views; |
19 | | - $this->mEdits = $edits; |
20 | | - $this->mGood = $good; |
21 | | - $this->mPages = $pages; |
22 | | - $this->mUsers = $users; |
23 | | - } |
24 | | - |
25 | | - function appendUpdate( &$sql, $field, $delta ) { |
26 | | - if ( $delta ) { |
27 | | - if ( $sql ) { |
28 | | - $sql .= ','; |
29 | | - } |
30 | | - if ( $delta < 0 ) { |
31 | | - $sql .= "$field=$field-1"; |
32 | | - } else { |
33 | | - $sql .= "$field=$field+1"; |
34 | | - } |
35 | | - } |
36 | | - } |
37 | | - |
38 | | - function doUpdate() { |
39 | | - $fname = 'SiteStatsUpdate::doUpdate'; |
40 | | - $dbw =& wfGetDB( DB_MASTER ); |
41 | | - |
42 | | - # First retrieve the row just to find out which schema we're in |
43 | | - $row = $dbw->selectRow( 'site_stats', '*', false, $fname ); |
44 | | - |
45 | | - $updates = ''; |
46 | | - |
47 | | - $this->appendUpdate( $updates, 'ss_total_views', $this->mViews ); |
48 | | - $this->appendUpdate( $updates, 'ss_total_edits', $this->mEdits ); |
49 | | - $this->appendUpdate( $updates, 'ss_good_articles', $this->mGood ); |
50 | | - |
51 | | - if ( isset( $row->ss_total_pages ) ) { |
52 | | - # Update schema if required |
53 | | - if ( $row->ss_total_pages == -1 && !$this->mViews ) { |
54 | | - $dbr =& wfGetDB( DB_SLAVE, array( 'SpecialStatistics', 'vslow') ); |
55 | | - extract( $dbr->tableNames( 'page', 'user' ) ); |
56 | | - |
57 | | - $sql = "SELECT COUNT(page_namespace) AS total FROM $page"; |
58 | | - $res = $dbr->query( $sql, $fname ); |
59 | | - $pageRow = $dbr->fetchObject( $res ); |
60 | | - $pages = $pageRow->total + $this->mPages; |
61 | | - |
62 | | - $sql = "SELECT COUNT(user_id) AS total FROM $user"; |
63 | | - $res = $dbr->query( $sql, $fname ); |
64 | | - $userRow = $dbr->fetchObject( $res ); |
65 | | - $users = $userRow->total + $this->mUsers; |
66 | | - |
67 | | - if ( $updates ) { |
68 | | - $updates .= ','; |
69 | | - } |
70 | | - $updates .= "ss_total_pages=$pages, ss_users=$users"; |
71 | | - } else { |
72 | | - $this->appendUpdate( $updates, 'ss_total_pages', $this->mPages ); |
73 | | - $this->appendUpdate( $updates, 'ss_users', $this->mUsers ); |
74 | | - } |
75 | | - } |
76 | | - if ( $updates ) { |
77 | | - $site_stats = $dbw->tableName( 'site_stats' ); |
78 | | - $sql = $dbw->limitResultForUpdate("UPDATE $site_stats SET $updates", 1); |
79 | | - $dbw->begin(); |
80 | | - $dbw->query( $sql, $fname ); |
81 | | - $dbw->commit(); |
82 | | - } |
83 | | - |
84 | | - /* |
85 | | - global $wgDBname, $wgTitle; |
86 | | - if ( $this->mGood && $wgDBname == 'enwiki' ) { |
87 | | - $good = $dbw->selectField( 'site_stats', 'ss_good_articles', '', $fname ); |
88 | | - error_log( $good . ' ' . $wgTitle->getPrefixedDBkey() . "\n", 3, '/home/wikipedia/logs/million.log' ); |
89 | | - } |
90 | | - */ |
91 | | - } |
92 | | -} |
93 | | -?> |
Index: trunk/phase3/includes/MagicWord.php |
— | — | @@ -298,7 +298,7 @@ |
299 | 299 | * Replaces the word with something else |
300 | 300 | */ |
301 | 301 | function replace( $replacement, $subject, $limit=-1 ) { |
302 | | - $res = preg_replace( $this->getRegex(), wfRegexReplacement( $replacement ), $subject, $limit ); |
| 302 | + $res = preg_replace( $this->getRegex(), StringUtils::escapeRegexReplacement( $replacement ), $subject, $limit ); |
303 | 303 | $this->mModified = !($res === $subject); |
304 | 304 | return $res; |
305 | 305 | } |
Index: trunk/phase3/includes/SpecialStatistics.php |
— | — | @@ -15,40 +15,15 @@ |
16 | 16 | $action = $wgRequest->getVal( 'action' ); |
17 | 17 | |
18 | 18 | $dbr =& wfGetDB( DB_SLAVE ); |
19 | | - extract( $dbr->tableNames( 'page', 'site_stats', 'user', 'user_groups' ) ); |
| 19 | + extract( $dbr->tableNames( 'site_stats', 'user', 'user_groups' ) ); |
20 | 20 | |
21 | | - $row = $dbr->selectRow( 'site_stats', '*', false, $fname ); |
22 | | - $views = $row->ss_total_views; |
23 | | - $edits = $row->ss_total_edits; |
24 | | - $good = $row->ss_good_articles; |
25 | | - $images = $row->ss_images; |
| 21 | + $views = SiteStats::views(); |
| 22 | + $edits = SiteStats::edits(); |
| 23 | + $good = SiteStats::articles(); |
| 24 | + $images = SiteStats::images(); |
| 25 | + $total = SiteStats::pages(); |
| 26 | + $users = SiteStats::users(); |
26 | 27 | |
27 | | - # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS |
28 | | - if ( isset( $row->ss_total_pages ) && $row->ss_total_pages == -1 ) { |
29 | | - # Update schema |
30 | | - $u = new SiteStatsUpdate( 0, 0, 0 ); |
31 | | - $u->doUpdate(); |
32 | | - $row = $dbr->selectRow( 'site_stats', '*', false, $fname ); |
33 | | - } |
34 | | - |
35 | | - if ( isset( $row->ss_total_pages ) ) { |
36 | | - $total = $row->ss_total_pages; |
37 | | - } else { |
38 | | - $sql = "SELECT COUNT(page_namespace) AS total FROM $page"; |
39 | | - $res = $dbr->query( $sql, $fname ); |
40 | | - $pageRow = $dbr->fetchObject( $res ); |
41 | | - $total = $pageRow->total; |
42 | | - } |
43 | | - |
44 | | - if ( isset( $row->ss_users ) ) { |
45 | | - $users = $row->ss_users; |
46 | | - } else { |
47 | | - $sql = "SELECT MAX(user_id) AS total FROM $user"; |
48 | | - $res = $dbr->query( $sql, $fname ); |
49 | | - $userRow = $dbr->fetchObject( $res ); |
50 | | - $users = $userRow->total; |
51 | | - } |
52 | | - |
53 | 28 | $admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), $fname ); |
54 | 29 | $numJobs = $dbr->selectField( 'job', 'COUNT(*)', '', $fname ); |
55 | 30 | |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -86,7 +86,6 @@ |
87 | 87 | 'FileStore' => 'includes/FileStore.php', |
88 | 88 | 'FSException' => 'includes/FileStore.php', |
89 | 89 | 'FSTransaction' => 'includes/FileStore.php', |
90 | | - 'ReplacerCallback' => 'includes/GlobalFunctions.php', |
91 | 90 | 'HTMLForm' => 'includes/HTMLForm.php', |
92 | 91 | 'HistoryBlob' => 'includes/HistoryBlob.php', |
93 | 92 | 'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php', |
— | — | @@ -150,7 +149,8 @@ |
151 | 150 | 'SearchUpdate' => 'includes/SearchUpdate.php', |
152 | 151 | 'SearchUpdateMyISAM' => 'includes/SearchUpdate.php', |
153 | 152 | 'SiteConfiguration' => 'includes/SiteConfiguration.php', |
154 | | - 'SiteStatsUpdate' => 'includes/SiteStatsUpdate.php', |
| 153 | + 'SiteStats' => 'includes/SiteStats.php', |
| 154 | + 'SiteStatsUpdate' => 'includes/SiteStats.php', |
155 | 155 | 'Skin' => 'includes/Skin.php', |
156 | 156 | 'MediaWiki_I18N' => 'includes/SkinTemplate.php', |
157 | 157 | 'SkinTemplate' => 'includes/SkinTemplate.php', |
— | — | @@ -215,6 +215,12 @@ |
216 | 216 | 'WantedPagesPage' => 'includes/SpecialWantedpages.php', |
217 | 217 | 'WhatLinksHerePage' => 'includes/SpecialWhatlinkshere.php', |
218 | 218 | 'SquidUpdate' => 'includes/SquidUpdate.php', |
| 219 | + 'ReplacementArray' => 'includes/StringUtils.php', |
| 220 | + 'Replacer' => 'includes/StringUtils.php', |
| 221 | + 'RegexlikeReplacer' => 'includes/StringUtils.php', |
| 222 | + 'DoubleReplacer' => 'includes/StringUtils.php', |
| 223 | + 'HashtableReplacer' => 'includes/StringUtils.php', |
| 224 | + 'StringUtils' => 'includes/StringUtils.php', |
219 | 225 | 'Title' => 'includes/Title.php', |
220 | 226 | 'User' => 'includes/User.php', |
221 | 227 | 'MailAddress' => 'includes/UserMailer.php', |
Index: trunk/phase3/includes/Database.php |
— | — | @@ -295,7 +295,7 @@ |
296 | 296 | * Turns on (false) or off (true) the automatic generation and sending |
297 | 297 | * of a "we're sorry, but there has been a database error" page on |
298 | 298 | * database errors. Default is on (false). When turned off, the |
299 | | - * code should use wfLastErrno() and wfLastError() to handle the |
| 299 | + * code should use lastErrno() and lastError() to handle the |
300 | 300 | * situation as appropriate. |
301 | 301 | */ |
302 | 302 | function ignoreErrors( $ignoreErrors = NULL ) { |
— | — | @@ -1296,7 +1296,7 @@ |
1297 | 1297 | } |
1298 | 1298 | |
1299 | 1299 | /** |
1300 | | - * Makes a wfStrencoded list from an array |
| 1300 | + * Makes an encoded list of strings from an array |
1301 | 1301 | * $mode: |
1302 | 1302 | * LIST_COMMA - comma separated, no field names |
1303 | 1303 | * LIST_AND - ANDed WHERE clause (without the WHERE) |
Index: trunk/phase3/includes/Linker.php |
— | — | @@ -959,7 +959,7 @@ |
960 | 960 | $match[1] = substr($match[1], 1); |
961 | 961 | $thelink = $this->makeLink( $match[1], $text, "", $trail ); |
962 | 962 | } |
963 | | - $comment = preg_replace( $linkRegexp, wfRegexReplacement( $thelink ), $comment, 1 ); |
| 963 | + $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 ); |
964 | 964 | } |
965 | 965 | wfProfileOut( __METHOD__ ); |
966 | 966 | return $comment; |
Index: trunk/phase3/includes/GlobalFunctions.php |
— | — | @@ -26,7 +26,6 @@ |
27 | 27 | $wgTotalEdits = -1; |
28 | 28 | |
29 | 29 | |
30 | | -require_once( 'DatabaseFunctions.php' ); |
31 | 30 | require_once( 'LogPage.php' ); |
32 | 31 | require_once( 'normal/UtfNormalUtil.php' ); |
33 | 32 | require_once( 'XmlFunctions.php' ); |
— | — | @@ -1736,16 +1735,10 @@ |
1737 | 1736 | } |
1738 | 1737 | |
1739 | 1738 | /** |
1740 | | - * Escape a string to make it suitable for inclusion in a preg_replace() |
1741 | | - * replacement parameter. |
1742 | | - * |
1743 | | - * @param string $string |
1744 | | - * @return string |
| 1739 | + * @deprecated use StringUtils::escapeRegexReplacement |
1745 | 1740 | */ |
1746 | 1741 | function wfRegexReplacement( $string ) { |
1747 | | - $string = str_replace( '\\', '\\\\', $string ); |
1748 | | - $string = str_replace( '$', '\\$', $string ); |
1749 | | - return $string; |
| 1742 | + return StringUtils::escapeRegexReplacement( $string ); |
1750 | 1743 | } |
1751 | 1744 | |
1752 | 1745 | /** |
— | — | @@ -1815,42 +1808,12 @@ |
1816 | 1809 | } |
1817 | 1810 | |
1818 | 1811 | /** |
1819 | | - * More or less "markup-safe" explode() |
1820 | | - * Ignores any instances of the separator inside <...> |
1821 | | - * @param string $separator |
1822 | | - * @param string $text |
1823 | | - * @return array |
| 1812 | + * @deprecated use StringUtils::explodeMarkup |
1824 | 1813 | */ |
1825 | 1814 | function wfExplodeMarkup( $separator, $text ) { |
1826 | | - $placeholder = "\x00"; |
1827 | | - |
1828 | | - // Just in case... |
1829 | | - $text = str_replace( $placeholder, '', $text ); |
1830 | | - |
1831 | | - // Trim stuff |
1832 | | - $replacer = new ReplacerCallback( $separator, $placeholder ); |
1833 | | - $cleaned = preg_replace_callback( '/(<.*?>)/', array( $replacer, 'go' ), $text ); |
1834 | | - |
1835 | | - $items = explode( $separator, $cleaned ); |
1836 | | - foreach( $items as $i => $str ) { |
1837 | | - $items[$i] = str_replace( $placeholder, $separator, $str ); |
1838 | | - } |
1839 | | - |
1840 | | - return $items; |
| 1815 | + return StringUtils::explodeMarkup( $separator, $text ); |
1841 | 1816 | } |
1842 | 1817 | |
1843 | | -class ReplacerCallback { |
1844 | | - function ReplacerCallback( $from, $to ) { |
1845 | | - $this->from = $from; |
1846 | | - $this->to = $to; |
1847 | | - } |
1848 | | - |
1849 | | - function go( $matches ) { |
1850 | | - return str_replace( $this->from, $this->to, $matches[1] ); |
1851 | | - } |
1852 | | -} |
1853 | | - |
1854 | | - |
1855 | 1818 | /** |
1856 | 1819 | * Convert an arbitrarily-long digit string from one numeric base |
1857 | 1820 | * to another, optionally zero-padding to a minimum column width. |
— | — | @@ -2074,4 +2037,20 @@ |
2075 | 2038 | } |
2076 | 2039 | } |
2077 | 2040 | |
| 2041 | +/* |
| 2042 | + * Get a Database object |
| 2043 | + * @param integer $db Index of the connection to get. May be DB_MASTER for the |
| 2044 | + * master (for write queries), DB_SLAVE for potentially lagged |
| 2045 | + * read queries, or an integer >= 0 for a particular server. |
| 2046 | + * |
| 2047 | + * @param array $groups Query groups. A list of group names that this query |
| 2048 | + * belongs to. |
| 2049 | + */ |
| 2050 | +function &wfGetDB( $db = DB_LAST, $groups = array() ) { |
| 2051 | + global $wgLoadBalancer; |
| 2052 | + $ret =& $wgLoadBalancer->getConnection( $db, true, $groups ); |
| 2053 | + return $ret; |
| 2054 | +} |
| 2055 | + |
| 2056 | + |
2078 | 2057 | ?> |
Index: trunk/phase3/includes/Parser.php |
— | — | @@ -97,7 +97,7 @@ |
98 | 98 | var $mTagHooks, $mFunctionHooks, $mFunctionSynonyms, $mVariables; |
99 | 99 | |
100 | 100 | # Cleared with clearState(): |
101 | | - var $mOutput, $mAutonumber, $mDTopen, $mStripState = array(); |
| 101 | + var $mOutput, $mAutonumber, $mDTopen, $mStripState; |
102 | 102 | var $mIncludeCount, $mArgStack, $mLastSection, $mInPre; |
103 | 103 | var $mInterwikiLinkHolders, $mLinkHolders, $mUniqPrefix; |
104 | 104 | var $mIncludeSizes; |
— | — | @@ -112,7 +112,9 @@ |
113 | 113 | $mTitle, // Title context, used for self-link rendering and similar things |
114 | 114 | $mOutputType, // Output type, one of the OT_xxx constants |
115 | 115 | $ot, // Shortcut alias, see setOutputType() |
116 | | - $mRevisionId; // ID to display in {{REVISIONID}} tags |
| 116 | + $mRevisionId, // ID to display in {{REVISIONID}} tags |
| 117 | + $mRevisionTimestamp, // The timestamp of the specified revision ID |
| 118 | + $mRevIdForTs; // The revision ID which was used to fetch the timestamp |
117 | 119 | |
118 | 120 | /**#@-*/ |
119 | 121 | |
— | — | @@ -174,7 +176,6 @@ |
175 | 177 | } |
176 | 178 | |
177 | 179 | $this->initialiseVariables(); |
178 | | - |
179 | 180 | $this->mFirstCall = false; |
180 | 181 | wfProfileOut( __METHOD__ ); |
181 | 182 | } |
— | — | @@ -194,7 +195,7 @@ |
195 | 196 | $this->mLastSection = ''; |
196 | 197 | $this->mDTopen = false; |
197 | 198 | $this->mIncludeCount = array(); |
198 | | - $this->mStripState = array(); |
| 199 | + $this->mStripState = new StripState; |
199 | 200 | $this->mArgStack = array(); |
200 | 201 | $this->mInPre = false; |
201 | 202 | $this->mInterwikiLinkHolders = array( |
— | — | @@ -208,8 +209,8 @@ |
209 | 210 | 'texts' => array(), |
210 | 211 | 'titles' => array() |
211 | 212 | ); |
212 | | - $this->mRevisionId = null; |
213 | | - |
| 213 | + $this->mRevisionTimestamp = $this->mRevisionId = null; |
| 214 | + |
214 | 215 | /** |
215 | 216 | * Prefix for temporary replacement strings for the multipass parser. |
216 | 217 | * \x07 should never appear in input as it's disallowed in XML. |
— | — | @@ -286,23 +287,18 @@ |
287 | 288 | $this->mOptions = $options; |
288 | 289 | $this->mTitle =& $title; |
289 | 290 | $oldRevisionId = $this->mRevisionId; |
| 291 | + $oldRevisionTimestamp = $this->mRevisionTimestamp; |
290 | 292 | if( $revid !== null ) { |
291 | 293 | $this->mRevisionId = $revid; |
| 294 | + $this->mRevisionTimestamp = null; |
292 | 295 | } |
293 | 296 | $this->setOutputType( OT_HTML ); |
294 | | - |
295 | | - //$text = $this->strip( $text, $this->mStripState ); |
296 | | - // VOODOO MAGIC FIX! Sometimes the above segfaults in PHP5. |
297 | | - $x =& $this->mStripState; |
298 | | - |
299 | | - wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$x ) ); |
300 | | - $text = $this->strip( $text, $x ); |
301 | | - wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$x ) ); |
302 | | - |
| 297 | + wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) ); |
| 298 | + $text = $this->strip( $text, $this->mStripState ); |
| 299 | + wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) ); |
303 | 300 | $text = $this->internalParse( $text ); |
| 301 | + $text = $this->mStripState->unstripGeneral( $text ); |
304 | 302 | |
305 | | - $text = $this->unstrip( $text, $this->mStripState ); |
306 | | - |
307 | 303 | # Clean up special characters, only run once, next-to-last before doBlockLevels |
308 | 304 | $fixtags = array( |
309 | 305 | # french spaces, last one Guillemet-left |
— | — | @@ -324,7 +320,7 @@ |
325 | 321 | # Side-effects: this calls $this->mOutput->setTitleText() |
326 | 322 | $text = $wgContLang->parserConvert( $text, $this ); |
327 | 323 | |
328 | | - $text = $this->unstripNoWiki( $text, $this->mStripState ); |
| 324 | + $text = $this->mStripState->unstripNoWiki( $text ); |
329 | 325 | |
330 | 326 | wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) ); |
331 | 327 | |
— | — | @@ -374,6 +370,7 @@ |
375 | 371 | } |
376 | 372 | $this->mOutput->setText( $text ); |
377 | 373 | $this->mRevisionId = $oldRevisionId; |
| 374 | + $this->mRevisionTimestamp = $oldRevisionTimestamp; |
378 | 375 | wfProfileOut( $fname ); |
379 | 376 | wfProfileOut( __METHOD__ ); |
380 | 377 | |
— | — | @@ -405,16 +402,14 @@ |
406 | 403 | $this->setOutputType( OT_PREPROCESS ); |
407 | 404 | $this->mOptions = $options; |
408 | 405 | $this->mTitle = $title; |
409 | | - $x =& $this->mStripState; |
410 | | - wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$x ) ); |
411 | | - $text = $this->strip( $text, $x ); |
412 | | - wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$x ) ); |
| 406 | + wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) ); |
| 407 | + $text = $this->strip( $text, $this->mStripState ); |
| 408 | + wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) ); |
413 | 409 | if ( $this->mOptions->getRemoveComments() ) { |
414 | 410 | $text = Sanitizer::removeHTMLcomments( $text ); |
415 | 411 | } |
416 | 412 | $text = $this->replaceVariables( $text ); |
417 | | - $text = $this->unstrip( $text, $x ); |
418 | | - $text = $this->unstripNowiki( $text, $x ); |
| 413 | + $text = $this->mStripState->unstripBoth( $text ); |
419 | 414 | wfProfileOut( __METHOD__ ); |
420 | 415 | return $text; |
421 | 416 | } |
— | — | @@ -521,8 +516,9 @@ |
522 | 517 | * Strips and renders nowiki, pre, math, hiero |
523 | 518 | * If $render is set, performs necessary rendering operations on plugins |
524 | 519 | * Returns the text, and fills an array with data needed in unstrip() |
525 | | - * If the $state is already a valid strip state, it adds to the state |
526 | 520 | * |
| 521 | + * @param StripState $state |
| 522 | + * |
527 | 523 | * @param bool $stripcomments when set, HTML comments <!-- like this --> |
528 | 524 | * will be stripped in addition to other tags. This is important |
529 | 525 | * for section editing, where these comments cause confusion when |
— | — | @@ -533,12 +529,12 @@ |
534 | 530 | * |
535 | 531 | * @private |
536 | 532 | */ |
537 | | - function strip( $text, &$state, $stripcomments = false , $dontstrip = array () ) { |
| 533 | + function strip( $text, $state, $stripcomments = false , $dontstrip = array () ) { |
538 | 534 | wfProfileIn( __METHOD__ ); |
539 | 535 | $render = ($this->mOutputType == OT_HTML); |
540 | 536 | |
541 | 537 | $uniq_prefix = $this->mUniqPrefix; |
542 | | - $commentState = array(); |
| 538 | + $commentState = new ReplacementArray; |
543 | 539 | |
544 | 540 | $elements = array_merge( |
545 | 541 | array( 'nowiki', 'gallery' ), |
— | — | @@ -583,7 +579,7 @@ |
584 | 580 | } |
585 | 581 | // Shouldn't happen otherwise. :) |
586 | 582 | case 'nowiki': |
587 | | - $output = wfEscapeHTMLTagsOnly( $content ); |
| 583 | + $output = Xml::escapeTagsOnly( $content ); |
588 | 584 | break; |
589 | 585 | case 'math': |
590 | 586 | $output = MathRenderer::renderMath( $content ); |
— | — | @@ -607,14 +603,14 @@ |
608 | 604 | |
609 | 605 | // Unstrip the output, because unstrip() is no longer recursive so |
610 | 606 | // it won't do it itself |
611 | | - $output = $this->unstrip( $output, $state ); |
| 607 | + $output = $state->unstripBoth( $output ); |
612 | 608 | |
613 | 609 | if( !$stripcomments && $element == '!--' ) { |
614 | | - $commentState[$marker] = $output; |
| 610 | + $commentState->setPair( $marker, $output ); |
615 | 611 | } elseif ( $element == 'html' || $element == 'nowiki' ) { |
616 | | - $state['nowiki'][$marker] = $output; |
| 612 | + $state->nowiki->setPair( $marker, $output ); |
617 | 613 | } else { |
618 | | - $state['general'][$marker] = $output; |
| 614 | + $state->general->setPair( $marker, $output ); |
619 | 615 | } |
620 | 616 | } |
621 | 617 | |
— | — | @@ -624,7 +620,7 @@ |
625 | 621 | # a comment.) |
626 | 622 | if ( !$stripcomments ) { |
627 | 623 | // Put them all back and forget them |
628 | | - $text = strtr( $text, $commentState ); |
| 624 | + $text = $commentState->replace( $text ); |
629 | 625 | } |
630 | 626 | |
631 | 627 | wfProfileOut( __METHOD__ ); |
— | — | @@ -636,35 +632,27 @@ |
637 | 633 | * |
638 | 634 | * always call unstripNoWiki() after this one |
639 | 635 | * @private |
| 636 | + * @deprecated use $this->mStripState->unstrip() |
640 | 637 | */ |
641 | 638 | function unstrip( $text, $state ) { |
642 | | - if ( !isset( $state['general'] ) ) { |
643 | | - return $text; |
644 | | - } |
645 | | - |
646 | | - wfProfileIn( __METHOD__ ); |
647 | | - # TODO: good candidate for FSS |
648 | | - $text = strtr( $text, $state['general'] ); |
649 | | - wfProfileOut( __METHOD__ ); |
650 | | - return $text; |
| 639 | + return $state->unstripGeneral( $text ); |
651 | 640 | } |
652 | 641 | |
653 | 642 | /** |
654 | 643 | * Always call this after unstrip() to preserve the order |
655 | 644 | * |
656 | 645 | * @private |
| 646 | + * @deprecated use $this->mStripState->unstrip() |
657 | 647 | */ |
658 | 648 | function unstripNoWiki( $text, $state ) { |
659 | | - if ( !isset( $state['nowiki'] ) ) { |
660 | | - return $text; |
661 | | - } |
| 649 | + return $state->unstripNoWiki( $text ); |
| 650 | + } |
662 | 651 | |
663 | | - wfProfileIn( __METHOD__ ); |
664 | | - # TODO: good candidate for FSS |
665 | | - $text = strtr( $text, $state['nowiki'] ); |
666 | | - wfProfileOut( __METHOD__ ); |
667 | | - |
668 | | - return $text; |
| 652 | + /** |
| 653 | + * @deprecated use $this->mStripState->unstripBoth() |
| 654 | + */ |
| 655 | + function unstripForHTML( $text ) { |
| 656 | + return $this->mStripState->unstripBoth( $text ); |
669 | 657 | } |
670 | 658 | |
671 | 659 | /** |
— | — | @@ -676,10 +664,7 @@ |
677 | 665 | */ |
678 | 666 | function insertStripItem( $text, &$state ) { |
679 | 667 | $rnd = $this->mUniqPrefix . '-item' . Parser::getRandomString(); |
680 | | - if ( !$state ) { |
681 | | - $state = array(); |
682 | | - } |
683 | | - $state['general'][$rnd] = $text; |
| 668 | + $state->general->setPair( $rnd, $text ); |
684 | 669 | return $rnd; |
685 | 670 | } |
686 | 671 | |
— | — | @@ -815,7 +800,7 @@ |
816 | 801 | if ( preg_match( '/^(:*)\{\|(.*)$/', $x, $matches ) ) { |
817 | 802 | $indent_level = strlen( $matches[1] ); |
818 | 803 | |
819 | | - $attributes = $this->unstripForHTML( $matches[2] ); |
| 804 | + $attributes = $this->mStripState->unstripBoth( $matches[2] ); |
820 | 805 | |
821 | 806 | $t[$k] = str_repeat( '<dl><dd>', $indent_level ) . |
822 | 807 | '<table' . Sanitizer::fixTagAttributes ( $attributes, 'table' ) . '>' ; |
— | — | @@ -849,7 +834,7 @@ |
850 | 835 | array_push ( $tr , false ) ; |
851 | 836 | array_push ( $td , false ) ; |
852 | 837 | array_push ( $ltd , '' ) ; |
853 | | - $attributes = $this->unstripForHTML( $x ); |
| 838 | + $attributes = $this->mStripState->unstripBoth( $x ); |
854 | 839 | array_push ( $ltr , Sanitizer::fixTagAttributes ( $attributes, 'tr' ) ) ; |
855 | 840 | } |
856 | 841 | else if ( '|' == $fc || '!' == $fc || '|+' == substr ( $x , 0 , 2 ) ) { # Caption |
— | — | @@ -865,7 +850,7 @@ |
866 | 851 | // FIXME: This can result in improper nesting of tags processed |
867 | 852 | // by earlier parser steps, but should avoid splitting up eg |
868 | 853 | // attribute values containing literal "||". |
869 | | - $after = wfExplodeMarkup( '||', $after ); |
| 854 | + $after = StringUtils::explodeMarkup( '||', $after ); |
870 | 855 | |
871 | 856 | $t[$k] = '' ; |
872 | 857 | |
— | — | @@ -906,7 +891,7 @@ |
907 | 892 | if ( count ( $y ) == 1 ) |
908 | 893 | $y = "{$z}<{$l}>{$y[0]}" ; |
909 | 894 | else { |
910 | | - $attributes = $this->unstripForHTML( $y[0] ); |
| 895 | + $attributes = $this->mStripState->unstripBoth( $y[0] ); |
911 | 896 | $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($attributes, $l).">{$y[1]}" ; |
912 | 897 | } |
913 | 898 | $t[$k] .= $y ; |
— | — | @@ -955,7 +940,7 @@ |
956 | 941 | # Remove <noinclude> tags and <includeonly> sections |
957 | 942 | $text = strtr( $text, array( '<onlyinclude>' => '' , '</onlyinclude>' => '' ) ); |
958 | 943 | $text = strtr( $text, array( '<noinclude>' => '', '</noinclude>' => '') ); |
959 | | - $text = preg_replace( '/<includeonly>.*?<\/includeonly>/s', '', $text ); |
| 944 | + $text = StringUtils::delimiterReplace( '<includeonly>', '</includeonly>', '', $text ); |
960 | 945 | |
961 | 946 | $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) ); |
962 | 947 | |
— | — | @@ -1611,7 +1596,7 @@ |
1612 | 1597 | |
1613 | 1598 | wfProfileOut( "$fname-misc" ); |
1614 | 1599 | wfProfileIn( "$fname-title" ); |
1615 | | - $nt = Title::newFromText( $this->unstripNoWiki($link, $this->mStripState) ); |
| 1600 | + $nt = Title::newFromText( $this->mStripState->unstripNoWiki($link) ); |
1616 | 1601 | if( !$nt ) { |
1617 | 1602 | $s .= $prefix . '[[' . $line; |
1618 | 1603 | wfProfileOut( "$fname-title" ); |
— | — | @@ -2434,15 +2419,15 @@ |
2435 | 2420 | case 'revisionid': |
2436 | 2421 | return $this->mRevisionId; |
2437 | 2422 | case 'revisionday': |
2438 | | - return intval( substr( wfRevisionTimestamp( $this->mRevisionId ), 6, 2 ) ); |
| 2423 | + return intval( substr( $this->getRevisionTimestamp(), 6, 2 ) ); |
2439 | 2424 | case 'revisionday2': |
2440 | | - return substr( wfRevisionTimestamp( $this->mRevisionId ), 6, 2 ); |
| 2425 | + return substr( $this->getRevisionTimestamp(), 6, 2 ); |
2441 | 2426 | case 'revisionmonth': |
2442 | | - return intval( substr( wfRevisionTimestamp( $this->mRevisionId ), 4, 2 ) ); |
| 2427 | + return intval( substr( $this->getRevisionTimestamp(), 4, 2 ) ); |
2443 | 2428 | case 'revisionyear': |
2444 | | - return substr( wfRevisionTimestamp( $this->mRevisionId ), 0, 4 ); |
| 2429 | + return substr( $this->getRevisionTimestamp(), 0, 4 ); |
2445 | 2430 | case 'revisiontimestamp': |
2446 | | - return wfRevisionTimestamp( $this->mRevisionId ); |
| 2431 | + return $this->getRevisionTimestamp(); |
2447 | 2432 | case 'namespace': |
2448 | 2433 | return str_replace('_',' ',$wgContLang->getNsText( $this->mTitle->getNamespace() ) ); |
2449 | 2434 | case 'namespacee': |
— | — | @@ -2484,15 +2469,15 @@ |
2485 | 2470 | case 'localdow': |
2486 | 2471 | return $varCache[$index] = $wgContLang->formatNum( $localDayOfWeek ); |
2487 | 2472 | case 'numberofarticles': |
2488 | | - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfArticles() ); |
| 2473 | + return $varCache[$index] = $wgContLang->formatNum( SiteStats::articles() ); |
2489 | 2474 | case 'numberoffiles': |
2490 | | - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfFiles() ); |
| 2475 | + return $varCache[$index] = $wgContLang->formatNum( SiteStats::images() ); |
2491 | 2476 | case 'numberofusers': |
2492 | | - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfUsers() ); |
| 2477 | + return $varCache[$index] = $wgContLang->formatNum( SiteStats::users() ); |
2493 | 2478 | case 'numberofpages': |
2494 | | - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfPages() ); |
| 2479 | + return $varCache[$index] = $wgContLang->formatNum( SiteStats::pages() ); |
2495 | 2480 | case 'numberofadmins': |
2496 | | - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfAdmins() ); |
| 2481 | + return $varCache[$index] = $wgContLang->formatNum( SiteStats::admins() ); |
2497 | 2482 | case 'currenttimestamp': |
2498 | 2483 | return $varCache[$index] = wfTimestampNow(); |
2499 | 2484 | case 'localtimestamp': |
— | — | @@ -3079,14 +3064,13 @@ |
3080 | 3065 | if ( !$noparse ) { |
3081 | 3066 | # If there are any <onlyinclude> tags, only include them |
3082 | 3067 | if ( in_string( '<onlyinclude>', $text ) && in_string( '</onlyinclude>', $text ) ) { |
3083 | | - $m = array(); |
3084 | | - preg_match_all( '/<onlyinclude>(.*?)\n?<\/onlyinclude>/s', $text, $m ); |
3085 | | - $text = ''; |
3086 | | - foreach ($m[1] as $piece) |
3087 | | - $text .= $piece; |
| 3068 | + $replacer = new OnlyIncludeReplacer; |
| 3069 | + StringUtils::delimiterReplaceCallback( '<onlyinclude>', '</onlyinclude>', |
| 3070 | + array( &$replacer, 'replace' ), $text ); |
| 3071 | + $text = $replacer->output; |
3088 | 3072 | } |
3089 | 3073 | # Remove <noinclude> sections and <includeonly> tags |
3090 | | - $text = preg_replace( '/<noinclude>.*?<\/noinclude>/s', '', $text ); |
| 3074 | + $text = StringUtils::delimiterReplace( '<noinclude>', '</noinclude>', '', $text ); |
3091 | 3075 | $text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) ); |
3092 | 3076 | |
3093 | 3077 | if( $this->ot['html'] || $this->ot['pre'] ) { |
— | — | @@ -3481,8 +3465,7 @@ |
3482 | 3466 | |
3483 | 3467 | # The canonized header is a version of the header text safe to use for links |
3484 | 3468 | # Avoid insertion of weird stuff like <math> by expanding the relevant sections |
3485 | | - $canonized_headline = $this->unstrip( $headline, $this->mStripState ); |
3486 | | - $canonized_headline = $this->unstripNoWiki( $canonized_headline, $this->mStripState ); |
| 3469 | + $canonized_headline = $this->mStripState->unstripBoth( $headline ); |
3487 | 3470 | |
3488 | 3471 | # Remove link placeholders by the link text. |
3489 | 3472 | # <!--LINK number--> |
— | — | @@ -3604,15 +3587,14 @@ |
3605 | 3588 | $this->clearState(); |
3606 | 3589 | } |
3607 | 3590 | |
3608 | | - $stripState = false; |
| 3591 | + $stripState = new StripState; |
3609 | 3592 | $pairs = array( |
3610 | 3593 | "\r\n" => "\n", |
3611 | 3594 | ); |
3612 | 3595 | $text = str_replace( array_keys( $pairs ), array_values( $pairs ), $text ); |
3613 | 3596 | $text = $this->strip( $text, $stripState, true, array( 'gallery' ) ); |
3614 | 3597 | $text = $this->pstPass2( $text, $stripState, $user ); |
3615 | | - $text = $this->unstrip( $text, $stripState ); |
3616 | | - $text = $this->unstripNoWiki( $text, $stripState ); |
| 3598 | + $text = $stripState->unstripBoth( $text ); |
3617 | 3599 | return $text; |
3618 | 3600 | } |
3619 | 3601 | |
— | — | @@ -3915,7 +3897,6 @@ |
3916 | 3898 | */ |
3917 | 3899 | function replaceLinkHolders( &$text, $options = 0 ) { |
3918 | 3900 | global $wgUser; |
3919 | | - global $wgOutputReplace; |
3920 | 3901 | global $wgContLang; |
3921 | 3902 | |
3922 | 3903 | $fname = 'Parser::replaceLinkHolders'; |
— | — | @@ -4095,7 +4076,7 @@ |
4096 | 4077 | |
4097 | 4078 | # Construct search and replace arrays |
4098 | 4079 | wfProfileIn( $fname.'-construct' ); |
4099 | | - $wgOutputReplace = array(); |
| 4080 | + $replacePairs = array(); |
4100 | 4081 | foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) { |
4101 | 4082 | $pdbk = $pdbks[$key]; |
4102 | 4083 | $searchkey = "<!--LINK $key-->"; |
— | — | @@ -4104,27 +4085,27 @@ |
4105 | 4086 | $linkCache->addBadLinkObj( $title ); |
4106 | 4087 | $colours[$pdbk] = 0; |
4107 | 4088 | $this->mOutput->addLink( $title, 0 ); |
4108 | | - $wgOutputReplace[$searchkey] = $sk->makeBrokenLinkObj( $title, |
| 4089 | + $replacePairs[$searchkey] = $sk->makeBrokenLinkObj( $title, |
4109 | 4090 | $this->mLinkHolders['texts'][$key], |
4110 | 4091 | $this->mLinkHolders['queries'][$key] ); |
4111 | 4092 | } elseif ( $colours[$pdbk] == 1 ) { |
4112 | | - $wgOutputReplace[$searchkey] = $sk->makeKnownLinkObj( $title, |
| 4093 | + $replacePairs[$searchkey] = $sk->makeKnownLinkObj( $title, |
4113 | 4094 | $this->mLinkHolders['texts'][$key], |
4114 | 4095 | $this->mLinkHolders['queries'][$key] ); |
4115 | 4096 | } elseif ( $colours[$pdbk] == 2 ) { |
4116 | | - $wgOutputReplace[$searchkey] = $sk->makeStubLinkObj( $title, |
| 4097 | + $replacePairs[$searchkey] = $sk->makeStubLinkObj( $title, |
4117 | 4098 | $this->mLinkHolders['texts'][$key], |
4118 | 4099 | $this->mLinkHolders['queries'][$key] ); |
4119 | 4100 | } |
4120 | 4101 | } |
| 4102 | + $replacer = new HashtableReplacer( $replacePairs, 1 ); |
4121 | 4103 | wfProfileOut( $fname.'-construct' ); |
4122 | 4104 | |
4123 | 4105 | # Do the thing |
4124 | 4106 | wfProfileIn( $fname.'-replace' ); |
4125 | | - |
4126 | 4107 | $text = preg_replace_callback( |
4127 | 4108 | '/(<!--LINK .*?-->)/', |
4128 | | - "wfOutputReplaceMatches", |
| 4109 | + $replacer->cb(), |
4129 | 4110 | $text); |
4130 | 4111 | |
4131 | 4112 | wfProfileOut( $fname.'-replace' ); |
— | — | @@ -4135,15 +4116,16 @@ |
4136 | 4117 | if ( !empty( $this->mInterwikiLinkHolders['texts'] ) ) { |
4137 | 4118 | wfProfileIn( $fname.'-interwiki' ); |
4138 | 4119 | # Make interwiki link HTML |
4139 | | - $wgOutputReplace = array(); |
| 4120 | + $replacePairs = array(); |
4140 | 4121 | foreach( $this->mInterwikiLinkHolders['texts'] as $key => $link ) { |
4141 | 4122 | $title = $this->mInterwikiLinkHolders['titles'][$key]; |
4142 | | - $wgOutputReplace[$key] = $sk->makeLinkObj( $title, $link ); |
| 4123 | + $replacePairs[$key] = $sk->makeLinkObj( $title, $link ); |
4143 | 4124 | } |
| 4125 | + $replacer = new HashtableReplacer( $replacePairs, 1 ); |
4144 | 4126 | |
4145 | 4127 | $text = preg_replace_callback( |
4146 | 4128 | '/<!--IWLINK (.*?)-->/', |
4147 | | - "wfOutputReplaceMatches", |
| 4129 | + $replacer->cb(), |
4148 | 4130 | $text ); |
4149 | 4131 | wfProfileOut( $fname.'-interwiki' ); |
4150 | 4132 | } |
— | — | @@ -4196,11 +4178,11 @@ |
4197 | 4179 | */ |
4198 | 4180 | function renderPreTag( $text, $attribs ) { |
4199 | 4181 | // Backwards-compatibility hack |
4200 | | - $content = preg_replace( '!<nowiki>(.*?)</nowiki>!is', '\\1', $text ); |
| 4182 | + $content = StringUtils::delimiterReplace( '<nowiki>', '</nowiki>', '$1', $text, 'i' ); |
4201 | 4183 | |
4202 | 4184 | $attribs = Sanitizer::validateTagAttributes( $attribs, 'pre' ); |
4203 | 4185 | return wfOpenElement( 'pre', $attribs ) . |
4204 | | - wfEscapeHTMLTagsOnly( $content ) . |
| 4186 | + Xml::escapeTagsOnly( $content ) . |
4205 | 4187 | '</pre>'; |
4206 | 4188 | } |
4207 | 4189 | |
— | — | @@ -4343,7 +4325,7 @@ |
4344 | 4326 | # make sure there are no placeholders in thumbnail attributes |
4345 | 4327 | # that are later expanded to html- so expand them now and |
4346 | 4328 | # remove the tags |
4347 | | - $alt = $this->unstrip($alt, $this->mStripState); |
| 4329 | + $alt = $this->mStripState->unstripBoth( $alt ); |
4348 | 4330 | $alt = Sanitizer::stripAllTags( $alt ); |
4349 | 4331 | |
4350 | 4332 | # Linker does the rest |
— | — | @@ -4370,15 +4352,10 @@ |
4371 | 4353 | */ |
4372 | 4354 | function attributeStripCallback( &$text, $args ) { |
4373 | 4355 | $text = $this->replaceVariables( $text, $args ); |
4374 | | - $text = $this->unstripForHTML( $text ); |
| 4356 | + $text = $this->mStripState->unstripBoth( $text ); |
4375 | 4357 | return $text; |
4376 | 4358 | } |
4377 | 4359 | |
4378 | | - function unstripForHTML( $text ) { |
4379 | | - $text = $this->unstrip( $text, $this->mStripState ); |
4380 | | - $text = $this->unstripNoWiki( $text, $this->mStripState ); |
4381 | | - return $text; |
4382 | | - } |
4383 | 4360 | /**#@-*/ |
4384 | 4361 | |
4385 | 4362 | /**#@+ |
— | — | @@ -4414,14 +4391,14 @@ |
4415 | 4392 | private function extractSections( $text, $section, $mode, $newtext='' ) { |
4416 | 4393 | # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML |
4417 | 4394 | # comments to be stripped as well) |
4418 | | - $striparray = array(); |
| 4395 | + $stripState = new StripState; |
4419 | 4396 | |
4420 | 4397 | $oldOutputType = $this->mOutputType; |
4421 | 4398 | $oldOptions = $this->mOptions; |
4422 | 4399 | $this->mOptions = new ParserOptions(); |
4423 | 4400 | $this->setOutputType( OT_WIKI ); |
4424 | 4401 | |
4425 | | - $striptext = $this->strip( $text, $striparray, true ); |
| 4402 | + $striptext = $this->strip( $text, $stripState, true ); |
4426 | 4403 | |
4427 | 4404 | $this->setOutputType( $oldOutputType ); |
4428 | 4405 | $this->mOptions = $oldOptions; |
— | — | @@ -4528,9 +4505,7 @@ |
4529 | 4506 | } |
4530 | 4507 | } |
4531 | 4508 | # reinsert stripped tags |
4532 | | - $rv = $this->unstrip( $rv, $striparray ); |
4533 | | - $rv = $this->unstripNoWiki( $rv, $striparray ); |
4534 | | - $rv = trim( $rv ); |
| 4509 | + $rv = trim( $stripState->unstripBoth( $rv ) ); |
4535 | 4510 | return $rv; |
4536 | 4511 | } |
4537 | 4512 | |
— | — | @@ -4553,6 +4528,23 @@ |
4554 | 4529 | return $this->extractSections( $oldtext, $section, "replace", $text ); |
4555 | 4530 | } |
4556 | 4531 | |
| 4532 | + /** |
| 4533 | + * Get the timestamp associated with the current revision, adjusted for |
| 4534 | + * the user's current timestamp |
| 4535 | + */ |
| 4536 | + function getRevisionTimestamp() { |
| 4537 | + if ( is_null( $this->mRevisionTimestamp ) ) { |
| 4538 | + wfProfileIn( __METHOD__ ); |
| 4539 | + global $wgContLang; |
| 4540 | + $dbr =& wfGetDB( DB_SLAVE ); |
| 4541 | + $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', |
| 4542 | + array( 'rev_id' => $id ), __METHOD__ ); |
| 4543 | + $this->mRevisionTimestamp = $wgContLang->userAdjust( $timestamp ); |
| 4544 | + |
| 4545 | + wfProfileOut( __METHOD__ ); |
| 4546 | + } |
| 4547 | + return $this->mRevisionTimestamp; |
| 4548 | + } |
4557 | 4549 | } |
4558 | 4550 | |
4559 | 4551 | /** |
— | — | @@ -4787,152 +4779,47 @@ |
4788 | 4780 | } |
4789 | 4781 | } |
4790 | 4782 | |
4791 | | -/** |
4792 | | - * Callback function used by Parser::replaceLinkHolders() |
4793 | | - * to substitute link placeholders. |
4794 | | - */ |
4795 | | -function &wfOutputReplaceMatches( $matches ) { |
4796 | | - global $wgOutputReplace; |
4797 | | - return $wgOutputReplace[$matches[1]]; |
4798 | | -} |
| 4783 | +class OnlyIncludeReplacer { |
| 4784 | + var $output = ''; |
4799 | 4785 | |
4800 | | -/** |
4801 | | - * Return the total number of articles |
4802 | | - */ |
4803 | | -function wfNumberOfArticles() { |
4804 | | - global $wgNumberOfArticles; |
4805 | | - |
4806 | | - wfLoadSiteStats(); |
4807 | | - return $wgNumberOfArticles; |
| 4786 | + function replace( $matches ) { |
| 4787 | + if ( substr( $matches[1], -1 ) == "\n" ) { |
| 4788 | + $this->output .= substr( $matches[1], 0, -1 ); |
| 4789 | + } else { |
| 4790 | + $this->output .= $matches[1]; |
| 4791 | + } |
| 4792 | + } |
4808 | 4793 | } |
4809 | 4794 | |
4810 | | -/** |
4811 | | - * Return the number of files |
4812 | | - */ |
4813 | | -function wfNumberOfFiles() { |
4814 | | - $fname = 'wfNumberOfFiles'; |
| 4795 | +class StripState { |
| 4796 | + var $general, $nowiki; |
4815 | 4797 | |
4816 | | - wfProfileIn( $fname ); |
4817 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4818 | | - $numImages = $dbr->selectField('site_stats', 'ss_images', array(), $fname ); |
4819 | | - wfProfileOut( $fname ); |
| 4798 | + function __construct() { |
| 4799 | + $this->general = new ReplacementArray; |
| 4800 | + $this->nowiki = new ReplacementArray; |
| 4801 | + } |
4820 | 4802 | |
4821 | | - return $numImages; |
4822 | | -} |
4823 | | - |
4824 | | -/** |
4825 | | - * Return the number of user accounts |
4826 | | - * @return integer |
4827 | | - */ |
4828 | | -function wfNumberOfUsers() { |
4829 | | - wfProfileIn( 'wfNumberOfUsers' ); |
4830 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4831 | | - $count = $dbr->selectField( 'site_stats', 'ss_users', array(), 'wfNumberOfUsers' ); |
4832 | | - wfProfileOut( 'wfNumberOfUsers' ); |
4833 | | - return (int)$count; |
4834 | | -} |
4835 | | - |
4836 | | -/** |
4837 | | - * Return the total number of pages |
4838 | | - * @return integer |
4839 | | - */ |
4840 | | -function wfNumberOfPages() { |
4841 | | - wfProfileIn( 'wfNumberOfPages' ); |
4842 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4843 | | - $count = $dbr->selectField( 'site_stats', 'ss_total_pages', array(), 'wfNumberOfPages' ); |
4844 | | - wfProfileOut( 'wfNumberOfPages' ); |
4845 | | - return (int)$count; |
4846 | | -} |
4847 | | - |
4848 | | -/** |
4849 | | - * Return the total number of admins |
4850 | | - * |
4851 | | - * @return integer |
4852 | | - */ |
4853 | | -function wfNumberOfAdmins() { |
4854 | | - static $admins = -1; |
4855 | | - wfProfileIn( 'wfNumberOfAdmins' ); |
4856 | | - if( $admins == -1 ) { |
4857 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4858 | | - $admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), 'wfNumberOfAdmins' ); |
| 4803 | + function unstripGeneral( $text ) { |
| 4804 | + wfProfileIn( __METHOD__ ); |
| 4805 | + $text = $this->general->replace( $text ); |
| 4806 | + wfProfileOut( __METHOD__ ); |
| 4807 | + return $text; |
4859 | 4808 | } |
4860 | | - wfProfileOut( 'wfNumberOfAdmins' ); |
4861 | | - return (int)$admins; |
4862 | | -} |
4863 | 4809 | |
4864 | | -/** |
4865 | | - * Count the number of pages in a particular namespace |
4866 | | - * |
4867 | | - * @param $ns Namespace |
4868 | | - * @return integer |
4869 | | - */ |
4870 | | -function wfPagesInNs( $ns ) { |
4871 | | - static $pageCount = array(); |
4872 | | - wfProfileIn( 'wfPagesInNs' ); |
4873 | | - if( !isset( $pageCount[$ns] ) ) { |
4874 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4875 | | - $pageCount[$ns] = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $ns ), 'wfPagesInNs' ); |
| 4810 | + function unstripNoWiki( $text ) { |
| 4811 | + wfProfileIn( __METHOD__ ); |
| 4812 | + $text = $this->nowiki->replace( $text ); |
| 4813 | + wfProfileOut( __METHOD__ ); |
| 4814 | + return $text; |
4876 | 4815 | } |
4877 | | - wfProfileOut( 'wfPagesInNs' ); |
4878 | | - return (int)$pageCount[$ns]; |
4879 | | -} |
4880 | 4816 | |
4881 | | -/** |
4882 | | - * Get various statistics from the database |
4883 | | - * @private |
4884 | | - */ |
4885 | | -function wfLoadSiteStats() { |
4886 | | - global $wgNumberOfArticles, $wgTotalViews, $wgTotalEdits; |
4887 | | - $fname = 'wfLoadSiteStats'; |
4888 | | - |
4889 | | - if ( -1 != $wgNumberOfArticles ) return; |
4890 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4891 | | - $s = $dbr->selectRow( 'site_stats', |
4892 | | - array( 'ss_total_views', 'ss_total_edits', 'ss_good_articles' ), |
4893 | | - array( 'ss_row_id' => 1 ), $fname |
4894 | | - ); |
4895 | | - |
4896 | | - if ( $s === false ) { |
4897 | | - return; |
4898 | | - } else { |
4899 | | - $wgTotalViews = $s->ss_total_views; |
4900 | | - $wgTotalEdits = $s->ss_total_edits; |
4901 | | - $wgNumberOfArticles = $s->ss_good_articles; |
| 4817 | + function unstripBoth( $text ) { |
| 4818 | + wfProfileIn( __METHOD__ ); |
| 4819 | + $text = $this->general->replace( $text ); |
| 4820 | + $text = $this->nowiki->replace( $text ); |
| 4821 | + wfProfileOut( __METHOD__ ); |
| 4822 | + return $text; |
4902 | 4823 | } |
4903 | 4824 | } |
4904 | 4825 | |
4905 | | -/** |
4906 | | - * Get revision timestamp from the database considering timecorrection |
4907 | | - * |
4908 | | - * @param $id Int: page revision id |
4909 | | - * @return integer |
4910 | | - */ |
4911 | | -function wfRevisionTimestamp( $id ) { |
4912 | | - global $wgContLang; |
4913 | | - $fname = 'wfRevisionTimestamp'; |
4914 | | - |
4915 | | - wfProfileIn( $fname ); |
4916 | | - $dbr =& wfGetDB( DB_SLAVE ); |
4917 | | - $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', |
4918 | | - array( 'rev_id' => $id ), __METHOD__ ); |
4919 | | - $timestamp = $wgContLang->userAdjust( $timestamp ); |
4920 | | - wfProfileOut( $fname ); |
4921 | | - |
4922 | | - return $timestamp; |
4923 | | -} |
4924 | | - |
4925 | | -/** |
4926 | | - * Escape html tags |
4927 | | - * Basically replacing " > and < with HTML entities ( ", >, <) |
4928 | | - * |
4929 | | - * @param $in String: text that might contain HTML tags. |
4930 | | - * @return string Escaped string |
4931 | | - */ |
4932 | | -function wfEscapeHTMLTagsOnly( $in ) { |
4933 | | - return str_replace( |
4934 | | - array( '"', '>', '<' ), |
4935 | | - array( '"', '>', '<' ), |
4936 | | - $in ); |
4937 | | -} |
4938 | | - |
4939 | 4826 | ?> |
Index: trunk/phase3/includes/CoreParserFunctions.php |
— | — | @@ -126,21 +126,21 @@ |
127 | 127 | |
128 | 128 | function statisticsFunction( $func, $raw = null ) { |
129 | 129 | if ( self::isRaw( $raw ) ) { |
130 | | - return call_user_func( $func ); |
| 130 | + return call_user_func( array( 'SiteStats', $func ) ); |
131 | 131 | } else { |
132 | 132 | global $wgContLang; |
133 | | - return $wgContLang->formatNum( call_user_func( $func ) ); |
| 133 | + return $wgContLang->formatNum( call_user_func( array( 'SiteStats', $func ) ) ); |
134 | 134 | } |
135 | 135 | } |
136 | 136 | |
137 | | - function numberofpages( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfPages', $raw ); } |
138 | | - function numberofusers( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfUsers', $raw ); } |
139 | | - function numberofarticles( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfArticles', $raw ); } |
140 | | - function numberoffiles( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfFiles', $raw ); } |
141 | | - function numberofadmins( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfAdmins', $raw ); } |
| 137 | + function numberofpages( $parser, $raw = null ) { return self::statisticsFunction( 'pages', $raw ); } |
| 138 | + function numberofusers( $parser, $raw = null ) { return self::statisticsFunction( 'users', $raw ); } |
| 139 | + function numberofarticles( $parser, $raw = null ) { return self::statisticsFunction( 'articles', $raw ); } |
| 140 | + function numberoffiles( $parser, $raw = null ) { return self::statisticsFunction( 'images', $raw ); } |
| 141 | + function numberofadmins( $parser, $raw = null ) { return self::statisticsFunction( 'admins', $raw ); } |
142 | 142 | |
143 | 143 | function pagesinnamespace( $parser, $namespace = 0, $raw = null ) { |
144 | | - $count = wfPagesInNs( intval( $namespace ) ); |
| 144 | + $count = SiteStats::pagesInNs( intval( $namespace ) ); |
145 | 145 | if ( self::isRaw( $raw ) ) { |
146 | 146 | global $wgContLang; |
147 | 147 | return $wgContLang->formatNum( $count ); |
Index: trunk/phase3/includes/BagOStuff.php |
— | — | @@ -492,11 +492,14 @@ |
493 | 493 | class APCBagOStuff extends BagOStuff { |
494 | 494 | function get($key) { |
495 | 495 | $val = apc_fetch($key); |
| 496 | + if ( is_string( $val ) ) { |
| 497 | + $val = unserialize( $val ); |
| 498 | + } |
496 | 499 | return $val; |
497 | 500 | } |
498 | 501 | |
499 | 502 | function set($key, $value, $exptime=0) { |
500 | | - apc_store($key, $value, $exptime); |
| 503 | + apc_store($key, serialize($value), $exptime); |
501 | 504 | return true; |
502 | 505 | } |
503 | 506 | |
Index: trunk/phase3/includes/Image.php |
— | — | @@ -1462,7 +1462,7 @@ |
1463 | 1463 | array( 'img_name' => $this->title->getDBkey() ), |
1464 | 1464 | __METHOD__ |
1465 | 1465 | ); |
1466 | | - if ( 0 == wfNumRows( $this->historyRes ) ) { |
| 1466 | + if ( 0 == $dbr->numRows( $this->historyRes ) ) { |
1467 | 1467 | return FALSE; |
1468 | 1468 | } |
1469 | 1469 | } else if ( $this->historyLine == 1 ) { |
Index: trunk/phase3/includes/SiteStats.php |
— | — | @@ -0,0 +1,168 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Static accessor class for site_stats and related things |
| 6 | + * @package MediaWiki |
| 7 | + */ |
| 8 | +class SiteStats { |
| 9 | + static $row, $loaded = false; |
| 10 | + static $admins; |
| 11 | + static $pageCount = array(); |
| 12 | + |
| 13 | + static function recache() { |
| 14 | + self::load( true ); |
| 15 | + } |
| 16 | + |
| 17 | + static function load( $recache = false ) { |
| 18 | + if ( self::$loaded && !$recache ) { |
| 19 | + return; |
| 20 | + } |
| 21 | + |
| 22 | + $dbr =& wfGetDB( DB_SLAVE ); |
| 23 | + self::$row = $dbr->selectRow( 'site_stats', '*', false, __METHOD__ ); |
| 24 | + |
| 25 | + # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS |
| 26 | + if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) { |
| 27 | + # Update schema |
| 28 | + $u = new SiteStatsUpdate( 0, 0, 0 ); |
| 29 | + $u->doUpdate(); |
| 30 | + self::$row = $dbr->selectRow( 'site_stats', '*', false, $fname ); |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + static function views() { |
| 35 | + self::load(); |
| 36 | + return self::$row->ss_total_views; |
| 37 | + } |
| 38 | + |
| 39 | + static function edits() { |
| 40 | + self::load(); |
| 41 | + return self::$row->ss_total_edits; |
| 42 | + } |
| 43 | + |
| 44 | + static function articles() { |
| 45 | + self::load(); |
| 46 | + return self::$row->ss_good_articles; |
| 47 | + } |
| 48 | + |
| 49 | + static function pages() { |
| 50 | + self::load(); |
| 51 | + return self::$row->ss_total_pages; |
| 52 | + } |
| 53 | + |
| 54 | + static function users() { |
| 55 | + self::load(); |
| 56 | + return self::$row->ss_users; |
| 57 | + } |
| 58 | + |
| 59 | + static function images() { |
| 60 | + self::load(); |
| 61 | + return self::$row->ss_images; |
| 62 | + } |
| 63 | + |
| 64 | + static function admins() { |
| 65 | + if ( !isset( self::$admins ) ) { |
| 66 | + $dbr =& wfGetDB( DB_SLAVE ); |
| 67 | + self::$admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), __METHOD__ ); |
| 68 | + } |
| 69 | + return self::$admins; |
| 70 | + } |
| 71 | + |
| 72 | + static function pagesInNs( $ns ) { |
| 73 | + wfProfileIn( __METHOD__ ); |
| 74 | + if( !isset( self::$pageCount[$ns] ) ) { |
| 75 | + $dbr =& wfGetDB( DB_SLAVE ); |
| 76 | + $pageCount[$ns] = (int)$dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $ns ), __METHOD__ ); |
| 77 | + } |
| 78 | + wfProfileOut( __METHOD__ ); |
| 79 | + return $pageCount[$ns]; |
| 80 | + } |
| 81 | + |
| 82 | +} |
| 83 | + |
| 84 | + |
| 85 | +/** |
| 86 | + * |
| 87 | + * @package MediaWiki |
| 88 | + */ |
| 89 | +class SiteStatsUpdate { |
| 90 | + |
| 91 | + var $mViews, $mEdits, $mGood, $mPages, $mUsers; |
| 92 | + |
| 93 | + function SiteStatsUpdate( $views, $edits, $good, $pages = 0, $users = 0 ) { |
| 94 | + $this->mViews = $views; |
| 95 | + $this->mEdits = $edits; |
| 96 | + $this->mGood = $good; |
| 97 | + $this->mPages = $pages; |
| 98 | + $this->mUsers = $users; |
| 99 | + } |
| 100 | + |
| 101 | + function appendUpdate( &$sql, $field, $delta ) { |
| 102 | + if ( $delta ) { |
| 103 | + if ( $sql ) { |
| 104 | + $sql .= ','; |
| 105 | + } |
| 106 | + if ( $delta < 0 ) { |
| 107 | + $sql .= "$field=$field-1"; |
| 108 | + } else { |
| 109 | + $sql .= "$field=$field+1"; |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + function doUpdate() { |
| 115 | + $fname = 'SiteStatsUpdate::doUpdate'; |
| 116 | + $dbw =& wfGetDB( DB_MASTER ); |
| 117 | + |
| 118 | + # First retrieve the row just to find out which schema we're in |
| 119 | + $row = $dbw->selectRow( 'site_stats', '*', false, $fname ); |
| 120 | + |
| 121 | + $updates = ''; |
| 122 | + |
| 123 | + $this->appendUpdate( $updates, 'ss_total_views', $this->mViews ); |
| 124 | + $this->appendUpdate( $updates, 'ss_total_edits', $this->mEdits ); |
| 125 | + $this->appendUpdate( $updates, 'ss_good_articles', $this->mGood ); |
| 126 | + |
| 127 | + if ( isset( $row->ss_total_pages ) ) { |
| 128 | + # Update schema if required |
| 129 | + if ( $row->ss_total_pages == -1 && !$this->mViews ) { |
| 130 | + $dbr =& wfGetDB( DB_SLAVE, array( 'SpecialStatistics', 'vslow') ); |
| 131 | + extract( $dbr->tableNames( 'page', 'user' ) ); |
| 132 | + |
| 133 | + $sql = "SELECT COUNT(page_namespace) AS total FROM $page"; |
| 134 | + $res = $dbr->query( $sql, $fname ); |
| 135 | + $pageRow = $dbr->fetchObject( $res ); |
| 136 | + $pages = $pageRow->total + $this->mPages; |
| 137 | + |
| 138 | + $sql = "SELECT COUNT(user_id) AS total FROM $user"; |
| 139 | + $res = $dbr->query( $sql, $fname ); |
| 140 | + $userRow = $dbr->fetchObject( $res ); |
| 141 | + $users = $userRow->total + $this->mUsers; |
| 142 | + |
| 143 | + if ( $updates ) { |
| 144 | + $updates .= ','; |
| 145 | + } |
| 146 | + $updates .= "ss_total_pages=$pages, ss_users=$users"; |
| 147 | + } else { |
| 148 | + $this->appendUpdate( $updates, 'ss_total_pages', $this->mPages ); |
| 149 | + $this->appendUpdate( $updates, 'ss_users', $this->mUsers ); |
| 150 | + } |
| 151 | + } |
| 152 | + if ( $updates ) { |
| 153 | + $site_stats = $dbw->tableName( 'site_stats' ); |
| 154 | + $sql = $dbw->limitResultForUpdate("UPDATE $site_stats SET $updates", 1); |
| 155 | + $dbw->begin(); |
| 156 | + $dbw->query( $sql, $fname ); |
| 157 | + $dbw->commit(); |
| 158 | + } |
| 159 | + |
| 160 | + /* |
| 161 | + global $wgDBname, $wgTitle; |
| 162 | + if ( $this->mGood && $wgDBname == 'enwiki' ) { |
| 163 | + $good = $dbw->selectField( 'site_stats', 'ss_good_articles', '', $fname ); |
| 164 | + error_log( $good . ' ' . $wgTitle->getPrefixedDBkey() . "\n", 3, '/home/wikipedia/logs/million.log' ); |
| 165 | + } |
| 166 | + */ |
| 167 | + } |
| 168 | +} |
| 169 | +?> |
Property changes on: trunk/phase3/includes/SiteStats.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 170 | + native |
Added: svn:keywords |
2 | 171 | + Author Date Id Revision |
Index: trunk/phase3/includes/Block.php |
— | — | @@ -338,7 +338,7 @@ |
339 | 339 | call_user_func( $callback, $block, $tag ); |
340 | 340 | } |
341 | 341 | } |
342 | | - wfFreeResult( $res ); |
| 342 | + $db->freeResult( $res ); |
343 | 343 | return $num_rows; |
344 | 344 | } |
345 | 345 | |
Index: trunk/phase3/includes/Xml.php |
— | — | @@ -297,5 +297,19 @@ |
298 | 298 | '</html>'; |
299 | 299 | return Xml::isWellFormed( $html ); |
300 | 300 | } |
| 301 | + |
| 302 | + /** |
| 303 | + * Escape html tags |
| 304 | + * Basically replacing " > and < with HTML entities ( ", >, <) |
| 305 | + * |
| 306 | + * @param $in String: text that might contain HTML tags. |
| 307 | + * @return string Escaped string |
| 308 | + */ |
| 309 | + function escapeTagsOnly( $in ) { |
| 310 | + return str_replace( |
| 311 | + array( '"', '>', '<' ), |
| 312 | + array( '"', '>', '<' ), |
| 313 | + $in ); |
| 314 | + } |
301 | 315 | } |
302 | 316 | ?> |
Index: trunk/phase3/includes/SpecialWatchlist.php |
— | — | @@ -381,8 +381,8 @@ |
382 | 382 | } |
383 | 383 | |
384 | 384 | if ($wgRCShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) { |
385 | | - $sql3 = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" .wfStrencode($obj->page_title). "' AND wl_namespace='{$obj->page_namespace}'" ; |
386 | | - $res3 = $dbr->query( $sql3, DB_READ, $fname ); |
| 385 | + $sql3 = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" .$dbr->strencode($obj->page_title). "' AND wl_namespace='{$obj->page_namespace}'" ; |
| 386 | + $res3 = $dbr->query( $sql3, $fname ); |
387 | 387 | $x = $dbr->fetchObject( $res3 ); |
388 | 388 | $rc->numberofWatchingusers = $x->n; |
389 | 389 | } else { |
Index: trunk/phase3/includes/DatabaseFunctions.php |
— | — | @@ -1,9 +1,8 @@ |
2 | 2 | <?php |
3 | 3 | /** |
4 | | - * Backwards compatibility wrapper for Database.php |
| 4 | + * Legacy database functions, for compatibility with pre-1.3 code |
| 5 | + * NOTE: this file is no longer loaded by default. |
5 | 6 | * |
6 | | - * Note: $wgDatabase has ceased to exist. Destroy all references. |
7 | | - * |
8 | 7 | * @package MediaWiki |
9 | 8 | */ |
10 | 9 | |
— | — | @@ -44,15 +43,6 @@ |
45 | 44 | return $ret; |
46 | 45 | } |
47 | 46 | |
48 | | -/* |
49 | | - * @todo document function |
50 | | - */ |
51 | | -function &wfGetDB( $db = DB_LAST, $groups = array() ) { |
52 | | - global $wgLoadBalancer; |
53 | | - $ret =& $wgLoadBalancer->getConnection( $db, true, $groups ); |
54 | | - return $ret; |
55 | | -} |
56 | | - |
57 | 47 | /** |
58 | 48 | * Turns on (false) or off (true) the automatic generation and sending |
59 | 49 | * of a "we're sorry, but there has been a database error" page on |
Index: trunk/phase3/includes/Sanitizer.php |
— | — | @@ -603,7 +603,8 @@ |
604 | 604 | $stripped = Sanitizer::decodeCharReferences( $value ); |
605 | 605 | |
606 | 606 | // Remove any comments; IE gets token splitting wrong |
607 | | - $stripped = preg_replace( '!/\\*.*?\\*/!S', ' ', $stripped ); |
| 607 | + $stripped = StringUtils::delimiterReplace( '/\*', '\*/', ' ', $stripped ); |
| 608 | + |
608 | 609 | $value = $stripped; |
609 | 610 | |
610 | 611 | // ... and continue checks |
— | — | @@ -1178,7 +1179,7 @@ |
1179 | 1180 | */ |
1180 | 1181 | static function stripAllTags( $text ) { |
1181 | 1182 | # Actual <tags> |
1182 | | - $text = preg_replace( '/ < .*? > /x', '', $text ); |
| 1183 | + $text = StringUtils::delimiterReplace( '<', '>', '', $text ); |
1183 | 1184 | |
1184 | 1185 | # Normalize &entities and whitespace |
1185 | 1186 | $text = Sanitizer::normalizeAttributeValue( $text ); |
Index: trunk/extensions/Cache404/extensions/Cache404.php |
— | — | @@ -32,6 +32,7 @@ |
33 | 33 | require_once("Skin.php"); |
34 | 34 | require_once("skins/MonoBook.php"); |
35 | 35 | require_once("SkinPHPTal.php"); |
| 36 | + require_once("DatabaseFunctions.php"); |
36 | 37 | |
37 | 38 | define("CACHE404_VERSION", "0.6"); |
38 | 39 | |
Index: trunk/extensions/ShowProcesslist/ShowProcesslist_body.php |
— | — | @@ -14,11 +14,12 @@ |
15 | 15 | return; |
16 | 16 | } |
17 | 17 | |
18 | | - $res = wfQuery( 'SHOW FULL PROCESSLIST' , DB_READ ); |
| 18 | + $dbr =& wfGetDB( DB_SLAVE ); |
| 19 | + $res = $dbr->query( 'SHOW FULL PROCESSLIST' ); |
19 | 20 | $output = array(); |
20 | 21 | $output = '<table border="1" cellspacing="0">'."\n"; |
21 | 22 | $output .= '<tr><th>Id</th><th>User</th><th>Host</th><th>db</th><th>Command</th><th>Time</th><th>State</th><th>Info</th>'."\n"; |
22 | | - while ( $row = wfFetchObject($res) ) { |
| 23 | + while ( $row = $dbr->fetchObject($res) ) { |
23 | 24 | $output .= '<tr>'; |
24 | 25 | $fields = get_object_vars($row); |
25 | 26 | foreach ($fields as $value ) { |
Index: trunk/extensions/StableVersion/StableVersion.php |
— | — | @@ -346,15 +346,26 @@ |
347 | 347 | |
348 | 348 | |
349 | 349 | function fixNoWiki( &$state ) { |
350 | | - if( !is_array( $state ) ) { |
| 350 | + if ( is_object( $state ) ) { |
| 351 | + # MW 1.9 version |
| 352 | + $array = $state->nowiki->getArray(); |
| 353 | + } elseif is_array( $state ) { |
| 354 | + $array = $state['nowiki']; |
| 355 | + } else { |
351 | 356 | return; |
352 | 357 | } |
353 | | - |
| 358 | + |
354 | 359 | # Surround nowiki content with <nowiki> again |
355 | | - for( $content = end( $state['nowiki'] ); $content !== false; $content = prev( $state['nowiki'] ) ) { |
356 | | - $key = key( $state['nowiki'] ); |
357 | | - $state['nowiki'][$key] = "<nowiki>" . $content . "</nowiki>"; |
| 360 | + for( $content = end( $array ); $content !== false; $content = prev( $array ) ) { |
| 361 | + $key = key( $array ); |
| 362 | + $array[$key] = "<nowiki>" . $content . "</nowiki>"; |
358 | 363 | } |
| 364 | + |
| 365 | + if ( is_object( $state ) ) { |
| 366 | + $state->nowiki->setArray( $array ); |
| 367 | + } else { |
| 368 | + $state['nowiki'] = $array; |
| 369 | + } |
359 | 370 | } |
360 | 371 | |
361 | 372 | /** |
Index: trunk/extensions/experimental/SpecialValidate.php |
— | — | @@ -23,6 +23,9 @@ |
24 | 24 | * @subpackage SpecialPage |
25 | 25 | */ |
26 | 26 | |
| 27 | +# Need legacy database functions |
| 28 | +require_once("DatabaseFunctions.php"); |
| 29 | + |
27 | 30 | /** |
28 | 31 | * |
29 | 32 | * @package MediaWiki |
Index: trunk/extensions/MakeDBError/MakeDBError_body.php |
— | — | @@ -16,7 +16,8 @@ |
17 | 17 | $db =& wfGetDB( 1234 ); |
18 | 18 | $wgOut->addHTML("<pre>" . var_export( $db, true ) . "</pre>" ); |
19 | 19 | } else { |
20 | | - wfQuery( "test", DB_READ ); |
| 20 | + $db =& wfGetDB( DB_SLAVE ); |
| 21 | + $db->query( "test" ); |
21 | 22 | } |
22 | 23 | } |
23 | 24 | } |
Index: trunk/extensions/FindSpam/FindSpam_body.php |
— | — | @@ -41,7 +41,7 @@ |
42 | 42 | $s = ''; |
43 | 43 | |
44 | 44 | foreach ( $wgLocalDatabases as $db ) { |
45 | | - $sql = "SELECT rc_namespace,rc_title,rc_timestamp,rc_user_text,rc_last_oldid FROM $db.recentchanges WHERE rc_ip='" . wfStrencode( $ip ) . |
| 45 | + $sql = "SELECT rc_namespace,rc_title,rc_timestamp,rc_user_text,rc_last_oldid FROM $db.recentchanges WHERE rc_ip='" . $dbr->strencode( $ip ) . |
46 | 46 | "' AND rc_this_oldid=0"; |
47 | 47 | $res = $dbr->query( $sql, "findspam.php" ); |
48 | 48 | list( $site, $lang ) = $wgConf->siteFromDB( $db ); |