follop-up to 68230: forgot to commit the styles needed for layout grids
[lhc/web/wiklou.git] / includes / LocalisationCache.php
index 0974f4a..12925b6 100644 (file)
@@ -143,6 +143,7 @@ class LocalisationCache {
                global $wgCacheDirectory;
 
                $this->conf = $conf;
+               $storeConf = array();
                if ( !empty( $conf['storeClass'] ) ) {
                        $storeClass = $conf['storeClass'];
                } else {
@@ -159,12 +160,16 @@ class LocalisationCache {
                                        break;
                                default:
                                        throw new MWException( 
-                                               'Please set $wgLocalisationConf[\'store\'] to something sensible.' );
+                                               'Please set $wgLocalisationCacheConf[\'store\'] to something sensible.' );
                        }
                }
 
                wfDebug( get_class( $this ) . ": using store $storeClass\n" );
-               $this->store = new $storeClass;
+               if ( !empty( $conf['storeDirectory'] ) ) {
+                       $storeConf['directory'] = $conf['storeDirectory'];
+               }
+
+               $this->store = new $storeClass( $storeConf );
                foreach ( array( 'manualRecache', 'forceRecache' ) as $var ) {
                        if ( isset( $conf[$var] ) ) {
                                $this->$var = $conf[$var];
@@ -213,20 +218,40 @@ class LocalisationCache {
                if ( isset( $this->legacyData[$code][$key][$subkey] ) ) {
                        return $this->legacyData[$code][$key][$subkey];
                }
-               if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) ) {
-                       if ( isset( $this->loadedItems[$code][$key] ) ) {
-                               if ( isset( $this->data[$code][$key][$subkey] ) ) {
-                                       return $this->data[$code][$key][$subkey];
-                               } else {
-                                       return null;
-                               }
+               if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) 
+                       && !isset( $this->loadedItems[$code][$key] ) ) 
+               {
+                       wfProfileIn( __METHOD__.'-load' );
+                       $this->loadSubitem( $code, $key, $subkey );
+                       wfProfileOut( __METHOD__.'-load' );
+               }
+               if ( isset( $this->data[$code][$key][$subkey] ) ) {
+                       return $this->data[$code][$key][$subkey];
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Get the list of subitem keys for a given item.
+        *
+        * This is faster than array_keys($lc->getItem(...)) for the items listed in 
+        * self::$splitKeys.
+        *
+        * Will return null if the item is not found, or false if the item is not an 
+        * array.
+        */
+       public function getSubitemList( $code, $key ) {
+               if ( in_array( $key, self::$splitKeys ) ) {
+                       return $this->getSubitem( $code, 'list', $key );
+               } else {
+                       $item = $this->getItem( $code, $key );
+                       if ( is_array( $item ) ) {
+                               return array_keys( $item );
                        } else {
-                               wfProfileIn( __METHOD__.'-load' );
-                               $this->loadSubitem( $code, $key, $subkey );
-                               wfProfileOut( __METHOD__.'-load' );
+                               return false;
                        }
                }
-               return $this->data[$code][$key][$subkey];
        }
 
        /**
@@ -270,7 +295,9 @@ class LocalisationCache {
                        $this->initLanguage( $code );
                }
                // Check to see if initLanguage() loaded it for us
-               if ( isset( $this->loadedSubitems[$code][$key][$subkey] ) ) {
+               if ( isset( $this->loadedItems[$code][$key] )
+                       || isset( $this->loadedSubitems[$code][$key][$subkey] ) )
+               {
                        return;
                }
                if ( isset( $this->shallowFallbacks[$code] ) ) {
@@ -297,7 +324,11 @@ class LocalisationCache {
                        return true;
                }
                foreach ( $deps as $dep ) {
-                       if ( $dep->isExpired() ) {
+                       // Because we're unserializing stuff from cache, we
+                       // could receive objects of classes that don't exist
+                       // anymore (e.g. uninstalled extensions)
+                       // When this happens, always expire the cache
+                       if ( !$dep instanceof CacheDependency || $dep->isExpired() ) {
                                wfDebug( __METHOD__."($code): cache for $code expired due to " . 
                                        get_class( $dep ) . "\n" );
                                return true;
@@ -370,9 +401,9 @@ class LocalisationCache {
         */
        protected function readPHPFile( $_fileName, $_fileType ) {
                // Disable APC caching
-               $_apcEnabled = ini_set( 'apc.enabled', '0' );
+               $_apcEnabled = ini_set( 'apc.cache_by_default', '0' );
                include( $_fileName );
-               ini_set( 'apc.enabled', $_apcEnabled );
+               ini_set( 'apc.cache_by_default', $_apcEnabled );
 
                if ( $_fileType == 'core' || $_fileType == 'extension' ) {
                        $data = compact( self::$allKeys );
@@ -505,8 +536,9 @@ class LocalisationCache {
                        $data = $this->readPHPFile( $fileName, 'extension' );
                        $used = false;
                        foreach ( $data as $key => $item ) {
-                               $used = $used |
-                                       $this->mergeExtensionItem( $codeSequence, $key, $allData[$key], $item );
+                               if( $this->mergeExtensionItem( $codeSequence, $key, $allData[$key], $item ) ) {
+                                       $used = true;
+                               }
                        }
                        if ( $used ) {
                                $deps[] = new FileDependency( $fileName );
@@ -554,9 +586,6 @@ class LocalisationCache {
                        $allData['defaultUserOptionOverrides'] = array();
                }
 
-               # Set the preload key
-               $allData['preload'] = $this->buildPreload( $allData );
-
                # Set the list keys
                $allData['list'] = array();
                foreach ( self::$splitKeys as $key ) {
@@ -571,6 +600,9 @@ class LocalisationCache {
                                'Check that your languages/messages/MessagesEn.php file is intact.' );
                }
 
+               # Set the preload key
+               $allData['preload'] = $this->buildPreload( $allData );
+
                # Save to the process cache and register the items loaded
                $this->data[$code] = $allData;
                foreach ( $allData as $key => $item ) {
@@ -633,6 +665,15 @@ class LocalisationCache {
                }
        }
 
+       /**
+        * Unload all data
+        */
+       public function unloadAll() {
+               foreach ( $this->initialisedLangs as $lang => $unused ) {
+                       $this->unload( $lang );
+               }
+       }
+
        /**
         * Add messages to the cache, from an extension that has not yet been 
         * migrated to $wgExtensionMessages or the LocalisationCacheRecache hook. 
@@ -654,6 +695,7 @@ class LocalisationCache {
         */
        public function disableBackend() {
                $this->store = new LCStore_Null;
+               $this->manualRecache = false;
        }
 }
 
@@ -709,6 +751,7 @@ class LCStore_DB implements LCStore {
        var $currentLang;
        var $writesDone = false;
        var $dbw, $batch;
+       var $readOnly = false;
 
        public function get( $code, $key ) {
                if ( $this->writesDone ) {
@@ -726,17 +769,34 @@ class LCStore_DB implements LCStore {
        }
 
        public function startWrite( $code ) {
+               if ( $this->readOnly ) {
+                       return;
+               }
                if ( !$code ) {
                        throw new MWException( __METHOD__.": Invalid language \"$code\"" );
                }
                $this->dbw = wfGetDB( DB_MASTER );
-               $this->dbw->begin();
-               $this->dbw->delete( 'l10n_cache', array( 'lc_lang' => $code ), __METHOD__ );
+               try {
+                       $this->dbw->begin();
+                       $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->ignoreErrors( false );
+                               return;
+                       } else {
+                               throw $e;
+                       }
+               }
                $this->currentLang = $code;
                $this->batch = array();
        }
 
        public function finishWrite() {
+               if ( $this->readOnly ) {
+                       return;
+               }
                if ( $this->batch ) {
                        $this->dbw->insert( 'l10n_cache', $this->batch, __METHOD__ );
                }
@@ -748,6 +808,9 @@ class LCStore_DB implements LCStore {
        }
 
        public function set( $key, $value ) {
+               if ( $this->readOnly ) {
+                       return;
+               }
                if ( is_null( $this->currentLang ) ) {
                        throw new MWException( __CLASS__.': must call startWrite() before calling set()' );
                }
@@ -775,8 +838,17 @@ class LCStore_DB implements LCStore {
  * See Cdb.php and http://cr.yp.to/cdb.html
  */
 class LCStore_CDB implements LCStore {
-       var $readers, $writer, $currentLang;
-       
+       var $readers, $writer, $currentLang, $directory;
+
+       function __construct( $conf = array() ) {
+               global $wgCacheDirectory;
+               if ( isset( $conf['directory'] ) ) {
+                       $this->directory = $conf['directory'];
+               } else {
+                       $this->directory = $wgCacheDirectory;
+               }
+       }
+
        public function get( $code, $key ) {
                if ( !isset( $this->readers[$code] ) ) {
                        $fileName = $this->getFileName( $code );
@@ -798,6 +870,16 @@ class LCStore_CDB implements LCStore {
        }
 
        public function startWrite( $code ) {
+               if ( !file_exists( $this->directory ) ) {
+                       if ( !wfMkdirParents( $this->directory ) ) {
+                               throw new MWException( "Unable to create the localisation store " . 
+                                       "directory \"{$this->directory}\"" );
+                       }
+               }
+               // Close reader to stop permission errors on write
+               if( !empty($this->readers[$code]) ) {
+                       $this->readers[$code]->close();
+               }
                $this->writer = CdbWriter::open( $this->getFileName( $code ) );
                $this->currentLang = $code;
        }
@@ -806,11 +888,6 @@ class LCStore_CDB implements LCStore {
                // Close the writer
                $this->writer->close();
                $this->writer = null;
-
-               // Reopen the reader
-               if ( !empty( $this->readers[$this->currentLang] ) ) {
-                       $this->readers[$this->currentLang]->close();
-               }
                unset( $this->readers[$this->currentLang] );
                $this->currentLang = null;
        }
@@ -823,11 +900,10 @@ class LCStore_CDB implements LCStore {
        }
 
        protected function getFileName( $code ) {
-               global $wgCacheDirectory;
                if ( !$code || strpos( $code, '/' ) !== false ) {
                        throw new MWException( __METHOD__.": Invalid language \"$code\"" );
                }
-               return "$wgCacheDirectory/l10n_cache-$code.cdb";
+               return "{$this->directory}/l10n_cache-$code.cdb";
        }
 }