44 parent::__construct();
46 $types = implode(
', ', array_map(
static function (
string $type ):
string {
52 'Path to the json file. Default: tables.json',
58 'Path to output. If --type=all is given, ' .
59 'the output will be placed in a directory named after the dbms. ' .
60 'For mysql, a directory will only be used if it already exists. Default: tables-generated.sql',
66 "Can be either $types, or 'all'. Default: mysql",
72 'Validate the schema instead of generating sql files.'
79 $platform = $this->
getOption(
'type',
'mysql' );
80 $jsonPath = $this->
getOption(
'json', dirname( __DIR__ ) );
85 if ( DIRECTORY_SEPARATOR ===
'\\' ) {
86 $installPath = strtr( $installPath,
'\\',
'/' );
87 $jsonPath = strtr( $jsonPath,
'\\',
'/' );
91 $this->getSchema( $jsonPath );
97 if ( is_dir( $jsonPath ) ) {
98 $jsonPath .=
'/tables.json';
101 $relativeJsonPath = str_replace(
102 [
"$installPath/extensions/",
"$installPath/" ],
107 if ( in_array( $platform, self::SUPPORTED_PLATFORMS,
true ) ) {
108 $platforms = [ $platform ];
109 } elseif ( $platform ===
'all' ) {
113 $this->
fatalError(
"'$platform' is not a supported platform!" );
116 foreach ( $platforms as $platform ) {
117 $sqlPath = $this->
getOption(
'sql', dirname( $jsonPath ) );
121 if ( $platform ===
'mysql' && !is_dir( $sqlPath .
'/mysql' ) ) {
123 if ( is_dir( $sqlPath ) ) {
124 $sqlPath = $this->getSqlPathWithFileName( $relativeJsonPath, $sqlPath );
128 if ( is_dir( $sqlPath ) ) {
129 $sqlPath .=
'/' . $platform;
130 $directory = $sqlPath;
131 $sqlPath = $this->getSqlPathWithFileName( $relativeJsonPath, $sqlPath );
132 } elseif ( count( $platforms ) > 1 ) {
133 $directory = dirname( $sqlPath ) .
'/' . $platform;
134 $sqlPath = $directory .
'/' . pathinfo( $sqlPath, PATHINFO_FILENAME ) .
'.sql';
140 if ( $directory !==
false && !is_dir( $directory )
141 && !mkdir( $directory ) && !is_dir( $directory )
143 $this->
error(
"Cannot create $directory for $platform" );
149 $this->writeSchema( $platform, $jsonPath, $relativeJsonPath, $sqlPath );
162 private function getSqlPathWithFileName(
string $relativeJsonPath,
string $sqlPath ): string {
163 $jsonFilename = pathinfo( $relativeJsonPath, PATHINFO_FILENAME );
164 if ( str_starts_with( $jsonFilename,
'tables' ) ) {
165 $sqlFileName = $jsonFilename .
'-generated.sql';
167 $sqlFileName = $jsonFilename .
'.sql';
170 return $sqlPath .
'/' . $sqlFileName;
173 private function writeSchema(
176 string $relativeJsonPath,
179 $abstractSchemaChange = $this->getSchema( $jsonPath );
182 "-- This file is automatically generated using maintenance/$this->scriptName.\n" .
183 "-- Source: $relativeJsonPath\n" .
184 "-- Do not modify this file directly.\n" .
185 "-- See https://www.mediawiki.org/wiki/Manual:Schema_changes\n";
187 $sql .= $this->generateSchema( $platform, $abstractSchemaChange );
190 if ( is_readable( $sqlPath ) ) {
191 $oldSql = file_get_contents( $sqlPath );
192 if ( $oldSql === $sql ) {
193 $this->output(
"Schema change is unchanged.\n" );
197 file_put_contents( $sqlPath, $sql );
198 $this->output(
'Schema change generated and written to ' . $sqlPath .
"\n" );
201 abstract protected function generateSchema(
string $platform, array $schema ): string;
209 private function getSchema(
string $jsonPath ): array {
210 $json = file_get_contents( $jsonPath );
214 "'$jsonPath' does not exist!\n"
218 $abstractSchema = json_decode( $json,
true );
220 if ( json_last_error() !== JSON_ERROR_NONE ) {
222 "'$jsonPath' seems to be invalid json. Check the syntax and try again!\n" . json_last_error_msg()
227 $this->fatalError( $msg );
232 $this->fatalError( $e->getMessage() );
235 return $abstractSchema;
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
error( $err, $die=0)
Throw an error to the user.
hasOption( $name)
Checks to see if a particular option was set.
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.
generateSchema(string $platform, array $schema)
const SUPPORTED_PLATFORMS