-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Runtime.php
148 lines (126 loc) · 5.11 KB
/
Runtime.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php
declare(strict_types=1);
namespace Drush\Runtime;
use Symfony\Component\Console\Output\ConsoleOutput;
use Drush\Application;
use Drush\Commands\DrushCommands;
use Drush\Drush;
use Drush\Preflight\Preflight;
/**
* Control the Drush runtime environment
*
* - Preflight
* - Symfony application run
* - Bootstrap
* - Command execution
* - Termination
*/
class Runtime
{
const DRUSH_RUNTIME_COMPLETED_NAMESPACE = 'runtime.execution.completed';
const DRUSH_RUNTIME_EXIT_CODE_NAMESPACE = 'runtime.exit_code';
public function __construct(protected Preflight $preflight, protected DependencyInjection $di)
{
}
/**
* Run the application, catching any errors that may be thrown.
* Typically, this will happen only for code that fails fast during
* preflight. Later code should catch and handle its own exceptions.
*/
public function run($argv): int
{
try {
$output = new ConsoleOutput();
$status = $this->doRun($argv, $output);
} catch (\Exception $e) {
// Fallback to status 1 if the Exception has not indicated otherwise.
$status = $e->getCode() ?: DrushCommands::EXIT_FAILURE;
$message = $e->getMessage();
// Uncaught exceptions could happen early, before our logger
// and other classes are initialized. Print them and exit.
$this->preflight->logger()->setDebug(true)->log($message);
}
return $status;
}
/**
* Start up Drush
*/
protected function doRun($argv, $output): int
{
// Do the preflight steps
[$preflightDidRedispatch, $exitStatus] = $this->preflight->preflight($argv);
// If preflight signals that we are done, then exit early.
if ($preflightDidRedispatch) {
return $exitStatus;
}
$commandfileSearchpath = $this->preflight->getCommandFilePaths();
$this->preflight->logger()->log('Commandfile search paths: ' . implode(',', $commandfileSearchpath));
$this->preflight->config()->set('runtime.commandfile.paths', $commandfileSearchpath);
// Load the Symfony compatability layer autoloader
$this->preflight->loadSymfonyCompatabilityAutoloader();
// Create the Symfony Application et. al.
$input = $this->preflight->createInput();
$application = new Application('Drush Commandline Tool', Drush::sanitizeVersionString(Drush::getVersion()));
// Set up the DI container.
$container = $this->di->initContainer(
$application,
$this->preflight->config(),
$input,
$output,
$this->preflight->environment()->loader(),
$this->preflight->drupalFinder(),
$this->preflight->aliasManager()
);
// Our termination handlers are set up via dependency injection,
// as they require classes that are set up in the DI container.
// We therefore cannot configure them any earlier than this.
$this->di->installHandlers($container);
// Now that the DI container has been set up, the Application object will
// have a reference to the bootstrap manager et. al., so we may use it
// as needed. Tell the application to coordinate between the Bootstrap
// manager and the alias manager to select a more specific URI, if
// one was not explicitly provided earlier in the preflight.
$application->refineUriSelection($this->preflight->environment()->cwd());
// Add global options and copy their values into Config.
$application->configureGlobalOptions();
// Configure the application object and register all of the commandfiles
// from the search paths we found above. After this point, the input
// and output objects are ready & we can start using the logger, etc.
$application->configureAndRegisterCommands($input, $output, $commandfileSearchpath, $this->preflight->environment()->loader());
// Run the Symfony Application
// Predispatch: call a remote Drush command if applicable (via a 'pre-init' hook)
// Bootstrap: bootstrap site to the level requested by the command (via a 'post-init' hook)
$status = $application->run($input, $output);
// Placate the Drush shutdown handler.
Runtime::setCompleted();
Runtime::setExitCode($status);
return $status;
}
/**
* Mark the current request as having completed successfully.
*/
public static function setCompleted(): void
{
Drush::config()->set(self::DRUSH_RUNTIME_COMPLETED_NAMESPACE, true);
}
/**
* Mark the exit code for current request.
*
* @deprecated
* Was used by backend.inc
*/
public static function setExitCode(int $code): void
{
Drush::config()->set(self::DRUSH_RUNTIME_EXIT_CODE_NAMESPACE, $code);
}
/**
* Get the exit code for current request.
*
* @deprecated
* Was used by backend.inc
*/
public static function exitCode()
{
return Drush::config()->get(self::DRUSH_RUNTIME_EXIT_CODE_NAMESPACE, 0);
}
}