diff --git a/composer.json b/composer.json index af7b515787..d2c50bd038 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "ext-dom": "*", "chi-teck/drupal-code-generator": "^2.4", "composer/semver": "^1.4 || ^3", - "consolidation/annotated-command": "^4.5", + "consolidation/annotated-command": "^4.5.3", "consolidation/config": "^2", "consolidation/filter-via-dot-access-data": "^2", "consolidation/robo": "^3.0.9", diff --git a/composer.lock b/composer.lock index 6fb8bb596e..daf0bb6959 100644 --- a/composer.lock +++ b/composer.lock @@ -4,44 +4,44 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ed9631751b0f789c52bb89dfd2d43f39", + "content-hash": "8094c1701a9d7c36a7478df78b0c9b5c", "packages": [ { "name": "chi-teck/drupal-code-generator", - "version": "2.4.1", + "version": "2.5.3", "source": { "type": "git", "url": "https://github.com/Chi-teck/drupal-code-generator.git", - "reference": "e7261a46a839a3433e4bbe24eeeb21ed8805a7d3" + "reference": "a49f29b0fe6b6c87fa7dc8979589ce8794c4d655" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Chi-teck/drupal-code-generator/zipball/e7261a46a839a3433e4bbe24eeeb21ed8805a7d3", - "reference": "e7261a46a839a3433e4bbe24eeeb21ed8805a7d3", + "url": "https://api.github.com/repos/Chi-teck/drupal-code-generator/zipball/a49f29b0fe6b6c87fa7dc8979589ce8794c4d655", + "reference": "a49f29b0fe6b6c87fa7dc8979589ce8794c4d655", "shasum": "" }, "require": { "ext-json": "*", "php": ">=7.4", - "psr/log": "^1.1", - "symfony/console": "^4.4.15 || ^5.1", - "symfony/filesystem": "^4.4 || ^5.1", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "symfony/console": "^4.4.15 || ^5.1 || ^6.0", + "symfony/filesystem": "^4.4 || ^5.1 || ^6", "symfony/polyfill-php80": "^1.23", "symfony/string": "^5.1 || ^6", - "twig/twig": "^2.12 || ^3.1" + "twig/twig": "^2.14.11 || ^3.1" }, "conflict": { "squizlabs/php_codesniffer": "<3.6" }, "require-dev": { - "chi-teck/drupal-coder-extension": "^1.0", - "drupal/coder": "^8.3.13", - "friendsoftwig/twigcs": "^5.0", + "chi-teck/drupal-coder-extension": "^1.2", + "drupal/coder": "^8.3.14", + "friendsoftwig/twigcs": "dev-master", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.4", "squizlabs/php_codesniffer": "^3.5", - "symfony/var-dumper": "^5.2", - "symfony/yaml": "^5.2" + "symfony/var-dumper": "^5.2 || ^6.0", + "symfony/yaml": "^5.2 || ^6.0" }, "bin": [ "bin/dcg" @@ -64,9 +64,9 @@ "description": "Drupal code generator", "support": { "issues": "https://github.com/Chi-teck/drupal-code-generator/issues", - "source": "https://github.com/Chi-teck/drupal-code-generator/tree/2.4.1" + "source": "https://github.com/Chi-teck/drupal-code-generator/tree/2.5.3" }, - "time": "2022-01-18T18:48:57+00:00" + "time": "2022-03-31T17:15:11+00:00" }, { "name": "composer/semver", @@ -151,16 +151,16 @@ }, { "name": "consolidation/annotated-command", - "version": "4.5.2", + "version": "4.5.3", "source": { "type": "git", "url": "https://github.com/consolidation/annotated-command.git", - "reference": "24c1529436b4f4beec3d19aab71fd127817f47ef" + "reference": "1941a743e63993288e09d0686a4cb7ed47813213" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/24c1529436b4f4beec3d19aab71fd127817f47ef", - "reference": "24c1529436b4f4beec3d19aab71fd127817f47ef", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/1941a743e63993288e09d0686a4cb7ed47813213", + "reference": "1941a743e63993288e09d0686a4cb7ed47813213", "shasum": "" }, "require": { @@ -180,7 +180,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.x-dev" + "dev-main": "5.x-dev" } }, "autoload": { @@ -201,38 +201,37 @@ "description": "Initialize Symfony Console commands from annotated command class methods.", "support": { "issues": "https://github.com/consolidation/annotated-command/issues", - "source": "https://github.com/consolidation/annotated-command/tree/4.5.2" + "source": "https://github.com/consolidation/annotated-command/tree/4.5.3" }, - "time": "2022-02-20T16:36:18+00:00" + "time": "2022-04-02T00:17:53+00:00" }, { "name": "consolidation/config", - "version": "2.0.4", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/consolidation/config.git", - "reference": "0eacfc0a883716fe814b974a9771f83ee7d2f46f" + "reference": "0c15841b2bf60d9af1ce29884673e7d9d50c3b75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/config/zipball/0eacfc0a883716fe814b974a9771f83ee7d2f46f", - "reference": "0eacfc0a883716fe814b974a9771f83ee7d2f46f", + "url": "https://api.github.com/repos/consolidation/config/zipball/0c15841b2bf60d9af1ce29884673e7d9d50c3b75", + "reference": "0c15841b2bf60d9af1ce29884673e7d9d50c3b75", "shasum": "" }, "require": { "dflydev/dot-access-data": "^1.1.0 || ^2 || ^3", - "grasmash/expander": "^1 || ^2", + "grasmash/expander": "^2.0.1", "php": ">=7.1.3", - "psr/log": "^1.1", - "symfony/event-dispatcher": "^4||^5" + "symfony/event-dispatcher": "^4 || ^5 || ^6" }, "require-dev": { "ext-json": "*", "phpunit/phpunit": ">=7.5.20", "squizlabs/php_codesniffer": "^3", - "symfony/console": "^4||^5", - "symfony/yaml": "^4||^5", - "yoast/phpunit-polyfills": "^0.2.0" + "symfony/console": "^4 || ^5 || ^6", + "symfony/yaml": "^4 || ^5 || ^6", + "yoast/phpunit-polyfills": "^1" }, "suggest": { "symfony/event-dispatcher": "Required to inject configuration into Command options", @@ -262,9 +261,9 @@ "description": "Provide configuration services for a commandline tool.", "support": { "issues": "https://github.com/consolidation/config/issues", - "source": "https://github.com/consolidation/config/tree/2.0.4" + "source": "https://github.com/consolidation/config/tree/2.1.0" }, - "time": "2022-02-15T17:41:57+00:00" + "time": "2022-02-24T00:32:42+00:00" }, { "name": "consolidation/filter-via-dot-access-data", @@ -318,21 +317,21 @@ }, { "name": "consolidation/log", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/consolidation/log.git", - "reference": "9efdd57031bf2fda033f6a256cd8b7902a4e6b92" + "reference": "3ad08dc57e8aff9400111bad36beb0ed387fe6a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/log/zipball/9efdd57031bf2fda033f6a256cd8b7902a4e6b92", - "reference": "9efdd57031bf2fda033f6a256cd8b7902a4e6b92", + "url": "https://api.github.com/repos/consolidation/log/zipball/3ad08dc57e8aff9400111bad36beb0ed387fe6a9", + "reference": "3ad08dc57e8aff9400111bad36beb0ed387fe6a9", "shasum": "" }, "require": { "php": ">=7.1.3", - "psr/log": "^1.0", + "psr/log": "^1 || ^2", "symfony/console": "^4 || ^5 || ^6" }, "require-dev": { @@ -364,9 +363,9 @@ "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.", "support": { "issues": "https://github.com/consolidation/log/issues", - "source": "https://github.com/consolidation/log/tree/2.1.0" + "source": "https://github.com/consolidation/log/tree/2.1.1" }, - "time": "2022-01-30T03:49:07+00:00" + "time": "2022-02-24T04:27:32+00:00" }, { "name": "consolidation/output-formatters", @@ -429,16 +428,16 @@ }, { "name": "consolidation/robo", - "version": "3.0.9", + "version": "3.0.10", "source": { "type": "git", "url": "https://github.com/consolidation/robo.git", - "reference": "33b2649c3ba4b3bf5e3fb77098c3241eda117338" + "reference": "206bbe23b34081a36bfefc4de2abbc1abcd29ef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/robo/zipball/33b2649c3ba4b3bf5e3fb77098c3241eda117338", - "reference": "33b2649c3ba4b3bf5e3fb77098c3241eda117338", + "url": "https://api.github.com/repos/consolidation/robo/zipball/206bbe23b34081a36bfefc4de2abbc1abcd29ef4", + "reference": "206bbe23b34081a36bfefc4de2abbc1abcd29ef4", "shasum": "" }, "require": { @@ -453,7 +452,7 @@ "symfony/event-dispatcher": "^4.4.19 || ^5 || ^6", "symfony/filesystem": "^4.4.9 || ^5 || ^6", "symfony/finder": "^4.4.9 || ^5 || ^6", - "symfony/process": "^4.4.9 || ^5", + "symfony/process": "^4.4.9 || ^5 || ^6", "symfony/yaml": "^4.4 || ^5 || ^6" }, "conflict": { @@ -522,9 +521,9 @@ "description": "Modern task runner", "support": { "issues": "https://github.com/consolidation/robo/issues", - "source": "https://github.com/consolidation/robo/tree/3.0.9" + "source": "https://github.com/consolidation/robo/tree/3.0.10" }, - "time": "2022-02-15T17:59:14+00:00" + "time": "2022-02-21T17:19:14+00:00" }, { "name": "consolidation/self-update", @@ -583,22 +582,22 @@ }, { "name": "consolidation/site-alias", - "version": "3.1.3", + "version": "3.1.5", "source": { "type": "git", "url": "https://github.com/consolidation/site-alias.git", - "reference": "e2784362e98f315c996fb2b9ed80a9118a0ba8b7" + "reference": "ef2eb7d37e59b3d837b4556d4d8070cb345b378c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/site-alias/zipball/e2784362e98f315c996fb2b9ed80a9118a0ba8b7", - "reference": "e2784362e98f315c996fb2b9ed80a9118a0ba8b7", + "url": "https://api.github.com/repos/consolidation/site-alias/zipball/ef2eb7d37e59b3d837b4556d4d8070cb345b378c", + "reference": "ef2eb7d37e59b3d837b4556d4d8070cb345b378c", "shasum": "" }, "require": { - "consolidation/config": "^1.2.1|^2", + "consolidation/config": "^1.2.1 || ^2", "php": ">=5.5.0", - "symfony/finder": "~2.3|^3|^4.4|^5" + "symfony/finder": "~2.3 || ^3 || ^4.4 || ^5 || ^6" }, "require-dev": { "php-coveralls/php-coveralls": "^2.4.2", @@ -635,9 +634,9 @@ "description": "Manage alias records for local and remote sites.", "support": { "issues": "https://github.com/consolidation/site-alias/issues", - "source": "https://github.com/consolidation/site-alias/tree/3.1.3" + "source": "https://github.com/consolidation/site-alias/tree/3.1.5" }, - "time": "2022-01-03T19:00:28+00:00" + "time": "2022-02-23T23:59:18+00:00" }, { "name": "consolidation/site-process", @@ -840,22 +839,22 @@ }, { "name": "grasmash/expander", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/grasmash/expander.git", - "reference": "2c81d9d806097180da40747787b14bf021c6d3c9" + "reference": "f4df21d01d1fbda38269cca89e3dbb6ba223da7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/grasmash/expander/zipball/2c81d9d806097180da40747787b14bf021c6d3c9", - "reference": "2c81d9d806097180da40747787b14bf021c6d3c9", + "url": "https://api.github.com/repos/grasmash/expander/zipball/f4df21d01d1fbda38269cca89e3dbb6ba223da7f", + "reference": "f4df21d01d1fbda38269cca89e3dbb6ba223da7f", "shasum": "" }, "require": { "dflydev/dot-access-data": "^3.0.0", "php": ">=5.6", - "psr/log": "^1.0" + "psr/log": "^1 | ^2" }, "require-dev": { "greg-1-anderson/composer-test-scenarios": "^1", @@ -886,9 +885,9 @@ "description": "Expands internal property references in PHP arrays file.", "support": { "issues": "https://github.com/grasmash/expander/issues", - "source": "https://github.com/grasmash/expander/tree/2.0.1" + "source": "https://github.com/grasmash/expander/tree/2.0.2" }, - "time": "2022-02-19T00:49:38+00:00" + "time": "2022-02-24T03:58:20+00:00" }, { "name": "guzzlehttp/guzzle", @@ -1446,16 +1445,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.1", + "version": "v0.11.2", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "570292577277f06f590635381a7f761a6cf4f026" + "reference": "7f7da640d68b9c9fec819caae7c744a213df6514" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/570292577277f06f590635381a7f761a6cf4f026", - "reference": "570292577277f06f590635381a7f761a6cf4f026", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/7f7da640d68b9c9fec819caae7c744a213df6514", + "reference": "7f7da640d68b9c9fec819caae7c744a213df6514", "shasum": "" }, "require": { @@ -1466,6 +1465,9 @@ "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, "require-dev": { "bamarni/composer-bin-plugin": "^1.2", "hoa/console": "3.17.05.02" @@ -1515,9 +1517,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.1" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.2" }, - "time": "2022-01-03T13:58:38+00:00" + "time": "2022-02-28T15:28:54+00:00" }, { "name": "ralouphie/getallheaders", @@ -1885,16 +1887,16 @@ }, { "name": "symfony/filesystem", - "version": "v5.4.3", + "version": "v5.4.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "0f0c4bf1840420f4aef3f32044a9dbb24682731b" + "reference": "d53a45039974952af7f7ebc461ccdd4295e29440" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/0f0c4bf1840420f4aef3f32044a9dbb24682731b", - "reference": "0f0c4bf1840420f4aef3f32044a9dbb24682731b", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d53a45039974952af7f7ebc461ccdd4295e29440", + "reference": "d53a45039974952af7f7ebc461ccdd4295e29440", "shasum": "" }, "require": { @@ -1929,7 +1931,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.3" + "source": "https://github.com/symfony/filesystem/tree/v5.4.6" }, "funding": [ { @@ -1945,7 +1947,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-03-02T12:42:23+00:00" }, { "name": "symfony/finder", @@ -5477,20 +5479,20 @@ }, { "name": "phpstan/phpstan", - "version": "1.4.6", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "8a7761f1c520e0dad6e04d862fdc697445457cfe" + "reference": "39953ac1452a8843702ee41a35b4861d3e8207a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8a7761f1c520e0dad6e04d862fdc697445457cfe", - "reference": "8a7761f1c520e0dad6e04d862fdc697445457cfe", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/39953ac1452a8843702ee41a35b4861d3e8207a7", + "reference": "39953ac1452a8843702ee41a35b4861d3e8207a7", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.2|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -5500,11 +5502,6 @@ "phpstan.phar" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, "autoload": { "files": [ "bootstrap.php" @@ -5517,7 +5514,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.4.6" + "source": "https://github.com/phpstan/phpstan/tree/1.5.3" }, "funding": [ { @@ -5537,7 +5534,7 @@ "type": "tidelift" } ], - "time": "2022-02-06T12:56:13+00:00" + "time": "2022-03-30T21:55:08+00:00" }, { "name": "phpunit/php-code-coverage", @@ -5859,16 +5856,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.19", + "version": "9.5.20", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807" + "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/35ea4b7f3acabb26f4bb640f8c30866c401da807", - "reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba", + "reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba", "shasum": "" }, "require": { @@ -5946,7 +5943,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.19" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20" }, "funding": [ { @@ -5958,7 +5955,7 @@ "type": "github" } ], - "time": "2022-03-15T09:57:31+00:00" + "time": "2022-04-01T12:37:26+00:00" }, { "name": "psr/cache", @@ -6066,21 +6063,21 @@ }, { "name": "rector/rector", - "version": "0.12.16", + "version": "0.12.19", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "13412efd0dfda2e2c310dd24397281804441cf7a" + "reference": "ed06366a1d56bf5709ddc854d0fea043513ac5ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/13412efd0dfda2e2c310dd24397281804441cf7a", - "reference": "13412efd0dfda2e2c310dd24397281804441cf7a", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/ed06366a1d56bf5709ddc854d0fea043513ac5ac", + "reference": "ed06366a1d56bf5709ddc854d0fea043513ac5ac", "shasum": "" }, "require": { "php": "^7.1|^8.0", - "phpstan/phpstan": "^1.4.2" + "phpstan/phpstan": "^1.4.8" }, "conflict": { "phpstan/phpdoc-parser": "<1.2", @@ -6114,7 +6111,7 @@ "description": "Instant Upgrade and Automated Refactoring of any PHP code", "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/0.12.16" + "source": "https://github.com/rectorphp/rector/tree/0.12.19" }, "funding": [ { @@ -6122,7 +6119,7 @@ "type": "github" } ], - "time": "2022-02-09T14:50:55+00:00" + "time": "2022-03-23T14:22:44+00:00" }, { "name": "sebastian/cli-parser", @@ -8698,5 +8695,5 @@ "platform-overrides": { "php": "7.4" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.2.0" } diff --git a/src/Style/DrushStyle.php b/src-symfony-compatibility/v4/Style/DrushStyle.php similarity index 100% rename from src/Style/DrushStyle.php rename to src-symfony-compatibility/v4/Style/DrushStyle.php diff --git a/src/Symfony/BufferedConsoleOutput.php b/src-symfony-compatibility/v4/Symfony/BufferedConsoleOutput.php similarity index 100% rename from src/Symfony/BufferedConsoleOutput.php rename to src-symfony-compatibility/v4/Symfony/BufferedConsoleOutput.php diff --git a/src/Symfony/IndiscriminateInputDefinition.php b/src-symfony-compatibility/v4/Symfony/IndiscriminateInputDefinition.php similarity index 100% rename from src/Symfony/IndiscriminateInputDefinition.php rename to src-symfony-compatibility/v4/Symfony/IndiscriminateInputDefinition.php diff --git a/src/Symfony/LessStrictArgvInput.php b/src-symfony-compatibility/v4/Symfony/LessStrictArgvInput.php similarity index 100% rename from src/Symfony/LessStrictArgvInput.php rename to src-symfony-compatibility/v4/Symfony/LessStrictArgvInput.php diff --git a/src-symfony-compatibility/v6/Style/DrushStyle.php b/src-symfony-compatibility/v6/Style/DrushStyle.php new file mode 100644 index 0000000000..aade71c683 --- /dev/null +++ b/src-symfony-compatibility/v6/Style/DrushStyle.php @@ -0,0 +1,68 @@ +comment($question . ': yes.'); + return true; + } elseif (Drush::negative()) { + // Automatically cancel confirmations if the --no argument was supplied. + $this->warning($question . ': no.'); + return false; + } + return parent::confirm($question, $default); + } + + public function choice(string $question, array $choices, mixed $default = null): mixed + { + // Display the choices without their keys. + $choices_values = array_values($choices); + $return = parent::choice($question, $choices_values, $default); + + return array_search($return, $choices); + } + + public function warning(string|array $message) + { + $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ! ', true); + } + + public function note(string|array $message) + { + $this->block($message, 'NOTE', 'fg=black;bg=yellow', ' ! '); + } + + public function caution(string|array $message) + { + $this->block($message, 'CAUTION', 'fg=black;bg=yellow', ' ! ', true); + } + + /** + * @return mixed + */ + public function askRequired($question) + { + $question = new Question($question); + $question->setValidator(function (?string $value) { + // FALSE is not considered as empty value because question helper use + // it as negative answer on confirmation questions. + if ($value === null || $value === '') { + throw new \UnexpectedValueException('This value is required.'); + } + + return $value; + }); + + return $this->askQuestion($question); + } +} diff --git a/src-symfony-compatibility/v6/Symfony/BufferedConsoleOutput.php b/src-symfony-compatibility/v6/Symfony/BufferedConsoleOutput.php new file mode 100644 index 0000000000..6ebfd01071 --- /dev/null +++ b/src-symfony-compatibility/v6/Symfony/BufferedConsoleOutput.php @@ -0,0 +1,51 @@ +stderr = new BufferedOutput($this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); + } + + /** + * {@inheritdoc} + */ + public function getErrorOutput(): OutputInterface + { + return $this->stderr; + } + + /** + * {@inheritdoc} + */ + public function setErrorOutput(OutputInterface $error): void + { + $this->stderr = $error; + } + + public function section(): ConsoleSectionOutput + { + // @todo + } +} diff --git a/src-symfony-compatibility/v6/Symfony/IndiscriminateInputDefinition.php b/src-symfony-compatibility/v6/Symfony/IndiscriminateInputDefinition.php new file mode 100644 index 0000000000..d7a353621c --- /dev/null +++ b/src-symfony-compatibility/v6/Symfony/IndiscriminateInputDefinition.php @@ -0,0 +1,47 @@ +tokens = $argv; + // strip the application name + array_shift($this->tokens); + + parent::__construct($argv, $definition); + } + + /** + * {@inheritdoc} + */ + public function getOption(string $name): mixed + { + if (array_key_exists($name, $this->options)) { + return $this->options[$name]; + } + if ($this->definition->hasOption($name)) { + return $this->definition->getOption($name)->getDefault(); + } + return false; + } + + protected function setTokens(array $tokens) + { + $this->tokens = $tokens; + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + $parseOptions = true; + $this->parsed = $this->tokens; + while (null !== $token = array_shift($this->parsed)) { + if ($parseOptions && '' == $token) { + $this->parseArgument($token); + } elseif ($parseOptions && '--' == $token) { + $parseOptions = false; + } elseif ($parseOptions && 0 === strpos($token, '--')) { + $this->parseLongOption($token); + } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { + $this->parseShortOption($token); + } else { + $this->parseArgument($token); + } + } + // Put back any options that were injected. + $this->options += $this->additionalOptions; + } + + /** + * Parses a short option. + * + * @param string $token The current token + */ + private function parseShortOption($token) + { + $name = substr($token, 1); + + if (strlen($name) > 1) { + if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { + // an option with a value (with no space) + $this->addShortOption($name[0], substr($name, 1)); + } else { + $this->parseShortOptionSet($name); + } + } else { + $this->addShortOption($name, null); + } + } + + /** + * Parses a short option set. + * + * @param string $name The current token + */ + private function parseShortOptionSet(string $name) + { + $len = strlen($name); + for ($i = 0; $i < $len; ++$i) { + if (!$this->definition->hasShortcut($name[$i])) { + $this->addShortOption($name[$i]); + } + + $option = $this->definition->getOptionForShortcut($name[$i]); + if ($option->acceptValue()) { + $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); + + break; + } else { + $this->addLongOption($option->getName(), null); + } + } + } + + /** + * Parses a long option. + * + * @param string $token The current token + */ + private function parseLongOption(string $token) + { + $name = substr($token, 2); + + if (false !== $pos = strpos($name, '=')) { + if (0 === strlen($value = substr($name, $pos + 1))) { + // if no value after "=" then substr() returns "" since php7 only, false before + // see http://php.net/manual/fr/migration70.incompatible.php#119151 + if (\PHP_VERSION_ID < 70000 && false === $value) { + $value = ''; + } + array_unshift($this->parsed, $value); + } + $this->addLongOption(substr($name, 0, $pos), $value); + } else { + $this->addLongOption($name, null); + } + } + + /** + * Parses an argument. + * + * @param string $token The current token + * + * @throws RuntimeException When too many arguments are given + */ + private function parseArgument(string $token) + { + $c = count($this->arguments); + + // if input is expecting another argument, add it + if ($this->definition->hasArgument($c)) { + $arg = $this->definition->getArgument($c); + $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; + + // if last argument isArray(), append token to last argument + } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { + $arg = $this->definition->getArgument($c - 1); + $this->arguments[$arg->getName()][] = $token; + + // unexpected argument + } else { + $all = $this->definition->getArguments(); + if (count($all)) { + throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s", provided arguments "%s".', implode('" "', array_keys($all)), implode('" "', array_keys($this->arguments)))); + } + + throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); + } + } + + /** + * Adds a short option value. + * + * @param string $shortcut The short option key + * @param mixed $value The value for the option + * + * @throws RuntimeException When option given doesn't exist + */ + private function addShortOption(string $shortcut, mixed $value) + { + if (!$this->definition->hasShortcut($shortcut)) { + // Hard to know what to do with unknown short options. Maybe + // these should be added to the end of the arguments. This would only + // be a good strategy if the last argument was an array argument. + // We'll try adding as a long option for now. + $this->addLongOption($shortcut, $value); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + public function injectAdditionalOptions($additionalOptions) + { + $this->additionalOptions += $additionalOptions; + $this->options += $additionalOptions; + } + + /** + * Adds a long option value. + * + * @param string $name The long option key + * @param mixed $value The value for the option + * + * @throws RuntimeException When option given doesn't exist + */ + private function addLongOption(string $name, mixed $value) + { + if (!$this->definition->hasOption($name)) { + // If we don't know anything about this option, then we'll + // assume it is generic. + $this->options[$name] = $value; + return; + } + + $option = $this->definition->getOption($name); + + if (null !== $value && !$option->acceptValue()) { + throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + } + + if (in_array($value, ['', null], true) && $option->acceptValue() && count($this->parsed)) { + // if option accepts an optional or mandatory argument + // let's see if there is one provided + $next = array_shift($this->parsed); + if ((isset($next[0]) && '-' !== $next[0]) || in_array($next, ['', null], true)) { + $value = $next; + } else { + array_unshift($this->parsed, $next); + } + } + + if (null === $value) { + if ($option->isValueRequired()) { + throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isArray() && !$option->isValueOptional()) { + $value = true; + } + } + + if ($option->isArray()) { + $this->options[$name][] = $value; + } else { + $this->options[$name] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument(): ?string + { + foreach ($this->tokens as $token) { + if ($token && '-' === $token[0]) { + continue; + } + + return $token; + } + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption(string|array $values, bool $onlyParams = false): bool + { + $values = (array) $values; + + foreach ($this->tokens as $token) { + if ($onlyParams && $token === '--') { + return false; + } + foreach ($values as $value) { + if ($token === $value || 0 === strpos($token, $value . '=')) { + return true; + } + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed + { + $values = (array) $values; + $tokens = $this->tokens; + + while (0 < count($tokens)) { + $token = array_shift($tokens); + if ($onlyParams && $token === '--') { + return false; + } + + foreach ($values as $value) { + if ($token === $value || 0 === strpos($token, $value . '=')) { + if (false !== $pos = strpos($token, '=')) { + return substr($token, $pos + 1); + } + + return array_shift($tokens); + } + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + * + * @return string + */ + public function __toString() + { + $tokens = array_map(function ($token) { + if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { + return $match[1] . $this->escapeToken($match[2]); + } + + if ($token && $token[0] !== '-') { + return $this->escapeToken($token); + } + + return $token; + }, $this->tokens); + + return implode(' ', $tokens); + } +} diff --git a/src/Preflight/Preflight.php b/src/Preflight/Preflight.php index 89475eb6f9..d32efb29c4 100644 --- a/src/Preflight/Preflight.php +++ b/src/Preflight/Preflight.php @@ -199,6 +199,38 @@ public function loadSiteAutoloader(): ClassLoader return $this->environment()->loadSiteAutoloader($this->drupalFinder()->getDrupalRoot()); } + public function loadSymfonyCompatabilityAutoloader(): ClassLoader + { + $symfonyMajorVersion = \Symfony\Component\HttpKernel\Kernel::MAJOR_VERSION; + $compatibilityMap = [ + 3 => false, // Drupal 8 + 4 => 'v4', // Drupal 9 + 5 => 'v4', // Early Drupal 10 (Symfony 5 works with Symfony 4 classes, so we don't keep an extra copy) + 6 => 'v6', // Drupal 10 + ]; + + if (empty($compatibilityMap[$symfonyMajorVersion])) { + throw new RuntimeException("Fatal error: Drush does not work with Symfony $symfonyMajorVersion. (In theory, Composer should not allow you to get this far.)"); + } + + $compatibilityBaseDir = dirname(__DIR__, 2) . '/src-symfony-compatibility'; + $compatibilityDir = $compatibilityBaseDir . '/' . $compatibilityMap[$symfonyMajorVersion]; + + // Next we will make a dynamic autoloader equivalent to an + // entry in the autoload.php file similar to: + // + // "psr-4": { + // "Drush\\": $compatibilityDir + // } + $loader = new \Composer\Autoload\ClassLoader(); + // register classes with namespaces + $loader->addPsr4('Drush\\', $compatibilityDir); + // activate the autoloader + $loader->register(); + + return $loader; + } + public function config(): DrushConfig { return $this->configLocator->config(); diff --git a/src/Preflight/PreflightArgs.php b/src/Preflight/PreflightArgs.php index 2654295dfc..518ccf211c 100644 --- a/src/Preflight/PreflightArgs.php +++ b/src/Preflight/PreflightArgs.php @@ -2,10 +2,10 @@ namespace Drush\Preflight; +use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputInterface; use Consolidation\Config\Config; use Consolidation\Config\ConfigInterface; -use Drush\Symfony\DrushArgvInput; use Drush\Utils\StringUtils; use Drush\Symfony\LessStrictArgvInput; @@ -492,7 +492,7 @@ public function createInput(): InputInterface // In strict mode (the default), create an ArgvInput. When // strict mode is disabled, create a more forgiving input object. if ($this->isStrict()) { - return new DrushArgvInput($this->args()); + return new ArgvInput($this->args()); } return new LessStrictArgvInput($this->args()); } diff --git a/src/Runtime/Runtime.php b/src/Runtime/Runtime.php index 438c8e065b..43bc7279b6 100644 --- a/src/Runtime/Runtime.php +++ b/src/Runtime/Runtime.php @@ -80,6 +80,9 @@ protected function doRun($argv, $output) // Require the Composer autoloader for Drupal (if different) $loader = $this->preflight->loadSiteAutoloader(); + // 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::getVersion()); diff --git a/src/Symfony/DrushArgvInput.php b/src/Symfony/DrushArgvInput.php index 9b06af7bdb..c81cd56855 100644 --- a/src/Symfony/DrushArgvInput.php +++ b/src/Symfony/DrushArgvInput.php @@ -1,361 +1,12 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - namespace Drush\Symfony; -use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\InputDefinition; /** - * ArgvInput represents an input coming from the CLI arguments. - * - * Usage: - * - * $input = new ArgvInput(); - * - * By default, the `$_SERVER['argv']` array is used for the input values. - * - * This can be overridden by explicitly passing the input values in the constructor: - * - * $input = new ArgvInput($_SERVER['argv']); - * - * If you pass it yourself, don't forget that the first element of the array - * is the name of the running application. - * - * When passing an argument to the constructor, be sure that it respects - * the same rules as the argv one. It's almost always better to use the - * `StringInput` when you want to provide your own input. - * - * @author Fabien Potencier - * - * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html - * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 + * DrushArgvInput is deprecated; use ArgvInput directly. */ class DrushArgvInput extends ArgvInput { - private $tokens; - private $parsed; - - /** - * @param array|null $argv An array of parameters from the CLI (in the argv format) - * @param InputDefinition|null $definition A InputDefinition instance - */ - public function __construct(array $argv = null, InputDefinition $definition = null) - { - if (null === $argv) { - $argv = $_SERVER['argv']; - } - - // strip the application name - array_shift($argv); - - $this->tokens = $argv; - - parent::__construct($definition); - } - - protected function setTokens(array $tokens): void - { - $this->tokens = $tokens; - } - - /** - * {@inheritdoc} - */ - protected function parse(): void - { - $parseOptions = true; - $this->parsed = $this->tokens; - while (null !== $token = array_shift($this->parsed)) { - if ($parseOptions && '' == $token) { - $this->parseArgument($token); - } elseif ($parseOptions && '--' == $token) { - $parseOptions = false; - } elseif ($parseOptions && 0 === strpos($token, '--')) { - $this->parseLongOption($token); - } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { - $this->parseShortOption($token); - } else { - $this->parseArgument($token); - } - } - } - - /** - * Parses a short option. - * - * @param string $token The current token - */ - private function parseShortOption($token): void - { - $name = substr($token, 1); - - if (strlen($name) > 1) { - if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { - // an option with a value (with no space) - $this->addShortOption($name[0], substr($name, 1)); - } else { - $this->parseShortOptionSet($name); - } - } else { - $this->addShortOption($name, null); - } - } - - /** - * Parses a short option set. - * - * @param string $name The current token - * - * @throws RuntimeException When option given doesn't exist - */ - private function parseShortOptionSet($name): void - { - $len = strlen($name); - for ($i = 0; $i < $len; ++$i) { - if (!$this->definition->hasShortcut($name[$i])) { - throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); - } - - $option = $this->definition->getOptionForShortcut($name[$i]); - if ($option->acceptValue()) { - $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); - - break; - } else { - $this->addLongOption($option->getName(), null); - } - } - } - - /** - * Parses a long option. - * - * @param string $token The current token - */ - private function parseLongOption($token): void - { - $name = substr($token, 2); - - if (false !== $pos = strpos($name, '=')) { - if (0 === strlen($value = substr($name, $pos + 1))) { - // if no value after "=" then substr() returns "" since php7 only, false before - // see http://php.net/manual/fr/migration70.incompatible.php#119151 - if (\PHP_VERSION_ID < 70000 && false === $value) { - $value = ''; - } - array_unshift($this->parsed, $value); - } - $this->addLongOption(substr($name, 0, $pos), $value); - } else { - $this->addLongOption($name, null); - } - } - - /** - * Parses an argument. - * - * @param string $token The current token - * - * @throws RuntimeException When too many arguments are given - */ - private function parseArgument($token): void - { - $c = count($this->arguments); - - // if input is expecting another argument, add it - if ($this->definition->hasArgument($c)) { - $arg = $this->definition->getArgument($c); - $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token; - - // if last argument isArray(), append token to last argument - } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { - $arg = $this->definition->getArgument($c - 1); - $this->arguments[$arg->getName()][] = $token; - - // unexpected argument - } else { - $all = $this->definition->getArguments(); - if (count($all)) { - throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); - } - - throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); - } - } - - /** - * Adds a short option value. - * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * - * @throws RuntimeException When option given doesn't exist - */ - private function addShortOption($shortcut, $value): void - { - if (!$this->definition->hasShortcut($shortcut)) { - throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); - } - - /** - * Adds a long option value. - * - * @param string $name The long option key - * @param mixed $value The value for the option - * - * @throws RuntimeException When option given doesn't exist - */ - private function addLongOption($name, $value): void - { - if (!$this->definition->hasOption($name)) { - throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); - } - - $option = $this->definition->getOption($name); - - if (null !== $value && !$option->acceptValue()) { - throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); - } - - if (in_array($value, array('', null), true) && $option->acceptValue() && count($this->parsed)) { - // if option accepts an optional or mandatory argument - // let's see if there is one provided - $next = array_shift($this->parsed); - if ((isset($next[0]) && '-' !== $next[0]) || in_array($next, array('', null), true)) { - $value = $next; - } else { - array_unshift($this->parsed, $next); - } - } - - if (null === $value) { - if ($option->isValueRequired()) { - throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); - } - - if (!$option->isArray() && !$option->isValueOptional()) { - $value = true; - } - } - - if ($option->isArray()) { - $this->options[$name][] = $value; - } else { - $this->options[$name] = $value; - } - } - - /** - * {@inheritdoc} - */ - public function getFirstArgument(): ?string - { - foreach ($this->tokens as $token) { - if ($token && '-' === $token[0]) { - continue; - } - - return $token; - } - } - - /** - * {@inheritdoc} - */ - public function hasParameterOption($values, $onlyParams = false): bool - { - $values = (array) $values; - - foreach ($this->tokens as $token) { - if ($onlyParams && '--' === $token) { - return false; - } - foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value . '=')) { - return true; - } - -/** - * Commented out until https://github.com/symfony/symfony/issues/25825 is resolved and released. - */ -// if (0 === strpos($token, '-') && 0 !== strpos($token, '--')) { -// $noValue = explode('=', $token); -// $token = $noValue[0]; -// $searchableToken = str_replace('-', '', $token); -// $searchableValue = str_replace('-', '', $value); -// if ('' !== $searchableToken && '' !== $searchableValue && false !== strpos($searchableToken, $searchableValue)) { -// return true; -// } -// } - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function getParameterOption($values, $default = false, $onlyParams = false) - { - $values = (array) $values; - $tokens = $this->tokens; - - while (0 < count($tokens)) { - $token = array_shift($tokens); - if ($onlyParams && '--' === $token) { - return false; - } - - foreach ($values as $value) { - if ($token === $value || 0 === strpos($token, $value . '=')) { - if (false !== $pos = strpos($token, '=')) { - return substr($token, $pos + 1); - } - - return array_shift($tokens); - } - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command. - * - * @return string - */ - public function __toString() - { - $tokens = array_map(function ($token) { - if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { - return $match[1] . $this->escapeToken($match[2]); - } - - if ($token && '-' !== $token[0]) { - return $this->escapeToken($token); - } - - return $token; - }, $this->tokens); - - return implode(' ', $tokens); - } } diff --git a/sut/drush/Commands/SimpleSutCommands.php b/sut/drush/Commands/SimpleSutCommands.php index ffccfcbc4a..e12b00493e 100644 --- a/sut/drush/Commands/SimpleSutCommands.php +++ b/sut/drush/Commands/SimpleSutCommands.php @@ -8,7 +8,7 @@ use Consolidation\Log\ConsoleLogLevel; use Consolidation\OutputFormatters\StructuredData\RowsOfFields; use Drush\Drush; -use Drush\Symfony\DrushArgvInput; +use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Logger\ConsoleLogger; use Symfony\Component\Console\Output\OutputInterface; @@ -42,7 +42,7 @@ public function example() * * @hook init sut:simple */ - public function customLogger(DrushArgvInput $argv, AnnotationData $annotationData): void + public function customLogger(InputInterface $argv, AnnotationData $annotationData): void { $verbosityLevelMap = [ConsoleLogLevel::SUCCESS => OutputInterface::VERBOSITY_NORMAL]; $formatLevelMap = [ConsoleLogLevel::SUCCESS => \Psr\Log\LogLevel::INFO]; diff --git a/tests/functional/QueueTest.php b/tests/functional/QueueTest.php index 4a32aee3b2..53005be32a 100644 --- a/tests/functional/QueueTest.php +++ b/tests/functional/QueueTest.php @@ -13,6 +13,10 @@ class QueueTest extends CommandUnishTestCase public function testQueue() { + if (!$this->isDrupalGreaterThanOrEqualTo('10.0.0')) { + $this->markTestSkipped('testQueue uses aggregator module, which has been removed in Drupal 10'); + } + $expected = 'aggregator_feeds,%items,"Drupal\Core\Queue\DatabaseQueue"'; $sites = $this->setUpDrupal(1, true); @@ -41,6 +45,10 @@ public function testQueue() */ public function testQueueDelete() { + if (!$this->isDrupalGreaterThanOrEqualTo('10.0.0')) { + $this->markTestSkipped('testQueueDelete uses aggregator module, which has been removed in Drupal 10'); + } + $expected = 'aggregator_feeds,%items,"Drupal\Core\Queue\DatabaseQueue"'; $sites = $this->setUpDrupal(1, true); diff --git a/tests/unish/Controllers/RuntimeController.php b/tests/unish/Controllers/RuntimeController.php index 005500fd0a..c89f8a397d 100644 --- a/tests/unish/Controllers/RuntimeController.php +++ b/tests/unish/Controllers/RuntimeController.php @@ -49,8 +49,6 @@ class RuntimeController private function __construct() { - // Create a reusable output buffer - $this->output = new \Drush\Symfony\BufferedConsoleOutput(); } public static function instance() @@ -84,6 +82,10 @@ public function input() public function output() { + if (!isset($this->output)) { + // Create a reusable output buffer + $this->output = new \Drush\Symfony\BufferedConsoleOutput(); + } return $this->output; } @@ -121,6 +123,9 @@ protected function initializeRuntime($root, $argv) // Require the Composer autoloader for Drupal (if different) $loader = $this->preflight->loadSiteAutoloader(); + // Load the Symfony compatability layer autoloader + $this->preflight->loadSymfonyCompatabilityAutoloader(); + // Create the Symfony Application et. al. $this->input = $this->preflight->createInput(); $this->application = new \Drush\Application('Drush Commandline Tool (Unish-scaffolded)', Drush::getVersion()); @@ -130,7 +135,7 @@ protected function initializeRuntime($root, $argv) $this->application, $this->preflight->config(), $this->input, - $this->output, + $this->output(), $loader, $this->preflight->drupalFinder(), $this->preflight->aliasManager() @@ -153,7 +158,7 @@ protected function initializeRuntime($root, $argv) // 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. - $this->application->configureAndRegisterCommands($this->input, $this->output, $commandfileSearchpath, $loader); + $this->application->configureAndRegisterCommands($this->input, $this->output(), $commandfileSearchpath, $loader); } protected function handleBootstrap()