Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Wikipedia: Mediawiki-CVS

SVN: [39563] branches/visual_diff/phase3

 

 

Wikipedia mediawiki-cvs RSS feed   Index | Next | Previous | View Threaded


guyvdb at svn

Aug 17, 2008, 5:10 PM

Post #1 of 1 (66 views)
Permalink
SVN: [39563] branches/visual_diff/phase3

Revision: 39563
Author: guyvdb
Date: 2008-08-18 00:10:23 +0000 (Mon, 18 Aug 2008)

Log Message:
-----------
Merge with trunk

Modified Paths:
--------------
branches/visual_diff/phase3/RELEASE-NOTES
branches/visual_diff/phase3/includes/Article.php
branches/visual_diff/phase3/includes/AutoLoader.php
branches/visual_diff/phase3/includes/ChangesList.php
branches/visual_diff/phase3/includes/Credits.php
branches/visual_diff/phase3/includes/DefaultSettings.php
branches/visual_diff/phase3/includes/Diff.php
branches/visual_diff/phase3/includes/DifferenceEngine.php
branches/visual_diff/phase3/includes/LinkCache.php
branches/visual_diff/phase3/includes/LinksUpdate.php
branches/visual_diff/phase3/includes/MessageCache.php
branches/visual_diff/phase3/includes/StringUtils.php
branches/visual_diff/phase3/includes/Title.php
branches/visual_diff/phase3/includes/ZhConversion.php
branches/visual_diff/phase3/includes/api/ApiLogin.php
branches/visual_diff/phase3/includes/api/ApiQuery.php
branches/visual_diff/phase3/includes/api/ApiQueryCategories.php
branches/visual_diff/phase3/includes/api/ApiQueryLinks.php
branches/visual_diff/phase3/includes/api/ApiQuerySearch.php
branches/visual_diff/phase3/includes/parser/CoreParserFunctions.php
branches/visual_diff/phase3/includes/parser/Parser.php
branches/visual_diff/phase3/includes/parser/Parser_DiffTest.php
branches/visual_diff/phase3/includes/specials/SpecialAllpages.php
branches/visual_diff/phase3/includes/specials/SpecialLog.php
branches/visual_diff/phase3/includes/specials/SpecialPreferences.php
branches/visual_diff/phase3/includes/specials/SpecialPrefixindex.php
branches/visual_diff/phase3/includes/specials/SpecialRecentchanges.php
branches/visual_diff/phase3/includes/specials/SpecialUserlogin.php
branches/visual_diff/phase3/includes/specials/SpecialWatchlist.php
branches/visual_diff/phase3/includes/templates/Userlogin.php
branches/visual_diff/phase3/includes/zhtable/toCN.manual
branches/visual_diff/phase3/includes/zhtable/toHK.manual
branches/visual_diff/phase3/includes/zhtable/toSG.manual
branches/visual_diff/phase3/includes/zhtable/toTW.manual
branches/visual_diff/phase3/includes/zhtable/tradphrases.manual
branches/visual_diff/phase3/languages/LanguageConverter.php
branches/visual_diff/phase3/languages/messages/MessagesAf.php
branches/visual_diff/phase3/languages/messages/MessagesAr.php
branches/visual_diff/phase3/languages/messages/MessagesArn.php
branches/visual_diff/phase3/languages/messages/MessagesArz.php
branches/visual_diff/phase3/languages/messages/MessagesAst.php
branches/visual_diff/phase3/languages/messages/MessagesBcc.php
branches/visual_diff/phase3/languages/messages/MessagesBe_tarask.php
branches/visual_diff/phase3/languages/messages/MessagesBg.php
branches/visual_diff/phase3/languages/messages/MessagesBs.php
branches/visual_diff/phase3/languages/messages/MessagesCa.php
branches/visual_diff/phase3/languages/messages/MessagesCs.php
branches/visual_diff/phase3/languages/messages/MessagesCu.php
branches/visual_diff/phase3/languages/messages/MessagesCy.php
branches/visual_diff/phase3/languages/messages/MessagesDa.php
branches/visual_diff/phase3/languages/messages/MessagesDe.php
branches/visual_diff/phase3/languages/messages/MessagesEn.php
branches/visual_diff/phase3/languages/messages/MessagesEs.php
branches/visual_diff/phase3/languages/messages/MessagesFa.php
branches/visual_diff/phase3/languages/messages/MessagesFi.php
branches/visual_diff/phase3/languages/messages/MessagesFr.php
branches/visual_diff/phase3/languages/messages/MessagesFur.php
branches/visual_diff/phase3/languages/messages/MessagesFy.php
branches/visual_diff/phase3/languages/messages/MessagesGrc.php
branches/visual_diff/phase3/languages/messages/MessagesHe.php
branches/visual_diff/phase3/languages/messages/MessagesHif_latn.php
branches/visual_diff/phase3/languages/messages/MessagesHr.php
branches/visual_diff/phase3/languages/messages/MessagesHu.php
branches/visual_diff/phase3/languages/messages/MessagesIa.php
branches/visual_diff/phase3/languages/messages/MessagesId.php
branches/visual_diff/phase3/languages/messages/MessagesIt.php
branches/visual_diff/phase3/languages/messages/MessagesJa.php
branches/visual_diff/phase3/languages/messages/MessagesKm.php
branches/visual_diff/phase3/languages/messages/MessagesKo.php
branches/visual_diff/phase3/languages/messages/MessagesKrj.php
branches/visual_diff/phase3/languages/messages/MessagesKsh.php
branches/visual_diff/phase3/languages/messages/MessagesLa.php
branches/visual_diff/phase3/languages/messages/MessagesLv.php
branches/visual_diff/phase3/languages/messages/MessagesMk.php
branches/visual_diff/phase3/languages/messages/MessagesMs.php
branches/visual_diff/phase3/languages/messages/MessagesMt.php
branches/visual_diff/phase3/languages/messages/MessagesNds.php
branches/visual_diff/phase3/languages/messages/MessagesNl.php
branches/visual_diff/phase3/languages/messages/MessagesNn.php
branches/visual_diff/phase3/languages/messages/MessagesNo.php
branches/visual_diff/phase3/languages/messages/MessagesOc.php
branches/visual_diff/phase3/languages/messages/MessagesPa.php
branches/visual_diff/phase3/languages/messages/MessagesPl.php
branches/visual_diff/phase3/languages/messages/MessagesPt.php
branches/visual_diff/phase3/languages/messages/MessagesQqq.php
branches/visual_diff/phase3/languages/messages/MessagesRif.php
branches/visual_diff/phase3/languages/messages/MessagesRu.php
branches/visual_diff/phase3/languages/messages/MessagesSv.php
branches/visual_diff/phase3/languages/messages/MessagesTk.php
branches/visual_diff/phase3/languages/messages/MessagesUk.php
branches/visual_diff/phase3/languages/messages/MessagesVec.php
branches/visual_diff/phase3/languages/messages/MessagesVi.php
branches/visual_diff/phase3/languages/messages/MessagesYue.php
branches/visual_diff/phase3/languages/messages/MessagesZh_classical.php
branches/visual_diff/phase3/languages/messages/MessagesZh_hans.php
branches/visual_diff/phase3/languages/messages/MessagesZh_hant.php
branches/visual_diff/phase3/languages/messages/MessagesZh_tw.php
branches/visual_diff/phase3/maintenance/language/messages.inc
branches/visual_diff/phase3/maintenance/parserTests.inc
branches/visual_diff/phase3/maintenance/parserTests.txt
branches/visual_diff/phase3/skins/common/shared.css

Added Paths:
-----------
branches/visual_diff/phase3/includes/parser/LinkHolderArray.php

Property Changed:
----------------
branches/visual_diff/phase3/skins/common/images/diffunderline.gif

Modified: branches/visual_diff/phase3/RELEASE-NOTES
===================================================================
--- branches/visual_diff/phase3/RELEASE-NOTES 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/RELEASE-NOTES 2008-08-18 00:10:23 UTC (rev 39563)
@@ -19,7 +19,6 @@
it from source control: http://www.mediawiki.org/wiki/Download_from_SVN

=== Configuration changes in 1.14 ===
-
* $wgExemptFromUserRobotsControl is an array of namespaces to be exempt from
the effect of the new __INDEX__/__NOINDEX__ magic words. (Default: null, ex-
empt all content namespaces.)
@@ -37,15 +36,18 @@
Backwards compatibility is maintained.
* $wgEnablePersistentCookies has been added. Setting to false disables the
setting of persistent cookies. Defaults to true.
-
+* $wgRestrictDisplayTitle controls if the use of the {{DISPLAYTITLE}} magic
+ word is restricted to titles equivalent to the actual page title. This
+ is true per default, but can be set to false to allow any title.
+
=== New features in 1.14 ===

-* New URL syntaxes for Special:ListUsers - 'Special:ListUsers/USER' and
- 'Special:ListUsers/GROUP/USER', in addition to the older syntax
+* New URL syntaxes for Special:ListUsers - 'Special:ListUsers/USER' and
+ 'Special:ListUsers/GROUP/USER', in addition to the older syntax
'Special:ListUsers/GROUP' where GROUP is a valid group name.
-* Configurable er-namespace and per-page notices for the edit form,
+* Configurable er-namespace and per-page notices for the edit form,
respectively MediaWiki:Editnotice-# where # is the namespace number, and
- MediaWiki:Editnotice-#-PAGENAME where # is the page's namespace number and
+ MediaWiki:Editnotice-#-PAGENAME where # is the page's namespace number and
PAGENAME is the page name minus the namespace prefix.
* (bug 8068) New __INDEX__ and __NOINDEX__ magic words allow user control of
search engine indexing on a per-article basis.
@@ -80,7 +82,7 @@
* (bug 14929) removeUnusedAccounts.php now supports 'ignore-touched' and
'ignore-groups'. Patch by Louperivois
* (bug 15127) Work around minor display glitch in Opera.
-* By default, reject file uploads that look like ZIP files, to avoid the
+* By default, reject file uploads that look like ZIP files, to avoid the
so-called GIFAR vulnerability.
* (bug 15141) Give ability to only list protected pages with the cascading
option enabled on Special:ProtectedPages
@@ -88,7 +90,11 @@
Show/Hide logged in users, Show/Hide anonymous, Invert namespace selection
* Added hook 'UserrightsChangeableGroups' to allow modification of what
groups may be added or removed via the Special:UserRights interface.
-
+* (bug 14468) Lines in classic RecentChanges and Watchlist have alternating
+ background colours based on classes "odd" and "even".
+* (bug 14187) In Special:Userlogin the buttons "Log in" and "E-mail new
+ password" now have classes "mw-loginbutton" and "mw-mailmypasswordbutton".
+
=== Bug fixes in 1.14 ===

* (bug 14907) DatabasePostgres::fieldType now defined.
@@ -130,6 +136,7 @@
gives results
* Avoid recursive crazy expansions in section edit comments for pages which
contain '/*' in the title
+* Fix excessive memory usage when parsing pages with lots of links

=== API changes in 1.14 ===

@@ -147,6 +154,9 @@
* (bug 15048) Added limit field for multivalue parameters to action=paraminfo
output.
* When the limit on multivalue parameters is exceeded, a warning is issued
+* list=search doesn't list missing pages any more
+* (bug 15178) Added clshow to prop=categories to allow filtering for hidden/
+ non-hidden categories

=== Languages updated in 1.14 ===


