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' ) {
112 $this->
fatalError(
"'$platform' is not a supported platform!" );
115 foreach ( $platforms as $platform ) {
116 $sqlPath = $this->
getOption(
'sql', dirname( $jsonPath ) );
120 if ( $platform ===
'mysql' && !is_dir( $sqlPath .
'/mysql' ) ) {
122 if ( is_dir( $sqlPath ) ) {
123 $sqlPath = $this->getSqlPathWithFileName( $relativeJsonPath, $sqlPath );
127 if ( is_dir( $sqlPath ) ) {
128 $sqlPath .=
'/' . $platform;
129 $directory = $sqlPath;
130 $sqlPath = $this->getSqlPathWithFileName( $relativeJsonPath, $sqlPath );
131 } elseif ( count( $platforms ) > 1 ) {
132 $directory = dirname( $sqlPath ) .
'/' . $platform;
133 $sqlPath = $directory .
'/' . pathinfo( $sqlPath, PATHINFO_FILENAME ) .
'.sql';
139 if ( $directory !==
false && !is_dir( $directory )
140 && !mkdir( $directory ) && !is_dir( $directory )
142 $this->
error(
"Cannot create $directory for $platform" );
148 $this->writeSchema( $platform, $jsonPath, $relativeJsonPath, $sqlPath );
161 private function getSqlPathWithFileName(
string $relativeJsonPath,
string $sqlPath ): string {
162 $jsonFilename = pathinfo( $relativeJsonPath, PATHINFO_FILENAME );
163 if ( str_starts_with( $jsonFilename,
'tables' ) ) {
164 $sqlFileName = $jsonFilename .
'-generated.sql';
166 $sqlFileName = $jsonFilename .
'.sql';
169 return $sqlPath .
'/' . $sqlFileName;
172 private function writeSchema(
175 string $relativeJsonPath,
178 $abstractSchemaChange = $this->getSchema( $jsonPath );
181 "-- This file is automatically generated using maintenance/$this->scriptName.\n" .
182 "-- Source: $relativeJsonPath\n" .
183 "-- Do not modify this file directly.\n" .
184 "-- See https://www.mediawiki.org/wiki/Manual:Schema_changes\n";
186 $sql .= $this->generateSchema( $platform, $abstractSchemaChange );
189 if ( is_readable( $sqlPath ) ) {
190 $oldSql = file_get_contents( $sqlPath );
191 if ( $oldSql === $sql ) {
192 $this->output(
"Schema change is unchanged.\n" );
196 file_put_contents( $sqlPath, $sql );
197 $this->output(
'Schema change generated and written to ' . $sqlPath .
"\n" );
200 abstract protected function generateSchema(
string $platform, array $schema ): string;
208 private function getSchema(
string $jsonPath ): array {
209 $json = file_get_contents( $jsonPath );
213 "'$jsonPath' does not exist!\n"
217 $abstractSchema = json_decode( $json,
true );
219 if ( json_last_error() !== JSON_ERROR_NONE ) {
221 "'$jsonPath' seems to be invalid json. Check the syntax and try again!\n" . json_last_error_msg()
226 $this->fatalError( $msg );
231 $this->fatalError( $e->getMessage() );
234 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