From 2f12a58d93a4783acb97956c945d0f28875e42c4 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Tue, 21 Nov 2006 09:53:45 +0000 Subject: [PATCH] * Introduced StringUtils.php, populated it with some generic string functions, both new and collected from various other files. * Removed some backtracking regexes with an O(N^2) worst case, replaced with StringUtils::delimiterReplace(). There is a beneficial functional difference: /*/ is no longer considered to be a complete CSS comment. * Changed the parser strip state from an array to an object. This should hopefully avoid the PHP bugs with array references. StripState uses the new ReplacementArray to do the replacements, thereby supporting FSS. * Removed DatabaseFunctions.php from the default startup sequence. Moved wfGetDB() to GlobalFunctions.php. * Introduced the SiteStats class, with a collection of cached site stats accessor functions. * Removed all global functions from Parser.php, they don't belong there. * Made LanguageConverter use the new ReplacementArray class instead of managing its own FSS objects. --- includes/AutoLoader.php | 10 +- includes/BagOStuff.php | 5 +- includes/Block.php | 2 +- includes/CoreParserFunctions.php | 16 +- includes/Database.php | 4 +- includes/DatabaseFunctions.php | 14 +- includes/GlobalFunctions.php | 61 +-- includes/Image.php | 2 +- includes/Linker.php | 2 +- includes/MagicWord.php | 2 +- includes/Parser.php | 371 ++++++------------ includes/Sanitizer.php | 5 +- .../{SiteStatsUpdate.php => SiteStats.php} | 80 +++- includes/SpecialStatistics.php | 39 +- includes/SpecialWatchlist.php | 4 +- includes/Xml.php | 14 + languages/LanguageConverter.php | 47 +-- languages/classes/LanguageKk.php | 11 +- languages/classes/LanguageSr.php | 17 +- languages/classes/LanguageZh.php | 17 +- maintenance/namespace2sql.php | 4 +- 21 files changed, 315 insertions(+), 412 deletions(-) rename includes/{SiteStatsUpdate.php => SiteStats.php} (57%) diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 15fe3e79d1..f826ec1c2c 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -86,7 +86,6 @@ function __autoload($className) { 'FileStore' => 'includes/FileStore.php', 'FSException' => 'includes/FileStore.php', 'FSTransaction' => 'includes/FileStore.php', - 'ReplacerCallback' => 'includes/GlobalFunctions.php', 'HTMLForm' => 'includes/HTMLForm.php', 'HistoryBlob' => 'includes/HistoryBlob.php', 'ConcatenatedGzipHistoryBlob' => 'includes/HistoryBlob.php', @@ -150,7 +149,8 @@ function __autoload($className) { 'SearchUpdate' => 'includes/SearchUpdate.php', 'SearchUpdateMyISAM' => 'includes/SearchUpdate.php', 'SiteConfiguration' => 'includes/SiteConfiguration.php', - 'SiteStatsUpdate' => 'includes/SiteStatsUpdate.php', + 'SiteStats' => 'includes/SiteStats.php', + 'SiteStatsUpdate' => 'includes/SiteStats.php', 'Skin' => 'includes/Skin.php', 'MediaWiki_I18N' => 'includes/SkinTemplate.php', 'SkinTemplate' => 'includes/SkinTemplate.php', @@ -215,6 +215,12 @@ function __autoload($className) { 'WantedPagesPage' => 'includes/SpecialWantedpages.php', 'WhatLinksHerePage' => 'includes/SpecialWhatlinkshere.php', 'SquidUpdate' => 'includes/SquidUpdate.php', + 'ReplacementArray' => 'includes/StringUtils.php', + 'Replacer' => 'includes/StringUtils.php', + 'RegexlikeReplacer' => 'includes/StringUtils.php', + 'DoubleReplacer' => 'includes/StringUtils.php', + 'HashtableReplacer' => 'includes/StringUtils.php', + 'StringUtils' => 'includes/StringUtils.php', 'Title' => 'includes/Title.php', 'User' => 'includes/User.php', 'MailAddress' => 'includes/UserMailer.php', diff --git a/includes/BagOStuff.php b/includes/BagOStuff.php index 1dc93a2fb0..75951268ca 100644 --- a/includes/BagOStuff.php +++ b/includes/BagOStuff.php @@ -492,11 +492,14 @@ class TurckBagOStuff extends BagOStuff { class APCBagOStuff extends BagOStuff { function get($key) { $val = apc_fetch($key); + if ( is_string( $val ) ) { + $val = unserialize( $val ); + } return $val; } function set($key, $value, $exptime=0) { - apc_store($key, $value, $exptime); + apc_store($key, serialize($value), $exptime); return true; } diff --git a/includes/Block.php b/includes/Block.php index 39ebe04c8b..547bf53a12 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -338,7 +338,7 @@ class Block call_user_func( $callback, $block, $tag ); } } - wfFreeResult( $res ); + $db->freeResult( $res ); return $num_rows; } diff --git a/includes/CoreParserFunctions.php b/includes/CoreParserFunctions.php index b2ee789dd2..c0cdba9546 100644 --- a/includes/CoreParserFunctions.php +++ b/includes/CoreParserFunctions.php @@ -126,21 +126,21 @@ class CoreParserFunctions { function statisticsFunction( $func, $raw = null ) { if ( self::isRaw( $raw ) ) { - return call_user_func( $func ); + return call_user_func( array( 'SiteStats', $func ) ); } else { global $wgContLang; - return $wgContLang->formatNum( call_user_func( $func ) ); + return $wgContLang->formatNum( call_user_func( array( 'SiteStats', $func ) ) ); } } - function numberofpages( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfPages', $raw ); } - function numberofusers( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfUsers', $raw ); } - function numberofarticles( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfArticles', $raw ); } - function numberoffiles( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfFiles', $raw ); } - function numberofadmins( $parser, $raw = null ) { return self::statisticsFunction( 'wfNumberOfAdmins', $raw ); } + function numberofpages( $parser, $raw = null ) { return self::statisticsFunction( 'pages', $raw ); } + function numberofusers( $parser, $raw = null ) { return self::statisticsFunction( 'users', $raw ); } + function numberofarticles( $parser, $raw = null ) { return self::statisticsFunction( 'articles', $raw ); } + function numberoffiles( $parser, $raw = null ) { return self::statisticsFunction( 'images', $raw ); } + function numberofadmins( $parser, $raw = null ) { return self::statisticsFunction( 'admins', $raw ); } function pagesinnamespace( $parser, $namespace = 0, $raw = null ) { - $count = wfPagesInNs( intval( $namespace ) ); + $count = SiteStats::pagesInNs( intval( $namespace ) ); if ( self::isRaw( $raw ) ) { global $wgContLang; return $wgContLang->formatNum( $count ); diff --git a/includes/Database.php b/includes/Database.php index 7b6df376e0..d8f7757f78 100644 --- a/includes/Database.php +++ b/includes/Database.php @@ -295,7 +295,7 @@ class Database { * Turns on (false) or off (true) the automatic generation and sending * of a "we're sorry, but there has been a database error" page on * database errors. Default is on (false). When turned off, the - * code should use wfLastErrno() and wfLastError() to handle the + * code should use lastErrno() and lastError() to handle the * situation as appropriate. */ function ignoreErrors( $ignoreErrors = NULL ) { @@ -1296,7 +1296,7 @@ class Database { } /** - * Makes a wfStrencoded list from an array + * Makes an encoded list of strings from an array * $mode: * LIST_COMMA - comma separated, no field names * LIST_AND - ANDed WHERE clause (without the WHERE) diff --git a/includes/DatabaseFunctions.php b/includes/DatabaseFunctions.php index 74b35a31bf..c9dc9e7259 100644 --- a/includes/DatabaseFunctions.php +++ b/includes/DatabaseFunctions.php @@ -1,8 +1,7 @@ getConnection( $db, true, $groups ); - return $ret; -} - /** * Turns on (false) or off (true) the automatic generation and sending * of a "we're sorry, but there has been a database error" page on diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index d6ee0d7846..663273585f 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -26,7 +26,6 @@ $wgTotalViews = -1; $wgTotalEdits = -1; -require_once( 'DatabaseFunctions.php' ); require_once( 'LogPage.php' ); require_once( 'normal/UtfNormalUtil.php' ); require_once( 'XmlFunctions.php' ); @@ -1736,16 +1735,10 @@ function wfUseMW( $req_ver ) { } /** - * Escape a string to make it suitable for inclusion in a preg_replace() - * replacement parameter. - * - * @param string $string - * @return string + * @deprecated use StringUtils::escapeRegexReplacement */ function wfRegexReplacement( $string ) { - $string = str_replace( '\\', '\\\\', $string ); - $string = str_replace( '$', '\\$', $string ); - return $string; + return StringUtils::escapeRegexReplacement( $string ); } /** @@ -1815,42 +1808,12 @@ function wfDoUpdates() } /** - * More or less "markup-safe" explode() - * Ignores any instances of the separator inside <...> - * @param string $separator - * @param string $text - * @return array + * @deprecated use StringUtils::explodeMarkup */ function wfExplodeMarkup( $separator, $text ) { - $placeholder = "\x00"; - - // Just in case... - $text = str_replace( $placeholder, '', $text ); - - // Trim stuff - $replacer = new ReplacerCallback( $separator, $placeholder ); - $cleaned = preg_replace_callback( '/(<.*?>)/', array( $replacer, 'go' ), $text ); - - $items = explode( $separator, $cleaned ); - foreach( $items as $i => $str ) { - $items[$i] = str_replace( $placeholder, $separator, $str ); - } - - return $items; + return StringUtils::explodeMarkup( $separator, $text ); } -class ReplacerCallback { - function ReplacerCallback( $from, $to ) { - $this->from = $from; - $this->to = $to; - } - - function go( $matches ) { - return str_replace( $this->from, $this->to, $matches[1] ); - } -} - - /** * Convert an arbitrarily-long digit string from one numeric base * to another, optionally zero-padding to a minimum column width. @@ -2074,4 +2037,20 @@ function wfWikiID() { } } +/* + * Get a Database object + * @param integer $db Index of the connection to get. May be DB_MASTER for the + * master (for write queries), DB_SLAVE for potentially lagged + * read queries, or an integer >= 0 for a particular server. + * + * @param array $groups Query groups. A list of group names that this query + * belongs to. + */ +function &wfGetDB( $db = DB_LAST, $groups = array() ) { + global $wgLoadBalancer; + $ret =& $wgLoadBalancer->getConnection( $db, true, $groups ); + return $ret; +} + + ?> diff --git a/includes/Image.php b/includes/Image.php index b2a63968ae..c03466b2b7 100644 --- a/includes/Image.php +++ b/includes/Image.php @@ -1462,7 +1462,7 @@ class Image array( 'img_name' => $this->title->getDBkey() ), __METHOD__ ); - if ( 0 == wfNumRows( $this->historyRes ) ) { + if ( 0 == $dbr->numRows( $this->historyRes ) ) { return FALSE; } } else if ( $this->historyLine == 1 ) { diff --git a/includes/Linker.php b/includes/Linker.php index 2a50547d61..f4e52ea509 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -959,7 +959,7 @@ class Linker { $match[1] = substr($match[1], 1); $thelink = $this->makeLink( $match[1], $text, "", $trail ); } - $comment = preg_replace( $linkRegexp, wfRegexReplacement( $thelink ), $comment, 1 ); + $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 ); } wfProfileOut( __METHOD__ ); return $comment; diff --git a/includes/MagicWord.php b/includes/MagicWord.php index 68cbe34531..350fb8ed16 100644 --- a/includes/MagicWord.php +++ b/includes/MagicWord.php @@ -298,7 +298,7 @@ class MagicWord { * Replaces the word with something else */ function replace( $replacement, $subject, $limit=-1 ) { - $res = preg_replace( $this->getRegex(), wfRegexReplacement( $replacement ), $subject, $limit ); + $res = preg_replace( $this->getRegex(), StringUtils::escapeRegexReplacement( $replacement ), $subject, $limit ); $this->mModified = !($res === $subject); return $res; } diff --git a/includes/Parser.php b/includes/Parser.php index e5550dc125..73ac43ce55 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -97,7 +97,7 @@ class Parser var $mTagHooks, $mFunctionHooks, $mFunctionSynonyms, $mVariables; # Cleared with clearState(): - var $mOutput, $mAutonumber, $mDTopen, $mStripState = array(); + var $mOutput, $mAutonumber, $mDTopen, $mStripState; var $mIncludeCount, $mArgStack, $mLastSection, $mInPre; var $mInterwikiLinkHolders, $mLinkHolders, $mUniqPrefix; var $mIncludeSizes; @@ -112,7 +112,9 @@ class Parser $mTitle, // Title context, used for self-link rendering and similar things $mOutputType, // Output type, one of the OT_xxx constants $ot, // Shortcut alias, see setOutputType() - $mRevisionId; // ID to display in {{REVISIONID}} tags + $mRevisionId, // ID to display in {{REVISIONID}} tags + $mRevisionTimestamp, // The timestamp of the specified revision ID + $mRevIdForTs; // The revision ID which was used to fetch the timestamp /**#@-*/ @@ -174,7 +176,6 @@ class Parser } $this->initialiseVariables(); - $this->mFirstCall = false; wfProfileOut( __METHOD__ ); } @@ -194,7 +195,7 @@ class Parser $this->mLastSection = ''; $this->mDTopen = false; $this->mIncludeCount = array(); - $this->mStripState = array(); + $this->mStripState = new StripState; $this->mArgStack = array(); $this->mInPre = false; $this->mInterwikiLinkHolders = array( @@ -208,8 +209,8 @@ class Parser 'texts' => array(), 'titles' => array() ); - $this->mRevisionId = null; - + $this->mRevisionTimestamp = $this->mRevisionId = null; + /** * Prefix for temporary replacement strings for the multipass parser. * \x07 should never appear in input as it's disallowed in XML. @@ -286,22 +287,17 @@ class Parser $this->mOptions = $options; $this->mTitle =& $title; $oldRevisionId = $this->mRevisionId; + $oldRevisionTimestamp = $this->mRevisionTimestamp; if( $revid !== null ) { $this->mRevisionId = $revid; + $this->mRevisionTimestamp = null; } $this->setOutputType( OT_HTML ); - - //$text = $this->strip( $text, $this->mStripState ); - // VOODOO MAGIC FIX! Sometimes the above segfaults in PHP5. - $x =& $this->mStripState; - - wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$x ) ); - $text = $this->strip( $text, $x ); - wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$x ) ); - + wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) ); + $text = $this->strip( $text, $this->mStripState ); + wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) ); $text = $this->internalParse( $text ); - - $text = $this->unstrip( $text, $this->mStripState ); + $text = $this->mStripState->unstripGeneral( $text ); # Clean up special characters, only run once, next-to-last before doBlockLevels $fixtags = array( @@ -324,7 +320,7 @@ class Parser # Side-effects: this calls $this->mOutput->setTitleText() $text = $wgContLang->parserConvert( $text, $this ); - $text = $this->unstripNoWiki( $text, $this->mStripState ); + $text = $this->mStripState->unstripNoWiki( $text ); wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) ); @@ -374,6 +370,7 @@ class Parser } $this->mOutput->setText( $text ); $this->mRevisionId = $oldRevisionId; + $this->mRevisionTimestamp = $oldRevisionTimestamp; wfProfileOut( $fname ); wfProfileOut( __METHOD__ ); @@ -405,16 +402,14 @@ class Parser $this->setOutputType( OT_PREPROCESS ); $this->mOptions = $options; $this->mTitle = $title; - $x =& $this->mStripState; - wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$x ) ); - $text = $this->strip( $text, $x ); - wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$x ) ); + wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) ); + $text = $this->strip( $text, $this->mStripState ); + wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) ); if ( $this->mOptions->getRemoveComments() ) { $text = Sanitizer::removeHTMLcomments( $text ); } $text = $this->replaceVariables( $text ); - $text = $this->unstrip( $text, $x ); - $text = $this->unstripNowiki( $text, $x ); + $text = $this->mStripState->unstripBoth( $text ); wfProfileOut( __METHOD__ ); return $text; } @@ -521,7 +516,8 @@ class Parser * Strips and renders nowiki, pre, math, hiero * If $render is set, performs necessary rendering operations on plugins * Returns the text, and fills an array with data needed in unstrip() - * If the $state is already a valid strip state, it adds to the state + * + * @param StripState $state * * @param bool $stripcomments when set, HTML comments * will be stripped in addition to other tags. This is important @@ -533,12 +529,12 @@ class Parser * * @private */ - function strip( $text, &$state, $stripcomments = false , $dontstrip = array () ) { + function strip( $text, $state, $stripcomments = false , $dontstrip = array () ) { wfProfileIn( __METHOD__ ); $render = ($this->mOutputType == OT_HTML); $uniq_prefix = $this->mUniqPrefix; - $commentState = array(); + $commentState = new ReplacementArray; $elements = array_merge( array( 'nowiki', 'gallery' ), @@ -583,7 +579,7 @@ class Parser } // Shouldn't happen otherwise. :) case 'nowiki': - $output = wfEscapeHTMLTagsOnly( $content ); + $output = Xml::escapeTagsOnly( $content ); break; case 'math': $output = MathRenderer::renderMath( $content ); @@ -607,14 +603,14 @@ class Parser // Unstrip the output, because unstrip() is no longer recursive so // it won't do it itself - $output = $this->unstrip( $output, $state ); + $output = $state->unstripBoth( $output ); if( !$stripcomments && $element == '!--' ) { - $commentState[$marker] = $output; + $commentState->setPair( $marker, $output ); } elseif ( $element == 'html' || $element == 'nowiki' ) { - $state['nowiki'][$marker] = $output; + $state->nowiki->setPair( $marker, $output ); } else { - $state['general'][$marker] = $output; + $state->general->setPair( $marker, $output ); } } @@ -624,7 +620,7 @@ class Parser # a comment.) if ( !$stripcomments ) { // Put them all back and forget them - $text = strtr( $text, $commentState ); + $text = $commentState->replace( $text ); } wfProfileOut( __METHOD__ ); @@ -636,35 +632,27 @@ class Parser * * always call unstripNoWiki() after this one * @private + * @deprecated use $this->mStripState->unstrip() */ function unstrip( $text, $state ) { - if ( !isset( $state['general'] ) ) { - return $text; - } - - wfProfileIn( __METHOD__ ); - # TODO: good candidate for FSS - $text = strtr( $text, $state['general'] ); - wfProfileOut( __METHOD__ ); - return $text; + return $state->unstripGeneral( $text ); } /** * Always call this after unstrip() to preserve the order * * @private + * @deprecated use $this->mStripState->unstrip() */ function unstripNoWiki( $text, $state ) { - if ( !isset( $state['nowiki'] ) ) { - return $text; - } - - wfProfileIn( __METHOD__ ); - # TODO: good candidate for FSS - $text = strtr( $text, $state['nowiki'] ); - wfProfileOut( __METHOD__ ); + return $state->unstripNoWiki( $text ); + } - return $text; + /** + * @deprecated use $this->mStripState->unstripBoth() + */ + function unstripForHTML( $text ) { + return $this->mStripState->unstripBoth( $text ); } /** @@ -676,10 +664,7 @@ class Parser */ function insertStripItem( $text, &$state ) { $rnd = $this->mUniqPrefix . '-item' . Parser::getRandomString(); - if ( !$state ) { - $state = array(); - } - $state['general'][$rnd] = $text; + $state->general->setPair( $rnd, $text ); return $rnd; } @@ -815,7 +800,7 @@ class Parser if ( preg_match( '/^(:*)\{\|(.*)$/', $x, $matches ) ) { $indent_level = strlen( $matches[1] ); - $attributes = $this->unstripForHTML( $matches[2] ); + $attributes = $this->mStripState->unstripBoth( $matches[2] ); $t[$k] = str_repeat( '
', $indent_level ) . '' ; @@ -849,7 +834,7 @@ class Parser array_push ( $tr , false ) ; array_push ( $td , false ) ; array_push ( $ltd , '' ) ; - $attributes = $this->unstripForHTML( $x ); + $attributes = $this->mStripState->unstripBoth( $x ); array_push ( $ltr , Sanitizer::fixTagAttributes ( $attributes, 'tr' ) ) ; } else if ( '|' == $fc || '!' == $fc || '|+' == substr ( $x , 0 , 2 ) ) { # Caption @@ -865,7 +850,7 @@ class Parser // FIXME: This can result in improper nesting of tags processed // by earlier parser steps, but should avoid splitting up eg // attribute values containing literal "||". - $after = wfExplodeMarkup( '||', $after ); + $after = StringUtils::explodeMarkup( '||', $after ); $t[$k] = '' ; @@ -906,7 +891,7 @@ class Parser if ( count ( $y ) == 1 ) $y = "{$z}<{$l}>{$y[0]}" ; else { - $attributes = $this->unstripForHTML( $y[0] ); + $attributes = $this->mStripState->unstripBoth( $y[0] ); $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($attributes, $l).">{$y[1]}" ; } $t[$k] .= $y ; @@ -955,7 +940,7 @@ class Parser # Remove tags and sections $text = strtr( $text, array( '' => '' , '' => '' ) ); $text = strtr( $text, array( '' => '', '' => '') ); - $text = preg_replace( '/.*?<\/includeonly>/s', '', $text ); + $text = StringUtils::delimiterReplace( '', '', '', $text ); $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) ); @@ -1611,7 +1596,7 @@ class Parser wfProfileOut( "$fname-misc" ); wfProfileIn( "$fname-title" ); - $nt = Title::newFromText( $this->unstripNoWiki($link, $this->mStripState) ); + $nt = Title::newFromText( $this->mStripState->unstripNoWiki($link) ); if( !$nt ) { $s .= $prefix . '[[' . $line; wfProfileOut( "$fname-title" ); @@ -2434,15 +2419,15 @@ class Parser case 'revisionid': return $this->mRevisionId; case 'revisionday': - return intval( substr( wfRevisionTimestamp( $this->mRevisionId ), 6, 2 ) ); + return intval( substr( $this->getRevisionTimestamp(), 6, 2 ) ); case 'revisionday2': - return substr( wfRevisionTimestamp( $this->mRevisionId ), 6, 2 ); + return substr( $this->getRevisionTimestamp(), 6, 2 ); case 'revisionmonth': - return intval( substr( wfRevisionTimestamp( $this->mRevisionId ), 4, 2 ) ); + return intval( substr( $this->getRevisionTimestamp(), 4, 2 ) ); case 'revisionyear': - return substr( wfRevisionTimestamp( $this->mRevisionId ), 0, 4 ); + return substr( $this->getRevisionTimestamp(), 0, 4 ); case 'revisiontimestamp': - return wfRevisionTimestamp( $this->mRevisionId ); + return $this->getRevisionTimestamp(); case 'namespace': return str_replace('_',' ',$wgContLang->getNsText( $this->mTitle->getNamespace() ) ); case 'namespacee': @@ -2484,15 +2469,15 @@ class Parser case 'localdow': return $varCache[$index] = $wgContLang->formatNum( $localDayOfWeek ); case 'numberofarticles': - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfArticles() ); + return $varCache[$index] = $wgContLang->formatNum( SiteStats::articles() ); case 'numberoffiles': - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfFiles() ); + return $varCache[$index] = $wgContLang->formatNum( SiteStats::images() ); case 'numberofusers': - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfUsers() ); + return $varCache[$index] = $wgContLang->formatNum( SiteStats::users() ); case 'numberofpages': - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfPages() ); + return $varCache[$index] = $wgContLang->formatNum( SiteStats::pages() ); case 'numberofadmins': - return $varCache[$index] = $wgContLang->formatNum( wfNumberOfAdmins() ); + return $varCache[$index] = $wgContLang->formatNum( SiteStats::admins() ); case 'currenttimestamp': return $varCache[$index] = wfTimestampNow(); case 'localtimestamp': @@ -3079,14 +3064,13 @@ class Parser if ( !$noparse ) { # If there are any tags, only include them if ( in_string( '', $text ) && in_string( '', $text ) ) { - $m = array(); - preg_match_all( '/(.*?)\n?<\/onlyinclude>/s', $text, $m ); - $text = ''; - foreach ($m[1] as $piece) - $text .= $piece; + $replacer = new OnlyIncludeReplacer; + StringUtils::delimiterReplaceCallback( '', '', + array( &$replacer, 'replace' ), $text ); + $text = $replacer->output; } # Remove sections and tags - $text = preg_replace( '/.*?<\/noinclude>/s', '', $text ); + $text = StringUtils::delimiterReplace( '', '', '', $text ); $text = strtr( $text, array( '' => '' , '' => '' ) ); if( $this->ot['html'] || $this->ot['pre'] ) { @@ -3481,8 +3465,7 @@ class Parser # The canonized header is a version of the header text safe to use for links # Avoid insertion of weird stuff like by expanding the relevant sections - $canonized_headline = $this->unstrip( $headline, $this->mStripState ); - $canonized_headline = $this->unstripNoWiki( $canonized_headline, $this->mStripState ); + $canonized_headline = $this->mStripState->unstripBoth( $headline ); # Remove link placeholders by the link text. # @@ -3604,15 +3587,14 @@ class Parser $this->clearState(); } - $stripState = false; + $stripState = new StripState; $pairs = array( "\r\n" => "\n", ); $text = str_replace( array_keys( $pairs ), array_values( $pairs ), $text ); $text = $this->strip( $text, $stripState, true, array( 'gallery' ) ); $text = $this->pstPass2( $text, $stripState, $user ); - $text = $this->unstrip( $text, $stripState ); - $text = $this->unstripNoWiki( $text, $stripState ); + $text = $stripState->unstripBoth( $text ); return $text; } @@ -3915,7 +3897,6 @@ class Parser */ function replaceLinkHolders( &$text, $options = 0 ) { global $wgUser; - global $wgOutputReplace; global $wgContLang; $fname = 'Parser::replaceLinkHolders'; @@ -4095,7 +4076,7 @@ class Parser # Construct search and replace arrays wfProfileIn( $fname.'-construct' ); - $wgOutputReplace = array(); + $replacePairs = array(); foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) { $pdbk = $pdbks[$key]; $searchkey = ""; @@ -4104,27 +4085,27 @@ class Parser $linkCache->addBadLinkObj( $title ); $colours[$pdbk] = 0; $this->mOutput->addLink( $title, 0 ); - $wgOutputReplace[$searchkey] = $sk->makeBrokenLinkObj( $title, + $replacePairs[$searchkey] = $sk->makeBrokenLinkObj( $title, $this->mLinkHolders['texts'][$key], $this->mLinkHolders['queries'][$key] ); } elseif ( $colours[$pdbk] == 1 ) { - $wgOutputReplace[$searchkey] = $sk->makeKnownLinkObj( $title, + $replacePairs[$searchkey] = $sk->makeKnownLinkObj( $title, $this->mLinkHolders['texts'][$key], $this->mLinkHolders['queries'][$key] ); } elseif ( $colours[$pdbk] == 2 ) { - $wgOutputReplace[$searchkey] = $sk->makeStubLinkObj( $title, + $replacePairs[$searchkey] = $sk->makeStubLinkObj( $title, $this->mLinkHolders['texts'][$key], $this->mLinkHolders['queries'][$key] ); } } + $replacer = new HashtableReplacer( $replacePairs, 1 ); wfProfileOut( $fname.'-construct' ); # Do the thing wfProfileIn( $fname.'-replace' ); - $text = preg_replace_callback( '/()/', - "wfOutputReplaceMatches", + $replacer->cb(), $text); wfProfileOut( $fname.'-replace' ); @@ -4135,15 +4116,16 @@ class Parser if ( !empty( $this->mInterwikiLinkHolders['texts'] ) ) { wfProfileIn( $fname.'-interwiki' ); # Make interwiki link HTML - $wgOutputReplace = array(); + $replacePairs = array(); foreach( $this->mInterwikiLinkHolders['texts'] as $key => $link ) { $title = $this->mInterwikiLinkHolders['titles'][$key]; - $wgOutputReplace[$key] = $sk->makeLinkObj( $title, $link ); + $replacePairs[$key] = $sk->makeLinkObj( $title, $link ); } + $replacer = new HashtableReplacer( $replacePairs, 1 ); $text = preg_replace_callback( '//', - "wfOutputReplaceMatches", + $replacer->cb(), $text ); wfProfileOut( $fname.'-interwiki' ); } @@ -4196,11 +4178,11 @@ class Parser */ function renderPreTag( $text, $attribs ) { // Backwards-compatibility hack - $content = preg_replace( '!(.*?)!is', '\\1', $text ); + $content = StringUtils::delimiterReplace( '', '', '$1', $text, 'i' ); $attribs = Sanitizer::validateTagAttributes( $attribs, 'pre' ); return wfOpenElement( 'pre', $attribs ) . - wfEscapeHTMLTagsOnly( $content ) . + Xml::escapeTagsOnly( $content ) . ''; } @@ -4343,7 +4325,7 @@ class Parser # make sure there are no placeholders in thumbnail attributes # that are later expanded to html- so expand them now and # remove the tags - $alt = $this->unstrip($alt, $this->mStripState); + $alt = $this->mStripState->unstripBoth( $alt ); $alt = Sanitizer::stripAllTags( $alt ); # Linker does the rest @@ -4370,15 +4352,10 @@ class Parser */ function attributeStripCallback( &$text, $args ) { $text = $this->replaceVariables( $text, $args ); - $text = $this->unstripForHTML( $text ); + $text = $this->mStripState->unstripBoth( $text ); return $text; } - function unstripForHTML( $text ) { - $text = $this->unstrip( $text, $this->mStripState ); - $text = $this->unstripNoWiki( $text, $this->mStripState ); - return $text; - } /**#@-*/ /**#@+ @@ -4414,14 +4391,14 @@ class Parser private function extractSections( $text, $section, $mode, $newtext='' ) { # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML # comments to be stripped as well) - $striparray = array(); + $stripState = new StripState; $oldOutputType = $this->mOutputType; $oldOptions = $this->mOptions; $this->mOptions = new ParserOptions(); $this->setOutputType( OT_WIKI ); - $striptext = $this->strip( $text, $striparray, true ); + $striptext = $this->strip( $text, $stripState, true ); $this->setOutputType( $oldOutputType ); $this->mOptions = $oldOptions; @@ -4528,9 +4505,7 @@ class Parser } } # reinsert stripped tags - $rv = $this->unstrip( $rv, $striparray ); - $rv = $this->unstripNoWiki( $rv, $striparray ); - $rv = trim( $rv ); + $rv = trim( $stripState->unstripBoth( $rv ) ); return $rv; } @@ -4553,6 +4528,23 @@ class Parser return $this->extractSections( $oldtext, $section, "replace", $text ); } + /** + * Get the timestamp associated with the current revision, adjusted for + * the user's current timestamp + */ + function getRevisionTimestamp() { + if ( is_null( $this->mRevisionTimestamp ) ) { + wfProfileIn( __METHOD__ ); + global $wgContLang; + $dbr =& wfGetDB( DB_SLAVE ); + $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', + array( 'rev_id' => $id ), __METHOD__ ); + $this->mRevisionTimestamp = $wgContLang->userAdjust( $timestamp ); + + wfProfileOut( __METHOD__ ); + } + return $this->mRevisionTimestamp; + } } /** @@ -4787,152 +4779,47 @@ class ParserOptions } } -/** - * Callback function used by Parser::replaceLinkHolders() - * to substitute link placeholders. - */ -function &wfOutputReplaceMatches( $matches ) { - global $wgOutputReplace; - return $wgOutputReplace[$matches[1]]; -} +class OnlyIncludeReplacer { + var $output = ''; -/** - * Return the total number of articles - */ -function wfNumberOfArticles() { - global $wgNumberOfArticles; - - wfLoadSiteStats(); - return $wgNumberOfArticles; -} - -/** - * Return the number of files - */ -function wfNumberOfFiles() { - $fname = 'wfNumberOfFiles'; - - wfProfileIn( $fname ); - $dbr =& wfGetDB( DB_SLAVE ); - $numImages = $dbr->selectField('site_stats', 'ss_images', array(), $fname ); - wfProfileOut( $fname ); - - return $numImages; -} - -/** - * Return the number of user accounts - * @return integer - */ -function wfNumberOfUsers() { - wfProfileIn( 'wfNumberOfUsers' ); - $dbr =& wfGetDB( DB_SLAVE ); - $count = $dbr->selectField( 'site_stats', 'ss_users', array(), 'wfNumberOfUsers' ); - wfProfileOut( 'wfNumberOfUsers' ); - return (int)$count; + function replace( $matches ) { + if ( substr( $matches[1], -1 ) == "\n" ) { + $this->output .= substr( $matches[1], 0, -1 ); + } else { + $this->output .= $matches[1]; + } + } } -/** - * Return the total number of pages - * @return integer - */ -function wfNumberOfPages() { - wfProfileIn( 'wfNumberOfPages' ); - $dbr =& wfGetDB( DB_SLAVE ); - $count = $dbr->selectField( 'site_stats', 'ss_total_pages', array(), 'wfNumberOfPages' ); - wfProfileOut( 'wfNumberOfPages' ); - return (int)$count; -} +class StripState { + var $general, $nowiki; -/** - * Return the total number of admins - * - * @return integer - */ -function wfNumberOfAdmins() { - static $admins = -1; - wfProfileIn( 'wfNumberOfAdmins' ); - if( $admins == -1 ) { - $dbr =& wfGetDB( DB_SLAVE ); - $admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), 'wfNumberOfAdmins' ); + function __construct() { + $this->general = new ReplacementArray; + $this->nowiki = new ReplacementArray; } - wfProfileOut( 'wfNumberOfAdmins' ); - return (int)$admins; -} -/** - * Count the number of pages in a particular namespace - * - * @param $ns Namespace - * @return integer - */ -function wfPagesInNs( $ns ) { - static $pageCount = array(); - wfProfileIn( 'wfPagesInNs' ); - if( !isset( $pageCount[$ns] ) ) { - $dbr =& wfGetDB( DB_SLAVE ); - $pageCount[$ns] = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $ns ), 'wfPagesInNs' ); + function unstripGeneral( $text ) { + wfProfileIn( __METHOD__ ); + $text = $this->general->replace( $text ); + wfProfileOut( __METHOD__ ); + return $text; } - wfProfileOut( 'wfPagesInNs' ); - return (int)$pageCount[$ns]; -} -/** - * Get various statistics from the database - * @private - */ -function wfLoadSiteStats() { - global $wgNumberOfArticles, $wgTotalViews, $wgTotalEdits; - $fname = 'wfLoadSiteStats'; - - if ( -1 != $wgNumberOfArticles ) return; - $dbr =& wfGetDB( DB_SLAVE ); - $s = $dbr->selectRow( 'site_stats', - array( 'ss_total_views', 'ss_total_edits', 'ss_good_articles' ), - array( 'ss_row_id' => 1 ), $fname - ); - - if ( $s === false ) { - return; - } else { - $wgTotalViews = $s->ss_total_views; - $wgTotalEdits = $s->ss_total_edits; - $wgNumberOfArticles = $s->ss_good_articles; + function unstripNoWiki( $text ) { + wfProfileIn( __METHOD__ ); + $text = $this->nowiki->replace( $text ); + wfProfileOut( __METHOD__ ); + return $text; } -} -/** - * Get revision timestamp from the database considering timecorrection - * - * @param $id Int: page revision id - * @return integer - */ -function wfRevisionTimestamp( $id ) { - global $wgContLang; - $fname = 'wfRevisionTimestamp'; - - wfProfileIn( $fname ); - $dbr =& wfGetDB( DB_SLAVE ); - $timestamp = $dbr->selectField( 'revision', 'rev_timestamp', - array( 'rev_id' => $id ), __METHOD__ ); - $timestamp = $wgContLang->userAdjust( $timestamp ); - wfProfileOut( $fname ); - - return $timestamp; -} - -/** - * Escape html tags - * Basically replacing " > and < with HTML entities ( ", >, <) - * - * @param $in String: text that might contain HTML tags. - * @return string Escaped string - */ -function wfEscapeHTMLTagsOnly( $in ) { - return str_replace( - array( '"', '>', '<' ), - array( '"', '>', '<' ), - $in ); + function unstripBoth( $text ) { + wfProfileIn( __METHOD__ ); + $text = $this->general->replace( $text ); + $text = $this->nowiki->replace( $text ); + wfProfileOut( __METHOD__ ); + return $text; + } } ?> diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php index 7d9ccc0fb7..4ed2692301 100644 --- a/includes/Sanitizer.php +++ b/includes/Sanitizer.php @@ -603,7 +603,8 @@ class Sanitizer { $stripped = Sanitizer::decodeCharReferences( $value ); // Remove any comments; IE gets token splitting wrong - $stripped = preg_replace( '!/\\*.*?\\*/!S', ' ', $stripped ); + $stripped = StringUtils::delimiterReplace( '/\*', '\*/', ' ', $stripped ); + $value = $stripped; // ... and continue checks @@ -1178,7 +1179,7 @@ class Sanitizer { */ static function stripAllTags( $text ) { # Actual - $text = preg_replace( '/ < .*? > /x', '', $text ); + $text = StringUtils::delimiterReplace( '<', '>', '', $text ); # Normalize &entities and whitespace $text = Sanitizer::normalizeAttributeValue( $text ); diff --git a/includes/SiteStatsUpdate.php b/includes/SiteStats.php similarity index 57% rename from includes/SiteStatsUpdate.php rename to includes/SiteStats.php index b91dcfeb54..4480ab5976 100644 --- a/includes/SiteStatsUpdate.php +++ b/includes/SiteStats.php @@ -1,9 +1,85 @@ selectRow( 'site_stats', '*', false, __METHOD__ ); + + # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS + if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) { + # Update schema + $u = new SiteStatsUpdate( 0, 0, 0 ); + $u->doUpdate(); + self::$row = $dbr->selectRow( 'site_stats', '*', false, $fname ); + } + } + + static function views() { + self::load(); + return self::$row->ss_total_views; + } + + static function edits() { + self::load(); + return self::$row->ss_total_edits; + } + + static function articles() { + self::load(); + return self::$row->ss_good_articles; + } + + static function pages() { + self::load(); + return self::$row->ss_total_pages; + } + + static function users() { + self::load(); + return self::$row->ss_users; + } + + static function images() { + self::load(); + return self::$row->ss_images; + } + + static function admins() { + if ( !isset( self::$admins ) ) { + $dbr =& wfGetDB( DB_SLAVE ); + self::$admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), __METHOD__ ); + } + return self::$admins; + } + + static function pagesInNs( $ns ) { + wfProfileIn( __METHOD__ ); + if( !isset( self::$pageCount[$ns] ) ) { + $dbr =& wfGetDB( DB_SLAVE ); + $pageCount[$ns] = (int)$dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $ns ), __METHOD__ ); + } + wfProfileOut( __METHOD__ ); + return $pageCount[$ns]; + } + +} + /** * diff --git a/includes/SpecialStatistics.php b/includes/SpecialStatistics.php index 4a51efd9b5..66b1424039 100644 --- a/includes/SpecialStatistics.php +++ b/includes/SpecialStatistics.php @@ -15,39 +15,14 @@ function wfSpecialStatistics() { $action = $wgRequest->getVal( 'action' ); $dbr =& wfGetDB( DB_SLAVE ); - extract( $dbr->tableNames( 'page', 'site_stats', 'user', 'user_groups' ) ); + extract( $dbr->tableNames( 'site_stats', 'user', 'user_groups' ) ); - $row = $dbr->selectRow( 'site_stats', '*', false, $fname ); - $views = $row->ss_total_views; - $edits = $row->ss_total_edits; - $good = $row->ss_good_articles; - $images = $row->ss_images; - - # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS - if ( isset( $row->ss_total_pages ) && $row->ss_total_pages == -1 ) { - # Update schema - $u = new SiteStatsUpdate( 0, 0, 0 ); - $u->doUpdate(); - $row = $dbr->selectRow( 'site_stats', '*', false, $fname ); - } - - if ( isset( $row->ss_total_pages ) ) { - $total = $row->ss_total_pages; - } else { - $sql = "SELECT COUNT(page_namespace) AS total FROM $page"; - $res = $dbr->query( $sql, $fname ); - $pageRow = $dbr->fetchObject( $res ); - $total = $pageRow->total; - } - - if ( isset( $row->ss_users ) ) { - $users = $row->ss_users; - } else { - $sql = "SELECT MAX(user_id) AS total FROM $user"; - $res = $dbr->query( $sql, $fname ); - $userRow = $dbr->fetchObject( $res ); - $users = $userRow->total; - } + $views = SiteStats::views(); + $edits = SiteStats::edits(); + $good = SiteStats::articles(); + $images = SiteStats::images(); + $total = SiteStats::pages(); + $users = SiteStats::users(); $admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), $fname ); $numJobs = $dbr->selectField( 'job', 'COUNT(*)', '', $fname ); diff --git a/includes/SpecialWatchlist.php b/includes/SpecialWatchlist.php index 0ce03b8b17..bc170b3634 100644 --- a/includes/SpecialWatchlist.php +++ b/includes/SpecialWatchlist.php @@ -381,8 +381,8 @@ function wfSpecialWatchlist( $par ) { } if ($wgRCShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) { - $sql3 = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" .wfStrencode($obj->page_title). "' AND wl_namespace='{$obj->page_namespace}'" ; - $res3 = $dbr->query( $sql3, DB_READ, $fname ); + $sql3 = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" .$dbr->strencode($obj->page_title). "' AND wl_namespace='{$obj->page_namespace}'" ; + $res3 = $dbr->query( $sql3, $fname ); $x = $dbr->fetchObject( $res3 ); $rc->numberofWatchingusers = $x->n; } else { diff --git a/includes/Xml.php b/includes/Xml.php index 3457445860..6e66fc416f 100644 --- a/includes/Xml.php +++ b/includes/Xml.php @@ -297,5 +297,19 @@ class Xml { ''; return Xml::isWellFormed( $html ); } + + /** + * Escape html tags + * Basically replacing " > and < with HTML entities ( ", >, <) + * + * @param $in String: text that might contain HTML tags. + * @return string Escaped string + */ + function escapeTagsOnly( $in ) { + return str_replace( + array( '"', '>', '<' ), + array( '"', '>', '<' ), + $in ); + } } ?> diff --git a/languages/LanguageConverter.php b/languages/LanguageConverter.php index a0f7ee1d9a..86e025c583 100644 --- a/languages/LanguageConverter.php +++ b/languages/LanguageConverter.php @@ -12,9 +12,7 @@ class LanguageConverter { var $mMainLanguageCode; var $mVariants, $mVariantFallbacks; var $mTablesLoaded = false; - var $mUseFss = false; var $mTables; - var $mFssObjects; var $mTitleDisplay=''; var $mDoTitleConvert=true, $mDoContentConvert=true; var $mCacheKey; @@ -49,9 +47,6 @@ class LanguageConverter { $this->mMarkup = array_merge($m, $markup); $f = array('A'=>'A', 'T'=>'T'); $this->mFlags = array_merge($f, $flags); - if ( function_exists( 'fss_prep_replace' ) ) { - $this->mUseFss = true; - } } /** @@ -194,19 +189,12 @@ class LanguageConverter { * @return string Translated text */ function translate( $text, $variant ) { + wfProfileIn( __METHOD__ ); if( !$this->mTablesLoaded ) $this->loadTables(); - if ( $this->mUseFss ) { - wfProfileIn( __METHOD__.'-fss' ); - $text = fss_exec_replace( $this->mFssObjects[$variant], $text ); - wfProfileOut( __METHOD__.'-fss' ); - return $text; - } else { - wfProfileIn( __METHOD__.'-strtr' ); - $text = strtr( $text, $this->mTables[$variant] ); - wfProfileOut( __METHOD__.'-strtr' ); - return $text; - } + $text = $this->mTables[$variant]->replace( $text ); + wfProfileOut( __METHOD__ ); + return $text; } /** @@ -407,13 +395,9 @@ class LanguageConverter { continue; if(!array_key_exists($vto, $carray)) continue; - $this->mTables[$vto][$carray[$vfrom]] = $carray[$vto]; - + $this->mTables[$vto]->setPair($carray[$vfrom], $carray[$vto]); } } - if ( $this->mUseFss ) { - $this->generateFssObjects(); - } } } else { @@ -557,8 +541,8 @@ class LanguageConverter { $this->mTables = $wgMemc->get( $this->mCacheKey ); wfProfileOut( __METHOD__.'-cache' ); } - if ( !$this->mTables ) { - wfProfileOut( __METHOD__.'-recache' ); + if ( !$this->mTables || !isset( $this->mTables['VERSION 2'] ) ) { + wfProfileIn( __METHOD__.'-recache' ); // not in cache, or we need a fresh reload. // we will first load the default tables // then update them using things in MediaWiki:Zhconversiontable/* @@ -566,10 +550,11 @@ class LanguageConverter { $this->loadDefaultTables(); foreach($this->mVariants as $var) { $cached = $this->parseCachedTable($var); - $this->mTables[$var] = array_merge($this->mTables[$var], $cached); + $this->mTables[$var]->mergeArray($cached); } $this->postLoadTables(); + $this->mTables['VERSION 2'] = true; if($this->lockCache()) { $wgMemc->set($this->mCacheKey, $this->mTables, 43200); @@ -577,23 +562,9 @@ class LanguageConverter { } wfProfileOut( __METHOD__.'-recache' ); } - if ( $this->mUseFss ) { - wfProfileIn( __METHOD__.'-fss' ); - $this->generateFssObjects(); - wfProfileOut( __METHOD__.'-fss' ); - } wfProfileOut( __METHOD__ ); } - /** - * Generate FSS objects. The FSS extension must be available. - */ - function generateFssObjects() { - foreach ( $this->mTables as $variant => $table ) { - $this->mFssObjects[$variant] = fss_prep_replace( $table ); - } - } - /** * Hook for post processig after conversion tables are loaded * diff --git a/languages/classes/LanguageKk.php b/languages/classes/LanguageKk.php index bfbdc54702..71ca081df4 100644 --- a/languages/classes/LanguageKk.php +++ b/languages/classes/LanguageKk.php @@ -89,11 +89,12 @@ class KkConverter extends LanguageConverter { ); function loadDefaultTables() { - $this->mTables = array(); - $this->mTables['kk-kz'] = $this->mLatinToCyrillic; - $this->mTables['kk-tr'] = $this->mCyrillicToLatin; - $this->mTables['kk-cn'] = $this->mCyrillicToArabic; - $this->mTables['kk'] = array(); + $this->mTables = array( + 'kk-kz' => new ReplacementArray( $this->mLatinToCyrillic ), + 'kk-tr' => new ReplacementArray( $this->mCyrillicToLatin ), + 'kk-cn' => new ReplacementArray( $this->mCyrillicToArabic ), + 'kk' => new ReplacementArray() + ); } /* diff --git a/languages/classes/LanguageSr.php b/languages/classes/LanguageSr.php index 412463f88b..fadfb35c1b 100644 --- a/languages/classes/LanguageSr.php +++ b/languages/classes/LanguageSr.php @@ -53,12 +53,13 @@ class SrConverter extends LanguageConverter { ); function loadDefaultTables() { - $this->mTables = array(); - $this->mTables['sr-ec'] = $this->mToCyrillics; - $this->mTables['sr-jc'] = $this->mToCyrillics; - $this->mTables['sr-el'] = $this->mToLatin; - $this->mTables['sr-jl'] = $this->mToLatin; - $this->mTables['sr'] = array(); + $this->mTables = array( + 'sr-ec' => new ReplacementArray( $this->mToCyrillics ), + 'sr-jc' => new ReplacementArray( $this->mToCyrillics), + 'sr-el' => new ReplacementArray( $this->mToLatin), + 'sr-jl' => new ReplacementArray( $this->mToLatin), + 'sr' => new ReplacementArray() + ); } /* rules should be defined as -{ekavian | iyekavian-} -or- @@ -139,7 +140,7 @@ class SrConverter extends LanguageConverter { $matches = preg_split($reg, $text, -1, PREG_SPLIT_OFFSET_CAPTURE); $m = array_shift($matches); - $ret = strtr($m[0], $this->mTables[$toVariant]); + $ret = $this->mTables[$toVariant]->replace( $m[0] ); $mstart = $m[1]+strlen($m[0]); foreach($matches as $m) { $ret .= substr($text, $mstart, $m[1]-$mstart); @@ -149,8 +150,6 @@ class SrConverter extends LanguageConverter { return $ret; } - - } class LanguageSr extends LanguageSr_ec { diff --git a/languages/classes/LanguageZh.php b/languages/classes/LanguageZh.php index c34315ac11..4f8a285a52 100644 --- a/languages/classes/LanguageZh.php +++ b/languages/classes/LanguageZh.php @@ -9,17 +9,18 @@ require_once( dirname(__FILE__).'/LanguageZh_cn.php' ); class ZhConverter extends LanguageConverter { function loadDefaultTables() { require( "includes/ZhConversion.php" ); - $this->mTables = array(); - $this->mTables['zh-cn'] = $zh2CN; - $this->mTables['zh-tw'] = $zh2TW; - $this->mTables['zh-sg'] = array_merge($zh2CN, $zh2SG); - $this->mTables['zh-hk'] = array_merge($zh2TW, $zh2HK); - $this->mTables['zh'] = array(); + $this->mTables = array( + 'zh-cn' => new ReplacementArray( $zh2CN ), + 'zh-tw' => new ReplacementArray( $zh2TW ), + 'zh-sg' => new ReplacementArray( array_merge($zh2CN, $zh2SG) ), + 'zh-hk' => new ReplacementArray( array_merge($zh2TW, $zh2HK) ), + 'zh' => new ReplacementArray + ); } function postLoadTables() { - $this->mTables['zh-sg'] = array_merge($this->mTables['zh-cn'], $this->mTables['zh-sg']); - $this->mTables['zh-hk'] = array_merge($this->mTables['zh-tw'], $this->mTables['zh-hk']); + $this->mTables['zh-sg']->merge( $this->mTables['zh-cn'] ); + $this->mTables['zh-hk']->merge( $this->mTables['zh-tw'] ); } /* there shouldn't be any latin text in Chinese conversion, so no need diff --git a/maintenance/namespace2sql.php b/maintenance/namespace2sql.php index 8084bfec60..081f609965 100644 --- a/maintenance/namespace2sql.php +++ b/maintenance/namespace2sql.php @@ -6,8 +6,8 @@ require_once( "commandLine.inc" ); for ($i = -2; $i < 16; ++$i) { - $nsname = wfStrencode( $wgLang->getNsText( $i ) ); - $dbname = wfStrencode( $wgDBname ); + $nsname = mysql_escape_string( $wgLang->getNsText( $i ) ); + $dbname = mysql_escape_string( $wgDBname ); print "INSERT INTO ns_name(ns_db, ns_num, ns_name) VALUES('$dbname', $i, '$nsname');\n"; } -- 2.20.1