Modified: branches/visual_diff/phase3/includes/Article.php
===================================================================
--- branches/visual_diff/phase3/includes/Article.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/Article.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -51,6 +51,16 @@
$this->mTitle =& $title;
$this->mOldId = $oldId;
}
+
+ /**
+ * Constructor from an article article
+ * @param $id The article ID to load
+ */
+ public static function newFromID( $id ) {
+ $t = Title::newFromID( $id );
+
+ return $t == null ? null : new Article( $t );
+ }

/**
* Tell the page view functions that this view was redirected
@@ -1390,8 +1400,12 @@
*
* @return bool success
*/
- function doEdit( $text, $summary, $flags = 0, $baseRevId = false ) {
+ function doEdit( $text, $summary, $flags = 0, $baseRevId = false, $user = null ) {
global $wgUser, $wgDBtransactions, $wgUseAutomaticEditSummaries;
+
+ if ($user == null) {
+ $user = $wgUser;
+ }

wfProfileIn( __METHOD__ );
$good = true;
@@ -1405,7 +1419,7 @@
}
}

- if( !wfRunHooks( 'ArticleSave', array( &$this, &$wgUser, &$text,
+ if( !wfRunHooks( 'ArticleSave', array( &$this, &$user, &$text,
&$summary, $flags & EDIT_MINOR,
null, null, &$flags ) ) )
{
@@ -1415,7 +1429,7 @@
}

# Silently ignore EDIT_MINOR if not allowed
- $isminor = ( $flags & EDIT_MINOR ) && $wgUser->isAllowed('minoredit');
+ $isminor = ( $flags & EDIT_MINOR ) && $user->isAllowed('minoredit');
$bot = $flags & EDIT_FORCE_BOT;

$oldtext = $this->getContent();
@@ -1484,17 +1498,17 @@

# Update recentchanges
if( !( $flags & EDIT_SUPPRESS_RC ) ) {
- $rcid = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $wgUser, $summary,
+ $rcid = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $user, $summary,
$lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
$revisionId );

# Mark as patrolled if the user can do so
- if( $GLOBALS['wgUseRCPatrol'] && $wgUser->isAllowed( 'autopatrol' ) ) {
+ if( $GLOBALS['wgUseRCPatrol'] && $user->isAllowed( 'autopatrol' ) ) {
RecentChange::markPatrolled( $rcid );
PatrolLog::record( $rcid, true );
}
}
- $wgUser->incEditCount();
+ $user->incEditCount();
$dbw->commit();
}
} else {
@@ -1550,15 +1564,15 @@
wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false) );

if( !( $flags & EDIT_SUPPRESS_RC ) ) {
- $rcid = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary, $bot,
+ $rcid = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot,
'', strlen( $text ), $revisionId );
# Mark as patrolled if the user can
- if( ($GLOBALS['wgUseRCPatrol'] || $GLOBALS['wgUseNPPatrol']) && $wgUser->isAllowed( 'autopatrol' ) ) {
+ if( ($GLOBALS['wgUseRCPatrol'] || $GLOBALS['wgUseNPPatrol']) && $user->isAllowed( 'autopatrol' ) ) {
RecentChange::markPatrolled( $rcid );
PatrolLog::record( $rcid, true );
}
}
- $wgUser->incEditCount();
+ $user->incEditCount();
$dbw->commit();

# Update links, etc.
@@ -1567,7 +1581,7 @@
# Clear caches
Article::onArticleCreate( $this->mTitle );

- wfRunHooks( 'ArticleInsertComplete', array( &$this, &$wgUser, $text, $summary,
+ wfRunHooks( 'ArticleInsertComplete', array( &$this, &$user, $text, $summary,
$flags & EDIT_MINOR, null, null, &$flags, $revision ) );
}

@@ -1576,7 +1590,7 @@
}

