MediaWiki  master
mergeMessageFileList.php
Go to the documentation of this file.
1 <?php
25 # Start from scratch
26 define( 'MW_NO_EXTENSION_MESSAGES', 1 );
27 
28 require_once __DIR__ . '/Maintenance.php';
29 $maintClass = MergeMessageFileList::class;
30 $mmfl = false;
31 
39  public function __construct() {
40  parent::__construct();
41  $this->addOption(
42  'list-file',
43  'A file containing a list of extension setup files, one per line.',
44  false,
45  true
46  );
47  $this->addOption( 'extensions-dir', 'Path where extensions can be found.', false, true );
48  $this->addOption( 'output', 'Send output to this file (omit for stdout)', false, true );
49  $this->addDescription( 'Merge $wgExtensionMessagesFiles and $wgMessagesDirs from ' .
50  ' various extensions to produce a single file listing all message files and dirs.'
51  );
52  }
53 
54  public function execute() {
55  global $mmfl;
57 
58  if ( !count( $wgExtensionEntryPointListFiles )
59  && !$this->hasOption( 'list-file' )
60  && !$this->hasOption( 'extensions-dir' )
61  ) {
62  $this->fatalError( "Either --list-file or --extensions-dir must be provided if " .
63  "\$wgExtensionEntryPointListFiles is not set" );
64  }
65 
66  $mmfl = [ 'setupFiles' => [] ];
67 
68  # Add setup files contained in file passed to --list-file
69  if ( $this->hasOption( 'list-file' ) ) {
70  $extensionPaths = $this->readFile( $this->getOption( 'list-file' ) );
71  $mmfl['setupFiles'] = array_merge( $mmfl['setupFiles'], $extensionPaths );
72  }
73 
74  # Now find out files in a directory
75  if ( $this->hasOption( 'extensions-dir' ) ) {
76  $extdir = $this->getOption( 'extensions-dir' );
77  # Allow multiple directories to be passed with ":" as delimiter
78  $extdirs = explode( ':', $extdir );
79  foreach ( $extdirs as $extdir ) {
80  $entries = scandir( $extdir );
81  foreach ( $entries as $extname ) {
82  if ( $extname == '.' || $extname == '..' || !is_dir( "$extdir/$extname" ) ) {
83  continue;
84  }
85  $possibilities = [
86  "$extdir/$extname/extension.json",
87  "$extdir/$extname/skin.json",
88  "$extdir/$extname/$extname.php"
89  ];
90  $found = false;
91  foreach ( $possibilities as $extfile ) {
92  if ( file_exists( $extfile ) ) {
93  $mmfl['setupFiles'][] = $extfile;
94  $found = true;
95  break;
96  }
97  }
98 
99  if ( !$found ) {
100  $this->error( "Extension {$extname} in {$extdir} lacks expected entry point: " .
101  "extension.json, skin.json, or {$extname}.php." );
102  }
103  }
104  }
105  }
106 
107  # Add setup files defined via configuration
108  foreach ( $wgExtensionEntryPointListFiles as $points ) {
109  $extensionPaths = $this->readFile( $points );
110  $mmfl['setupFiles'] = array_merge( $mmfl['setupFiles'], $extensionPaths );
111  }
112 
113  if ( $this->hasOption( 'output' ) ) {
114  $mmfl['output'] = $this->getOption( 'output' );
115  }
116  if ( $this->hasOption( 'quiet' ) ) {
117  $mmfl['quiet'] = true;
118  }
119  }
120 
125  private function readFile( $fileName ) {
126  global $IP;
127 
128  $files = [];
129  $fileLines = file( $fileName );
130  if ( $fileLines === false ) {
131  $this->error( "Unable to open list file $fileName." );
132 
133  return $files;
134  }
135  # Strip comments, discard empty lines, and trim leading and trailing
136  # whitespace. Comments start with '#' and extend to the end of the line.
137  foreach ( $fileLines as $extension ) {
138  $extension = trim( preg_replace( '/#.*/', '', $extension ) );
139  if ( $extension !== '' ) {
140  # Paths may use the string $IP to be substituted by the actual value
141  $extension = str_replace( '$IP', $IP, $extension );
142  if ( file_exists( $extension ) ) {
143  $files[] = $extension;
144  } else {
145  $this->error( "Extension {$extension} doesn't exist" );
146  }
147  }
148  }
149 
150  return $files;
151  }
152 }
153 
154 require_once RUN_MAINTENANCE_IF_MAIN;
155 
156 $queue = [];
157 '@phan-var string[][] $mmfl';
158 foreach ( $mmfl['setupFiles'] as $fileName ) {
159  if ( strval( $fileName ) === '' ) {
160  continue;
161  }
162  if ( empty( $mmfl['quiet'] ) ) {
163  fwrite( STDERR, "Loading data from $fileName\n" );
164  }
165  // Using extension.json or skin.json
166  if ( substr( $fileName, -strlen( '.json' ) ) === '.json' ) {
167  $queue[$fileName] = 1;
168  } else {
169  require_once $fileName;
170  }
171 }
172 
173 if ( $queue ) {
174  $registry = new ExtensionRegistry();
175  $data = $registry->readFromQueue( $queue );
176  foreach ( [ 'wgExtensionMessagesFiles', 'wgMessagesDirs' ] as $var ) {
177  if ( isset( $data['globals'][$var] ) ) {
178  $GLOBALS[$var] = array_merge( $data['globals'][$var], $GLOBALS[$var] );
179  }
180  }
181 }
182 
183 fwrite( STDERR, "\n" );
184 $s =
185  "<?php\n" .
186  "## This file is generated by mergeMessageFileList.php. Do not edit it directly.\n\n" .
187  "if ( defined( 'MW_NO_EXTENSION_MESSAGES' ) ) return;\n\n" .
188  '$wgExtensionMessagesFiles = ' . var_export( $wgExtensionMessagesFiles, true ) . ";\n\n" .
189  '$wgMessagesDirs = ' . var_export( $wgMessagesDirs, true ) . ";\n\n";
190 
191 $dirs = [
192  $IP,
193  dirname( __DIR__ ),
194  realpath( $IP )
195 ];
196 
197 foreach ( $dirs as $dir ) {
198  $s = preg_replace( "/'" . preg_quote( $dir, '/' ) . "([^']*)'/", '"$IP\1"', $s );
199 }
200 
201 if ( isset( $mmfl['output'] ) ) {
202  file_put_contents( $mmfl['output'], $s );
203 } else {
204  echo $s;
205 }
RUN_MAINTENANCE_IF_MAIN
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:38
Maintenance\fatalError
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Definition: Maintenance.php:487
Maintenance\addDescription
addDescription( $text)
Set the description text.
Definition: Maintenance.php:327
ExtensionRegistry
ExtensionRegistry class.
Definition: ExtensionRegistry.php:17
$wgExtensionMessagesFiles
$wgExtensionMessagesFiles
Extension messages files.
Definition: DefaultSettings.php:7730
$wgMessagesDirs
$wgMessagesDirs
Extension messages directories.
Definition: DefaultSettings.php:7757
$maintClass
$maintClass
Definition: mergeMessageFileList.php:29
$s
$s
Definition: mergeMessageFileList.php:184
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:55
MergeMessageFileList
Maintenance script that merges $wgExtensionMessagesFiles from various extensions to produce a single ...
Definition: mergeMessageFileList.php:38
MergeMessageFileList\readFile
readFile( $fileName)
Definition: mergeMessageFileList.php:125
$wgExtensionEntryPointListFiles
$wgExtensionEntryPointListFiles
Array of files with list(s) of extension entry points to be used in maintenance/mergeMessageFileList....
Definition: DefaultSettings.php:7764
$mmfl
$mmfl
Definition: mergeMessageFileList.php:30
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:245
$queue
$queue
Definition: mergeMessageFileList.php:156
$dirs
$dirs
Definition: mergeMessageFileList.php:191
MergeMessageFileList\__construct
__construct()
Default constructor.
Definition: mergeMessageFileList.php:39
MergeMessageFileList\execute
execute()
Do the actual work.
Definition: mergeMessageFileList.php:54
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:281
Maintenance\error
error( $err, $die=0)
Throw an error to the user.
Definition: Maintenance.php:463
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular option exists.
Definition: Maintenance.php:266
$IP
$IP
Definition: WebStart.php:49
$GLOBALS
$GLOBALS['IP']
Definition: ComposerHookHandler.php:6