14use Symfony\Component\Yaml\Yaml;
16require_once __DIR__ .
'/Maintenance.php';
27 parent::__construct();
28 $this->
addDescription(
'Create the database and tables for a new wiki, ' .
29 'using a pre-existing LocalSettings.php' );
31 'Execute only the specified task',
false,
true );
33 'Skip the specified task',
false,
true,
false,
true );
35 'Specify a configuration variable with name=value. The value is in YAML format.',
36 false,
true,
'c',
true );
38 'Specify an installer option with name=value. The value is in YAML format.',
39 false,
true,
'o',
true );
41 'Show the list of tasks to be executed, do not actually install' );
46 return Maintenance::DB_ADMIN;
50 parent::finalSetup( $settingsBuilder );
55 foreach ( $this->
getOption(
'override-config' ) ?? [] as $str ) {
56 [ $name, $value ] = $this->parseKeyValue( $str );
57 if ( str_starts_with( $name,
'wg' ) ) {
58 $name = substr( $name, 2 );
67 $taskFactory = $this->createTaskFactory( $context );
68 $taskList = $this->createTaskList( $taskFactory );
69 $taskRunner = $this->createTaskRunner( $taskList, $taskFactory );
71 Installer::disableStorage( $this->
getConfig(),
'en' );
74 $taskRunner->loadExtensions();
75 echo $taskRunner->dumpTaskList();
80 $status = $taskRunner->runNamedTask( $this->
getOption(
'task' ) );
82 $status = $taskRunner->execute();
85 if ( $status->
isOK() ) {
86 $this->
output(
"Installation complete.\n" );
89 $this->
error(
"Installation failed at task \"" .
90 $taskRunner->getCurrentTaskName() .
'"' );
102 private function parseKeyValue(
string $str ) {
103 $parts = explode(
'=', $str, 2 );
104 if ( count( $parts ) !== 2 ) {
105 $this->
fatalError(
"Invalid configuration variable \"$str\"" );
107 return [ $parts[0], Yaml::parse( $parts[1], Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE ) ];
114 if ( !$this->taskContext ) {
115 $this->taskContext = $this->createTaskContext();
117 return $this->taskContext;
126 private function createTaskContext() {
133 $context->setOption(
'Extensions',
134 array_keys( ExtensionRegistry::getInstance()->getAllThings() ) );
136 foreach ( $this->
getOption(
'override-option' ) ?? [] as $str ) {
137 [ $name, $value ] = $this->parseKeyValue( $str );
138 $context->setOption( $name, $value );
141 $context->setOption( $name, $value );
163 private function createTaskList(
TaskFactory $taskFactory ) {
166 $reg = ExtensionRegistry::getInstance();
169 'class' => CannedProvider::class,
173 'HookContainer' => $this->getHookContainer(),
174 'VirtualDomains' => $reg->getAttribute(
'DatabaseVirtualDomains' ),
175 'ExtensionTaskSpecs' => $reg->getAttribute(
'InstallerTasks' ),
181 $taskList->
add( $taskFactory->
create( $spec ) );
207 $taskRunner =
new TaskRunner( $taskList, $taskFactory, TaskFactory::PROFILE_ADD_WIKI );
208 $taskRunner->setSkippedTasks( $this->
getOption(
'skip' ) ?? [] );
210 $taskRunner->addTaskStartListener(
function (
Task $task ) {
213 $this->
output(
"[$name] $desc... " );
216 $taskRunner->addTaskEndListener(
function ( $task,
StatusValue $status ) {
217 if ( $status->
isOK() ) {
218 $this->
output(
"done\n" );
222 if ( !$status->
isGood() ) {
224 $this->
error( $status );
225 }
catch ( InvalidArgumentException $e ) {
226 $this->
error( (
string)$status );
240 private function createTaskFactory(
ITaskContext $context ) {
249require_once RUN_MAINTENANCE_IF_MAIN;
A task context for use in installPreConfigured.php.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
output( $out, $channel=null)
Throw some output to the user.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
hasOption( $name)
Checks to see if a particular option was set.
getOption( $name, $default=null)
Get an option, or return the default.
error( $err, $die=0)
Throw an error to the user.
getServiceContainer()
Returns the main service container.
addDescription( $text)
Set the description text.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
isOK()
Returns whether the operation completed.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Dependency bundle and execution context for installer tasks.