if ( $good ) {
- wfRunHooks( 'ArticleSaveComplete', array( &$this, &$wgUser, $text, $summary,
+ wfRunHooks( 'ArticleSaveComplete', array( &$this, &$user, $text, $summary,
$flags & EDIT_MINOR, null, null, &$flags, $revision ) );
}


Modified: branches/visual_diff/phase3/includes/AutoLoader.php
===================================================================
--- branches/visual_diff/phase3/includes/AutoLoader.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/AutoLoader.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -32,6 +32,7 @@
'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php',
'ConstantDependency' => 'includes/CacheDependency.php',
'DBABagOStuff' => 'includes/BagOStuff.php',
+ 'DelegatingContentHandler' => 'includes/HTMLDiff.php',
'DependencyWrapper' => 'includes/CacheDependency.php',
'_DiffEngine' => 'includes/DifferenceEngine.php',
'DifferenceEngine' => 'includes/DifferenceEngine.php',
@@ -57,6 +58,7 @@
'DumpOutput' => 'includes/Export.php',
'DumpPipeOutput' => 'includes/Export.php',
'eAccelBagOStuff' => 'includes/BagOStuff.php',
+ 'EchoingContentHandler' => 'includes/HTMLDiff.php',
'EditPage' => 'includes/EditPage.php',
'EmaillingJob' => 'includes/EmaillingJob.php',
'EmailNotification' => 'includes/UserMailer.php',
@@ -64,6 +66,7 @@
'EnotifNotifyJob' => 'includes/EnotifNotifyJob.php',
'ErrorPageError' => 'includes/Exception.php',
'Exif' => 'includes/Exif.php',
+ 'ExplodeIterator' => 'includes/StringUtils.php',
'ExternalEdit' => 'includes/ExternalEdit.php',
'ExternalStoreDB' => 'includes/ExternalStoreDB.php',
'ExternalStoreHttp' => 'includes/ExternalStoreHttp.php',
@@ -89,7 +92,9 @@
'HistoryBlobStub' => 'includes/HistoryBlob.php',
'HTMLCacheUpdate' => 'includes/HTMLCacheUpdate.php',
'HTMLCacheUpdateJob' => 'includes/HTMLCacheUpdate.php',
+ 'HTMLDiffer' => 'includes/HTMLDiff.php',
'HTMLFileCache' => 'includes/HTMLFileCache.php',
+ 'HTMLOutput' => 'includes/HTMLDiff.php',
'Http' => 'includes/HttpFunctions.php',
'_HWLDF_WordAccumulator' => 'includes/DifferenceEngine.php',
'ImageGallery' => 'includes/ImageGallery.php',
@@ -149,6 +154,7 @@
'ProtectionForm' => 'includes/ProtectionForm.php',
'QueryPage' => 'includes/QueryPage.php',
'QuickTemplate' => 'includes/SkinTemplate.php',
+ 'RangeDifference' => 'includes/Diff.php',
'RawPage' => 'includes/RawPage.php',
'RCCacheEntry' => 'includes/ChangesList.php',
'RecentChange' => 'includes/RecentChange.php',
@@ -206,6 +212,7 @@
'WatchlistEditor' => 'includes/WatchlistEditor.php',
'WebRequest' => 'includes/WebRequest.php',
'WebResponse' => 'includes/WebResponse.php',
+ 'WikiDiff3' => 'includes/Diff.php',
'WikiError' => 'includes/WikiError.php',
'WikiErrorMsg' => 'includes/WikiError.php',
'WikiExporter' => 'includes/Export.php',
@@ -351,6 +358,7 @@
# includes/parser
'CoreParserFunctions' => 'includes/parser/CoreParserFunctions.php',
'DateFormatter' => 'includes/parser/DateFormatter.php',
+ 'LinkHolderArray' => 'includes/parser/LinkHolderArray.php',
'OnlyIncludeReplacer' => 'includes/parser/Parser.php',
'PPDAccum_Hash' => 'includes/parser/Preprocessor_Hash.php',
'PPDPart' => 'includes/parser/Preprocessor_DOM.php',

Modified: branches/visual_diff/phase3/includes/ChangesList.php
===================================================================
--- branches/visual_diff/phase3/includes/ChangesList.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/ChangesList.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -306,7 +306,7 @@
/**
* Format a line using the old system (aka without any javascript).
*/
- public function recentChangesLine( &$rc, $watched = false ) {
+ public function recentChangesLine( &$rc, $watched = false, $linenumber = NULL ) {
global $wgContLang, $wgRCShowChangedSize, $wgUser;

$fname = 'ChangesList::recentChangesLineOld';
@@ -321,7 +321,17 @@

$this->insertDateHeader($s,$rc_timestamp);

- $s .= '<li>';
+ // use even/odd class only if linenumber is given (feature from bug 14468)
+ if( $linenumber ) {
+ if( $linenumber & 1 ) {
+ $s .= '<li class="odd">';
+ }
+ else {
+ $s .= '<li class="even">';
+ }
+ } else {
+ $s .= '<li>';
+ }

// Moved pages
if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {

Modified: branches/visual_diff/phase3/includes/Credits.php
===================================================================
--- branches/visual_diff/phase3/includes/Credits.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/Credits.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -144,7 +144,7 @@
# "ThisSite user(s) A, B and C"

if (!empty($user)) {
- $user = wfMsg('siteusers', $user);
+ $user = wfMsgExt('siteusers', array( 'parsemag' ), array( $user, count($contributors) ) );
}

# This is the big list, all mooshed together. We sift for blank strings

Modified: branches/visual_diff/phase3/includes/DefaultSettings.php
===================================================================
--- branches/visual_diff/phase3/includes/DefaultSettings.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/DefaultSettings.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -1382,7 +1382,7 @@
* to ensure that client-side caches don't keep obsolete copies of global
* styles.
*/
-$wgStyleVersion = '165';
+$wgStyleVersion = '166';


# Server-side caching:
@@ -2377,6 +2377,9 @@
/** Name of the external diff engine to use */
$wgExternalDiffEngine = false;

+/** Whether to use inline diff */
+$wgEnableHtmlDiff = false;
+
/** Use RC Patrolling to check for vandalism */
$wgUseRCPatrol = true;

@@ -3154,6 +3157,11 @@
$wgAllowDisplayTitle = true;

/**
+ * for consistency, restrict DISPLAYTITLE to titles that normalize to the same canonical DB key
+ */
+$wgRestrictDisplayTitle = true;
+
+/**
* Array of usernames which may not be registered or logged in from
* Maintenance scripts can still use these
*/

Modified: branches/visual_diff/phase3/includes/Diff.php
===================================================================
--- branches/visual_diff/phase3/includes/Diff.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/Diff.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -566,4 +566,3 @@
$this->rightlength = $rightend-$rightstart;
}
}
-

Modified: branches/visual_diff/phase3/includes/DifferenceEngine.php
===================================================================
--- branches/visual_diff/phase3/includes/DifferenceEngine.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/DifferenceEngine.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -327,7 +327,7 @@


function renderHtmlDiff() {
- global $wgOut, $IP;
+ global $wgOut;
wfProfileIn( __METHOD__ );

$this->showDiffStyle();
@@ -378,7 +378,6 @@

unset($parserOutput,$popts);

- require_once( "$IP/includes/HTMLDiff.php" );
$differ = new HTMLDiffer(new DelegatingContentHandler($wgOut));
$differ->htmlDiff($oldHtml, $newHtml);

@@ -1042,8 +1041,6 @@

if($wgExternalDiffEngine == 'wikidiff3'){
// wikidiff3
- global $IP;
- require_once( "$IP/includes/Diff.php" );
$wikidiff3 = new WikiDiff3();
$wikidiff3->diff($from_lines, $to_lines);
$this->xchanged = $wikidiff3->removed;
@@ -2089,4 +2086,4 @@
}
wfProfileOut( __METHOD__ );
}
-}
+}
\ No newline at end of file

Modified: branches/visual_diff/phase3/includes/LinkCache.php
===================================================================
--- branches/visual_diff/phase3/includes/LinkCache.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/LinkCache.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -9,7 +9,6 @@
// becomes incompatible with the new version.
/* private */ var $mClassVer = 4;

- /* private */ var $mPageLinks;
/* private */ var $mGoodLinks, $mBadLinks;
/* private */ var $mForUpdate;

@@ -26,7 +25,6 @@

function __construct() {
$this->mForUpdate = false;
- $this->mPageLinks = array();
$this->mGoodLinks = array();
$this->mGoodLinkFields = array();
$this->mBadLinks = array();
@@ -78,14 +76,12 @@
$dbkey = $title->getPrefixedDbKey();
$this->mGoodLinks[$dbkey] = $id;
$this->mGoodLinkFields[$dbkey] = array( 'length' => $len, 'redirect' => $redir );
- $this->mPageLinks[$dbkey] = $title;
}

public function addBadLinkObj( $title ) {
$dbkey = $title->getPrefixedDbKey();
if ( ! $this->isBadLink( $dbkey ) ) {
$this->mBadLinks[$dbkey] = 1;
- $this->mPageLinks[$dbkey] = $title;
}
}

@@ -96,7 +92,6 @@
/* obsolete, for old $wgLinkCacheMemcached stuff */
public function clearLink( $title ) {}

- public function getPageLinks() { return $this->mPageLinks; }
public function getGoodLinks() { return $this->mGoodLinks; }
public function getBadLinks() { return array_keys( $this->mBadLinks ); }

@@ -181,7 +176,6 @@
* Clears cache
*/
public function clear() {
- $this->mPageLinks = array();
$this->mGoodLinks = array();
$this->mGoodLinkFields = array();
$this->mBadLinks = array();

Modified: branches/visual_diff/phase3/includes/LinksUpdate.php
===================================================================
--- branches/visual_diff/phase3/includes/LinksUpdate.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/LinksUpdate.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -87,7 +87,7 @@

}

- function doIncrementalUpdate() {
+ protected function doIncrementalUpdate() {
wfProfileIn( __METHOD__ );

# Page links
@@ -158,7 +158,7 @@
* May be slower or faster depending on level of lock contention and write speed of DB
* Also useful where link table corruption needs to be repaired, e.g. in refreshLinks.php
*/
- function doDumbUpdate() {
+ protected function doDumbUpdate() {
wfProfileIn( __METHOD__ );

# Refresh category pages and image description pages

Modified: branches/visual_diff/phase3/includes/MessageCache.php
===================================================================
--- branches/visual_diff/phase3/includes/MessageCache.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/MessageCache.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -44,7 +44,6 @@

/**
* ParserOptions is lazy initialised.
- * Access should probably be protected.
*/
function getParserOptions() {
if ( !$this->mParserOptions ) {

Modified: branches/visual_diff/phase3/includes/StringUtils.php
===================================================================
--- branches/visual_diff/phase3/includes/StringUtils.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/StringUtils.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -167,6 +167,18 @@
$string = str_replace( '$', '\\$', $string );
return $string;
}
+
+ /**
+ * Workalike for explode() with limited memory usage.
+ * Returns an Iterator
+ */
+ static function explode( $separator, $subject ) {
+ if ( substr_count( $subject, $separator ) > 1000 ) {
+ return new ExplodeIterator( $separator, $subject );
+ } else {
+ return new ArrayIterator( explode( $separator, $subject ) );
+ }
+ }
}

/**
@@ -310,3 +322,90 @@
return $result;
}
}
+
+/**
+ * An iterator which works exactly like:
+ *
+ * foreach ( explode( $delim, $s ) as $element ) {
+ * ...
+ * }
+ *
+ * Except it doesn't use 193 byte per element
+ */
+class ExplodeIterator implements Iterator {
+ // The subject string
+ var $subject, $subjectLength;
+
+ // The delimiter
+ var $delim, $delimLength;
+
+ // The position of the start of the line
+ var $curPos;
+
+ // The position after the end of the next delimiter
+ var $endPos;
+
+ // The current token
+ var $current;
+
+ /**
+ * Construct a DelimIterator
+ */
+ function __construct( $delim, $s ) {
+ $this->subject = $s;
+ $this->delim = $delim;
+
+ // Micro-optimisation (theoretical)
+ $this->subjectLength = strlen( $s );
+ $this->delimLength = strlen( $delim );
+
+ $this->rewind();
+ }
+
+ function rewind() {
+ $this->curPos = 0;
+ $this->endPos = strpos( $this->subject, $this->delim );
+ $this->refreshCurrent();
+ }
+
+
+ function refreshCurrent() {
+ if ( $this->curPos === false ) {
+ $this->current = false;
+ } elseif ( $this->curPos >= $this->subjectLength ) {
+ $this->current = '';
+ } elseif ( $this->endPos === false ) {
+ $this->current = substr( $this->subject, $this->curPos );
+ } else {
+ $this->current = substr( $this->subject, $this->curPos, $this->endPos - $this->curPos );
+ }
+ }
+
+ function current() {
+ return $this->current;
+ }
+
+ function key() {
+ return $this->curPos;
+ }
+
+ function next() {
+ if ( $this->endPos === false ) {
+ $this->curPos = false;
+ } else {
+ $this->curPos = $this->endPos + $this->delimLength;
+ if ( $this->curPos >= $this->subjectLength ) {
+ $this->endPos = false;
+ } else {
+ $this->endPos = strpos( $this->subject, $this->delim, $this->curPos );
+ }
+ }
+ $this->refreshCurrent();
+ return $this->current;
+ }
+
+ function valid() {
+ return $this->curPos !== false;
+ }
+}
+

Modified: branches/visual_diff/phase3/includes/Title.php
===================================================================
--- branches/visual_diff/phase3/includes/Title.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/Title.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -10,12 +10,6 @@

define ( 'GAID_FOR_UPDATE', 1 );

-/**
- * Title::newFromText maintains a cache to avoid expensive re-normalization of
- * commonly used titles. On a batch operation this can become a memory leak
- * if not bounded. After hitting this many titles reset the cache.
- */
-define( 'MW_TITLECACHE_MAX', 1000 );

/**
* Constants for pr_cascade bitfield
@@ -36,6 +30,14 @@
//@}

/**
+ * Title::newFromText maintains a cache to avoid expensive re-normalization of
+ * commonly used titles. On a batch operation this can become a memory leak
+ * if not bounded. After hitting this many titles reset the cache.
+ */
+ const CACHE_MAX = 1000;
+
+
+ /**
* @name Private member variables
* Please use the accessor functions instead.
* @private
@@ -131,7 +133,7 @@
static $cachedcount = 0 ;
if( $t->secureAndSplit() ) {
if( $defaultNamespace == NS_MAIN ) {
- if( $cachedcount >= MW_TITLECACHE_MAX ) {
+ if( $cachedcount >= self::CACHE_MAX ) {
# Avoid memory leaks on mass operations...
Title::$titleCache = array();
$cachedcount=0;

Modified: branches/visual_diff/phase3/includes/ZhConversion.php
===================================================================
--- branches/visual_diff/phase3/includes/ZhConversion.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/ZhConversion.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -6228,7 +6228,6 @@
"退烧药" => "退燒藥",
"逋发" => "逋髮",
"透辟" => "透闢",
-"这么着" => "這么著",
"这里" => "這裏",
"这里" => "這裡",
"这只" => "這隻",
@@ -6922,7 +6921,6 @@
"斗斗" => "鬥鬥",
"斗鱼" => "鬥魚",
"斗鹌鹑" => "鬥鵪鶉",
-"闹着玩儿" => "鬧著玩儿",
"闹着玩儿" => "鬧著玩兒",
"闹钟" => "鬧鐘",
"哄动" => "鬨動",
@@ -10695,7 +10693,6 @@
"服务器" => "伺服器",
"等于" => "等於",
"局域网" => "區域網",
-"计算机" => "電腦",
"扫瞄仪" => "掃瞄器",
"宽带" => "寬頻",
"数据库" => "資料庫",
@@ -10753,7 +10750,6 @@
"伯利兹" => "貝里斯",
"伯利茲" => "貝里斯",
"佛得角" => "維德角",
-"佛得角" => "維德角",
"克罗地亚" => "克羅埃西亞",
"克羅地亞" => "克羅埃西亞",
"冈比亚" => "甘比亞",
@@ -10822,17 +10818,14 @@
"尼日尔" => "尼日",
"尼日爾" => "尼日",
"巴巴多斯" => "巴貝多",
-"巴巴多斯" => "巴貝多",
"巴布亚新几内亚" => "巴布亞紐幾內亞",
"巴布亞新畿內亞" => "巴布亞紐幾內亞",
"布基纳法索" => "布吉納法索",
"布基納法索" => "布吉納法索",
"布隆迪" => "蒲隆地",
"布隆迪" => "蒲隆地",
-"希腊" => "希臘",
"帕劳" => "帛琉",
"意大利" => "義大利",
-"意大利" => "義大利",
"所罗门群岛" => "索羅門群島",
"所羅門群島" => "索羅門群島",
"文莱" => "汶萊",
@@ -10886,7 +10879,6 @@
"赞比亚" => "尚比亞",
"贊比亞" => "尚比亞",
"阿塞拜疆" => "亞塞拜然",
-"阿塞拜疆" => "亞塞拜然",
"阿拉伯联合酋长国" => "阿拉伯聯合大公國",
"阿拉伯聯合酋長國" => "阿拉伯聯合大公國",
"马尔代夫" => "馬爾地夫",
@@ -10917,7 +10909,6 @@
"積架" => "捷豹",
"福士" => "福斯",
"雪铁龙" => "雪鐵龍",
-"马自达" => "馬自達",
"萬事得" => "馬自達",
"拿破仑" => "拿破崙",
"拿破侖" => "拿破崙",
@@ -10937,29 +10928,17 @@
"“" => "「",
"‘" => "『",
"’" => "』",
-"凶殺" => "兇殺",
-"凶殘" => "兇殘",
-"緝凶" => "緝兇",
-"買凶" => "買兇",
-"打印机" => "打印機",
"印表機" => "打印機",
"字节" => "位元組",
"字節" => "位元組",
-"打印" => "打印",
"列印" => "打印",
"硬件" => "硬件",
"硬體" => "硬件",
-"二极管" => "二極管",
"二極體" => "二極管",
-"三极管" => "三極管",
"三極體" => "三極管",
-"数码" => "數碼",
"數位" => "數碼",
-"软件" => "軟件",
"軟體" => "軟件",
-"网络" => "網絡",
"網路" => "網絡",
-"人工智能" => "人工智能",
"人工智慧" => "人工智能",
"航天飞机" => "穿梭機",
"太空梭" => "穿梭機",
@@ -10969,141 +10948,88 @@
"機器人" => "機械人",
"移动电话" => "流動電話",
"行動電話" => "流動電話",
-"调制解调器" => "調制解調器",
"數據機" => "調制解調器",
"短信" => "短訊",
"簡訊" => "短訊",
-"乍得" => "乍得",
"查德" => "乍得",
-"也门" => "也門",
"葉門" => "也門",
-"伯利兹" => "伯利茲",
"貝里斯" => "伯利茲",
-"佛得角" => "佛得角",
"維德角" => "佛得角",
-"克罗地亚" => "克羅地亞",
"克羅埃西亞" => "克羅地亞",
-"冈比亚" => "岡比亞",
"甘比亞" => "岡比亞",
-"几内亚比绍" => "幾內亞比紹",
"幾內亞比索" => "幾內亞比紹",
-"列支敦士登" => "列支敦士登",
"列支敦斯登" => "列支敦士登",
-"利比里亚" => "利比里亞",
"賴比瑞亞" => "利比里亞",
-"加纳" => "加納",
"迦納" => "加納",
-"加蓬" => "加蓬",
"加彭" => "加蓬",
-"博茨瓦纳" => "博茨瓦納",
"波札那" => "博茨瓦納",
-"卡塔尔" => "卡塔爾",
"卡達" => "卡塔爾",
-"卢旺达" => "盧旺達",
"盧安達" => "盧旺達",
-"危地马拉" => "危地馬拉",
"瓜地馬拉" => "危地馬拉",
"厄瓜多尔" => "厄瓜多爾",
+"厄瓜多爾" => "厄瓜多爾",
"厄瓜多" => "厄瓜多爾",
-"厄立特里亚" => "厄立特里亞",
"厄利垂亞" => "厄立特里亞",
-"吉布提" => "吉布堤",
"吉布地" => "吉布堤",
-"哥斯达黎加" => "哥斯達黎加",
"哥斯大黎加" => "哥斯達黎加",
-"图瓦卢" => "圖瓦盧",
"吐瓦魯" => "圖瓦盧",
-"圣卢西亚" => "聖盧西亞",
"聖露西亞" => "聖盧西亞",
"圣基茨和尼维斯" => "聖吉斯納域斯",
"聖克里斯多福及尼維斯" => "聖吉斯納域斯",
-"圣文森特和格林纳丁斯" => "聖文森特和格林納丁斯",
"聖文森及格瑞那丁" => "聖文森特和格林納丁斯",
-"圣马力诺" => "聖馬力諾",
"聖馬利諾" => "聖馬力諾",
-"圭亚那" => "圭亞那",
"蓋亞那" => "圭亞那",
-"坦桑尼亚" => "坦桑尼亞",
"坦尚尼亞" => "坦桑尼亞",
-"埃塞俄比亚" => "埃塞俄比亞",
"衣索匹亞" => "埃塞俄比亞",
"衣索比亞" => "埃塞俄比亞",
-"基里巴斯" => "基里巴斯",
"吉里巴斯" => "基里巴斯",
-"狮子山" => "獅子山",
"塞普勒斯" => "塞浦路斯",
-"塞舌尔" => "塞舌爾",
"塞席爾" => "塞舌爾",
"多米尼加" => "多明尼加共和國",
"多明尼加" => "多明尼加共和國",
"多米尼加联邦" => "多明尼加聯邦",
"多米尼克" => "多明尼加聯邦",
-"安提瓜和巴布达" => "安提瓜和巴布達",
"安地卡及巴布達" => "安提瓜和巴布達",
"尼日利亚" => "尼日利亞",
+"尼日利亞" => "尼日利亞",
"奈及利亞" => "尼日利亞",
"尼日尔" => "尼日爾",
+"尼日爾" => "尼日爾",
"尼日" => "尼日爾",
-"巴巴多斯" => "巴巴多斯",
"巴貝多" => "巴巴多斯",
-"巴布亚新几内亚" => "巴布亞新畿內亞",
"巴布亞紐幾內亞" => "巴布亞新畿內亞",
-"布基纳法索" => "布基納法索",
"布吉納法索" => "布基納法索",
-"布隆迪" => "布隆迪",
"蒲隆地" => "布隆迪",
+"帕劳" => "帛琉",
"義大利" => "意大利",
-"所罗门群岛" => "所羅門群島",
"索羅門群島" => "所羅門群島",
-"斯威士兰" => "斯威士蘭",
+"文莱" => "汶萊",
"史瓦濟蘭" => "斯威士蘭",
-"斯洛文尼亚" => "斯洛文尼亞",
"斯洛維尼亞" => "斯洛文尼亞",
-"新西兰" => "新西蘭",
"紐西蘭" => "新西蘭",
-"格林纳达" => "格林納達",
"格瑞那達" => "格林納達",
-"格鲁吉亚" => "喬治亞",
-"格魯吉亞" => "喬治亞",
-"梵蒂冈" => "梵蒂岡",
-"毛里塔尼亚" => "毛里塔尼亞",
"茅利塔尼亞" => "毛里塔尼亞",
"毛里求斯" => "毛里裘斯",
"模里西斯" => "毛里裘斯",
+"沙地阿拉伯" => "沙特阿拉伯",
"沙烏地阿拉伯" => "沙特阿拉伯",
-"波斯尼亚和黑塞哥维那" => "波斯尼亞黑塞哥維那",
"波士尼亞赫塞哥維納" => "波斯尼亞黑塞哥維那",
-"津巴布韦" => "津巴布韋",
"辛巴威" => "津巴布韋",
-"洪都拉斯" => "洪都拉斯",
"宏都拉斯" => "洪都拉斯",
-"特立尼达和托巴哥" => "特立尼達和多巴哥",
"千里達托貝哥" => "特立尼達和多巴哥",
-"瑙鲁" => "瑙魯",
"諾魯" => "瑙魯",
-"瓦努阿图" => "瓦努阿圖",
"萬那杜" => "瓦努阿圖",
-"科摩罗" => "科摩羅",
"葛摩" => "科摩羅",
-"索马里" => "索馬里",
"索馬利亞" => "索馬里",
-"老挝" => "老撾",
"寮國" => "老撾",
"肯尼亚" => "肯雅",
"肯亞" => "肯雅",
-"莫桑比克" => "莫桑比克",
"莫三比克" => "莫桑比克",
-"莱索托" => "萊索托",
"賴索托" => "萊索托",
-"贝宁" => "貝寧",
"貝南" => "貝寧",
-"赞比亚" => "贊比亞",
"尚比亞" => "贊比亞",
-"阿塞拜疆" => "阿塞拜疆",
"亞塞拜然" => "阿塞拜疆",
-"阿拉伯联合酋长国" => "阿拉伯聯合酋長國",
"阿拉伯聯合大公國" => "阿拉伯聯合酋長國",
-"马尔代夫" => "馬爾代夫",
"馬爾地夫" => "馬爾代夫",
"馬利共和國" => "馬里共和國",
"方便面" => "即食麵",
@@ -11135,11 +11061,9 @@
"拿破崙" => "拿破侖",
"布什" => "布殊",
"布希" => "布殊",
-"克林顿" => "克林頓",
"柯林頓" => "克林頓",
"萨达姆" => "薩達姆",
"海珊" => "侯賽因",
-"侯赛因" => "侯賽因",
"大卫·贝克汉姆" => "大衛碧咸",
"迈克尔·欧文" => "米高奧雲",
"珍妮弗·卡普里亚蒂" => "卡佩雅蒂",
@@ -11262,150 +11186,95 @@
"簡訊" => "短信",
"烏茲別克" => "乌兹别克斯坦",
"查德" => "乍得",
-"乍得" => "乍得",
-"也門" => "",
"葉門" => "也门",
"伯利茲" => "伯利兹",
"貝里斯" => "伯利兹",
"維德角" => "佛得角",
-"佛得角" => "佛得角",
-"克羅地亞" => "克罗地亚",
"克羅埃西亞" => "克罗地亚",
-"岡比亞" => "冈比亚",
"甘比亞" => "冈比亚",
-"幾內亞比紹" => "几内亚比绍",
"幾內亞比索" => "几内亚比绍",
"列支敦斯登" => "列支敦士登",
-"列支敦士登" => "列支敦士登",
-"利比里亞" => "利比里亚",
"賴比瑞亞" => "利比里亚",
-"加納" => "加纳",
"迦納" => "加纳",
"加彭" => "加蓬",
-"加蓬" => "加蓬",
-"博茨瓦納" => "博茨瓦纳",
"波札那" => "博茨瓦纳",
-"卡塔爾" => "卡塔尔",
"卡達" => "卡塔尔",
-"盧旺達" => "卢旺达",
"盧安達" => "卢旺达",
-"危地馬拉" => "危地马拉",
"瓜地馬拉" => "危地马拉",
"厄瓜多爾" => "厄瓜多尔",
+"厄瓜多尔" => "厄瓜多尔",
"厄瓜多" => "厄瓜多尔",
-"厄立特里亞" => "厄立特里亚",
"厄利垂亞" => "厄立特里亚",
-"吉布堤" => "吉布提",
"吉布地" => "吉布提",
"哈薩克" => "哈萨克斯坦",
-"哥斯達黎加" => "哥斯达黎加",
"哥斯大黎加" => "哥斯达黎加",
-"圖瓦盧" => "图瓦卢",
"吐瓦魯" => "图瓦卢",
"土庫曼" => "土库曼斯坦",
-"聖盧西亞" => "圣卢西亚",
"聖露西亞" => "圣卢西亚",
"聖吉斯納域斯" => "圣基茨和尼维斯",
"聖克里斯多福及尼維斯" => "圣基茨和尼维斯",
-"聖文森特和格林納丁斯" => "圣文森特和格林纳丁斯",
"聖文森及格瑞那丁" => "圣文森特和格林纳丁斯",
-"聖馬力諾" => "圣马力诺",
"聖馬利諾" => "圣马力诺",
-"圭亞那" => "圭亚那",
"蓋亞那" => "圭亚那",
-"坦桑尼亞" => "坦桑尼亚",
"坦尚尼亞" => "坦桑尼亚",
-"埃塞俄比亞" => "埃塞俄比亚",
"衣索匹亞" => "埃塞俄比亚",
"衣索比亞" => "埃塞俄比亚",
"吉里巴斯" => "基里巴斯",
-"基里巴斯" => "基里巴斯",
"塔吉克" => "塔吉克斯坦",
"塞拉利昂" => "塞拉利昂",
"塞普勒斯" => "塞浦路斯",
-"塞浦路斯" => "塞浦路斯",
-"塞舌爾" => "塞舌尔",
"塞席爾" => "塞舌尔",
"多明尼加共和國" => "多米尼加",
"多明尼加" => "多米尼加",
"多明尼加聯邦" => "多米尼加联邦",
"多米尼克" => "多米尼加联邦",
-"安提瓜和巴布達" => "安提瓜和巴布达",
"安地卡及巴布達" => "安提瓜和巴布达",
"尼日利亞" => "尼日利亚",
+"尼日利亚" => "尼日利亚",
"奈及利亞" => "尼日利亚",
"尼日爾" => "尼日尔",
+"尼日尔" => "尼日尔",
"尼日" => "尼日尔",
"巴貝多" => "巴巴多斯",
-"巴巴多斯" => "巴巴多斯",
-"巴布亞新畿內亞" => "巴布亚新几内亚",
"巴布亞紐幾內亞" => "巴布亚新几内亚",
"布基納法索" => "布基纳法索",
"布吉納法索" => "布基纳法索",
"蒲隆地" => "布隆迪",
-"布隆迪" => "布隆迪",
-"希臘" => "希腊",
"帛琉" => "帕劳",
"義大利" => "意大利",
-"意大利" => "意大利",
-"所羅門群島" => "所罗门群岛",
"索羅門群島" => "所罗门群岛",
"汶萊" => "文莱",
-"斯威士蘭" => "斯威士兰",
"史瓦濟蘭" => "斯威士兰",
-"斯洛文尼亞" => "斯洛文尼亚",
"斯洛維尼亞" => "斯洛文尼亚",
-"新西蘭" => "新西兰",
"紐西蘭" => "新西兰",
-"格林納達" => "格林纳达",
"格瑞那達" => "格林纳达",
-"格魯吉亞" => "乔治亚",
-"喬治亞" => "乔治亚",
-"梵蒂岡" => "梵蒂冈",
-"毛里塔尼亞" => "毛里塔尼亚",
"茅利塔尼亞" => "毛里塔尼亚",
"毛里裘斯" => "毛里求斯",
"模里西斯" => "毛里求斯",
"沙地阿拉伯" => "沙特阿拉伯",
"沙烏地阿拉伯" => "沙特阿拉伯",
-"波斯尼亞黑塞哥維那" => "波斯尼亚和黑塞哥维那",
"波士尼亞赫塞哥維納" => "波斯尼亚和黑塞哥维那",
-"津巴布韋" => "津巴布韦",
"辛巴威" => "津巴布韦",
"宏都拉斯" => "洪都拉斯",
-"洪都拉斯" => "洪都拉斯",
-"特立尼達和多巴哥" => "特立尼达和托巴哥",
"千里達托貝哥" => "特立尼达和托巴哥",
-"瑙魯" => "瑙鲁",
"諾魯" => "瑙鲁",
-"瓦努阿圖" => "瓦努阿图",
"萬那杜" => "瓦努阿图",
"溫納圖" => "瓦努阿图",
-"科摩羅" => "科摩罗",
"葛摩" => "科摩罗",
"象牙海岸" => "科特迪瓦",
"突尼西亞" => "突尼斯",
-"索馬里" => "索马里",
"索馬利亞" => "索马里",
-"老撾" => "老挝",
"寮國" => "老挝",
"肯雅" => "肯尼亚",
"肯亞" => "肯尼亚",
"蘇利南" => "苏里南",
"莫三比克" => "莫桑比克",
-"莫桑比克" => "莫桑比克",
-"萊索托" => "莱索托",
"賴索托" => "莱索托",
-"貝寧" => "贝宁",
"貝南" => "贝宁",
-"贊比亞" => "赞比亚",
"尚比亞" => "赞比亚",
"亞塞拜然" => "阿塞拜疆",
-"阿塞拜疆" => "阿塞拜疆",
-"阿拉伯聯合酋長國" => "阿拉伯联合酋长国",
"阿拉伯聯合大公國" => "阿拉伯联合酋长国",
"南韓" => "韩国",
-"馬爾代夫" => "马尔代夫",
"馬爾地夫" => "马尔代夫",
"馬爾他" => "马耳他",
"馬利共和國" => "马里共和国",
@@ -11415,7 +11284,7 @@
"泡麵" => "方便面",
"笨豬跳" => "蹦极跳",
"绑紧跳" => "蹦极跳",
-"冷盤  " => "凉菜",
+"冷盤" => "凉菜",
"冷菜" => "凉菜",
"散钱" => "零钱",
"谐星" => "笑星",
@@ -11443,16 +11312,12 @@
"積架" => "捷豹",
"福斯" => "大众",
"福士" => "大众",
-"雪鐵龍" => "雪铁龙",
"萬事得" => "马自达",
-"馬自達" => "马自达",
"寶獅" => "标志",
"拿破崙" => "拿破仑",
"布殊" => "布什",
"布希" => "布什",
"柯林頓" => "克林顿",
-"克林頓" => "克林顿",
-"薩達姆" => "萨达姆",
"海珊" => "萨达姆",
"梵谷" => "凡高",
"大衛碧咸" => "大卫·贝克汉姆",
@@ -11472,6 +11337,7 @@
"方便面" => "快速面",
"速食麵" => "快速面",
"即食麵" => "快速面",
+"泡麵" => "快速面",
"蹦极跳" => "绑紧跳",
"笨豬跳" => "绑紧跳",
"凉菜" => "冷菜",
@@ -11483,6 +11349,5 @@
"民乐" => "华乐",
"住房" => "住屋",
"房价" => "屋价",
-"泡麵" => "快速面",

);
\ No newline at end of file

Modified: branches/visual_diff/phase3/includes/api/ApiLogin.php
===================================================================
--- branches/visual_diff/phase3/includes/api/ApiLogin.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/api/ApiLogin.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -139,6 +139,9 @@
$result['result'] = 'CreateBlocked';
$result['details'] = 'Your IP address is blocked from account creation';
break;
+ case LoginForm :: THROTTLED :
+ $result['result'] = 'Throttled';
+ break;
default :
ApiBase :: dieDebug(__METHOD__, 'Unhandled case value');
}

Modified: branches/visual_diff/phase3/includes/api/ApiQuery.php
===================================================================
--- branches/visual_diff/phase3/includes/api/ApiQuery.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/api/ApiQuery.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -229,8 +229,8 @@
* Create instances of all modules requested by the client
*/
private function InstantiateModules(&$modules, $param, $moduleList) {
- $list = $this->params[$param];
- if (isset ($list))
+ $list = @$this->params[$param];
+ if (!is_null ($list))
foreach ($list as $moduleName)
$modules[] = new $moduleList[$moduleName] ($this, $moduleName);
}

Modified: branches/visual_diff/phase3/includes/api/ApiQueryCategories.php
===================================================================
--- branches/visual_diff/phase3/includes/api/ApiQueryCategories.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/api/ApiQueryCategories.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -54,6 +54,7 @@

$params = $this->extractRequestParams();
$prop = $params['prop'];
+ $show = array_flip((array)$params['show']);

$this->addFields(array (
'cl_from',
@@ -91,6 +92,15 @@
"(cl_from = $clfrom AND ".
"cl_to >= '$clto')");
}
+ if(isset($show['hidden']) && isset($show['!hidden']))
+ $this->dieUsage("Incorrect parameter - mutually exclusive values may not be supplied", 'show');
+ if(isset($show['hidden']) || isset($show['!hidden']))
+ {
+ $this->addTables('category');
+ $this->addWhere(array( 'cl_to = cat_title',
+ 'cat_hidden' => isset($show['hidden'])));
+ }
+
# Don't order by cl_from if it's constant in the WHERE clause
if(count($this->getPageSet()->getGoodTitles()) == 1)
$this->addOption('ORDER BY', 'cl_to');
@@ -166,6 +176,13 @@
'timestamp',
)
),
+ 'show' => array(
+ ApiBase :: PARAM_ISMULTI => true,
+ ApiBase :: PARAM_TYPE => array(
+ 'hidden',
+ '!hidden',
+ )
+ ),
'limit' => array(
ApiBase :: PARAM_DFLT => 10,
ApiBase :: PARAM_TYPE => 'limit',
@@ -181,6 +198,7 @@
return array (
'prop' => 'Which additional properties to get for each category.',
'limit' => 'How many categories to return',
+ 'show' => 'Which kind of categories to show',
'continue' => 'When more results are available, use this to continue',
);
}

Modified: branches/visual_diff/phase3/includes/api/ApiQueryLinks.php
===================================================================
--- branches/visual_diff/phase3/includes/api/ApiQueryLinks.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/api/ApiQueryLinks.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -76,9 +76,9 @@
$params = $this->extractRequestParams();

$this->addFields(array (
- $this->prefix . '_from pl_from',
- $this->prefix . '_namespace pl_namespace',
- $this->prefix . '_title pl_title'
+ $this->prefix . '_from AS pl_from',
+ $this->prefix . '_namespace AS pl_namespace',
+ $this->prefix . '_title AS pl_title'
));

$this->addTables($this->table);

Modified: branches/visual_diff/phase3/includes/api/ApiQuerySearch.php
===================================================================
--- branches/visual_diff/phase3/includes/api/ApiQuerySearch.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/api/ApiQuerySearch.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -93,8 +93,9 @@
break;
}

- // Silently skip broken titles
- if ($result->isBrokenTitle()) continue;
+ // Silently skip broken and missing titles
+ if ($result->isBrokenTitle() || $result->isMissingRevision())
+ continue;

$title = $result->getTitle();
if (is_null($resultPageSet)) {

Modified: branches/visual_diff/phase3/includes/parser/CoreParserFunctions.php
===================================================================
--- branches/visual_diff/phase3/includes/parser/CoreParserFunctions.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/parser/CoreParserFunctions.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -56,7 +56,10 @@
static function intFunction( $parser, $part1 = '' /*, ... */ ) {
if ( strval( $part1 ) !== '' ) {
$args = array_slice( func_get_args(), 2 );
- return wfMsgReal( $part1, $args, true );
+ $message = wfMsgGetKey( $part1, true, false, false );
+ $message = $parser->replaceVariables( $message ); // like $wgMessageCache->transform()
+ $message = wfMsgReplaceArgs( $message, $args );
+ return $message;
} else {
return array( 'found' => false );
}
@@ -167,10 +170,16 @@
* @return string
*/
static function displaytitle( $parser, $text = '' ) {
+ global $wgRestrictDisplayTitle;
$text = trim( Sanitizer::decodeCharReferences( $text ) );
- $title = Title::newFromText( $text );
- if( $title instanceof Title && $title->getFragment() == '' && $title->equals( $parser->mTitle ) )
+
+ if ( !$wgRestrictDisplayTitle ) {
$parser->mOutput->setDisplayTitle( $text );
+ } else {
+ $title = Title::newFromText( $text );
+ if( $title instanceof Title && $title->getFragment() == '' && $title->equals( $parser->mTitle ) )
+ $parser->mOutput->setDisplayTitle( $text );
+ }
return '';
}


Copied: branches/visual_diff/phase3/includes/parser/LinkHolderArray.php (from rev 39562, trunk/phase3/includes/parser/LinkHolderArray.php)
===================================================================
--- branches/visual_diff/phase3/includes/parser/LinkHolderArray.php (rev 0)
+++ branches/visual_diff/phase3/includes/parser/LinkHolderArray.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -0,0 +1,406 @@
+<?php
+
+class LinkHolderArray {
+ var $batchSize = 1000;
+
+ var $internals = array(), $interwikis = array();
+ var $size = 0;
+ var $parent;
+
+ function __construct( $parent ) {
+ $this->parent = $parent;
+ }
+
+ /**
+ * Merge another LinkHolderArray into this one
+ */
+ function merge( $other ) {
+ foreach ( $other->internals as $ns => $entries ) {
+ $this->size += count( $entries );
+ if ( !isset( $this->internals[$ns] ) ) {
+ $this->internals[$ns] = $entries;
+ } else {
+ $this->internals[$ns] += $entries;
+ }
+ }
+ $this->interwikis += $other->interwikis;
+ }
+
+ /**
+ * Returns true if the memory requirements of this object are getting large
+ */
+ function isBig() {
+ return $this->size > $this->batchSize;
+ }
+
+ /**
+ * Clear all stored link holders.
+ * Make sure you don't have any text left using these link holders, before you call this
+ */
+ function clear() {
+ $this->internals = array();
+ $this->interwikis = array();
+ $this->size = 0;
+ }
+
+ /**
+ * Make a link placeholder. The text returned can be later resolved to a real link with
+ * replaceLinkHolders(). This is done for two reasons: firstly to avoid further
+ * parsing of interwiki links, and secondly to allow all existence checks and
+ * article length checks (for stub links) to be bundled into a single query.
+ *
+ */
+ function makeHolder( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+ wfProfileIn( __METHOD__ );
+ if ( ! is_object($nt) ) {
+ # Fail gracefully
+ $retVal = "<!-- ERROR -->{$prefix}{$text}{$trail}";
+ } else {
+ # Separate the link trail from the rest of the link
+ list( $inside, $trail ) = Linker::splitTrail( $trail );
+
+ $entry = array(
+ 'title' => $nt,
+ 'text' => $prefix.$text.$inside,
+ 'pdbk' => $nt->getPrefixedDBkey(),
+ );
+ if ( $query !== '' ) {
+ $entry['query'] = $query;
+ }
+
+ if ( $nt->isExternal() ) {
+ // Use a globally unique ID to keep the objects mergable
+ $key = $this->parent->nextLinkID();
+ $this->interwikis[$key] = $entry;
+ $retVal = "<!--IWLINK $key-->{$trail}";
+ } else {
+ $key = $this->parent->nextLinkID();
+ $ns = $nt->getNamespace();
+ $this->internals[$ns][$key] = $entry;
+ $retVal = "<!--LINK $ns:$key-->{$trail}";
+ }
+ $this->size++;
+ }
+ wfProfileOut( __METHOD__ );
+ return $retVal;
+ }
+
+ /**
+ * Replace <!--LINK--> link placeholders with actual links, in the buffer
+ * Placeholders created in Skin::makeLinkObj()
+ * Returns an array of link CSS classes, indexed by PDBK.
+ */
+ function replace( &$text ) {
+ wfProfileIn( __METHOD__ );
+
+ $colours = $this->replaceInternal( $text );
+ $this->replaceInterwiki( $text );
+
+ wfProfileOut( __METHOD__ );
+ return $colours;
+ }
+
+ /**
+ * Replace internal links
+ */
+ protected function replaceInternal( &$text ) {
+ if ( !$this->internals ) {
+ return;
+ }
+
+ wfProfileIn( __METHOD__ );
+ global $wgUser, $wgContLang;
+
+ $pdbks = array();
+ $colours = array();
+ $linkcolour_ids = array();
+ $sk = $this->parent->getOptions()->getSkin();
+ $linkCache = LinkCache::singleton();
+ $output = $this->parent->getOutput();
+
+ wfProfileIn( __METHOD__.'-check' );
+ $dbr = wfGetDB( DB_SLAVE );
+ $page = $dbr->tableName( 'page' );
+ $threshold = $wgUser->getOption('stubthreshold');
+
+ # Sort by namespace
+ ksort( $this->internals );
+
+ # Generate query
+ $query = false;
+ $current = null;
+ foreach ( $this->internals as $ns => $entries ) {
+ foreach ( $entries as $index => $entry ) {
+ $key = "$ns:$index";
+ $title = $entry['title'];
+ $pdbk = $entry['pdbk'];
+
+ # Skip invalid entries.
+ # Result will be ugly, but prevents crash.
+ if ( is_null( $title ) ) {
+ continue;
+ }
+
+ # Check if it's a static known link, e.g. interwiki
+ if ( $title->isAlwaysKnown() ) {
+ $colours[$pdbk] = '';
+ } elseif ( ( $id = $linkCache->getGoodLinkID( $pdbk ) ) != 0 ) {
+ $colours[$pdbk] = '';
+ $output->addLink( $title, $id );
+ } elseif ( $linkCache->isBadLink( $pdbk ) ) {
+ $colours[$pdbk] = 'new';
+ } elseif ( $title->getNamespace() == NS_SPECIAL && !SpecialPage::exists( $pdbk ) ) {
+ $colours[$pdbk] = 'new';
+ } else {
+ # Not in the link cache, add it to the query
+ if ( !isset( $current ) ) {
+ $current = $ns;
+ $query = "SELECT page_id, page_namespace, page_title, page_is_redirect, page_len";
+ $query .= " FROM $page WHERE (page_namespace=$ns AND page_title IN(";
+ } elseif ( $current != $ns ) {
+ $current = $ns;
+ $query .= ")) OR (page_namespace=$ns AND page_title IN(";
+ } else {
+ $query .= ', ';
+ }
+
+ $query .= $dbr->addQuotes( $title->getDBkey() );
+ }
+ }
+ }
+ if ( $query ) {
+ $query .= '))';
+
+ $res = $dbr->query( $query, __METHOD__ );
+
+ # Fetch data and form into an associative array
+ # non-existent = broken
+ while ( $s = $dbr->fetchObject($res) ) {
+ $title = Title::makeTitle( $s->page_namespace, $s->page_title );
+ $pdbk = $title->getPrefixedDBkey();
+ $linkCache->addGoodLinkObj( $s->page_id, $title, $s->page_len, $s->page_is_redirect );
+ $output->addLink( $title, $s->page_id );
+ $colours[$pdbk] = $sk->getLinkColour( $title, $threshold );
+ //add id to the extension todolist
+ $linkcolour_ids[$s->page_id] = $pdbk;
+ }
+ unset( $res );
+ //pass an array of page_ids to an extension
+ wfRunHooks( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
+ }
+ wfProfileOut( __METHOD__.'-check' );
+
+ # Do a second query for different language variants of links and categories
+ if($wgContLang->hasVariants()){
+ $linkBatch = new LinkBatch();
+ $variantMap = array(); // maps $pdbkey_Variant => $keys (of link holders)
+ $categoryMap = array(); // maps $category_variant => $category (dbkeys)
+ $varCategories = array(); // category replacements oldDBkey => newDBkey
+
+ $categories = $output->getCategoryLinks();
+
+ // Add variants of links to link batch
+ foreach ( $this->internals as $ns => $entries ) {
+ foreach ( $entries as $index => $entry ) {
+ $key = "$ns:$index";
+ $pdbk = $entry['pdbk'];
+ $title = $entry['title'];
+ $titleText = $title->getText();
+
+ // generate all variants of the link title text
+ $allTextVariants = $wgContLang->convertLinkToAllVariants($titleText);
+
+ // if link was not found (in first query), add all variants to query
+ if ( !isset($colours[$pdbk]) ){
+ foreach($allTextVariants as $textVariant){
+ if($textVariant != $titleText){
+ $variantTitle = Title::makeTitle( $ns, $textVariant );
+ if(is_null($variantTitle)) continue;
+ $linkBatch->addObj( $variantTitle );
+ $variantMap[$variantTitle->getPrefixedDBkey()][] = $key;
+ }
+ }
+ }
+ }
+ }
+
+ // process categories, check if a category exists in some variant
+ foreach( $categories as $category ){
+ $variants = $wgContLang->convertLinkToAllVariants($category);
+ foreach($variants as $variant){
+ if($variant != $category){
+ $variantTitle = Title::newFromDBkey( Title::makeName(NS_CATEGORY,$variant) );
+ if(is_null($variantTitle)) continue;
+ $linkBatch->addObj( $variantTitle );
+ $categoryMap[$variant] = $category;
+ }
+ }
+ }
+
+
+ if(!$linkBatch->isEmpty()){
+ // construct query
+ $titleClause = $linkBatch->constructSet('page', $dbr);
+
+ $variantQuery = "SELECT page_id, page_namespace, page_title, page_is_redirect, page_len";
+
+ $variantQuery .= " FROM $page WHERE $titleClause";
+
+ $varRes = $dbr->query( $variantQuery, __METHOD__ );
+
+ // for each found variants, figure out link holders and replace
+ while ( $s = $dbr->fetchObject($varRes) ) {
+
+ $variantTitle = Title::makeTitle( $s->page_namespace, $s->page_title );
+ $varPdbk = $variantTitle->getPrefixedDBkey();
+ $vardbk = $variantTitle->getDBkey();
+
+ $holderKeys = array();
+ if(isset($variantMap[$varPdbk])){
+ $holderKeys = $variantMap[$varPdbk];
+ $linkCache->addGoodLinkObj( $s->page_id, $variantTitle, $s->page_len, $s->page_is_redirect );
+ $output->addLink( $variantTitle, $s->page_id );
+ }
+
+ // loop over link holders
+ foreach($holderKeys as $key){
+ list( $ns, $index ) = explode( ':', $key, 2 );
+ $entry =& $this->internals[$ns][$index];
+ $pdbk = $entry['pdbk'];
+
+ if(!isset($colours[$pdbk])){
+ // found link in some of the variants, replace the link holder data
+ $entry['title'] = $variantTitle;
+ $entry['pdbk'] = $varPdbk;
+
+ // set pdbk and colour
+ $colours[$varPdbk] = $sk->getLinkColour( $variantTitle, $threshold );
+ $linkcolour_ids[$s->page_id] = $pdbk;
+ }
+ wfRunHooks( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
+ }
+
+ // check if the object is a variant of a category
+ if(isset($categoryMap[$vardbk])){
+ $oldkey = $categoryMap[$vardbk];
+ if($oldkey != $vardbk)
+ $varCategories[$oldkey]=$vardbk;
+ }
+ }
+
+ // rebuild the categories in original order (if there are replacements)
+ if(count($varCategories)>0){
+ $newCats = array();
+ $originalCats = $output->getCategories();
+ foreach($originalCats as $cat => $sortkey){
+ // make the replacement
+ if( array_key_exists($cat,$varCategories) )
+ $newCats[$varCategories[$cat]] = $sortkey;
+ else $newCats[$cat] = $sortkey;
+ }
+ $this->mOutput->parent->setCategoryLinks($newCats);
+ }
+ }
+ }
+
+ # Construct search and replace arrays
+ wfProfileIn( __METHOD__.'-construct' );
+ $replacePairs = array();
+ foreach ( $this->internals as $ns => $entries ) {
+ foreach ( $entries as $index => $entry ) {
+ $pdbk = $entry['pdbk'];
+ $title = $entry['title'];
+ $query = isset( $entry['query'] ) ? $entry['query'] : '';
+ $key = "$ns:$index";
+ $searchkey = "<!--LINK $key-->";
+ if ( !isset( $colours[$pdbk] ) || $colours[$pdbk] == 'new' ) {
+ $linkCache->addBadLinkObj( $title );
+ $colours[$pdbk] = 'new';
+ $output->addLink( $title, 0 );
+ $replacePairs[$searchkey] = $sk->makeBrokenLinkObj( $title,
+ $entry['text'],
+ $query );
+ } else {
+ $replacePairs[$searchkey] = $sk->makeColouredLinkObj( $title, $colours[$pdbk],
+ $entry['text'],
+ $query );
+ }
+ }
+ }
+ $replacer = new HashtableReplacer( $replacePairs, 1 );
+ wfProfileOut( __METHOD__.'-construct' );
+
+ # Do the thing
+ wfProfileIn( __METHOD__.'-replace' );
+ $text = preg_replace_callback(
+ '/(<!--LINK .*?-->)/',
+ $replacer->cb(),
+ $text);
+
+ wfProfileOut( __METHOD__.'-replace' );
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Replace interwiki links
+ */
+ protected function replaceInterwiki( &$text ) {
+ if ( empty( $this->interwikis ) ) {
+ return;
+ }
+
+ wfProfileIn( __METHOD__ );
+ # Make interwiki link HTML
+ $sk = $this->parent->getOptions()->getSkin();
+ $replacePairs = array();
+ foreach( $this->interwikis as $key => $link ) {
+ $replacePairs[$key] = $sk->link( $link['title'], $link['text'] );
+ }
+ $replacer = new HashtableReplacer( $replacePairs, 1 );
+
+ $text = preg_replace_callback(
+ '/<!--IWLINK (.*?)-->/',
+ $replacer->cb(),
+ $text );
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Replace <!--LINK--> link placeholders with plain text of links
+ * (not HTML-formatted).
+ * @param string $text
+ * @return string
+ */
+ function replaceText( $text ) {
+ wfProfileIn( __METHOD__ );
+
+ $text = preg_replace_callback(
+ '/<!--(LINK|IWLINK) (.*?)-->/',
+ array( &$this, 'replaceTextCallback' ),
+ $text );
+
+ wfProfileOut( __METHOD__ );
+ return $text;
+ }
+
+ /**
+ * @param array $matches
+ * @return string
+ * @private
+ */
+ function replaceTextCallback( $matches ) {
+ $type = $matches[1];
+ $key = $matches[2];
+ if( $type == 'LINK' ) {
+ list( $ns, $index ) = explode( ':', $key, 2 );
+ if( isset( $this->internals[$ns][$index]['text'] ) ) {
+ return $this->internals[$ns][$index]['text'];
+ }
+ } elseif( $type == 'IWLINK' ) {
+ if( isset( $this->interwikis[$key]['text'] ) ) {
+ return $this->interwikis[$key]['text'];
+ }
+ }
+ return $matches[0];
+ }
+}

Modified: branches/visual_diff/phase3/includes/parser/Parser.php
===================================================================
--- branches/visual_diff/phase3/includes/parser/Parser.php 2008-08-17 23:32:07 UTC (rev 39562)
+++ branches/visual_diff/phase3/includes/parser/Parser.php 2008-08-18 00:10:23 UTC (rev 39563)
@@ -98,7 +98,7 @@
# Cleared with clearState():
var $mOutput, $mAutonumber, $mDTopen, $mStripState;
var $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
- var $mInterwikiLinkHolders, $mLinkHolders;
+ var $mLinkHolders, $mLinkID;
var $mIncludeSizes, $mPPNodeCount, $mDefaultSort;
var $mTplExpandCache; // empty-frame expansion cache
var $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores;
@@ -179,17 +179,8 @@
$this->mStripState = new StripState;
$this->mArgStack = false;
$this->mInPre = false;
- $this->mInterwikiLinkHolders = array(
- 'texts' => array(),
- 'titles' => array()
- );
- $this->mLinkHolders = array(
- 'namespaces' => array(),
- 'dbkeys' => array(),
- 'queries' => array(),
- 'texts' => array(),
- 'titles' => array()
- );
+ $this->mLinkHolders = new LinkHolderArray( $this );
+ $this->mLinkID = 0;
$this->mRevisionTimestamp = $this->mRevisionId = null;

/**
@@ -204,7 +195,7 @@
*/
#$this->mUniqPrefix = "\x07UNIQ" . Parser::getRandomString();
# Changed to \x7f to allow XML double-parsing -- TS
- $this->mUniqPrefix = "\x7fUNIQ" . Parser::getRandomString();
+ $this->mUniqPrefix = "\x7fUNIQ" . self::getRandomString();


# Clear these on every parse, bug 4549
@@ -294,7 +285,7 @@
*/

global $wgUseTidy, $wgAlwaysUseTidy, $wgContLang;
- $fname = 'Parser::parse-' . wfGetCaller();
+ $fname = __METHOD__.'-' . wfGetCaller();
wfProfileIn( __METHOD__ );
wfProfileIn( $fname );

@@ -328,7 +319,6 @@
);
$text = preg_replace( array_keys($fixtags), array_values($fixtags), $text );

- # only once and last
$text = $this->doBlockLevels( $text, $linestart );

$this->replaceLinkHolders( $text );
@@ -348,7 +338,7 @@
$uniq_prefix = $this->mUniqPrefix;
$matches = array();
$elements = array_keys( $this->mTransparentTagHooks );
- $text = Parser::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
+ $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );

foreach( $matches as $marker => $data ) {
list( $element, $content, $params, $tag ) = $data;
@@ -366,7 +356,7 @@
$text = Sanitizer::normalizeCharReferences( $text );

if (($wgUseTidy and $this->mOptions->mTidy) or $wgAlwaysUseTidy) {
- $text = Parser::tidy($text);
+ $text = self::tidy($text);
} else {
# attempt to sanitize at least some nesting problems
# (bug #2702 and quite a few others)
@@ -471,6 +461,8 @@
function &getTitle() { return $this->mTitle; }
function getOptions() { return $this->mOptions; }
function getRevisionId() { return $this->mRevisionId; }
+ function getOutput() { return $this->mOutput; }
+ function nextLinkID() { return $this->mLinkID++; }

function getFunctionLang() {
global $wgLang, $wgContLang;
@@ -658,9 +650,9 @@
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>'.
'<head><title>test</title></head><body>'.$text.'</body></html>';
if( $wgTidyInternal ) {
- $correctedtext = Parser::internalTidy( $wrappedtext );
+ $correctedtext = self::internalTidy( $wrappedtext );
} else {
- $correctedtext = Parser::externalTidy( $wrappedtext );
+ $correctedtext = self::externalTidy( $wrappedtext );
}
if( is_null( $correctedtext ) ) {
wfDebug( "Tidy error detected!\n" );
@@ -677,8 +669,7 @@
*/
function externalTidy( $text ) {
global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
- $fname = 'Parser::externalTidy';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

$cleansource = '';
$opts = ' -utf8';
@@ -707,7 +698,7 @@
}
}

- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );

if( $cleansource == '' && $text != '') {
// Some kind of error happened, so we couldn't get the corrected text.
@@ -729,8 +720,7 @@
*/
function internalTidy( $text ) {
global $wgTidyConf, $IP, $wgDebugTidy;
- $fname = 'Parser::internalTidy';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

$tidy = new tidy;
$tidy->parseString( $text, $wgTidyConf, 'utf8' );
@@ -748,7 +738,7 @@
"\n-->";
}

- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $cleansource;
}

@@ -758,34 +748,35 @@
* @private
*/
function doTableStuff ( $text ) {
- $fname = 'Parser::doTableStuff';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

- $lines = explode ( "\n" , $text );
+ $lines = StringUtils::explode( "\n", $text );
+ $out = '';
$td_history = array (); // Is currently a td tag open?
$last_tag_history = array (); // Save history of last lag activated (td, th or caption)
$tr_history = array (); // Is currently a tr tag open?
$tr_attributes = array (); // history of tr attributes
$has_opened_tr = array(); // Did this table open a <tr> element?
$indent_level = 0; // indent level of the table
- foreach ( $lines as $key => $line )
- {
- $line = trim ( $line );

+ foreach ( $lines as $outLine ) {
+ $line = trim( $outLine );
+
if( $line == '' ) { // empty line, go to next line
+ $out .= "\n";
continue;
}
- $first_character = $line{0};
+ $first_character = $line[0];
$matches = array();

- if ( preg_match( '/^(:*)\{\|(.*)$/' , $line , $matches ) ) {
+ if ( preg_match( '/^(:*)\{\|(.*)$/', $line , $matches ) ) {
// First check if we are starting a new table
$indent_level = strlen( $matches[1] );

$attributes = $this->mStripState->unstripBoth( $matches[2] );
$attributes = Sanitizer::fixTagAttributes ( $attributes , 'table' );

- $lines[$key] = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>";
+ $outLine = str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>";
array_push ( $td_history , false );
array_push ( $last_tag_history , '' );
array_push ( $tr_history , false );
@@ -793,6 +784,7 @@
array_push ( $has_opened_tr , false );
} else if ( count ( $td_history ) == 0 ) {
// Don't do any of the following
+ $out .= $outLine."\n";
continue;
} else if ( substr ( $line , 0 , 2 ) == '|}' ) {
// We are ending a table
@@ -811,7 +803,7 @@
$line = "</{$last_tag}>{$line}";
}
array_pop ( $tr_attributes );
- $lines[$key] = $line . str_repeat( '</dd></dl>' , $indent_level );
+ $outLine = $line . str_repeat( '</dd></dl>' , $indent_level );
} else if ( substr ( $line , 0 , 2 ) == '|-' ) {
// Now we have a table row
$line = preg_replace( '#^\|-+#', '', $line );
@@ -835,7 +827,7 @@
$line = "</{$last_tag}>{$line}";
}

- $lines[$key] = $line;
+ $outLine = $line;
array_push ( $tr_history , false );
array_push ( $td_history , false );
array_push ( $last_tag_history , '' );
@@ -859,7 +851,7 @@
// attribute values containing literal "||".
$cells = StringUtils::explodeMarkup( '||' , $line );

- $lines[$key] = '';
+ $outLine = '';

// Loop through each table cell
foreach ( $cells as $cell )
@@ -910,38 +902,42 @@
$cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}";
}

- $lines[$key] .= $cell;
+ $outLine .= $cell;
array_push ( $td_history , true );
}
}
+ $out .= $outLine . "\n";
}

// Closing open td, tr && table
while ( count ( $td_history ) > 0 )
{
if ( array_pop ( $td_history ) ) {
- $lines[] = '</td>' ;
+ $out .= "</td>\n";
}
if ( array_pop ( $tr_history ) ) {
- $lines[] = '</tr>' ;
+ $out .= "</tr>\n";
}
if ( !array_pop ( $has_opened_tr ) ) {
- $lines[] = "<tr><td></td></tr>" ;
+ $out .= "<tr><td></td></tr>\n" ;
}

- $lines[] = '</table>' ;
+ $out .= "</table>\n";
}

- $output = implode ( "\n" , $lines ) ;
+ // Remove trailing line-ending (b/c)
+ if ( substr( $out, -1 ) == "\n" ) {
+ $out = substr( $out, 0, -1 );
+ }

// special case: don't return empty table
- if( $output == "<table>\n<tr><td></td></tr>\n</table>" ) {
- $output = '';
+ if( $out == "<table>\n<tr><td></td></tr>\n</table>" ) {
+ $out = '';
}

- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );

- return $output;
+ return $out;
}

/**
@@ -952,12 +948,11 @@
*/
function internalParse( $text ) {
$isMain = true;
- $fname = 'Parser::internalParse';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

# Hook to suspend the parser in this state
if ( !wfRunHooks( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $text ;
}

@@ -990,7 +985,7 @@
$text = $this->doMagicLinks( $text );
$text = $this->formatHeadings( $text, $isMain );

- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $text;
}

@@ -1060,14 +1055,13 @@
* @private
*/
function doHeadings( $text ) {
- $fname = 'Parser::doHeadings';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );
for ( $i = 6; $i >= 1; --$i ) {
$h = str_repeat( '=', $i );
$text = preg_replace( "/^$h(.+)$h\\s*$/m",
"<h$i>\\1</h$i>", $text );
}
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $text;
}

@@ -1077,15 +1071,14 @@
* @return string the altered text
*/
function doAllQuotes( $text ) {
- $fname = 'Parser::doAllQuotes';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );
$outtext = '';
- $lines = explode( "\n", $text );
+ $lines = StringUtils::explode( "\n", $text );
foreach ( $lines as $line ) {
- $outtext .= $this->doQuotes ( $line ) . "\n";
+ $outtext .= $this->doQuotes( $line ) . "\n";
}
$outtext = substr($outtext, 0,-1);
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $outtext;
}

@@ -1264,8 +1257,7 @@
*/
function replaceExternalLinks( $text ) {
global $wgContLang;
- $fname = 'Parser::replaceExternalLinks';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

$sk = $this->mOptions->getSkin();

@@ -1335,11 +1327,11 @@
# Register link in the output object.
# Replace unnecessary URL escape codes with the referenced character
# This prevents spammers from hiding links from the filters
- $pasteurized = Parser::replaceUnusualEscapes( $url );
+ $pasteurized = self::replaceUnusualEscapes( $url );
$this->mOutput->addExternalLink( $pasteurized );
}

- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $s;
}

@@ -1349,8 +1341,7 @@
*/
function replaceFreeExternalLinks( $text ) {
global $wgContLang;
- $fname = 'Parser::replaceFreeExternalLinks';
- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

$bits = preg_split( '/(\b(?:' . wfUrlProtocols() . '))/S', $text, -1, PREG_SPLIT_DELIM_CAPTURE );
$s = array_shift( $bits );
@@ -1412,7 +1403,7 @@
$text = $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free', $this->mTitle->getNamespace() );
# Register it in the output object...
# Replace unnecessary URL escape codes with their equivalent characters
- $pasteurized = Parser::replaceUnusualEscapes( $url );
+ $pasteurized = self::replaceUnusualEscapes( $url );
$this->mOutput->addExternalLink( $pasteurized );
}
$s .= $text . $trail;
@@ -1420,7 +1411,7 @@
$s .= $protocol . $remainder;
}
}
- wfProfileOut( $fname );
+ wfProfileOut( __METHOD__ );
return $s;
}

