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' );
45 return Maintenance::DB_ADMIN;
49 parent::finalSetup( $settingsBuilder );
54 foreach ( $this->
getOption(
'override-config' ) ?? [] as $str ) {
55 [ $name, $value ] = $this->parseKeyValue( $str );
56 if ( str_starts_with( $name,
'wg' ) ) {
57 $name = substr( $name, 2 );
65 $taskFactory = $this->createTaskFactory( $context );
66 $taskList = $this->createTaskList( $taskFactory );
67 $taskRunner = $this->createTaskRunner( $taskList, $taskFactory );
69 Installer::disableStorage( $this->
getConfig(),
'en' );
72 $taskRunner->loadExtensions();
73 echo $taskRunner->dumpTaskList();
78 $status = $taskRunner->runNamedTask( $this->
getOption(
'task' ) );
80 $status = $taskRunner->execute();
83 if ( $status->
isOK() ) {
84 $this->
output(
"Installation complete.\n" );
87 $this->
error(
"Installation failed at task \"" .
88 $taskRunner->getCurrentTaskName() .
'"' );
100 private function parseKeyValue(
string $str ) {
101 $parts = explode(
'=', $str, 2 );
102 if ( count( $parts ) !== 2 ) {
103 $this->
fatalError(
"Invalid configuration variable \"$str\"" );
105 return [ $parts[0], Yaml::parse( $parts[1], Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE ) ];
112 if ( !$this->taskContext ) {
113 $this->taskContext = $this->createTaskContext();
115 return $this->taskContext;
124 private function createTaskContext() {
131 $context->setOption(
'Extensions',
132 array_keys( ExtensionRegistry::getInstance()->getAllThings() ) );
134 foreach ( $this->
getOption(
'override-option' ) ?? [] as $str ) {
135 [ $name, $value ] = $this->parseKeyValue( $str );
136 $context->setOption( $name, $value );
139 $context->setOption( $name, $value );
161 private function createTaskList(
TaskFactory $taskFactory ) {
164 $reg = ExtensionRegistry::getInstance();
167 'class' => CannedProvider::class,
171 'HookContainer' => $this->getHookContainer(),
172 'VirtualDomains' => $reg->getAttribute(
'DatabaseVirtualDomains' ),
173 'ExtensionTaskSpecs' => $reg->getAttribute(
'InstallerTasks' ),
179 $taskList->
add( $taskFactory->
create( $spec ) );
205 $taskRunner =
new TaskRunner( $taskList, $taskFactory, TaskFactory::PROFILE_ADD_WIKI );
206 $taskRunner->setSkippedTasks( $this->
getOption(
'skip' ) ?? [] );
208 $taskRunner->addTaskStartListener(
function (
Task $task ) {
211 $this->
output(
"[$name] $desc... " );
214 $taskRunner->addTaskEndListener(
function ( $task,
StatusValue $status ) {
215 if ( $status->
isOK() ) {
216 $this->
output(
"done\n" );
220 if ( !$status->
isGood() ) {
222 $this->
error( $status );
223 }
catch ( InvalidArgumentException $e ) {
224 $this->
error( (
string)$status );
238 private function createTaskFactory(
ITaskContext $context ) {
247require_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.