9 use Drush\SiteAlias\SiteAliasManager;
10 use League\Container\ContainerInterface;
11 use Psr\Log\LoggerInterface;
12 use SebastianBergmann\Version;
13 use Symfony\Component\Console\Application;
14 use Symfony\Component\Console\Input\InputInterface;
15 use Symfony\Component\Console\Output\OutputInterface;
17 // TODO: Not sure if we should have a reference to PreflightArgs here.
18 // Maybe these constants should be in config, and PreflightArgs can
19 // reference them from there as well.
20 use Drush\Preflight\PreflightArgs;
23 * Static Service Container wrapper.
25 * This code is analogous to the \Drupal class in Drupal 8.
27 * We would like to move Drush towards the model of using constructor
28 * injection rather than globals. This class serves as a unified global
29 * accessor to arbitrary services for use by legacy Drush code.
31 * Advice from Drupal 8's 'Drupal' class:
33 * This class exists only to support legacy code that cannot be dependency
34 * injected. If your code needs it, consider refactoring it to be object
35 * oriented, if possible. When this is not possible, and your code is more
36 * than a few non-reusable lines, it is recommended to instantiate an object
37 * implementing the actual logic.
40 * // Legacy procedural code.
41 * $object = drush_get_context('DRUSH_CLASS_LABEL');
44 * $object = Drush::service('label');
52 * The version of Drush from the drush.info file, or FALSE if not read yet.
56 protected static $version = false;
57 protected static $majorVersion = false;
58 protected static $minorVersion = false;
61 * The currently active container object, or NULL if not initialized yet.
63 * @var \League\Container\ContainerInterface|null
65 protected static $container;
68 * The Robo Runner -- manages and constructs all commandfile classes
72 protected static $runner;
75 * Return the current Drush version.
77 * n.b. Called before the DI container is initialized.
78 * Do not log, etc. here.
80 public static function getVersion()
82 if (!static::$version) {
83 $drush_info = static::drushReadDrushInfo();
84 $instance = new Version($drush_info['drush_version'], dirname(__DIR__));
85 static::$version = $instance->getversion();
87 return static::$version;
90 public static function getMajorVersion()
92 if (!static::$majorVersion) {
93 $drush_version = static::getVersion();
94 $version_parts = explode('.', $drush_version);
95 static::$majorVersion = $version_parts[0];
97 return static::$majorVersion;
100 public static function getMinorVersion()
102 if (!static::$minorVersion) {
103 $drush_version = static::getVersion();
104 $version_parts = explode('.', $drush_version);
105 static::$minorVersion = $version_parts[1];
107 return static::$minorVersion;
111 * Sets a new global container.
113 * @param \League\Container\Container $container
114 * A new container instance to replace the current.
116 public static function setContainer(ContainerInterface $container)
118 static::$container = $container;
122 * Unsets the global container.
124 public static function unsetContainer()
126 static::$container = null;
130 * Returns the currently active global container.
132 * @return \League\Container\ContainerInterface|null
134 * @throws RuntimeException
136 public static function getContainer()
138 if (static::$container === null) {
139 debug_print_backtrace();
140 throw new \RuntimeException('Drush::$container is not initialized yet. \Drupal::setContainer() must be called with a real container.');
142 return static::$container;
146 * Returns TRUE if the container has been initialized, FALSE otherwise.
150 public static function hasContainer()
152 return static::$container !== null;
156 * Get the current Symfony Console Application.
158 * @return Application
160 public static function getApplication()
162 return self::getContainer()->get('application');
166 * Return the Robo runner.
168 * @return \Robo\Runner
170 public static function runner()
172 if (!isset(static::$runner)) {
173 static::$runner = new \Robo\Runner();
175 return static::$runner;
179 * Retrieves a service from the container.
181 * Use this method if the desired service is not one of those with a dedicated
182 * accessor method below. If it is listed below, those methods are preferred
183 * as they can return useful type hints.
186 * The ID of the service to retrieve.
189 * The specified service.
191 public static function service($id)
193 return static::getContainer()->get($id);
197 * Indicates if a service is defined in the container.
200 * The ID of the service to check.
203 * TRUE if the specified service exists, FALSE otherwise.
205 public static function hasService($id)
207 // Check hasContainer() first in order to always return a Boolean.
208 return static::hasContainer() && static::getContainer()->has($id);
212 * Return command factory
214 * @return \Consolidation\AnnotatedCommand\AnnotatedCommandFactory
216 public static function commandFactory()
218 return static::service('commandFactory');
222 * Return the Drush logger object.
224 * @return LoggerInterface
226 public static function logger()
228 return static::service('logger');
232 * Return the configuration object
234 * @return \Drush\Config\DrushConfig
236 public static function config()
238 return static::service('config');
242 * @return SiteAliasManager
244 public static function aliasManager()
246 return static::service('site.alias.manager');
250 * Return the input object
252 * @return InputInterface
254 public static function input()
256 return static::service('input');
260 * Return the output object
262 * @return OutputInterface
264 public static function output()
266 return static::service('output');
270 * Return 'true' if we are in simulated mode
272 public static function simulate()
274 return \Drush\Drush::config()->get(\Robo\Config\Config::SIMULATE);
278 * Return 'true' if we are in backend mode
280 public static function backend()
282 return \Drush\Drush::config()->get(PreflightArgs::BACKEND);
286 * Return 'true' if we are in affirmative mode
288 public static function affirmative()
290 if (!static::hasService('input')) {
291 throw new \Exception('No input service available.');
293 return Drush::input()->getOption('yes') || (Drush::backend() && !Drush::negative());
297 * Return 'true' if we are in negative mode
299 public static function negative()
301 if (!static::hasService('input')) {
302 throw new \Exception('No input service available.');
304 return Drush::input()->getOption('no');
308 * Return 'true' if we are in verbose mode
310 public static function verbose()
312 if (!static::hasService('output')) {
315 return \Drush\Drush::output()->isVerbose();
319 * Return 'true' if we are in debug mode
321 public static function debug()
323 if (!static::hasService('output')) {
326 return \Drush\Drush::output()->isDebug();
330 * Return the Bootstrap Manager.
332 * @return \Drush\Boot\BootstrapManager
334 public static function bootstrapManager()
336 return static::service('bootstrap.manager');
340 * Return the Bootstrap object.
342 * @return \Drush\Boot\Boot
344 public static function bootstrap()
346 return static::bootstrapManager()->bootstrap();
349 public static function redispatchOptions($input = null)
351 $input = $input ?: static::input();
353 // $input->getOptions() returns an associative array of option => value
354 $options = $input->getOptions();
356 // The 'runtime.options' config contains a list of option names on th cli
357 $optionNamesFromCommandline = static::config()->get('runtime.options');
359 // Remove anything in $options that was not on the cli
360 $options = array_intersect_key($options, array_flip($optionNamesFromCommandline));
362 // Add in the 'runtime.context' items, which includes --include, --alias-path et. al.
363 return $options + array_filter(static::config()->get(PreflightArgs::DRUSH_RUNTIME_CONTEXT_NAMESPACE));
367 * Read the drush info file.
369 private static function drushReadDrushInfo()
371 $drush_info_file = dirname(__FILE__) . '/../drush.info';
373 return parse_ini_file($drush_info_file);