MediaWiki REL1_37
mergeMessageFileList.php
Go to the documentation of this file.
1<?php
25// NO_AUTOLOAD -- file-scope define() used to modify behaviour
26
27# Start from scratch
28define( 'MW_NO_EXTENSION_MESSAGES', 1 );
29
30require_once __DIR__ . '/Maintenance.php';
31$maintClass = MergeMessageFileList::class;
32$mmfl = false;
33
41 public function __construct() {
42 parent::__construct();
43 $this->addOption(
44 'list-file',
45 'A file containing a list of extension setup files, one per line.',
46 false,
47 true
48 );
49 $this->addOption( 'extensions-dir', 'Path where extensions can be found.', false, true );
50 $this->addOption( 'output', 'Send output to this file (omit for stdout)', false, true );
51 $this->addDescription( 'Merge $wgExtensionMessagesFiles and $wgMessagesDirs from ' .
52 ' various extensions to produce a single file listing all message files and dirs.'
53 );
54 }
55
56 public function execute() {
57 global $mmfl;
59
61 && !$this->hasOption( 'list-file' )
62 && !$this->hasOption( 'extensions-dir' )
63 ) {
64 $this->fatalError( "Either --list-file or --extensions-dir must be provided if " .
65 "\$wgExtensionEntryPointListFiles is not set" );
66 }
67
68 $mmfl = [ 'setupFiles' => [] ];
69
70 # Add setup files contained in file passed to --list-file
71 if ( $this->hasOption( 'list-file' ) ) {
72 $extensionPaths = $this->readFile( $this->getOption( 'list-file' ) );
73 $mmfl['setupFiles'] = array_merge( $mmfl['setupFiles'], $extensionPaths );
74 }
75
76 # Now find out files in a directory
77 if ( $this->hasOption( 'extensions-dir' ) ) {
78 $extdir = $this->getOption( 'extensions-dir' );
79 # Allow multiple directories to be passed with ":" as delimiter
80 $extdirs = explode( ':', $extdir );
81 foreach ( $extdirs as $extdir ) {
82 $entries = scandir( $extdir );
83 foreach ( $entries as $extname ) {
84 if ( $extname == '.' || $extname == '..' || !is_dir( "$extdir/$extname" ) ) {
85 continue;
86 }
87 $possibilities = [
88 "$extdir/$extname/extension.json",
89 "$extdir/$extname/skin.json",
90 "$extdir/$extname/$extname.php"
91 ];
92 $found = false;
93 foreach ( $possibilities as $extfile ) {
94 if ( file_exists( $extfile ) ) {
95 $mmfl['setupFiles'][] = $extfile;
96 $found = true;
97 break;
98 }
99 }
100
101 if ( !$found ) {
102 $this->error( "Extension {$extname} in {$extdir} lacks expected entry point: " .
103 "extension.json, skin.json, or {$extname}.php." );
104 }
105 }
106 }
107 }
108
109 # Add setup files defined via configuration
110 foreach ( $wgExtensionEntryPointListFiles as $points ) {
111 $extensionPaths = $this->readFile( $points );
112 $mmfl['setupFiles'] = array_merge( $mmfl['setupFiles'], $extensionPaths );
113 }
114
115 if ( $this->hasOption( 'output' ) ) {
116 $mmfl['output'] = $this->getOption( 'output' );
117 }
118 if ( $this->hasOption( 'quiet' ) ) {
119 $mmfl['quiet'] = true;
120 }
121 }
122
123 public function finalSetup() {
124 # This script commonly needs to be run before the l10n cache. But if
125 # $wgLanguageCode is not 'en', it won't be able to run because there is
126 # no l10n cache. Break the cycle by forcing $wgLanguageCode = 'en'.
127 global $wgLanguageCode;
128 $wgLanguageCode = 'en';
129 parent::finalSetup();
130 }
131
137 public function getDbType() {
139 }
140
145 private function readFile( $fileName ) {
146 global $IP;
147
148 $files = [];
149 $fileLines = file( $fileName );
150 if ( $fileLines === false ) {
151 $this->error( "Unable to open list file $fileName." );
152
153 return $files;
154 }
155 # Strip comments, discard empty lines, and trim leading and trailing
156 # whitespace. Comments start with '#' and extend to the end of the line.
157 foreach ( $fileLines as $extension ) {
158 $extension = trim( preg_replace( '/#.*/', '', $extension ) );
159 if ( $extension !== '' ) {
160 # Paths may use the string $IP to be substituted by the actual value
161 $extension = str_replace( '$IP', $IP, $extension );
162 if ( file_exists( $extension ) ) {
163 $files[] = $extension;
164 } else {
165 $this->error( "Extension {$extension} doesn't exist" );
166 }
167 }
168 }
169
170 return $files;
171 }
172}
173
174require_once RUN_MAINTENANCE_IF_MAIN;
175
177'@phan-var string[][] $mmfl';
178foreach ( $mmfl['setupFiles'] as $fileName ) {
179 if ( strval( $fileName ) === '' ) {
180 continue;
181 }
182 if ( empty( $mmfl['quiet'] ) ) {
183 fwrite( STDERR, "Loading data from $fileName\n" );
184 }
185 // Using extension.json or skin.json
186 if ( substr( $fileName, -strlen( '.json' ) ) === '.json' ) {
187 $queue[$fileName] = 1;
188 } else {
189 require_once $fileName;
190 }
191}
192
193if ( $queue ) {
194 $registry = new ExtensionRegistry();
195 $data = $registry->readFromQueue( $queue );
196 foreach ( [ 'wgExtensionMessagesFiles', 'wgMessagesDirs' ] as $var ) {
197 if ( isset( $data['globals'][$var] ) ) {
198 $GLOBALS[$var] = array_merge( $data['globals'][$var], $GLOBALS[$var] );
199 }
200 }
201}
202
203if ( empty( $mmfl['quiet'] ) ) {
204 fwrite( STDERR, "\n" );
205}
207 "<?php\n" .
208 "## This file is generated by mergeMessageFileList.php. Do not edit it directly.\n\n" .
209 "if ( defined( 'MW_NO_EXTENSION_MESSAGES' ) ) return;\n\n" .
210 '$wgExtensionMessagesFiles = ' . var_export( $wgExtensionMessagesFiles, true ) . ";\n\n" .
211 '$wgMessagesDirs = ' . var_export( $wgMessagesDirs, true ) . ";\n\n";
212
213$dirs = [
214 $IP,
215 dirname( __DIR__ ),
216 realpath( $IP )
217];
218
219foreach ( $dirs as $dir ) {
220 $s = preg_replace( "/'" . preg_quote( $dir, '/' ) . "([^']*)'/", '"$IP\1"', $s );
221}
222
223if ( isset( $mmfl['output'] ) ) {
224 $outputFile = $mmfl['output'];
225 $res = file_put_contents( $outputFile, $s );
226 if ( $res === false ) {
227 fwrite( STDERR, "Failed to write to $outputFile\n" );
228 exit( 1 );
229 }
230} else {
231 echo $s;
232}
$wgExtensionEntryPointListFiles
Array of files with list(s) of extension entry points to be used in maintenance/mergeMessageFileList....
$wgLanguageCode
Site language code.
$wgMessagesDirs
Extension messages directories.
$wgExtensionMessagesFiles
Extension messages files.
$IP
Definition WebStart.php:49
The Registry loads JSON files, and uses a Processor to extract information from them.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
error( $err, $die=0)
Throw an error to the user.
const DB_NONE
Constants for DB access type.
hasOption( $name)
Checks to see if a particular option was set.
addDescription( $text)
Set the description text.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Maintenance script that merges $wgExtensionMessagesFiles from various extensions to produce a single ...
getDbType()
Database access is not needed.
execute()
Do the actual work.
finalSetup()
Handle some last-minute setup here.
__construct()
Default constructor.
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s