@@ -1436,7 +1427,7 @@
*/
static function replaceUnusualEscapes( $url ) {
return preg_replace_callback( '/%[0-9A-Fa-f]{2}/',
- array( 'Parser', 'replaceUnusualEscapesCallback' ), $url );
+ array( __CLASS__, 'replaceUnusualEscapesCallback' ), $url );
}

/**
@@ -1480,35 +1471,48 @@

/**
* Process [[ ]] wikilinks
+ * @return processed text
*
* @private
*/
function replaceInternalLinks( $s ) {
+ $this->mLinkHolders->merge( $this->replaceInternalLinks2( $s ) );
+ return $s;
+ }
+
+ /**
+ * Process [[ ]] wikilinks
+ * @return LinkHolderArray
+ *
+ * @private
+ */
+ function replaceInternalLinks2( &$s ) {
global $wgContLang;
- static $fname = 'Parser::replaceInternalLinks' ;

- wfProfileIn( $fname );
+ wfProfileIn( __METHOD__ );

- wfProfileIn( $fname.'-setup' );
- static $tc = FALSE;
+ wfProfileIn( __METHOD__.'-setup' );
+ static $tc = FALSE, $e1, $e1_img;
# the % is needed to support urlencoded titles as well
- if ( !$tc ) { $tc = Title::legalChars() . '#%'; }
+ if ( !$tc ) {
+ $tc = Title::legalChars() . '#%';
+ # Match a link having the form [[namespace:link|alternate]]trail
+ $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD";
+ # Match cases where there is no "]]", which might still be images
+ $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD";
+ }

$sk = $this->mOptions->getSkin();
+ $holders = new LinkHolderArray( $this );

#split the entire text string on occurences of [.[.
- $a = explode( '[.[.', ' ' . $s );
+ $a = StringUtils::explode( '[.[.', ' ' . $s );
#get the first element (all text up to first [.[.), and remove the space we added
- $s = array_shift( $a );
+ $s = $a->current();
+ $a->next();
+ $line = $a->current(); # Workaround for broken ArrayIterator::next() that returns "void"
$s = substr( $s, 1 );

- # Match a link having the form [[namespace:link|alternate]]trail
- static $e1 = FALSE;
- if ( !$e1 ) { $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; }
- # Match cases where there is no "]]", which might still be images
- static $e1_img = FALSE;
- if ( !$e1_img ) { $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; }
-
$useLinkPrefixExtension = $wgContLang->linkPrefixExtension();
$e2 = null;
if ( $useLinkPrefixExtension ) {
@@ -1518,8 +1522,8 @@
}

if( is_null( $this->mTitle ) ) {
- wfProfileOut( $fname );
- wfProfileOut( $fname.'-setup' );
+ wfProfileOut( __METHOD__ );
+ wfProfileOut( __METHOD__.'-setup' );
throw new MWException( __METHOD__.": \$this->mTitle is null\n" );
}
$nottalk = !$this->mTitle->isTalkPage();
@@ -1541,13 +1545,20 @@
$selflink = array($this->mTitle->getPrefixedText());
}
$useSubpages = $this->areSubpagesAllowed();
- wfProfileOut( $fname.'-setup' );
+ wfProfileOut( __METHOD__.'-setup' );

