Added ORMIterator interface which can be used for type hinting (in particular when...
[lhc/web/wiklou.git] / includes / LocalisationCache.php
index 4382ad8..9ce26d0 100644 (file)
@@ -1,4 +1,24 @@
 <?php
+/**
+ * Cache of the contents of localisation files.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
 
 define( 'MW_LC_VERSION', 2 );
 
@@ -134,7 +154,7 @@ class LocalisationCache {
         */
        static public $preloadedKeys = array( 'dateFormats', 'namespaceNames' );
 
-       var $mergeableKeys = array();
+       var $mergeableKeys = null;
 
        /**
         * Constructor.
@@ -159,6 +179,9 @@ class LocalisationCache {
                                case 'db':
                                        $storeClass = 'LCStore_DB';
                                        break;
+                               case 'accel':
+                                       $storeClass = 'LCStore_Accel';
+                                       break;
                                case 'detect':
                                        $storeClass = $wgCacheDirectory ? 'LCStore_CDB' : 'LCStore_DB';
                                        break;
@@ -188,7 +211,7 @@ class LocalisationCache {
         * @return bool
         */
        public function isMergeableKey( $key ) {
-               if ( !isset( $this->mergeableKeys ) ) {
+               if ( $this->mergeableKeys === null ) {
                        $this->mergeableKeys = array_flip( array_merge(
                                self::$mergeableMapKeys,
                                self::$mergeableListKeys,
@@ -207,7 +230,7 @@ class LocalisationCache {
         * need to fetch all of the subitems from the cache individually.
         * @param $code
         * @param $key
-        * @return string
+        * @return mixed
         */
        public function getItem( $code, $key ) {
                if ( !isset( $this->loadedItems[$code][$key] ) ) {
@@ -231,9 +254,8 @@ class LocalisationCache {
         * @return null
         */
        public function getSubitem( $code, $key, $subkey ) {
-               if ( !isset( $this->loadedSubitems[$code][$key][$subkey] )
-                       && !isset( $this->loadedItems[$code][$key] ) )
-               {
+               if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
+                        !isset( $this->loadedItems[$code][$key] ) ) {
                        wfProfileIn( __METHOD__.'-load' );
                        $this->loadSubitem( $code, $key, $subkey );
                        wfProfileOut( __METHOD__.'-load' );
@@ -324,9 +346,8 @@ class LocalisationCache {
                }
 
                // Check to see if initLanguage() loaded it for us
-               if ( isset( $this->loadedItems[$code][$key] )
-                       || isset( $this->loadedSubitems[$code][$key][$subkey] ) )
-               {
+               if ( isset( $this->loadedItems[$code][$key] ) ||
+                        isset( $this->loadedSubitems[$code][$key][$subkey] ) ) {
                        return;
                }
 
@@ -342,6 +363,7 @@ class LocalisationCache {
 
        /**
         * Returns true if the cache identified by $code is missing or expired.
+        * @return bool
         */
        public function isExpired( $code ) {
                if ( $this->forceRecache && !isset( $this->recachedLangs[$code] ) ) {
@@ -350,7 +372,10 @@ class LocalisationCache {
                }
 
                $deps = $this->store->get( $code, 'deps' );
-               if ( $deps === null ) {
+               $keys = $this->store->get( $code, 'list', 'messages' );
+               $preload = $this->store->get( $code, 'preload' );
+               // Different keys may expire separately, at least in LCStore_Accel
+               if ( $deps === null || $keys === null || $preload === null ) {
                        wfDebug( __METHOD__."($code): cache missing, need to make one\n" );
                        return true;
                }
@@ -544,7 +569,7 @@ class LocalisationCache {
         * @param $code
         */
        public function recache( $code ) {
-               global $wgExtensionMessagesFiles, $wgExtensionAliasesFiles;
+               global $wgExtensionMessagesFiles;
                wfProfileIn( __METHOD__ );
 
                if ( !$code ) {
@@ -639,22 +664,6 @@ class LocalisationCache {
                        }
                }
 
-               # Load deprecated $wgExtensionAliasesFiles
-               foreach ( $wgExtensionAliasesFiles as $fileName ) {
-                       $data = $this->readPHPFile( $fileName, 'aliases' );
-
-                       if ( !isset( $data['aliases'] ) ) {
-                               continue;
-                       }
-
-                       $used = $this->mergeExtensionItem( $codeSequence, 'specialPageAliases',
-                               $allData['specialPageAliases'], $data['aliases'] );
-
-                       if ( $used ) {
-                               $deps[] = new FileDependency( $fileName );
-                       }
-               }
-
                # Merge core data into extension data
                foreach ( $coreData as $key => $item ) {
                        $this->mergeItem( $key, $allData[$key], $item );
@@ -662,7 +671,6 @@ class LocalisationCache {
 
                # Add cache dependencies for any referenced globals
                $deps['wgExtensionMessagesFiles'] = new GlobalDependency( 'wgExtensionMessagesFiles' );
-               $deps['wgExtensionAliasesFiles'] = new GlobalDependency( 'wgExtensionAliasesFiles' );
                $deps['version'] = new ConstantDependency( 'MW_LC_VERSION' );
 
                # Add dependencies to the cache entry
@@ -806,8 +814,8 @@ class LocalisationCache {
 interface LCStore {
        /**
         * Get a value.
-        * @param $code Language code
-        * @param $key Cache key
+        * @param $code string Language code
+        * @param $key string Cache key
         */
        function get( $code, $key );
 
@@ -831,6 +839,55 @@ interface LCStore {
        function set( $key, $value );
 }
 
+/**
+ * LCStore implementation which uses PHP accelerator to store data.
+ * This will work if one of XCache, WinCache or APC cacher is configured.
+ * (See ObjectCache.php)
+ */
+class LCStore_Accel implements LCStore {
+       var $currentLang;
+       var $keys;
+
+       public function __construct() {
+               $this->cache = wfGetCache( CACHE_ACCEL );
+       }
+
+       public function get( $code, $key ) {
+               $k = wfMemcKey( 'l10n', $code, 'k', $key );
+               $r = $this->cache->get( $k );
+               return $r === false ? null : $r;
+       }
+
+       public function startWrite( $code ) {
+               $k = wfMemcKey( 'l10n', $code, 'l' );
+               $keys = $this->cache->get( $k );
+               if ( $keys ) {
+                       foreach ( $keys as $k ) {
+                               $this->cache->delete( $k );
+                       }
+               }
+               $this->currentLang = $code;
+               $this->keys = array();
+       }
+
+       public function finishWrite() {
+               if ( $this->currentLang ) {
+                       $k = wfMemcKey( 'l10n', $this->currentLang, 'l' );
+                       $this->cache->set( $k, array_keys( $this->keys ) );
+               }
+               $this->currentLang = null;
+               $this->keys = array();
+       }
+
+       public function set( $key, $value ) {
+               if ( $this->currentLang ) {
+                       $k = wfMemcKey( 'l10n', $this->currentLang, 'k', $key );
+                       $this->keys[$k] = true;
+                       $this->cache->set( $k, $value );
+               }
+       }
+}
+
 /**
  * LCStore implementation which uses the standard DB functions to store data.
  * This will work on any MediaWiki installation.
@@ -872,12 +929,12 @@ class LCStore_DB implements LCStore {
 
                $this->dbw = wfGetDB( DB_MASTER );
                try {
-                       $this->dbw->begin();
+                       $this->dbw->begin( __METHOD__ );
                        $this->dbw->delete( 'l10n_cache', array( 'lc_lang' => $code ), __METHOD__ );
                } catch ( DBQueryError $e ) {
                        if ( $this->dbw->wasReadOnlyError() ) {
                                $this->readOnly = true;
-                               $this->dbw->rollback();
+                               $this->dbw->rollback( __METHOD__ );
                                $this->dbw->ignoreErrors( false );
                                return;
                        } else {
@@ -898,7 +955,7 @@ class LCStore_DB implements LCStore {
                        $this->dbw->insert( 'l10n_cache', $this->batch, __METHOD__ );
                }
 
-               $this->dbw->commit();
+               $this->dbw->commit( __METHOD__ );
                $this->currentLang = null;
                $this->dbw = null;
                $this->batch = array();
@@ -1079,7 +1136,7 @@ class LocalisationCache_BulkLoad extends LocalisationCache {
        /**
         * @param $code
         * @param $key
-        * @return string
+        * @return mixed
         */
        public function getItem( $code, $key ) {
                unset( $this->mruLangs[$code] );