53720800c284f6ae9b945afad4a81e8cafd1abc4
[yaffs-website] / vendor / drush / drush / src / Runtime / Runtime.php
1 <?php
2 namespace Drush\Runtime;
3
4 use Consolidation\AnnotatedCommand\CommandData;
5 use Consolidation\AnnotatedCommand\Hooks\ValidatorInterface;
6 use Drush\Drush;
7 use Drush\Preflight\Preflight;
8
9 /**
10  * Control the Drush runtime environment
11  *
12  * - Preflight
13  * - Symfony application run
14  * - Bootstrap
15  * - Command execution
16  * - Termination
17  */
18 class Runtime
19 {
20     /** @var Preflight */
21     protected $preflight;
22
23     /**
24      * Runtime constructor
25      *
26      * @param Preflight $preflight the prefligth object
27      */
28     public function __construct(Preflight $preflight)
29     {
30         $this->preflight = $preflight;
31     }
32
33     /**
34      * Run the application, catching any errors that may be thrown.
35      * Typically, this will happen only for code that fails fast during
36      * preflight. Later code should catch and handle its own exceptions.
37      */
38     public function run($argv)
39     {
40         try {
41             $status = $this->doRun($argv);
42         } catch (\Exception $e) {
43             $status = $e->getCode();
44             $message = $e->getMessage();
45             // Uncaught exceptions could happen early, before our logger
46             // and other classes are initialized. Print them and exit.
47             $this->preflight->logger()->setDebug(true)->log($message);
48         }
49         return $status;
50     }
51
52     /**
53      * Start up Drush
54      */
55     protected function doRun($argv)
56     {
57         // Do the preflight steps
58         $status = $this->preflight->preflight($argv);
59
60         // If preflight signals that we are done, then exit early.
61         if ($status !== false) {
62             return $status;
63         }
64
65         $commandfileSearchpath = $this->preflight->getCommandFilePaths();
66         $this->preflight->logger()->log('Commandfile search paths: ' . implode(',', $commandfileSearchpath));
67         $this->preflight->config()->set('runtime.commandfile.paths', $commandfileSearchpath);
68
69         // Require the Composer autoloader for Drupal (if different)
70         $loader = $this->preflight->loadSiteAutoloader();
71
72         // Create the Symfony Application et. al.
73         $input = $this->preflight->createInput();
74         $output = new \Symfony\Component\Console\Output\ConsoleOutput();
75         $application = new \Drush\Application('Drush Commandline Tool', Drush::getVersion());
76
77         // Set up the DI container.
78         $container = DependencyInjection::initContainer(
79             $application,
80             $this->preflight->config(),
81             $input,
82             $output,
83             $loader,
84             $this->preflight->drupalFinder(),
85             $this->preflight->aliasManager()
86         );
87
88         // Now that the DI container has been set up, the Application object will
89         // have a reference to the bootstrap manager et. al., so we may use it
90         // as needed. Tell the application to coordinate between the Bootstrap
91         // manager and the alias manager to select a more specific URI, if
92         // one was not explicitly provided earlier in the preflight.
93         $application->refineUriSelection($this->preflight->environment()->cwd());
94
95         // Our termination handlers depend on classes we set up via DependencyInjection,
96         // so we do not want to enable it any earlier than this.
97         // TODO: Inject a termination handler into this class, so that we don't
98         // need to add these e.g. when testing.
99         $this->setTerminationHandlers();
100
101         // Add global options and copy their values into Config.
102         $application->configureGlobalOptions();
103
104         // Configure the application object and register all of the commandfiles
105         // from the search paths we found above.  After this point, the input
106         // and output objects are ready & we can start using the logger, etc.
107         $application->configureAndRegisterCommands($input, $output, $commandfileSearchpath);
108
109         // Run the Symfony Application
110         // Predispatch: call a remote Drush command if applicable (via a 'pre-init' hook)
111         // Bootstrap: bootstrap site to the level requested by the command (via a 'post-init' hook)
112         $status = $application->run($input, $output);
113
114         // Placate the Drush shutdown handler.
115         // TODO: use a more modern termination management strategy
116         drush_set_context('DRUSH_EXECUTION_COMPLETED', true);
117
118         // For backwards compatibility (backend invoke needs this in drush_backend_output())
119         drush_set_context('DRUSH_ERROR_CODE', $status);
120
121         return $status;
122     }
123
124     /**
125      * Make sure we are notified on exit, and when bad things happen.
126      */
127     protected function setTerminationHandlers()
128     {
129         // Set an error handler and a shutdown function
130         // TODO: move these to a class somewhere
131         set_error_handler('drush_error_handler');
132         register_shutdown_function('drush_shutdown');
133     }
134 }