# Loop for each link
- for ($k = 0; isset( $a[$k] ); $k++) {
- $line = $a[$k];
+ for ( ; $line !== false && $line !== null ; $a->next(), $line = $a->current() ) {
+ # Check for excessive memory usage
+ if ( $holders->isBig() ) {
+ # Too big
+ # Do the existence check, replace the link holders and clear the array
+ $holders->replace( $s );
+ $holders->clear();
+ }
+
if ( $useLinkPrefixExtension ) {
- wfProfileIn( $fname.'-prefixhandling' );
+ wfProfileIn( __METHOD__.'-prefixhandling' );
if ( preg_match( $e2, $s, $m ) ) {
$prefix = $m[2];
$s = $m[1];
@@ -1559,12 +1570,12 @@
$prefix = $first_prefix;
$first_prefix = false;
}
- wfProfileOut( $fname.'-prefixhandling' );
+ wfProfileOut( __METHOD__.'-prefixhandling' );
}

$might_be_img = false;

- wfProfileIn( "$fname-e1" );
+ wfProfileIn( __METHOD__."-e1" );
if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt
$text = $m[2];
# If we get a ] at the beginning of $m[3] that means we have a link that's something like:
@@ -1598,18 +1609,18 @@
$trail = "";
} else { # Invalid form; output directly
$s .= $prefix . '[.[.' . $line ;
- wfProfileOut( "$fname-e1" );
+ wfProfileOut( __METHOD__."-e1" );
continue;
}
- wfProfileOut( "$fname-e1" );
- wfProfileIn( "$fname-misc" );
+ wfProfileOut( __METHOD__."-e1" );
+ wfProfileIn( __METHOD__."-misc" );

# Don't allow internal links to pages containing
# PROTO: where PROTO is a valid URL protocol; these
# should be external links.
if (preg_match('/^\b(?:' . wfUrlProtocols() . ')/', $m[1])) {
$s .= $prefix . '[.[.' . $line ;
- wfProfileOut( "$fname-misc" );
+ wfProfileOut( __METHOD__."-misc" );
continue;
}

@@ -1626,27 +1637,30 @@
$link = substr($link, 1);
}

