diff --git a/commands/core/cli.drush.inc b/commands/core/cli.drush.inc index e8f7026920..0c3971915f 100644 --- a/commands/core/cli.drush.inc +++ b/commands/core/cli.drush.inc @@ -80,7 +80,7 @@ function drush_cli_core_cli() { // command in preflight still, but the subscriber instances are already // created from before. Call terminate() regardless, this is a no-op for all // DrupalBoot classes except DrupalBoot8. - if ($bootstrap = drush_get_bootstrap_object()) { + if ($bootstrap = \Drush::bootstrap()) { $bootstrap->terminate(); } diff --git a/commands/core/core.drush.inc b/commands/core/core.drush.inc index 1415b1740d..a3808d7ad6 100644 --- a/commands/core/core.drush.inc +++ b/commands/core/core.drush.inc @@ -500,7 +500,7 @@ function _core_site_credentials($right_margin = 0) { function _core_path_aliases($project = '') { $paths = array(); $site_wide = drush_drupal_sitewide_directory(); - $boot = drush_get_bootstrap_object(); + $boot = \Drush::bootstrap(); if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) { $paths['%root'] = $drupal_root; if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) { @@ -564,7 +564,7 @@ function _core_site_status_table($project = '') { $phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE'); if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) { $status_table['drupal-version'] = drush_drupal_version(); - $boot_object = drush_get_bootstrap_object(); + $boot_object = \Drush::bootstrap(); $conf_dir = $boot_object->conf_path(); $settings_file = "$conf_dir/settings.php"; $status_table['drupal-settings-file'] = file_exists($settings_file) ? $settings_file : ''; @@ -890,7 +890,7 @@ function drush_core_quick_drupal() { drush_set_option('backend', TRUE); drush_set_option('strict', FALSE); // We fail option validation because do so much internal drush_invoke(). $makefile = drush_get_option('makefile'); - $root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $root = \Drush::bootstrapManager()->getRoot(); if (drush_get_option('use-existing', ($root != FALSE))) { if (!$root) { return drush_set_error('QUICK_DRUPAL_NO_ROOT_SPECIFIED', 'Must specify site with --root when using --use-existing.'); @@ -947,9 +947,9 @@ function drush_core_quick_drupal() { drush_set_option('db-url', 'sqlite://' . $base . '/sites/' . strtolower(drush_get_option('sites-subdir', 'default')) . "/$name.sqlite"); } // We have just created a site root where one did not exist before. - // We therefore must manually reset DRUSH_SELECTED_DRUPAL_ROOT to + // We therefore must manually reset the selected root to // our new root, and force a bootstrap to DRUSH_BOOTSTRAP_DRUPAL_ROOT. - drush_set_context('DRUSH_SELECTED_DRUPAL_ROOT', $root); + \Drush::bootstrapManager()->setRoot($root); if (!drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_ROOT)) { return drush_set_error('QUICK_DRUPAL_ROOT_LOCATE_FAIL', 'Unable to locate Drupal root directory.'); } @@ -990,7 +990,7 @@ function drush_core_quick_drupal() { // Current CLI user is also the web server user, which is for development // only. Hence we can safely make the site directory writable. This makes // it easier to delete and edit settings.php. - $boot = drush_get_bootstrap_object(); + $boot = \Drush::bootstrap(); @chmod($boot->conf_path(), 0700); drush_invoke_process(array('root' => $root, 'uri' => $server_uri), 'runserver', array($server)); } @@ -1306,7 +1306,7 @@ function drush_core_execute() { $cmd = implode(' ', $args); // If we selected a Drupal site, then cwd to the site root prior to exec $cwd = FALSE; - if ($selected_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT')) { + if ($selected_root = \Drush::bootstrapManager()->getRoot()) { if (is_dir($selected_root)) { $cwd = getcwd(); drush_op('chdir', $selected_root); @@ -1345,7 +1345,7 @@ function drush_core_twig_compile() { require_once DRUSH_DRUPAL_CORE . "/themes/engines/twig/twig.engine"; // Scan all enabled modules and themes. // @todo Refactor to not reuse commandfile paths directly. - $boot = drush_get_bootstrap_object(); + $boot = \Drush::bootstrap(); $searchpaths = $boot->commandfile_searchpaths(DRUSH_BOOTSTRAP_DRUPAL_FULL); $searchpaths[] = drupal_get_path('theme', drush_theme_get_default());; $searchpaths[] = drupal_get_path('theme', drush_theme_get_admin()); diff --git a/commands/core/drupal/environment.inc b/commands/core/drupal/environment.inc index ac059ab11c..d588e230aa 100644 --- a/commands/core/drupal/environment.inc +++ b/commands/core/drupal/environment.inc @@ -198,7 +198,7 @@ function drush_module_enable($modules) { drush_module_install($modules); // Our logger got blown away during the container rebuild above. - $boot = drush_select_bootstrap_class(); + $boot = \Drush::bootstrapManager()->bootstrap(); $boot->add_logger(); // Flush all caches. No longer needed in D8 per https://github.com/drush-ops/drush/issues/1207 @@ -226,7 +226,7 @@ function drush_module_disable($modules) { function drush_module_uninstall($modules) { \Drupal::service('module_installer')->uninstall($modules); // Our logger got blown away during the container rebuild above. - $boot = drush_select_bootstrap_class(); + $boot = \Drush::bootstrapManager()->bootstrap(); $boot->add_logger(); } @@ -319,7 +319,7 @@ function drush_theme_disable($themes) { function drush_theme_uninstall($themes) { \Drupal::service('theme_handler')->uninstall($themes); // Our logger got blown away during the container rebuild above. - $boot = drush_select_bootstrap_class(); + $boot = \Drush::bootstrapManager()->bootstrap(); $boot->add_logger(); } diff --git a/composer.json b/composer.json index c9ecbb1131..9fe02f3c06 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,8 @@ "psy/psysh": "~0.6", "symfony/yaml": "~2.3|~3.0", "symfony/var-dumper": "~2.7|~3.0", + "league/container": "~2", + "symfony/config": "~2.2", "pear/console_table": "~1.3.0" }, "require-dev": { @@ -47,7 +49,10 @@ "autoload": { "psr-0": { "Drush": "lib/" - } + }, + "files": [ + "lib/Drush.php" + ] }, "autoload-dev": { "psr-0": { diff --git a/composer.lock b/composer.lock index 790c754aca..6590cb465b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,36 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "5d3ff591b7d55c908701113adb2e2404", - "content-hash": "55dc316c74bf06c6fd93daf5b0dad7b4", + "hash": "5c2ee54246d99e90e6d452342c1f4e76", + "content-hash": "17235ef5060daf9f43736336bdc6ba1a", "packages": [ + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "time": "2014-12-30 15:22:37" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "0.1", @@ -127,18 +154,82 @@ ], "time": "2015-04-20 18:58:01" }, + { + "name": "league/container", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/container.git", + "reference": "d4b5e0dde44aec50e4025c7249d668ea74b1ae44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/container/zipball/d4b5e0dde44aec50e4025c7249d668ea74b1ae44", + "reference": "d4b5e0dde44aec50e4025c7249d668ea74b1ae44", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "php": ">=5.4.0" + }, + "provide": { + "container-interop/container-interop-implementation": "^1.1" + }, + "replace": { + "orno/di": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev", + "dev-1.x": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Container\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Phil Bennett", + "email": "philipobenito@gmail.com", + "homepage": "http://www.philipobenito.com", + "role": "Developer" + } + ], + "description": "A fast and intuitive dependency injection container.", + "homepage": "https://github.com/thephpleague/container", + "keywords": [ + "container", + "dependency", + "di", + "injection", + "league", + "provider", + "service" + ], + "time": "2015-09-07 10:16:18" + }, { "name": "nikic/php-parser", - "version": "v2.0.0", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c542e5d86a9775abd1021618eb2430278bfc1e01" + "reference": "ce5be709d59b32dd8a88c80259028759991a4206" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c542e5d86a9775abd1021618eb2430278bfc1e01", - "reference": "c542e5d86a9775abd1021618eb2430278bfc1e01", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ce5be709d59b32dd8a88c80259028759991a4206", + "reference": "ce5be709d59b32dd8a88c80259028759991a4206", "shasum": "" }, "require": { @@ -176,7 +267,7 @@ "parser", "php" ], - "time": "2015-12-04 15:28:43" + "time": "2016-02-28 19:48:28" }, { "name": "pear/console_table", @@ -273,16 +364,16 @@ }, { "name": "psy/psysh", - "version": "v0.7.0", + "version": "v0.7.2", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "1573b36948a32bdaf43db525edf5e95d5a08ed06" + "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1573b36948a32bdaf43db525edf5e95d5a08ed06", - "reference": "1573b36948a32bdaf43db525edf5e95d5a08ed06", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e64e10b20f8d229cac76399e1f3edddb57a0f280", + "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280", "shasum": "" }, "require": { @@ -311,7 +402,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-develop": "0.7.x-dev" + "dev-develop": "0.8.x-dev" } }, "autoload": { @@ -341,20 +432,73 @@ "interactive", "shell" ], - "time": "2016-02-20 16:27:05" + "time": "2016-03-09 05:03:14" + }, + { + "name": "symfony/config", + "version": "v2.8.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "0f8f94e6a32b5c480024eed5fa5cbd2790d0ad19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/0f8f94e6a32b5c480024eed5fa5cbd2790d0ad19", + "reference": "0f8f94e6a32b5c480024eed5fa5cbd2790d0ad19", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/filesystem": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2016-02-22 16:12:45" }, { "name": "symfony/console", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5a02eaadaa285e2bb727eb6bbdfb8201fcd971b0" + "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5a02eaadaa285e2bb727eb6bbdfb8201fcd971b0", - "reference": "5a02eaadaa285e2bb727eb6bbdfb8201fcd971b0", + "url": "https://api.github.com/repos/symfony/console/zipball/2ed5e2706ce92313d120b8fe50d1063bcfd12e04", + "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04", "shasum": "" }, "require": { @@ -401,7 +545,56 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-02-02 13:44:19" + "time": "2016-02-28 16:24:34" + }, + { + "name": "symfony/filesystem", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "23ae8f9648d0a7fe94a47c8e20e5bf37c489a451" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/23ae8f9648d0a7fe94a47c8e20e5bf37c489a451", + "reference": "23ae8f9648d0a7fe94a47c8e20e5bf37c489a451", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2016-02-23 15:16:06" }, { "name": "symfony/polyfill-mbstring", @@ -464,16 +657,16 @@ }, { "name": "symfony/var-dumper", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "24bb94807eff00db49374c37ebf56a0304e8aef3" + "reference": "9a6a883c48acb215d4825ce9de61dccf93d62074" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/24bb94807eff00db49374c37ebf56a0304e8aef3", - "reference": "24bb94807eff00db49374c37ebf56a0304e8aef3", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9a6a883c48acb215d4825ce9de61dccf93d62074", + "reference": "9a6a883c48acb215d4825ce9de61dccf93d62074", "shasum": "" }, "require": { @@ -523,20 +716,20 @@ "debug", "dump" ], - "time": "2016-01-07 13:38:51" + "time": "2016-02-13 09:23:44" }, { "name": "symfony/yaml", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "3cf0709d7fe936e97bee9e954382e449003f1d9a" + "reference": "b5ba64cd67ecd6887f63868fa781ca094bd1377c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3cf0709d7fe936e97bee9e954382e449003f1d9a", - "reference": "3cf0709d7fe936e97bee9e954382e449003f1d9a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/b5ba64cd67ecd6887f63868fa781ca094bd1377c", + "reference": "b5ba64cd67ecd6887f63868fa781ca094bd1377c", "shasum": "" }, "require": { @@ -572,7 +765,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-02-02 13:44:19" + "time": "2016-02-23 15:16:06" } ], "packages-dev": [ @@ -1227,16 +1420,16 @@ }, { "name": "sebastian/environment", - "version": "1.3.3", + "version": "1.3.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6e7133793a8e5a5714a551a8324337374be209df" + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", - "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", "shasum": "" }, "require": { @@ -1273,7 +1466,7 @@ "environment", "hhvm" ], - "time": "2015-12-02 08:37:27" + "time": "2016-02-26 18:40:46" }, { "name": "sebastian/exporter", @@ -1482,16 +1675,16 @@ }, { "name": "symfony/process", - "version": "v2.7.9", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0570b9ca51135ee7da0f19239eaf7b07ffb87034" + "reference": "faa89438017392585abdf7f5a47f3f5f282d93c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0570b9ca51135ee7da0f19239eaf7b07ffb87034", - "reference": "0570b9ca51135ee7da0f19239eaf7b07ffb87034", + "url": "https://api.github.com/repos/symfony/process/zipball/faa89438017392585abdf7f5a47f3f5f282d93c1", + "reference": "faa89438017392585abdf7f5a47f3f5f282d93c1", "shasum": "" }, "require": { @@ -1527,7 +1720,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-01-06 09:57:37" + "time": "2016-02-02 13:32:58" } ], "aliases": [], diff --git a/drush-services.yml b/drush-services.yml new file mode 100644 index 0000000000..f253be472c --- /dev/null +++ b/drush-services.yml @@ -0,0 +1,42 @@ +# +# Drush services +# +# This file defines the core Drush service classes. +# +services: + # + # logger: + # Write messages to the error log. Note that the Drush logger conforms + # to the Psr/Log standard, but has been enhanced to support backend + # invoke (the remote end can write logs to the initiating end in real + # time, and still return structured results at the end.) + # + logger: + class: Drush\Log\Logger + # + # bootstrap.manager: + # The bootstrap manager is responsible for keeping track of the bootstrap + # objects that know how to bootstrap different frameworks. Drush will have + # a mechanism for this to be extended, e.g. by Backdrop. + # + bootstrap.manager: + class: Drush\Boot\BootstrapManager + arguments: ['@bootstrap.default', '@logger'] + bootstrap.default: + class: Drush\Boot\EmptyBoot + arguments: ['@logger'] + bootstrap.drupal8: + class: Drush\Boot\DrupalBoot8 + arguments: ['@logger'] + tags: + - { name: bootstrap.boot } + bootstrap.drupal7: + class: Drush\Boot\DrupalBoot7 + arguments: ['@logger'] + tags: + - { name: bootstrap.boot } + bootstrap.drupal6: + class: Drush\Boot\DrupalBoot6 + arguments: ['@logger'] + tags: + - { name: bootstrap.boot } diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 9b08db8acb..422d09987f 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -109,139 +109,6 @@ define('DRUSH_BOOTSTRAP_DRUPAL_FULL', 5); */ define('DRUSH_BOOTSTRAP_DRUPAL_LOGIN', 6); -/** - * Return the list of bootstrap objects that are available for - * initializing a CMS with Drush. We insure that any given candidate - * class is instantiated only once. - * - * @return \Drush\Boot\Boot[] - */ -function drush_get_bootstrap_candidates() { - $candidate_classes = drush_get_bootstrap_candidate_classnames(); - - $cache =& drush_get_context('DRUSH_BOOTSTRAP_CANDIDATE_OBJECTS'); - - $result = array(); - foreach($candidate_classes as $candidate_class) { - if (array_key_exists($candidate_class, $cache)) { - $result[$candidate_class] = $cache[$candidate_class]; - } - else { - $result[$candidate_class] = new $candidate_class; - } - } - - $cache = $result; - return $result; -} - -/** - * Find the list of bootstrap classnames available for initializing a - * CMS with Drush. - * - * @return array - */ -function drush_get_bootstrap_candidate_classnames() { - // Give all commandfiles a chance to return candidates. They should - // return STRINGS with the class name of the bootstrap object they provide. - $candidates = drush_command_invoke_all('bootstrap_candidates'); - // If a bootstrap class was specified on the command line, consider it first. - $bootstrap_class = drush_get_option('bootstrap_class', FALSE); - if ($bootstrap_class) { - array_unshift($candidates, $bootstrap_class); - } - // Add candidate bootstrap classes for Drupal - foreach (array('8', '7', '6') as $version) { - $drupal_bootstrap_class = 'Drush\Boot\DrupalBoot' . $version; - $candidates[] = $drupal_bootstrap_class; - } - // Always consider our default bootstrap class last. - $candidates[] = 'Drush\Boot\EmptyBoot'; - - return $candidates; -} - -/** - * Look up the best bootstrap class for the given location - * from the set of available candidates. - */ -function drush_bootstrap_class_for_root($path) { - drush_load_bootstrap_commandfile_at_path($path); - $candidates = drush_get_bootstrap_candidates(); - foreach ($candidates as $candidate) { - if ($candidate->valid_root($path)) { - return $candidate; - } - } - return NULL; -} - -/** - * Check to see if there is a bootstrap class available - * at the specified location; if there is, load it. - */ -function drush_load_bootstrap_commandfile_at_path($path) { - static $paths = array(); - - if (!empty($path) && (!array_key_exists($path, $paths))) { - $paths[$path] = TRUE; - // Check to see if we have any bootstrap classes in this location. - $bootstrap_class_dir = $path . '/drush/bootstrap'; - if (is_dir($bootstrap_class_dir)) { - _drush_add_commandfiles(array($bootstrap_class_dir), DRUSH_BOOTSTRAP_NONE); - } - } -} - -/** - * Select the bootstrap class to use. If this is called multiple - * times, the bootstrap class returned might change on subsequent - * calls, if the root directory changes. Once the bootstrap object - * starts changing the state of the system, however, it will - * be 'latched', and further calls to drush_select_bootstrap_class() - * will always return the same object. - */ -function drush_select_bootstrap_class() { - $root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); - - // Once we have selected a Drupal root, we will reduce our bootstrap - // candidates down to just the one used to select this site root. - $bootstrap = drush_bootstrap_class_for_root($root); - // If we have not found a bootstrap class by this point, - // then take the last one and use it. This should be our - // default bootstrap class. The default bootstrap class - // should pass through all calls without doing anything that - // changes state in a CMS-specific way. - if ($bootstrap == NULL) { - $candidates = drush_get_bootstrap_candidates(); - $bootstrap = array_pop($candidates); - } - - return $bootstrap; -} - -/** - * Don't allow the bootstrap object to change once we start bootstrapping - */ -function drush_latch_bootstrap_object($bootstrap) { - drush_set_context('DRUSH_BOOTSTRAP_OBJECT', $bootstrap); -} - -/** - * Get the appropriate bootstrap object. We'll search for a new - * bootstrap object every time someone asks for one until we start - * bootstrapping; then we'll returned the same cached one every time. - * - * @return \Drush\Boot\Boot - */ -function drush_get_bootstrap_object() { - $bootstrap = drush_get_context('DRUSH_BOOTSTRAP_OBJECT', FALSE); - if (!$bootstrap) { - $bootstrap = drush_select_bootstrap_class(); - } - return $bootstrap; -} - /** * Find the URI that has been selected by the cwd * if it was not previously set via the --uri / -l option @@ -295,7 +162,7 @@ function drush_bootstrap_value($context, $value = null) { function _drush_bootstrap_phases($function_names = FALSE) { $result = array(); - if ($bootstrap = drush_get_bootstrap_object()) { + if ($bootstrap = \Drush::bootstrap()) { $result = $bootstrap->bootstrap_phases(); if (!$function_names) { $result = array_keys($result); @@ -324,7 +191,7 @@ function _drush_bootstrap_phases($function_names = FALSE) { * @see \Drush\Boot\Boot::bootstrap_phases() */ function drush_bootstrap($phase, $phase_max = FALSE) { - $bootstrap = drush_get_bootstrap_object(); + $bootstrap = \Drush::bootstrap(); $phases = _drush_bootstrap_phases(TRUE); $result = TRUE; @@ -338,7 +205,7 @@ function drush_bootstrap($phase, $phase_max = FALSE) { // Once we start bootstrapping past the DRUSH_BOOTSTRAP_DRUSH phase, we // will latch the bootstrap object, and prevent it from changing. if ($phase > DRUSH_BOOTSTRAP_DRUSH) { - drush_latch_bootstrap_object($bootstrap); + \Drush::bootstrapManager()->latch($bootstrap); } drush_set_context('DRUSH_BOOTSTRAPPING', TRUE); @@ -411,7 +278,7 @@ function drush_has_boostrapped($phase) { * @see \Drush\Boot\Boot::bootstrap_phases() */ function drush_bootstrap_validate($phase) { - $bootstrap = drush_get_bootstrap_object(); + $bootstrap = \Drush::bootstrap(); $phases = _drush_bootstrap_phases(TRUE); static $result_cache = array(); diff --git a/includes/command.inc b/includes/command.inc index 0e11b8bbb6..7c6f9cdb56 100644 --- a/includes/command.inc +++ b/includes/command.inc @@ -1211,7 +1211,7 @@ function drush_command_defaults($key, $commandfile, $path) { // additional defaults if needed. The bootstrap command defaults // will be merged into the command object again just before // running it in bootstrap_and_dispatch(). - if ($bootstrap = drush_get_bootstrap_object()) { + if ($bootstrap = \Drush::bootstrap()) { $defaults = array_merge($defaults, $bootstrap->command_defaults()); } return $defaults; @@ -1514,7 +1514,7 @@ function drush_commandfile_list() { function _drush_find_commandfiles($phase, $phase_max = FALSE) { drush_log(dt("Find command files for phase !phase (max=!max)", array('!phase' => $phase, '!max' => (string)$phase_max)), LogLevel::DEBUG); - if ($bootstrap = drush_get_bootstrap_object()) { + if ($bootstrap = \Drush::bootstrap()) { $searchpath = $bootstrap->commandfile_searchpaths($phase, $phase_max); _drush_add_commandfiles($searchpath, $phase); } diff --git a/includes/complete.inc b/includes/complete.inc index 91c50e13f7..f746e6eef6 100644 --- a/includes/complete.inc +++ b/includes/complete.inc @@ -252,8 +252,8 @@ function drush_complete_process_argv() { // Check for and record any site alias. drush_sitealias_check_arg(); drush_sitealias_check_site_env(); - // We might have just changed our root--run drush_select_bootstrap_class() again. - $bootstrap = drush_select_bootstrap_class(); + // We might have just changed our root--re-select the bootstrap object to use + $bootstrap = \Drush::bootstrapManager()->bootstrap(); // Return the new argv for easy reference. return $argv; diff --git a/includes/context.inc b/includes/context.inc index a10996d486..1785daff11 100644 --- a/includes/context.inc +++ b/includes/context.inc @@ -110,7 +110,7 @@ function _drush_config_file($context, $prefix = NULL, $version = '') { } } - if ($drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT')) { + if ($drupal_root = \Drush::bootstrapManager()->getRoot()) { $configs['drupal'] = array( $drupal_root . '/../drush/' . $config_file, $drupal_root . '/sites/all/drush/' . $config_file, diff --git a/includes/drupal.inc b/includes/drupal.inc index cee6c48e83..72e6a83962 100644 --- a/includes/drupal.inc +++ b/includes/drupal.inc @@ -38,7 +38,7 @@ function drush_drupal_version($drupal_root = NULL) { if (!$version) { if (($drupal_root != NULL) || ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT'))) { - $bootstrap = drush_bootstrap_class_for_root($drupal_root); + $bootstrap = \Drush::bootstrapManager()->bootstrapObjectForRoot($drupal_root); if ($bootstrap) { $version = $bootstrap->get_version($drupal_root); } diff --git a/includes/drush.inc b/includes/drush.inc index e40b4f488c..74f61fd1c6 100644 --- a/includes/drush.inc +++ b/includes/drush.inc @@ -1261,20 +1261,15 @@ function drush_log($message, $type = LogLevel::NOTICE, $error = null) { return _drush_log($entry); } -/** - * Future: add some sort of dependency injection to Drush. - */ -function _drush_create_default_logger() { - $drush_logger = new Logger(); - drush_set_context('DRUSH_LOG_CALLBACK', $drush_logger); -} - /** * Call the default logger, or the user's log callback, as * appropriate. */ function _drush_log($entry) { $callback = drush_get_context('DRUSH_LOG_CALLBACK'); + if (!$callback) { + $callback = \Drush::logger(); + } if ($callback instanceof LoggerInterface) { $context = $entry; diff --git a/includes/environment.inc b/includes/environment.inc index 7d118e01ad..7c04dad628 100644 --- a/includes/environment.inc +++ b/includes/environment.inc @@ -199,7 +199,7 @@ function drush_site_path($path = NULL) { else { // Move up dir by dir and check each. // Stop if we get to a Drupal root. We don't care - // if it is DRUSH_SELECTED_DRUPAL_ROOT or some other root. + // if it is the selected or some other root. while (($path = _drush_shift_path_up($path)) && !drush_valid_root($path)) { if (file_exists($path . '/settings.php')) { $site_path = $path; @@ -208,7 +208,7 @@ function drush_site_path($path = NULL) { } } - $site_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $site_root = \Drush::bootstrapManager()->getRoot(); if (file_exists($site_root . '/sites/sites.php')) { $sites = array(); // This will overwrite $sites with the desired mappings. @@ -242,7 +242,7 @@ function drush_site_path($path = NULL) { */ function drush_site_dir_lookup_from_hostname($hostname, $site_root = NULL) { if (!isset($site_root)) { - $site_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $site_root = \Drush::bootstrapManager()->getRoot(); } if (!empty($site_root) && file_exists($site_root . '/sites/sites.php')) { $sites = array(); @@ -269,7 +269,7 @@ function drush_site_dir_lookup_from_hostname($hostname, $site_root = NULL) { * (drushrc.php) stored with the site's drush folders might not be found. */ function drush_conf_path($server_uri, $require_settings = TRUE) { - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); if(empty($drupal_root) || empty($server_uri)) { return NULL; } @@ -363,8 +363,8 @@ function drush_locate_root($start_path = NULL) { * The relative path to common.inc (varies by Drupal version), or FALSE if not * a Drupal root. */ -function drush_valid_root($path) { - $bootstrap_class = drush_bootstrap_class_for_root($path); +function drush_valid_root($root) { + $bootstrap_class = \Drush::bootstrapManager()->bootstrapObjectForRoot($root); return $bootstrap_class != NULL; } @@ -613,15 +613,6 @@ function _drush_test_os($os, $os_list_to_check) { return FALSE; } -/** - * Read the drush info file. - */ -function drush_read_drush_info() { - $drush_info_file = dirname(__FILE__) . '/../drush.info'; - - return parse_ini_file($drush_info_file); -} - /** * Make a determination whether or not the given * host is local or not. diff --git a/includes/preflight.inc b/includes/preflight.inc index 767c92627d..6e33b8e194 100644 --- a/includes/preflight.inc +++ b/includes/preflight.inc @@ -7,6 +7,8 @@ use Drush\Log\LogLevel; +use League\Container\Container; + /** * The main Drush function. * @@ -71,7 +73,7 @@ function drush_main() { // the bootstrap object returned from drush_preflight(). This will // require some adjustments to Drush bootstrapping. // See: https://github.com/drush-ops/drush/pull/1303 - if ($bootstrap = drush_get_bootstrap_object()) { + if ($bootstrap = \Drush::bootstrap()) { $bootstrap->terminate(); } drush_postflight(); @@ -138,8 +140,9 @@ function drush_preflight_prepare() { drush_set_context('DRUSH_VENDOR_PATH', dirname($vendor_path)); drush_set_context('DRUSH_CLASSLOADER', $classloader); - // Can't log until we have a logger, so we'll create this ASAP. - _drush_create_default_logger(); + // We need to load our services right away, as we cannot log + // or do much else until after this is done. + drush_init_dependency_injection_container(); // Terminate immediately unless invoked as a command line script if (!drush_verify_cli()) { @@ -160,9 +163,11 @@ function drush_preflight_prepare() { return; // An error was logged. } - $drush_info = drush_read_drush_info(); - define('DRUSH_VERSION', $drush_info['drush_version']); - $version_parts = explode('.', DRUSH_VERSION); + // Set up for backwards-compatibility. New code should call + // \Drush::getVersion() and \Drush::getMajorVersion() directly + $drush_version = \Drush::getVersion(); + $version_parts = explode('.', $drush_version); + define('DRUSH_VERSION', $drush_version); define('DRUSH_MAJOR_VERSION', $version_parts[0]); define('DRUSH_MINOR_VERSION', $version_parts[1]); @@ -183,6 +188,33 @@ function drush_preflight_prepare() { drush_log(dt("Drush preflight prepare loaded autoloader at !autoloader", array('!autoloader' => realpath($vendor_path))), LogLevel::PREFLIGHT); } +/** + * Set up our dependency injection container, and load drush-services.yml. + */ +function drush_init_dependency_injection_container() { + + // Set up our dependency injection container. + $container = new Container(); + + $container->share('logger', 'Drush\Log\Logger'); + $container->share('bootstrap.default', 'Drush\Boot\EmptyBoot'); + $container->share('bootstrap.drupal6', 'Drush\Boot\DrupalBoot6'); + $container->share('bootstrap.drupal7', 'Drush\Boot\DrupalBoot7'); + $container->share('bootstrap.drupal8', 'Drush\Boot\DrupalBoot8'); + $container->share('bootstrap.manager', 'Drush\Boot\BootstrapManager') + ->withArgument('bootstrap.default'); + $container->extend('bootstrap.manager') + ->withMethodCall('add', ['bootstrap.drupal6']) + ->withMethodCall('add', ['bootstrap.drupal7']) + ->withMethodCall('add', ['bootstrap.drupal8']); + + $container->inflector('Psr\Log\LoggerAwareInterface') + ->invokeMethod('setLogger', ['logger']); + + // Store the container in the \Drush object + \Drush::setContainer($container); +} + /** * During the initialization of Drush, this is the first * step where we load our configuration and commandfiles, @@ -309,7 +341,7 @@ function drush_preflight() { drush_set_environment_vars($alias_record); // Select the bootstrap object and return it. - return drush_select_bootstrap_class(); + return \Drush::bootstrapManager()->bootstrap(); } /** @@ -323,9 +355,8 @@ function drush_preflight_root() { if ($root) { $root = realpath($root); } - // @todo This context name should not mention Drupal. // @todo Drupal code should use DRUSH_DRUPAL_ROOT instead of this constant. - drush_set_context('DRUSH_SELECTED_DRUPAL_ROOT', $root); + \Drush::bootstrapManager()->setRoot($root); // Load the config options from Drupal's /drush, ../drush, and sites/all/drush directories, // even prior to bootstrapping the root. @@ -568,7 +599,7 @@ function drush_preflight_command_dispatch() { } $args = drush_get_arguments(); $command_name = array_shift($args); - $root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $root = \Drush::bootstrapManager()->getRoot(); $local_drush = drush_get_option('drush-script'); if (empty($local_drush) && !empty($root)) { $local_drush = find_wrapper_or_launcher($root); diff --git a/includes/sitealias.inc b/includes/sitealias.inc index 8c08b0e7f3..90617c24e1 100644 --- a/includes/sitealias.inc +++ b/includes/sitealias.inc @@ -91,7 +91,7 @@ function drush_sitealias_check_site_env() { function drush_sitealias_create_self_alias() { $self_record = drush_sitealias_get_record('@self'); if (!array_key_exists('root', $self_record) && !array_key_exists('remote-host', $self_record)) { - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); $uri = drush_get_context('DRUSH_SELECTED_URI'); if (!empty($drupal_root) && !empty($uri)) { // Create an alias '@self' @@ -403,7 +403,7 @@ function drush_sitealias_alias_path($alias_path_context = NULL) { // If the user defined the root of a drupal site, then also // look for alias files in /drush and /sites/all/drush. - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); if (!empty($drupal_root)) { $site_paths[] = drush_sitealias_alias_base_directory($drupal_root . '/../drush'); $site_paths[] = drush_sitealias_alias_base_directory($drupal_root . '/drush'); @@ -666,7 +666,7 @@ function _drush_sitealias_find_and_load_alias($aliasname, $alias_path_context = } } else { - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); } if (isset($drupal_root) && !is_array($drupal_root)) { drush_sitealias_create_sites_alias($drupal_root); @@ -1081,7 +1081,7 @@ function drush_sitealias_bootstrapped_site_name() { $site_name = $self_record['#name']; } if (!isset($site_name) || ($site_name == '@self')) { - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); if (isset($drupal_root)) { $drupal_uri = drush_get_context('DRUSH_SELECTED_URI', 'default'); $drupal_uri = str_replace('http://', '', $drupal_uri); @@ -1530,7 +1530,7 @@ function _drush_sitealias_find_record_for_local_site($alias, $drupal_root = NULL } if (!isset($drupal_root)) { - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); } if (!empty($drupal_root)) { diff --git a/lib/Drush.php b/lib/Drush.php new file mode 100644 index 0000000000..a2128cb502 --- /dev/null +++ b/lib/Drush.php @@ -0,0 +1,189 @@ +get($id); + } + + /** + * Indicates if a service is defined in the container. + * + * @param string $id + * The ID of the service to check. + * + * @return bool + * TRUE if the specified service exists, FALSE otherwise. + */ + public static function hasService($id) { + // Check hasContainer() first in order to always return a Boolean. + return static::hasContainer() && static::getContainer()->has($id); + } + + /** + * Return the Drush logger object. + * + * @return LoggerInterface + */ + public static function logger() { + return static::service('logger'); + } + + /** + * Return the Bootstrap Manager. + * + * @return Drush\Boot\BootstrapManager + */ + public static function bootstrapManager() { + return static::service('bootstrap.manager'); + } + + /** + * Return the Bootstrap object. + * + * @return Drush\Boot\Boot + */ + public static function bootstrap() { + return static::bootstrapManager()->bootstrap(); + } + + /** + * Read the drush info file. + */ + private static function drush_read_drush_info() { + $drush_info_file = dirname(__FILE__) . '/../drush.info'; + + return parse_ini_file($drush_info_file); + } +} diff --git a/lib/Drush/Boot/BaseBoot.php b/lib/Drush/Boot/BaseBoot.php index c816988c45..e804b7203d 100644 --- a/lib/Drush/Boot/BaseBoot.php +++ b/lib/Drush/Boot/BaseBoot.php @@ -3,8 +3,13 @@ namespace Drush\Boot; use Drush\Log\LogLevel; +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; -abstract class BaseBoot implements Boot { + +abstract class BaseBoot implements Boot, LoggerAwareInterface { + use LoggerAwareTrait; function __construct() { } @@ -60,7 +65,7 @@ function bootstrap_and_dispatch() { $this->enforce_requirement($command); if ($bootstrap_result && empty($command['bootstrap_errors'])) { - drush_log(dt("Found command: !command (commandfile=!commandfile)", array('!command' => $command['command'], '!commandfile' => $command['commandfile'])), LogLevel::BOOTSTRAP); + $this->logger->log(LogLevel::BOOTSTRAP, dt("Found command: !command (commandfile=!commandfile)", array('!command' => $command['command'], '!commandfile' => $command['commandfile']))); $command_found = TRUE; // Dispatch the command(s). diff --git a/lib/Drush/Boot/BootstrapManager.php b/lib/Drush/Boot/BootstrapManager.php new file mode 100644 index 0000000000..5b90539b7d --- /dev/null +++ b/lib/Drush/Boot/BootstrapManager.php @@ -0,0 +1,142 @@ +defaultBootstrapObject = $default; + } + + /** + * Add a bootstrap object to the list of candidates + * + * @param Boot|Array + * List of boot candidates + */ + public function add($candidateList) { + foreach (func_get_args() as $candidate) { + $this->bootstrapCandidates[] = $candidate; + } + } + + /** + * Return the framework root selected by the user. + */ + public function getRoot() { + return $this->root; + } + + public function setRoot($root) { + // TODO: Throw if we already bootstrapped a framework? + $this->root = $root; + } + + /** + * Return the framework root selected by the user. + */ + public function getUri() { + return $this->uri; + } + + public function setUri($uri) { + // TODO: Throw if we already bootstrapped a framework? + $this->uri = $root; + } + + /** + * Return the bootstrap object in use. This will + * be the latched bootstrap object if we have started + * bootstrapping; otherwise, it will be whichever bootstrap + * object is best for the selected root. + */ + public function bootstrap() { + if ($this->bootstrap) { + return $this->bootstrap; + } + return $this->selectBootstrapClass(); + } + + /** + * Look up the best bootstrap class for the given location + * from the set of available candidates. + */ + public function bootstrapObjectForRoot($path) { + foreach ($this->bootstrapCandidates as $candidate) { + if ($candidate->valid_root($path)) { + return $candidate; + } + } + return NULL; + } + + /** + * Select the bootstrap class to use. If this is called multiple + * times, the bootstrap class returned might change on subsequent + * calls, if the root directory changes. Once the bootstrap object + * starts changing the state of the system, however, it will + * be 'latched', and further calls to \Drush::bootstrapf() + * will always return the same object. + */ + protected function selectBootstrapClass() { + // Once we have selected a Drupal root, we will reduce our bootstrap + // candidates down to just the one used to select this site root. + $bootstrap = $this->bootstrapObjectForRoot($this->root); + // If we have not found a bootstrap class by this point, + // then return our default bootstrap object. The default bootstrap object + // should pass through all calls without doing anything that + // changes state in a CMS-specific way. + if ($bootstrap == NULL) { + $bootstrap = $this->defaultBootstrapObject; + } + + return $bootstrap; + } + + /** + * Once bootstrapping has started, we stash the bootstrap + * object being used, and do not allow it to change any + * longer. + */ + public function latch($bootstrap) { + $this->bootstrap = $bootstrap; + } + +} diff --git a/lib/Drush/Boot/DrupalBoot.php b/lib/Drush/Boot/DrupalBoot.php index 16a0e1bd14..8cacb9338a 100644 --- a/lib/Drush/Boot/DrupalBoot.php +++ b/lib/Drush/Boot/DrupalBoot.php @@ -3,12 +3,10 @@ namespace Drush\Boot; use Drush\Log\LogLevel; +use Psr\Log\LoggerInterface; abstract class DrupalBoot extends BaseBoot { - function __construct() { - } - function valid_root($path) { } @@ -111,7 +109,7 @@ function commandfile_searchpaths($phase, $phase_max = FALSE) { $searchpath = array(); switch ($phase) { case DRUSH_BOOTSTRAP_DRUPAL_ROOT: - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); $searchpath[] = $drupal_root . '/../drush'; $searchpath[] = $drupal_root . '/drush'; $searchpath[] = $drupal_root . '/sites/all/drush'; @@ -256,7 +254,7 @@ function drush_enforce_requirement_drupal_dependencies(&$command) { * context and DRUPAL_ROOT constant if it is considered a valid option. */ function bootstrap_drupal_root_validate() { - $drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT'); + $drupal_root = \Drush::bootstrapManager()->getRoot(); if (empty($drupal_root)) { return drush_bootstrap_error('DRUSH_NO_DRUPAL_ROOT', dt("A Drupal installation directory could not be found")); @@ -309,7 +307,7 @@ function bootstrap_drupal_root() { _drush_preflight_global_options(); - drush_log(dt("Initialized Drupal !version root directory at !drupal_root", array("!version" => $version, '!drupal_root' => $drupal_root)), LogLevel::BOOTSTRAP); + $this->logger->log(LogLevel::BOOTSTRAP, dt("Initialized Drupal !version root directory at !drupal_root", array("!version" => $version, '!drupal_root' => $drupal_root))); } /** @@ -408,7 +406,7 @@ function bootstrap_do_drupal_site() { $site = drush_set_context('DRUSH_DRUPAL_SITE', drush_bootstrap_value('site')); $conf_path = drush_set_context('DRUSH_DRUPAL_SITE_ROOT', drush_bootstrap_value('conf_path')); - drush_log(dt("Initialized Drupal site !site at !site_root", array('!site' => $site, '!site_root' => $conf_path)), LogLevel::BOOTSTRAP); + $this->logger->log(LogLevel::BOOTSTRAP, dt("Initialized Drupal site !site at !site_root", array('!site' => $site, '!site_root' => $conf_path))); _drush_preflight_global_options(); } @@ -520,7 +518,7 @@ function bootstrap_drupal_database_has_table($required_tables) { function bootstrap_drupal_database() { // We presume that our derived classes will connect and then // either fail, or call us via parent:: - drush_log(dt("Successfully connected to the Drupal database."), LogLevel::BOOTSTRAP); + $this->logger->log(LogLevel::BOOTSTRAP, dt("Successfully connected to the Drupal database.")); } /** diff --git a/lib/Drush/Boot/DrupalBoot6.php b/lib/Drush/Boot/DrupalBoot6.php index 9539f38777..a7eb4ee455 100644 --- a/lib/Drush/Boot/DrupalBoot6.php +++ b/lib/Drush/Boot/DrupalBoot6.php @@ -2,6 +2,8 @@ namespace Drush\Boot; +use Psr\Log\LoggerInterface; + class DrupalBoot6 extends DrupalBoot { function valid_root($path) { diff --git a/lib/Drush/Boot/DrupalBoot7.php b/lib/Drush/Boot/DrupalBoot7.php index 31d4a6d964..5387f75732 100644 --- a/lib/Drush/Boot/DrupalBoot7.php +++ b/lib/Drush/Boot/DrupalBoot7.php @@ -2,6 +2,8 @@ namespace Drush\Boot; +use Psr\Log\LoggerInterface; + class DrupalBoot7 extends DrupalBoot { function valid_root($path) { diff --git a/lib/Drush/Boot/DrupalBoot8.php b/lib/Drush/Boot/DrupalBoot8.php index 0f6f22eebd..6d9f6075b1 100644 --- a/lib/Drush/Boot/DrupalBoot8.php +++ b/lib/Drush/Boot/DrupalBoot8.php @@ -4,6 +4,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Psr\Log\LoggerInterface; use Drupal\Core\DrupalKernel; class DrupalBoot8 extends DrupalBoot { @@ -70,7 +71,8 @@ function add_logger() { // channel. $container = \Drupal::getContainer(); $parser = $container->get('logger.log_message_parser'); - $drushLogger = drush_get_context('DRUSH_LOG_CALLBACK'); + + $drushLogger = \Drush::logger(); $logger = new \Drush\Log\DrushLog($parser, $drushLogger); $container->get('logger.factory')->addLogger($logger); } diff --git a/lib/Drush/Boot/EmptyBoot.php b/lib/Drush/Boot/EmptyBoot.php index e7d9d62105..c5b73f6cc0 100644 --- a/lib/Drush/Boot/EmptyBoot.php +++ b/lib/Drush/Boot/EmptyBoot.php @@ -2,6 +2,8 @@ namespace Drush\Boot; +use Psr\Log\LoggerInterface; + /** * This is a do-nothing 'Boot' class that is used when there * is no site at --root, or when no root is specified. @@ -12,9 +14,6 @@ */ class EmptyBoot extends BaseBoot { - function __construct() { - } - function valid_root($path) { return FALSE; } diff --git a/lib/Drush/Log/Logger.php b/lib/Drush/Log/Logger.php index ff2680fa28..cfe3c212ed 100644 --- a/lib/Drush/Log/Logger.php +++ b/lib/Drush/Log/Logger.php @@ -32,9 +32,12 @@ class Logger extends AbstractLogger { public function log($level, $message, array $context = array()) { // Convert to old $entry array for b/c calls - $entry = $context; - $entry['type'] = $level; - $entry['message'] = $message; + $entry = $context + [ + 'type' => $level, + 'message' => $message, + 'timestamp' => microtime(TRUE), + 'memory' => memory_get_usage(), + ]; // Drush\Log\Logger should take over all of the responsibilities // of drush_log, including caching the log messages and sending diff --git a/lib/Drush/Symfony/BootstrapCompilerPass.php b/lib/Drush/Symfony/BootstrapCompilerPass.php new file mode 100644 index 0000000000..58e8b78cba --- /dev/null +++ b/lib/Drush/Symfony/BootstrapCompilerPass.php @@ -0,0 +1,31 @@ +has('bootstrap.manager')) { + return; + } + + $definition = $container->findDefinition( + 'bootstrap.manager' + ); + + $taggedServices = $container->findTaggedServiceIds( + 'bootstrap.boot' + ); + foreach ($taggedServices as $id => $tags) { + $definition->addMethodCall( + 'add', + array(new Reference($id)) + ); + } + } +}