]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - maintenance/rebuildLocalisationCache.php
MediaWiki 1.30.2 renames
[autoinstalls/mediawiki.git] / maintenance / rebuildLocalisationCache.php
1 <?php
2
3 /**
4  * Rebuild the localisation cache. Useful if you disabled automatic updates
5  * using $wgLocalisationCacheConf['manualRecache'] = true;
6  *
7  * Usage:
8  *    php rebuildLocalisationCache.php [--force] [--threads=N]
9  *
10  * Use --force to rebuild all files, even the ones that are not out of date.
11  * Use --threads=N to fork more threads.
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  * http://www.gnu.org/copyleft/gpl.html
27  *
28  * @file
29  * @ingroup Maintenance
30  */
31
32 require_once __DIR__ . '/Maintenance.php';
33
34 /**
35  * Maintenance script to rebuild the localisation cache.
36  *
37  * @ingroup Maintenance
38  */
39 class RebuildLocalisationCache extends Maintenance {
40         public function __construct() {
41                 parent::__construct();
42                 $this->addDescription( 'Rebuild the localisation cache' );
43                 $this->addOption( 'force', 'Rebuild all files, even ones not out of date' );
44                 $this->addOption( 'threads', 'Fork more than one thread', false, true );
45                 $this->addOption( 'outdir', 'Override the output directory (normally $wgCacheDirectory)',
46                         false, true );
47                 $this->addOption( 'lang', 'Only rebuild these languages, comma separated.',
48                         false, true );
49         }
50
51         public function finalSetup() {
52                 # This script needs to be run to build the inital l10n cache. But if
53                 # $wgLanguageCode is not 'en', it won't be able to run because there is
54                 # no l10n cache. Break the cycle by forcing $wgLanguageCode = 'en'.
55                 global $wgLanguageCode;
56                 $wgLanguageCode = 'en';
57                 parent::finalSetup();
58         }
59
60         public function execute() {
61                 global $wgLocalisationCacheConf;
62
63                 $force = $this->hasOption( 'force' );
64                 $threads = $this->getOption( 'threads', 1 );
65                 if ( $threads < 1 || $threads != intval( $threads ) ) {
66                         $this->output( "Invalid thread count specified; running single-threaded.\n" );
67                         $threads = 1;
68                 }
69                 if ( $threads > 1 && wfIsWindows() ) {
70                         $this->output( "Threaded rebuild is not supported on Windows; running single-threaded.\n" );
71                         $threads = 1;
72                 }
73                 if ( $threads > 1 && !function_exists( 'pcntl_fork' ) ) {
74                         $this->output( "PHP pcntl extension is not present; running single-threaded.\n" );
75                         $threads = 1;
76                 }
77
78                 $conf = $wgLocalisationCacheConf;
79                 $conf['manualRecache'] = false; // Allow fallbacks to create CDB files
80                 if ( $force ) {
81                         $conf['forceRecache'] = true;
82                 }
83                 if ( $this->hasOption( 'outdir' ) ) {
84                         $conf['storeDirectory'] = $this->getOption( 'outdir' );
85                 }
86                 $lc = new LocalisationCacheBulkLoad( $conf );
87
88                 $allCodes = array_keys( Language::fetchLanguageNames( null, 'mwfile' ) );
89                 if ( $this->hasOption( 'lang' ) ) {
90                         # Validate requested languages
91                         $codes = array_intersect( $allCodes,
92                                 explode( ',', $this->getOption( 'lang' ) ) );
93                         # Bailed out if nothing is left
94                         if ( count( $codes ) == 0 ) {
95                                 $this->error( 'None of the languages specified exists.', 1 );
96                         }
97                 } else {
98                         # By default get all languages
99                         $codes = $allCodes;
100                 }
101                 sort( $codes );
102
103                 // Initialise and split into chunks
104                 $numRebuilt = 0;
105                 $total = count( $codes );
106                 $chunks = array_chunk( $codes, ceil( count( $codes ) / $threads ) );
107                 $pids = [];
108                 $parentStatus = 0;
109                 foreach ( $chunks as $codes ) {
110                         // Do not fork for only one thread
111                         $pid = ( $threads > 1 ) ? pcntl_fork() : -1;
112
113                         if ( $pid === 0 ) {
114                                 // Child, reseed because there is no bug in PHP:
115                                 // https://bugs.php.net/bug.php?id=42465
116                                 mt_srand( getmypid() );
117
118                                 $this->doRebuild( $codes, $lc, $force );
119                                 exit( 0 );
120                         } elseif ( $pid === -1 ) {
121                                 // Fork failed or one thread, do it serialized
122                                 $numRebuilt += $this->doRebuild( $codes, $lc, $force );
123                         } else {
124                                 // Main thread
125                                 $pids[] = $pid;
126                         }
127                 }
128                 // Wait for all children
129                 foreach ( $pids as $pid ) {
130                         $status = 0;
131                         pcntl_waitpid( $pid, $status );
132                         if ( pcntl_wexitstatus( $status ) ) {
133                                 // Pass a fatal error code through to the caller
134                                 $parentStatus = pcntl_wexitstatus( $status );
135                         }
136                 }
137
138                 if ( !$pids ) {
139                         $this->output( "$numRebuilt languages rebuilt out of $total\n" );
140                         if ( $numRebuilt === 0 ) {
141                                 $this->output( "Use --force to rebuild the caches which are still fresh.\n" );
142                         }
143                 }
144                 if ( $parentStatus ) {
145                         exit( $parentStatus );
146                 }
147         }
148
149         /**
150          * Helper function to rebuild list of languages codes. Prints the code
151          * for each language which is rebuilt.
152          * @param array $codes List of language codes to rebuild.
153          * @param LocalisationCache $lc Instance of LocalisationCacheBulkLoad (?)
154          * @param bool $force Rebuild up-to-date languages
155          * @return int Number of rebuilt languages
156          */
157         private function doRebuild( $codes, $lc, $force ) {
158                 $numRebuilt = 0;
159                 foreach ( $codes as $code ) {
160                         if ( $force || $lc->isExpired( $code ) ) {
161                                 $this->output( "Rebuilding $code...\n" );
162                                 $lc->recache( $code );
163                                 $numRebuilt++;
164                         }
165                 }
166
167                 return $numRebuilt;
168         }
169
170         /**
171          * Sets whether a run of this maintenance script has the force parameter set
172          *
173          * @param bool $forced
174          */
175         public function setForce( $forced = true ) {
176                 $this->mOptions['force'] = $forced;
177         }
178 }
179
180 $maintClass = "RebuildLocalisationCache";
181 require_once RUN_MAINTENANCE_IF_MAIN;