- wfProfileOut( "$fname-misc" );
- wfProfileIn( "$fname-title" );
+ wfProfileOut( __METHOD__."-misc" );
+ wfProfileIn( __METHOD__."-title" );
$nt = Title::newFromText( $this->mStripState->unstripNoWiki($link) );
if( !$nt ) {
$s .= $prefix . '[.[.' . $line;
- wfProfileOut( "$fname-title" );
+ wfProfileOut( __METHOD__."-title" );
continue;
}

$ns = $nt->getNamespace();
$iw = $nt->getInterWiki();
- wfProfileOut( "$fname-title" );
+ wfProfileOut( __METHOD__."-title" );

if ($might_be_img) { # if this is actually an invalid link
- wfProfileIn( "$fname-might_be_img" );
+ wfProfileIn( __METHOD__."-might_be_img" );
if ($ns == NS_IMAGE && $noforce) { #but might be an image
$found = false;
- while (isset ($a[$k+1]) ) {
+ while ( true ) {
#look at the next 'line' to see if we can close it there
- $spliced = array_splice( $a, $k + 1, 1 );
- $next_line = array_shift( $spliced );
+ $a->next();
+ $next_line = $a->current();
+ if ( $next_line === false || $next_line === null ) {
+ break;
+ }
$m = explode( ']]', $next_line, 3 );
if ( count( $m ) == 3 ) {
# the first ]] closes the inner link, the second the image
@@ -1666,19 +1680,19 @@
if ( !$found ) {
# we couldn't find the end of this imageLink, so output it raw
#but don't ignore what might be perfectly normal links in the text we've examined
- $text = $this->replaceInternalLinks($text);
+ $holders->merge( $this->replaceInternalLinks2( $text ) );
$s .= "{$prefix}[[$link|$text";
# note: no $trail, because without an end, there *is* no trail
- wfProfileOut( "$fname-might_be_img" );
+ wfProfileOut( __METHOD__."-might_be_img" );
continue;
}
} else { #it's not an image, so output it raw
$s .= "{$prefix}[[$link|$text";
# note: no $trail, because without an end, there *is* no trail
- wfProfileOut( "$fname-might_be_img" );
+ wfProfileOut( __METHOD__."-might_be_img" );
continue;
}
- wfProfileOut( "$fname-might_be_img" );
+ wfProfileOut( __METHOD__."-might_be_img" );
}

$wasblank = ( '' == $text );
@@ -1688,41 +1702,38 @@
if( $noforce ) {

# Interwikis
- wfProfileIn( "$fname-interwiki" );
+ wfProfileIn( __METHOD__."-interwiki" );
if( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
$this->mOutput->addLanguageLink( $nt->getFullText() );
$s = rtrim($s . $prefix);
$s .= trim($trail, "\n") == '' ? '': $prefix . $trail;
- wfProfileOut( "$fname-interwiki" );
+ wfProfileOut( __METHOD__."-interwiki" );
continue;
}
- wfProfileOut( "$fname-interwiki" );
+ wfProfileOut( __METHOD__."-interwiki" );

if ( $ns == NS_IMAGE ) {
- wfProfileIn( "$fname-image" );
+ wfProfileIn( __METHOD__."-image" );
if ( !wfIsBadImage( $nt->getDBkey(), $this->mTitle ) ) {
# recursively parse links inside the image caption
# actually, this will parse them in any other parameters, too,
# but it might be hard to fix that, and it doesn't matter ATM
$text = $this->replaceExternalLinks($text);
- $text = $this->replaceInternalLinks($text);
+ $holders->merge( $this->replaceInternalLinks2( $text ) );

# cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them
- $s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text ) ) . $trail;
- $this->mOutput->addImage( $nt->getDBkey() );
+ $s .= $prefix . $this->armorLinks( $this->makeImage( $nt, $text, $holders ) ) . $trail;

- wfProfileOut( "$fname-image" );
- continue;
- } else {
- # We still need to record the image's presence on the page
- $this->mOutput->addImage( $nt->getDBkey() );
+ wfProfileOut( __METHOD__."-image" );
}
- wfProfileOut( "$fname-image" );
+ $this->mOutput->addImage( $nt->getDBkey() );
+ wfProfileOut( __METHOD__."-image" );
+ continue;

}

if ( $ns == NS_CATEGORY ) {
- wfProfileIn( "$fname-category" );
+ wfProfileIn( __METHOD__."-category" );
$s = rtrim($s . "\n"); # bug 87

if ( $wasblank ) {
@@ -1741,7 +1752,7 @@
*/
$s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;

- wfProfileOut( "$fname-category" );
+