From 6f532c809cafb46e045687bf974ab6ede1951565 Mon Sep 17 00:00:00 2001 From: Sebastian Schreiber Date: Wed, 1 Apr 2020 21:28:59 +0200 Subject: [PATCH] [TASK] Add symfony service dependency injection container (#378) * [TASK] Add symfony service container * [TASK] Simplify command name configuration * [TASK] Sort packages in composer.json * Pass console parameters via config Co-authored-by: Simon Schaufelberger --- .gitignore | 1 + .php_cs | 1 + Resources/services.yaml | 31 + bin/surf | 10 +- composer.json | 14 +- composer.lock | 1216 +++++++++++++---- .../CommandsToApplicationCompilerPass.php | 31 + src/Cli/Symfony/ConsoleApplication.php | 24 +- src/Cli/Symfony/ConsoleKernel.php | 57 + src/Cli/Symfony/ConsoleOutputFactory.php | 35 + src/Cli/Symfony/Logger/ConsoleHandler.php | 33 +- src/Cli/Symfony/Logger/LoggerFactory.php | 32 + src/Command/DeployCommand.php | 33 +- src/Command/DescribeCommand.php | 31 +- src/Command/RollbackCommand.php | 36 +- src/Command/SelfUpdateCommand.php | 21 +- src/Command/ShowCommand.php | 31 +- src/Command/SimulateCommand.php | 34 +- src/Domain/Model/Deployment.php | 26 +- src/Domain/Model/SimpleWorkflow.php | 5 +- src/Domain/Model/Workflow.php | 4 +- .../ShellCommandServiceAwareInterface.php | 2 +- .../Service/ShellCommandServiceAwareTrait.php | 2 +- src/Domain/Service/TaskFactory.php | 21 +- src/Domain/Service/TaskManager.php | 5 +- src/Integration/Factory.php | 72 +- src/Integration/FactoryAwareInterface.php | 20 - src/Integration/FactoryAwareTrait.php | 28 - src/Integration/FactoryInterface.php | 9 - src/Task/CleanupReleasesTask.php | 6 +- src/Task/CreateArchiveTask.php | 8 +- .../Php/WebOpcacheResetCreateScriptTask.php | 12 +- src/Task/Php/WebOpcacheResetExecuteTask.php | 7 +- src/Task/Test/HttpTestTask.php | 10 +- tests/Unit/Application/Neos/FlowTest.php | 3 +- tests/Unit/Command/DeployCommandTest.php | 46 +- tests/Unit/Command/DescribeCommandTest.php | 25 +- tests/Unit/Domain/Model/DeploymentTest.php | 22 +- tests/Unit/Domain/Service/TaskFactoryTest.php | 28 +- tests/Unit/Integration/FactoryTest.php | 28 +- tests/Unit/KernelAwareTrait.php | 32 + tests/Unit/Task/BaseTaskTest.php | 4 + tests/Unit/Task/CleanupReleasesTaskTest.php | 4 + tests/Unit/Task/Test/HttpTestTaskTest.php | 2 +- 44 files changed, 1414 insertions(+), 688 deletions(-) create mode 100644 Resources/services.yaml create mode 100644 src/Cli/Symfony/CompilerPasses/CommandsToApplicationCompilerPass.php create mode 100644 src/Cli/Symfony/ConsoleKernel.php create mode 100644 src/Cli/Symfony/ConsoleOutputFactory.php create mode 100644 src/Cli/Symfony/Logger/LoggerFactory.php delete mode 100644 src/Integration/FactoryAwareInterface.php delete mode 100644 src/Integration/FactoryAwareTrait.php create mode 100644 tests/Unit/KernelAwareTrait.php diff --git a/.gitignore b/.gitignore index b17f7f08..18be8028 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ vendor/ sphpdox.phar _Output/ Documentation/.doctrees +var/ diff --git a/.php_cs b/.php_cs index 625a6ab7..7fd37b8a 100644 --- a/.php_cs +++ b/.php_cs @@ -13,6 +13,7 @@ if (PHP_SAPI !== 'cli') { // Define in which folders to search and which folders to exclude // Exclude some directories that are excluded by Git anyways to speed up the sniffing $finder = PhpCsFixer\Finder::create() + ->exclude('var') ->exclude('.github') ->exclude('Configuration') ->exclude('Documentation') diff --git a/Resources/services.yaml b/Resources/services.yaml new file mode 100644 index 00000000..4d7314ef --- /dev/null +++ b/Resources/services.yaml @@ -0,0 +1,31 @@ +parameters: + name: 'TYPO3 Surf' + version: '3.0.0-alpha' + +services: + _defaults: + autowire: true + autoconfigure: true + public: true + bind: + $name: '%name%' + $version: '%version%' + TYPO3\Surf\: + resource: '../src/*' + exclude: '../src/{Cli,Application,Exception,Domain/Model,DeprecationMessageFactory.php,Exception.php,functions.php}' + Symfony\Component\Console\Output\OutputInterface: + factory: ['@TYPO3\Surf\Cli\Symfony\ConsoleOutputFactory', 'createOutput'] + Psr\Log\LoggerInterface: + factory: ['@TYPO3\Surf\Cli\Symfony\Logger\LoggerFactory', 'createLogger'] + TYPO3\Surf\Integration\Factory: + arguments: ['@TYPO3\Surf\Domain\Filesystem\FilesystemInterface', '@Psr\Log\LoggerInterface'] + TYPO3\Surf\Integration\FactoryInterface: '@TYPO3\Surf\Integration\Factory' + GuzzleHttp\Client: ~ + GuzzleHttp\ClientInterface: '@GuzzleHttp\Client' + TYPO3\Surf\Cli\Symfony\Logger\ConsoleHandler: ~ + TYPO3\Surf\Cli\Symfony\ConsoleApplication: ~ + Symfony\Component\Console\Application: ~ + TYPO3\Surf\Domain\Model\SimpleWorkflow: + shared: false + TYPO3\Surf\Cli\Symfony\ConsoleOutputFactory: ~ + TYPO3\Surf\Cli\Symfony\Logger\LoggerFactory: ~ diff --git a/bin/surf b/bin/surf index 55d430c1..dba5c0e9 100755 --- a/bin/surf +++ b/bin/surf @@ -3,9 +3,13 @@ requireAutoloader(); -$app = new \TYPO3\Surf\Cli\Symfony\ConsoleApplication('TYPO3 Surf', '3.0.0-alpha'); -$app->setFactory(new \TYPO3\Surf\Integration\Factory()); -$app->run(); +$kernel = new \TYPO3\Surf\Cli\Symfony\ConsoleKernel('prod', false); +$kernel->boot(); +/* @var \Symfony\Component\DependencyInjection\Container $container */ +$container = $kernel->getContainer(); + +$application = $container->get(\TYPO3\Surf\Cli\Symfony\ConsoleApplication::class); +$application->run(); function requireAutoloader() { diff --git a/composer.json b/composer.json index f3d2794a..54814cba 100644 --- a/composer.json +++ b/composer.json @@ -4,21 +4,25 @@ "license": "GPL-3.0-or-later", "require": { "php": "^7.2", + "guzzlehttp/guzzle": "^6.0", "monolog/monolog": "^1.17", "neos/utility-files": "^3.0", "padraic/phar-updater": "1.0.5", + "symfony/config": "^5.0", "symfony/console": "^4.0", - "symfony/process": "^4.0", + "symfony/dependency-injection": "^5.0", + "symfony/http-kernel": "^4.0", "symfony/options-resolver": "^4.0", - "guzzlehttp/guzzle": "^6.0", + "symfony/process": "^4.0", + "symfony/yaml": "^5.0", "webmozart/assert": "^1.4" }, "require-dev": { - "phpunit/phpunit": "^7.0", "friendsofphp/php-cs-fixer": "^2.14", + "jangregor/phpstan-prophecy": "^0.6.2", "phpstan/phpstan": "^0.12.14", "phpstan/phpstan-webmozart-assert": "^0.12.2", - "jangregor/phpstan-prophecy": "^0.6.2" + "phpunit/phpunit": "^7.0" }, "scripts": { "release-phar": "bin/box build", @@ -46,6 +50,8 @@ "bin/surf" ], "config": { + "optimize-autoloader": true, + "sort-packages": true, "platform": { "php": "7.2.5" } diff --git a/composer.lock b/composer.lock index b5ca827e..5d7a99b0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d3131934a8ba595d23bf6b15f9a3c40e", + "content-hash": "162c9a90bec6e32e758aa10c56b64107", "packages": [ { "name": "composer/ca-bundle", @@ -676,59 +676,689 @@ "description": "A polyfill for getallheaders.", "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "symfony/config", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "938905f46df484b2aeae9016fd658aed577cdceb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/938905f46df484b2aeae9016fd658aed577cdceb", + "reference": "938905f46df484b2aeae9016fd658aed577cdceb", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-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": "2020-02-04T09:41:09+00:00" + }, { "name": "symfony/console", "version": "v4.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "f512001679f37e6a042b51897ed24a2f05eba656" + "url": "https://github.com/symfony/console.git", + "reference": "f512001679f37e6a042b51897ed24a2f05eba656" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/f512001679f37e6a042b51897ed24a2f05eba656", + "reference": "f512001679f37e6a042b51897ed24a2f05eba656", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "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 Console Component", + "homepage": "https://symfony.com", + "time": "2020-01-25T12:44:29+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.4.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "a980d87a659648980d89193fd8b7a7ca89d97d21" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/a980d87a659648980d89193fd8b7a7ca89d97d21", + "reference": "a980d87a659648980d89193fd8b7a7ca89d97d21", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "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 Debug Component", + "homepage": "https://symfony.com", + "time": "2020-02-23T14:41:43+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "3575004a9b0d51ead83473ec90121045b3a0b56f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/3575004a9b0d51ead83473ec90121045b3a0b56f", + "reference": "3575004a9b0d51ead83473ec90121045b3a0b56f", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "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 DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2020-02-24T15:05:31+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v4.4.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "89aa4b9ac6f1f35171b8621b24f60477312085be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/89aa4b9ac6f1f35171b8621b24f60477312085be", + "reference": "89aa4b9ac6f1f35171b8621b24f60477312085be", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0", + "symfony/debug": "^4.4.5", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "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 ErrorHandler Component", + "homepage": "https://symfony.com", + "time": "2020-02-26T11:45:31+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9e3de195e5bc301704dd6915df55892f6dfc208b", + "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "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 EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2020-01-10T21:54:01+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-09-17T09:54:03+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "3afadc0f57cd74f86379d073e694b0f2cda2a88c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/3afadc0f57cd74f86379d073e694b0f2cda2a88c", + "reference": "3afadc0f57cd74f86379d073e694b0f2cda2a88c", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.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": "2020-01-21T08:40:24+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "6f9c2ba72f4295d7ce6cf9f79dbb18036291d335" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6f9c2ba72f4295d7ce6cf9f79dbb18036291d335", + "reference": "6f9c2ba72f4295d7ce6cf9f79dbb18036291d335", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "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 HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2020-02-14T07:43:07+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v4.4.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "02ee1d0d616b031fb48a1c9c3e5dc092dd7e448d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/02ee1d0d616b031fb48a1c9c3e5dc092dd7e448d", + "reference": "02ee1d0d616b031fb48a1c9c3e5dc092dd7e448d", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0", + "symfony/error-handler": "^4.4", + "symfony/event-dispatcher": "^4.4", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9" + }, + "conflict": { + "symfony/browser-kit": "<4.3", + "symfony/config": "<3.4", + "symfony/console": ">=5", + "symfony/dependency-injection": "<4.3", + "symfony/translation": "<4.2", + "twig/twig": "<1.34|<2.4,>=2" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "^4.3|^5.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/console": "^3.4|^4.0", + "symfony/css-selector": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^4.3|^5.0", + "symfony/dom-crawler": "^3.4|^4.0|^5.0", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/finder": "^3.4|^4.0|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/routing": "^3.4|^4.0|^5.0", + "symfony/stopwatch": "^3.4|^4.0|^5.0", + "symfony/templating": "^3.4|^4.0|^5.0", + "symfony/translation": "^4.2|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^1.34|^2.4|^3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "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 HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2020-03-27T08:32:28+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "9b3e5b5e58c56bbd76628c952d2b78556d305f3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f512001679f37e6a042b51897ed24a2f05eba656", - "reference": "f512001679f37e6a042b51897ed24a2f05eba656", + "url": "https://api.github.com/repos/symfony/mime/zipball/9b3e5b5e58c56bbd76628c952d2b78556d305f3c", + "reference": "9b3e5b5e58c56bbd76628c952d2b78556d305f3c", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/service-contracts": "^1.1|^2" + "php": "^7.2.5", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3|>=5", - "symfony/lock": "<4.4", - "symfony/process": "<3.3" - }, - "provide": { - "psr/log-implementation": "1.0" + "symfony/mailer": "<4.4" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/event-dispatcher": "^4.3", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/var-dumper": "^4.3|^5.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "^4.4|^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Console\\": "" + "Symfony\\Component\\Mime\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -748,9 +1378,13 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "A library to manipulate MIME messages", "homepage": "https://symfony.com", - "time": "2020-01-25T12:44:29+00:00" + "keywords": [ + "mime", + "mime-type" + ], + "time": "2020-02-04T09:41:09+00:00" }, { "name": "symfony/options-resolver", @@ -864,6 +1498,68 @@ ], "time": "2020-01-13T11:15:53+00:00" }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.14.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6842f1a39cf7d580655688069a03dd7cd83d244a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6842f1a39cf7d580655688069a03dd7cd83d244a", + "reference": "6842f1a39cf7d580655688069a03dd7cd83d244a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.14-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2020-01-17T12:01:36+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.14.0", @@ -923,6 +1619,61 @@ ], "time": "2020-01-13T11:15:53+00:00" }, + { + "name": "symfony/polyfill-php72", + "version": "v1.14.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", + "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.14-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2020-01-13T11:15:53+00:00" + }, { "name": "symfony/polyfill-php73", "version": "v1.14.0", @@ -1049,18 +1800,160 @@ "psr/container": "^1.0" }, "suggest": { - "symfony/service-implementation": "" + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "3a37aeb1132d1035536d3d6aa9cb06c2ff9355e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3a37aeb1132d1035536d3d6aa9cb06c2ff9355e9", + "reference": "3a37aeb1132d1035536d3d6aa9cb06c2ff9355e9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2020-02-26T22:30:10+00:00" + }, + { + "name": "symfony/yaml", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "a4b613d7e44f62941adff5a802cff70adee57d3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a4b613d7e44f62941adff5a802cff70adee57d3f", + "reference": "a4b613d7e44f62941adff5a802cff70adee57d3f", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "symfony/console": "^4.4|^5.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1068,25 +1961,17 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "time": "2019-11-18T17:27:11+00:00" + "time": "2020-02-03T13:51:17+00:00" }, { "name": "webmozart/assert", @@ -3033,184 +3918,6 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, - { - "name": "symfony/event-dispatcher", - "version": "v4.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9e3de195e5bc301704dd6915df55892f6dfc208b", - "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "symfony/event-dispatcher-contracts": "^1.1" - }, - "conflict": { - "symfony/dependency-injection": "<3.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "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 EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2020-01-10T21:54:01+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", - "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "suggest": { - "psr/event-dispatcher": "", - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "time": "2019-09-17T09:54:03+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "3afadc0f57cd74f86379d073e694b0f2cda2a88c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3afadc0f57cd74f86379d073e694b0f2cda2a88c", - "reference": "3afadc0f57cd74f86379d073e694b0f2cda2a88c", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.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": "2020-01-21T08:40:24+00:00" - }, { "name": "symfony/finder", "version": "v5.0.4", @@ -3319,61 +4026,6 @@ ], "time": "2020-01-13T11:15:53+00:00" }, - { - "name": "symfony/polyfill-php72", - "version": "v1.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", - "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.14-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2020-01-13T11:15:53+00:00" - }, { "name": "symfony/stopwatch", "version": "v5.0.4", diff --git a/src/Cli/Symfony/CompilerPasses/CommandsToApplicationCompilerPass.php b/src/Cli/Symfony/CompilerPasses/CommandsToApplicationCompilerPass.php new file mode 100644 index 00000000..62007be2 --- /dev/null +++ b/src/Cli/Symfony/CompilerPasses/CommandsToApplicationCompilerPass.php @@ -0,0 +1,31 @@ +getDefinition(ConsoleApplication::class); + + foreach ($container->getDefinitions() as $name => $definition) { + if (is_a($definition->getClass(), Command::class, true)) { + $applicationDefinition->addMethodCall('add', [new Reference($name)]); + } + } + } +} diff --git a/src/Cli/Symfony/ConsoleApplication.php b/src/Cli/Symfony/ConsoleApplication.php index b81bb922..52293edf 100644 --- a/src/Cli/Symfony/ConsoleApplication.php +++ b/src/Cli/Symfony/ConsoleApplication.php @@ -9,10 +9,8 @@ */ use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use TYPO3\Surf\Integration\FactoryAwareInterface; use TYPO3\Surf\Integration\FactoryInterface; /** @@ -25,24 +23,20 @@ class ConsoleApplication extends Application */ protected $factory; - public function setFactory(FactoryInterface $factory): void + /** + * @var OutputInterface + */ + private $output; + + public function __construct(FactoryInterface $factory, OutputInterface $output, string $name, string $version) { + parent::__construct($name, $version); $this->factory = $factory; + $this->output = $output; } public function run(InputInterface $input = null, OutputInterface $output = null): int { - foreach ($this->factory->createCommands() as $command) { - $this->add($command); - } - return parent::run($input, $this->factory->createOutput()); - } - - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output): int - { - if ($command instanceof FactoryAwareInterface) { - $command->setFactory($this->factory); - } - return parent::doRunCommand($command, $input, $output); + return parent::run($input, $this->output); } } diff --git a/src/Cli/Symfony/ConsoleKernel.php b/src/Cli/Symfony/ConsoleKernel.php new file mode 100644 index 00000000..a7484543 --- /dev/null +++ b/src/Cli/Symfony/ConsoleKernel.php @@ -0,0 +1,57 @@ +load(__DIR__.'/../../../Resources/services.yaml'); + } + + /** + * @inheritDoc + */ + protected function build(ContainerBuilder $containerBuilder): void + { + $containerBuilder->addCompilerPass(new CommandsToApplicationCompilerPass()); + $containerBuilder->registerForAutoconfiguration( + ContainerAwareInterface::class)->addMethodCall( + 'setContainer', [new Reference(ContainerInterface::class)] + ); + $containerBuilder->registerForAutoconfiguration( + ShellCommandServiceAwareInterface::class)->addMethodCall( + 'setShellCommandService', [new Reference(ShellCommandService::class)] + ); + } +} diff --git a/src/Cli/Symfony/ConsoleOutputFactory.php b/src/Cli/Symfony/ConsoleOutputFactory.php new file mode 100644 index 00000000..8d53fadb --- /dev/null +++ b/src/Cli/Symfony/ConsoleOutputFactory.php @@ -0,0 +1,35 @@ +getFormatter()->setStyle('b', new OutputFormatterStyle(null, null, ['bold'])); + $output->getFormatter()->setStyle('i', new OutputFormatterStyle('black', 'white')); + $output->getFormatter()->setStyle('u', new OutputFormatterStyle(null, null, ['underscore'])); + $output->getFormatter()->setStyle('em', new OutputFormatterStyle(null, null, ['reverse'])); + $output->getFormatter()->setStyle('strike', new OutputFormatterStyle(null, null, ['conceal'])); + $output->getFormatter()->setStyle('success', new OutputFormatterStyle('green')); + $output->getFormatter()->setStyle('warning', new OutputFormatterStyle('black', 'yellow')); + $output->getFormatter()->setStyle('notice', new OutputFormatterStyle('yellow')); + $output->getFormatter()->setStyle('info', new OutputFormatterStyle('white', null, ['bold'])); + $output->getFormatter()->setStyle('debug', new OutputFormatterStyle('white')); + + return $output; + } +} diff --git a/src/Cli/Symfony/Logger/ConsoleHandler.php b/src/Cli/Symfony/Logger/ConsoleHandler.php index 1a10b30c..5722284a 100644 --- a/src/Cli/Symfony/Logger/ConsoleHandler.php +++ b/src/Cli/Symfony/Logger/ConsoleHandler.php @@ -29,7 +29,7 @@ class ConsoleHandler extends AbstractProcessingHandler { /** - * @var OutputInterface|null + * @var OutputInterface */ private $output; @@ -43,16 +43,7 @@ class ConsoleHandler extends AbstractProcessingHandler OutputInterface::VERBOSITY_DEBUG => Logger::DEBUG, ]; - /** - * Constructor. - * - * @param OutputInterface|null $output The console output to use (the handler remains disabled when passing null - * until the output is set, e.g. by using console events) - * @param bool $bubble Whether the messages that are handled can bubble up the stack - * @param array $verbosityLevelMap Array that maps the OutputInterface verbosity to a minimum logging - * level (leave empty to use the default mapping) - */ - public function __construct(OutputInterface $output = null, $bubble = true, array $verbosityLevelMap = []) + public function __construct(OutputInterface $output, bool $bubble = true, array $verbosityLevelMap = []) { parent::__construct(Logger::DEBUG, $bubble); $this->output = $output; @@ -73,7 +64,7 @@ public function isHandling(array $record) /** * {@inheritdoc} */ - public function handle(array $record) + public function handle(array $record): bool { // we have to update the logging level each time because the verbosity of the // console output might have changed in the meantime (it is not immutable) @@ -81,17 +72,7 @@ public function handle(array $record) } /** - * Sets the console output to use for printing logs. - * - * @param OutputInterface $output The console output to use - */ - public function setOutput(OutputInterface $output) - { - $this->output = $output; - } - - /** - * Disables the output. + * {@inheritdoc} */ public function close() { @@ -103,7 +84,7 @@ public function close() /** * {@inheritdoc} */ - protected function write(array $record) + protected function write(array $record): void { $this->output->write((string)$record['formatted']); } @@ -118,10 +99,8 @@ protected function getDefaultFormatter() /** * Updates the logging level based on the verbosity setting of the console output. - * - * @return bool Whether the handler is enabled and verbosity is not set to quiet. */ - private function updateLevel() + private function updateLevel(): bool { if (null === $this->output || OutputInterface::VERBOSITY_QUIET === $verbosity = $this->output->getVerbosity()) { return false; diff --git a/src/Cli/Symfony/Logger/LoggerFactory.php b/src/Cli/Symfony/Logger/LoggerFactory.php new file mode 100644 index 00000000..01c66a70 --- /dev/null +++ b/src/Cli/Symfony/Logger/LoggerFactory.php @@ -0,0 +1,32 @@ +consoleHandler = $consoleHandler; + } + + public function createLogger(): LoggerInterface + { + return new Logger('TYPO3 Surf', [$this->consoleHandler]); + } +} diff --git a/src/Command/DeployCommand.php b/src/Command/DeployCommand.php index 98f0156f..5bf0b13b 100755 --- a/src/Command/DeployCommand.php +++ b/src/Command/DeployCommand.php @@ -14,23 +14,29 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use TYPO3\Surf\Integration\FactoryAwareInterface; -use TYPO3\Surf\Integration\FactoryAwareTrait; +use TYPO3\Surf\Integration\FactoryInterface; -/** - * Surf deploy command - */ -class DeployCommand extends Command implements FactoryAwareInterface +class DeployCommand extends Command { - use FactoryAwareTrait; + /** + * @var FactoryInterface + */ + private $factory; /** - * Configure + * @var string */ - protected function configure() + protected static $defaultName = 'deploy'; + + public function __construct(FactoryInterface $factory) { - $this->setName('deploy') - ->setDescription('Deploys the application with the given name') + parent::__construct(); + $this->factory = $factory; + } + + protected function configure(): void + { + $this->setDescription('Deploys the application with the given name') ->addArgument( 'deploymentName', InputArgument::OPTIONAL, @@ -50,10 +56,7 @@ protected function configure() ); } - /** - * @return int|null null or 0 if everything went fine, or an error code - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $configurationPath = $input->getOption('configurationPath'); $deploymentName = $input->getArgument('deploymentName'); diff --git a/src/Command/DescribeCommand.php b/src/Command/DescribeCommand.php index 8737f991..fc3fa3a8 100755 --- a/src/Command/DescribeCommand.php +++ b/src/Command/DescribeCommand.php @@ -18,16 +18,10 @@ use TYPO3\Surf\Domain\Model\FailedDeployment; use TYPO3\Surf\Domain\Model\SimpleWorkflow; use TYPO3\Surf\Domain\Model\Workflow; -use TYPO3\Surf\Integration\FactoryAwareInterface; -use TYPO3\Surf\Integration\FactoryAwareTrait; +use TYPO3\Surf\Integration\FactoryInterface; -/** - * Surf describe command - */ -class DescribeCommand extends Command implements FactoryAwareInterface +class DescribeCommand extends Command { - use FactoryAwareTrait; - /** * @var InputInterface */ @@ -38,10 +32,25 @@ class DescribeCommand extends Command implements FactoryAwareInterface */ protected $output; + /** + * @var FactoryInterface + */ + private $factory; + + /** + * @var string + */ + protected static $defaultName = 'describe'; + + public function __construct(FactoryInterface $factory) + { + parent::__construct(); + $this->factory = $factory; + } + protected function configure() { - $this->setName('describe') - ->setDescription('Describes the flow for the given name') + $this->setDescription('Describes the flow for the given name') ->addArgument( 'deploymentName', InputArgument::REQUIRED, @@ -55,7 +64,7 @@ protected function configure() ); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $this->input = $input; $this->output = $output; diff --git a/src/Command/RollbackCommand.php b/src/Command/RollbackCommand.php index c275dece..297ca77b 100644 --- a/src/Command/RollbackCommand.php +++ b/src/Command/RollbackCommand.php @@ -14,17 +14,29 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use TYPO3\Surf\Integration\FactoryAwareInterface; -use TYPO3\Surf\Integration\FactoryAwareTrait; +use TYPO3\Surf\Integration\FactoryInterface; -class RollbackCommand extends Command implements FactoryAwareInterface +class RollbackCommand extends Command { - use FactoryAwareTrait; + /** + * @var FactoryInterface + */ + private $factory; + + /** + * @var string + */ + protected static $defaultName = 'rollback'; - protected function configure() + public function __construct(FactoryInterface $factory) { - $this->setName('rollback') - ->setDescription('Rollback current to previous release and remove current folder') + parent::__construct(); + $this->factory = $factory; + } + + protected function configure(): void + { + $this->setDescription('Rollback current to previous release and remove current folder') ->addArgument( 'deploymentName', InputArgument::OPTIONAL, @@ -43,15 +55,7 @@ protected function configure() ); } - /** - * @param InputInterface $input - * @param OutputInterface $output - * - * @return int|null - * @throws \TYPO3\Surf\Exception - * @throws \TYPO3\Surf\Exception\InvalidConfigurationException - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $configurationPath = $input->getOption('configurationPath'); $deploymentName = $input->getArgument('deploymentName'); diff --git a/src/Command/SelfUpdateCommand.php b/src/Command/SelfUpdateCommand.php index 4b2970b1..74c3b6fd 100755 --- a/src/Command/SelfUpdateCommand.php +++ b/src/Command/SelfUpdateCommand.php @@ -18,23 +18,21 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -/** - * Surf list command - */ class SelfUpdateCommand extends Command { /** - * @return bool + * @var string */ - public function isEnabled() + protected static $defaultName = 'self-update'; + + public function isEnabled(): bool { return Phar::running() !== ''; } - protected function configure() + protected function configure(): void { - $this->setName('self-update') - ->addOption( + $this->addOption( 'stability', null, InputOption::VALUE_OPTIONAL, @@ -53,7 +51,7 @@ protected function configure() )->setDescription(sprintf('Update %s to most recent stable build', $this->getLocalPharName())); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $updater = new Updater(null, false, Updater::STRATEGY_GITHUB); /** @var GithubStrategy $strategy */ @@ -106,10 +104,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - /** - * @return string - */ - private function getLocalPharName() + private function getLocalPharName(): string { return basename(Phar::running()); } diff --git a/src/Command/ShowCommand.php b/src/Command/ShowCommand.php index 0d3a1165..b3f24b20 100755 --- a/src/Command/ShowCommand.php +++ b/src/Command/ShowCommand.php @@ -12,20 +12,29 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use TYPO3\Surf\Integration\FactoryAwareInterface; -use TYPO3\Surf\Integration\FactoryAwareTrait; +use TYPO3\Surf\Integration\FactoryInterface; -/** - * Surf list command - */ -class ShowCommand extends Command implements FactoryAwareInterface +class ShowCommand extends Command { - use FactoryAwareTrait; + /** + * @var FactoryInterface + */ + private $factory; + + /** + * @var string + */ + protected static $defaultName = 'show'; + + public function __construct(FactoryInterface $factory) + { + parent::__construct(); + $this->factory = $factory; + } - protected function configure() + protected function configure(): void { - $this->setName('show') - ->setDescription('Shows all the deployments depending on the directory configuration') + $this->setDescription('Shows all the deployments depending on the directory configuration') ->addOption( 'configurationPath', null, @@ -34,7 +43,7 @@ protected function configure() ); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $configurationPath = $input->getOption('configurationPath'); $deploymentNames = $this->factory->getDeploymentNames($configurationPath); diff --git a/src/Command/SimulateCommand.php b/src/Command/SimulateCommand.php index 882da54b..12fd103c 100755 --- a/src/Command/SimulateCommand.php +++ b/src/Command/SimulateCommand.php @@ -14,20 +14,29 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use TYPO3\Surf\Integration\FactoryAwareInterface; -use TYPO3\Surf\Integration\FactoryAwareTrait; +use TYPO3\Surf\Integration\FactoryInterface; -/** - * Surf simulate command - */ -class SimulateCommand extends Command implements FactoryAwareInterface +class SimulateCommand extends Command { - use FactoryAwareTrait; + /** + * @var FactoryInterface + */ + private $factory; + + /** + * @var string + */ + protected static $defaultName = 'simulate'; - protected function configure() + public function __construct(FactoryInterface $factory) { - $this->setName('simulate') - ->setDescription('Simulates the deployment for the given name') + parent::__construct(); + $this->factory = $factory; + } + + protected function configure(): void + { + $this->setDescription('Simulates the deployment for the given name') ->addArgument( 'deploymentName', InputArgument::OPTIONAL, @@ -47,10 +56,7 @@ protected function configure() ); } - /** - * @return int - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $configurationPath = $input->getOption('configurationPath'); $deploymentName = $input->getArgument('deploymentName'); diff --git a/src/Domain/Model/Deployment.php b/src/Domain/Model/Deployment.php index 1fc016a0..96068789 100644 --- a/src/Domain/Model/Deployment.php +++ b/src/Domain/Model/Deployment.php @@ -11,6 +11,8 @@ use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; use TYPO3\Surf\Exception as SurfException; /** @@ -19,8 +21,10 @@ * This is the base object exposed to a deployment configuration script and serves as a configuration builder and * model for an actual deployment. */ -class Deployment implements LoggerAwareInterface +class Deployment implements LoggerAwareInterface, ContainerAwareInterface { + use ContainerAwareTrait; + public const STATUS_SUCCESS = 0; public const STATUS_FAILED = 1; public const STATUS_CANCELLED = 2; @@ -116,12 +120,6 @@ class Deployment implements LoggerAwareInterface */ private $deploymentLockIdentifier; - /** - * Constructor - * - * @param string $name - * @param string|null $deploymentLockIdentifier - */ public function __construct($name, $deploymentLockIdentifier = null) { $this->name = $name; @@ -146,7 +144,7 @@ public function initialize() throw new SurfException('Already initialized', 1335976472); } if ($this->workflow === null) { - $this->workflow = new SimpleWorkflow(); + $this->workflow = $this->container->get(SimpleWorkflow::class); } foreach ($this->applications as $application) { @@ -530,19 +528,11 @@ public function getTemporaryPath() return $this->temporaryPath; } - /** - * Rollback a deployment - * - * @param bool $dryRun - * - * @throws SurfException - * @throws SurfException\InvalidConfigurationException - */ - public function rollback($dryRun = false) + public function rollback(bool $dryRun = false) { $this->logger->notice('Rollback deployment ' . $this->name . ' (' . $this->releaseIdentifier . ')'); - $this->setWorkflow(new RollbackWorkflow()); + $this->setWorkflow($this->container->get(RollbackWorkflow::class)); $this->initialize(); if ($dryRun) { $this->setDryRun(true); diff --git a/src/Domain/Model/SimpleWorkflow.php b/src/Domain/Model/SimpleWorkflow.php index 0c086b35..807ec431 100644 --- a/src/Domain/Model/SimpleWorkflow.php +++ b/src/Domain/Model/SimpleWorkflow.php @@ -119,10 +119,7 @@ public function run(Deployment $deployment) } } - /** - * @return string - */ - public function getName() + public function getName(): string { return 'Simple workflow'; } diff --git a/src/Domain/Model/Workflow.php b/src/Domain/Model/Workflow.php index 3676a2dd..4548e0b5 100644 --- a/src/Domain/Model/Workflow.php +++ b/src/Domain/Model/Workflow.php @@ -27,9 +27,9 @@ abstract class Workflow */ protected $tasks = []; - public function __construct(TaskManager $taskManager = null) + public function __construct(TaskManager $taskManager) { - $this->taskManager = $taskManager ?: new TaskManager(); + $this->taskManager = $taskManager; } public function run(Deployment $deployment) diff --git a/src/Domain/Service/ShellCommandServiceAwareInterface.php b/src/Domain/Service/ShellCommandServiceAwareInterface.php index c9799547..0997ed5d 100644 --- a/src/Domain/Service/ShellCommandServiceAwareInterface.php +++ b/src/Domain/Service/ShellCommandServiceAwareInterface.php @@ -12,5 +12,5 @@ */ interface ShellCommandServiceAwareInterface { - public function setShellCommandService(ShellCommandService $shellCommandService); + public function setShellCommandService(ShellCommandService $shellCommandService): void; } diff --git a/src/Domain/Service/ShellCommandServiceAwareTrait.php b/src/Domain/Service/ShellCommandServiceAwareTrait.php index b22040a4..7efbd2c7 100644 --- a/src/Domain/Service/ShellCommandServiceAwareTrait.php +++ b/src/Domain/Service/ShellCommandServiceAwareTrait.php @@ -17,7 +17,7 @@ trait ShellCommandServiceAwareTrait */ protected $shell; - public function setShellCommandService(ShellCommandService $shellCommandService) + public function setShellCommandService(ShellCommandService $shellCommandService): void { $this->shell = $shellCommandService; } diff --git a/src/Domain/Service/TaskFactory.php b/src/Domain/Service/TaskFactory.php index 718d5034..0293659a 100644 --- a/src/Domain/Service/TaskFactory.php +++ b/src/Domain/Service/TaskFactory.php @@ -10,14 +10,18 @@ * file that was distributed with this source code. */ +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; use TYPO3\Surf\Domain\Model\Task; use TYPO3\Surf\Exception as SurfException; /** * @final */ -class TaskFactory +class TaskFactory implements ContainerAwareInterface { + use ContainerAwareTrait; + /** * Create a task instance from the given task name * @@ -25,25 +29,12 @@ class TaskFactory */ public function createTaskInstance(string $taskName) { - $taskClassName = $this->mapTaskNameToTaskClass($taskName); - $task = new $taskClassName(); + $task = $this->container->get($taskName); if (!$task instanceof Task) { throw new SurfException(sprintf('The task %s is not a subclass of %s but of class %s', $taskName, Task::class, get_class($task)), 1451210811); } - if ($task instanceof ShellCommandServiceAwareInterface) { - $task->setShellCommandService(new ShellCommandService()); - } return $task; } - - private function mapTaskNameToTaskClass(string $taskName): string - { - if (!class_exists($taskName)) { - throw new SurfException(sprintf('No task found for identifier "%s". Make sure this is a valid class name or a defined task with valid base class name!', $taskName), 1451210811); - } - - return $taskName; - } } diff --git a/src/Domain/Service/TaskManager.php b/src/Domain/Service/TaskManager.php index 038beb9a..a6824f5e 100644 --- a/src/Domain/Service/TaskManager.php +++ b/src/Domain/Service/TaskManager.php @@ -11,7 +11,6 @@ use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; use TYPO3\Surf\Domain\Model\Node; -use TYPO3\Surf\Domain\Model\Task; use TYPO3\Surf\Domain\Model\TaskInHistory; /** @@ -29,9 +28,9 @@ class TaskManager */ private $taskFactory; - public function __construct(TaskFactory $taskFactory = null) + public function __construct(TaskFactory $taskFactory) { - $this->taskFactory = $taskFactory ?? new TaskFactory(); + $this->taskFactory = $taskFactory; } public function execute(string $taskName, Node $node, Application $application, Deployment $deployment, $stage, array $options = [], string $definedTaskName = ''): void diff --git a/src/Integration/Factory.php b/src/Integration/Factory.php index a64492fd..788a8657 100644 --- a/src/Integration/Factory.php +++ b/src/Integration/Factory.php @@ -11,34 +11,27 @@ use Monolog\Handler\StreamHandler; use Monolog\Logger; -use Psr\Log\LoggerInterface; use RuntimeException; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; use TYPO3\Flow\Utility\Files; -use TYPO3\Surf\Cli\Symfony\Logger\ConsoleHandler; -use TYPO3\Surf\Command\DeployCommand; -use TYPO3\Surf\Command\DescribeCommand; -use TYPO3\Surf\Command\RollbackCommand; -use TYPO3\Surf\Command\SelfUpdateCommand; -use TYPO3\Surf\Command\ShowCommand; -use TYPO3\Surf\Command\SimulateCommand; -use TYPO3\Surf\Domain\Filesystem\Filesystem; use TYPO3\Surf\Domain\Filesystem\FilesystemInterface; use TYPO3\Surf\Domain\Model\Deployment; use TYPO3\Surf\Domain\Model\FailedDeployment; use TYPO3\Surf\Exception\InvalidConfigurationException; -class Factory implements FactoryInterface +class Factory implements FactoryInterface, ContainerAwareInterface { + use ContainerAwareTrait; + /** * @var OutputInterface */ protected $output; /** - * @var LoggerInterface + * @var Logger */ protected $logger; @@ -47,43 +40,10 @@ class Factory implements FactoryInterface */ protected $filesystem; - public function __construct(FilesystemInterface $filesystem = null) - { - $this->filesystem = $filesystem ?? new Filesystem(); - } - - /** - * @inheritDoc - */ - public function createCommands(): array - { - return [ - new ShowCommand(), - new SimulateCommand(), - new DescribeCommand(), - new DeployCommand(), - new RollbackCommand(), - new SelfUpdateCommand(), - ]; - } - - public function createOutput(): OutputInterface + public function __construct(FilesystemInterface $filesystem, Logger $logger) { - if ($this->output === null) { - $this->output = new ConsoleOutput(); - $this->output->getFormatter()->setStyle('b', new OutputFormatterStyle(null, null, ['bold'])); - $this->output->getFormatter()->setStyle('i', new OutputFormatterStyle('black', 'white')); - $this->output->getFormatter()->setStyle('u', new OutputFormatterStyle(null, null, ['underscore'])); - $this->output->getFormatter()->setStyle('em', new OutputFormatterStyle(null, null, ['reverse'])); - $this->output->getFormatter()->setStyle('strike', new OutputFormatterStyle(null, null, ['conceal'])); - $this->output->getFormatter()->setStyle('success', new OutputFormatterStyle('green')); - $this->output->getFormatter()->setStyle('warning', new OutputFormatterStyle('black', 'yellow')); - $this->output->getFormatter()->setStyle('notice', new OutputFormatterStyle('yellow')); - $this->output->getFormatter()->setStyle('info', new OutputFormatterStyle('white', null, ['bold'])); - $this->output->getFormatter()->setStyle('debug', new OutputFormatterStyle('white')); - } - - return $this->output; + $this->filesystem = $filesystem; + $this->logger = $logger; } public function getDeployment(string $deploymentName, string $configurationPath = null, bool $simulateDeployment = true, bool $initialize = true, bool $forceDeployment = false): Deployment @@ -92,9 +52,9 @@ public function getDeployment(string $deploymentName, string $configurationPath if ($deployment->getLogger() === null) { if (! $simulateDeployment) { $logFilePath = Files::concatenatePaths([$this->getWorkspacesBasePath($configurationPath), 'logs', $deployment->getName() . '.log']); - $this->createLogger()->pushHandler(new StreamHandler($logFilePath)); + $this->logger()->pushHandler(new StreamHandler($logFilePath)); } - $deployment->setLogger($this->createLogger()); + $deployment->setLogger($this->logger()); } $deployment->setForceRun($forceDeployment); @@ -190,6 +150,7 @@ protected function createDeployment(string $deploymentName, string $path = null) $deploymentPathAndFilename = Files::concatenatePaths([$deploymentConfigurationPath, $deploymentName . '.php']); if ($this->filesystem->fileExists($deploymentPathAndFilename)) { $deployment = new Deployment($deploymentName); + $deployment->setContainer($this->container); $deployment->setDeploymentBasePath($deploymentConfigurationPath); $deployment->setWorkspacesBasePath($workspacesBasePath); $tempPath = Files::concatenatePaths([$workspacesBasePath, $deploymentName]); @@ -198,7 +159,7 @@ protected function createDeployment(string $deploymentName, string $path = null) require($deploymentPathAndFilename); } else { - $this->createLogger()->error(sprintf("The deployment file %s does not exist.\n", $deploymentPathAndFilename)); + $this->logger()->error(sprintf("The deployment file %s does not exist.\n", $deploymentPathAndFilename)); $deployment = new FailedDeployment(); } @@ -235,13 +196,8 @@ protected function getHomeDirectory(): string return $home; } - protected function createLogger(): Logger + protected function logger(): Logger { - if ($this->logger === null) { - $consoleHandler = new ConsoleHandler($this->createOutput()); - $this->logger = new Logger('TYPO3 Surf', [$consoleHandler]); - } - return $this->logger; } diff --git a/src/Integration/FactoryAwareInterface.php b/src/Integration/FactoryAwareInterface.php deleted file mode 100644 index 300c0920..00000000 --- a/src/Integration/FactoryAwareInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -factory = $factory; - } -} diff --git a/src/Integration/FactoryInterface.php b/src/Integration/FactoryInterface.php index 87bad8d6..c53e3ef8 100644 --- a/src/Integration/FactoryInterface.php +++ b/src/Integration/FactoryInterface.php @@ -8,19 +8,10 @@ * file that was distributed with this source code. */ -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Output\OutputInterface; use TYPO3\Surf\Domain\Model\Deployment; interface FactoryInterface { - /** - * @return Command[] - */ - public function createCommands(): array; - - public function createOutput(): OutputInterface; - public function getDeployment(string $deploymentName, string $configurationPath = null, bool $simulateDeployment = true, bool $initialize = true, bool $forceDeployment = false): Deployment; /** diff --git a/src/Task/CleanupReleasesTask.php b/src/Task/CleanupReleasesTask.php index 8be4afc7..acb25082 100644 --- a/src/Task/CleanupReleasesTask.php +++ b/src/Task/CleanupReleasesTask.php @@ -48,12 +48,8 @@ class CleanupReleasesTask extends Task implements ShellCommandServiceAwareInterf */ private $clock; - public function __construct(ClockInterface $clock = null) + public function __construct(ClockInterface $clock) { - if (null === $clock) { - $clock = new SystemClock(); - } - $this->clock = $clock; } diff --git a/src/Task/CreateArchiveTask.php b/src/Task/CreateArchiveTask.php index ad1e9a90..6e68b2d8 100644 --- a/src/Task/CreateArchiveTask.php +++ b/src/Task/CreateArchiveTask.php @@ -10,9 +10,7 @@ */ use Symfony\Component\OptionsResolver\OptionsResolver; -use TYPO3\Surf\Domain\Filesystem\Filesystem; use TYPO3\Surf\Domain\Filesystem\FilesystemInterface; -use TYPO3\Surf\Domain\Generator\IdGenerator; use TYPO3\Surf\Domain\Generator\IdGeneratorInterface; use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; @@ -62,10 +60,10 @@ class CreateArchiveTask extends Task implements ShellCommandServiceAwareInterfac */ private $idGenerator; - public function __construct(FilesystemInterface $filesystem = null, IdGeneratorInterface $idGenerator = null) + public function __construct(FilesystemInterface $filesystem, IdGeneratorInterface $idGenerator) { - $this->filesystem = $filesystem ?? new Filesystem(); - $this->idGenerator = $idGenerator ?? new IdGenerator(); + $this->filesystem = $filesystem; + $this->idGenerator = $idGenerator; } public function execute(Node $node, Application $application, Deployment $deployment, array $options = []) diff --git a/src/Task/Php/WebOpcacheResetCreateScriptTask.php b/src/Task/Php/WebOpcacheResetCreateScriptTask.php index 647057db..53ad656e 100644 --- a/src/Task/Php/WebOpcacheResetCreateScriptTask.php +++ b/src/Task/Php/WebOpcacheResetCreateScriptTask.php @@ -10,9 +10,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use TYPO3\Flow\Utility\Files; -use TYPO3\Surf\Domain\Filesystem\Filesystem; use TYPO3\Surf\Domain\Filesystem\FilesystemInterface; -use TYPO3\Surf\Domain\Generator\RandomBytesGenerator; use TYPO3\Surf\Domain\Generator\RandomBytesGeneratorInterface; use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; @@ -57,16 +55,8 @@ class WebOpcacheResetCreateScriptTask extends Task implements ShellCommandServic */ private $filesystem; - public function __construct(RandomBytesGeneratorInterface $randomBytesGenerator = null, FilesystemInterface $filesystem = null) + public function __construct(RandomBytesGeneratorInterface $randomBytesGenerator, FilesystemInterface $filesystem) { - if (! $randomBytesGenerator instanceof RandomBytesGeneratorInterface) { - $randomBytesGenerator = new RandomBytesGenerator(); - } - - if (! $filesystem instanceof FilesystemInterface) { - $filesystem = new Filesystem(); - } - $this->filesystem = $filesystem; $this->randomBytesGenerator = $randomBytesGenerator; } diff --git a/src/Task/Php/WebOpcacheResetExecuteTask.php b/src/Task/Php/WebOpcacheResetExecuteTask.php index ebd2eaee..17a03cb7 100644 --- a/src/Task/Php/WebOpcacheResetExecuteTask.php +++ b/src/Task/Php/WebOpcacheResetExecuteTask.php @@ -11,7 +11,6 @@ use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; -use TYPO3\Surf\Domain\Filesystem\Filesystem; use TYPO3\Surf\Domain\Filesystem\FilesystemInterface; use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; @@ -49,12 +48,8 @@ class WebOpcacheResetExecuteTask extends Task */ private $filesystem; - public function __construct(FilesystemInterface $filesystem = null) + public function __construct(FilesystemInterface $filesystem) { - if (! $filesystem instanceof FilesystemInterface) { - $filesystem = new Filesystem(); - } - $this->filesystem = $filesystem; } diff --git a/src/Task/Test/HttpTestTask.php b/src/Task/Test/HttpTestTask.php index be414ad1..8d13ed4b 100644 --- a/src/Task/Test/HttpTestTask.php +++ b/src/Task/Test/HttpTestTask.php @@ -39,16 +39,8 @@ class HttpTestTask extends Task implements ShellCommandServiceAwareInterface */ private $client; - /** - * HttpTestTask constructor. - * - * @param ClientInterface|null $client - */ - public function __construct(ClientInterface $client = null) + public function __construct(ClientInterface $client) { - if (! $client instanceof ClientInterface) { - $client = new Client(); - } $this->client = $client; } diff --git a/tests/Unit/Application/Neos/FlowTest.php b/tests/Unit/Application/Neos/FlowTest.php index 4347e773..07382850 100644 --- a/tests/Unit/Application/Neos/FlowTest.php +++ b/tests/Unit/Application/Neos/FlowTest.php @@ -13,6 +13,7 @@ use TYPO3\Surf\Application\Neos\Flow; use TYPO3\Surf\Domain\Model\Deployment; use TYPO3\Surf\Domain\Model\SimpleWorkflow; +use TYPO3\Surf\Domain\Service\TaskManager; use TYPO3\Surf\Task\Composer\InstallTask; class FlowTest extends TestCase @@ -90,7 +91,7 @@ public function getFlowScriptName(string $version, string $expectedFlowScriptNam public function registerComposerInstallTask(): void { $deployment = $this->prophesize(Deployment::class); - $workflow = new SimpleWorkflow(); + $workflow = new SimpleWorkflow($this->prophesize(TaskManager::class)->reveal()); $this->subject->setOption('updateMethod', 'composer'); $this->subject->registerTasks($workflow, $deployment->reveal()); $tasks = $workflow->getTasks(); diff --git a/tests/Unit/Command/DeployCommandTest.php b/tests/Unit/Command/DeployCommandTest.php index 572600b2..9ff182ac 100644 --- a/tests/Unit/Command/DeployCommandTest.php +++ b/tests/Unit/Command/DeployCommandTest.php @@ -10,60 +10,46 @@ */ use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; +use Prophecy\Argument; +use Prophecy\Prophecy\ObjectProphecy; use Symfony\Component\Console\Tester\CommandTester; use TYPO3\Surf\Command\DeployCommand; -use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; -use TYPO3\Surf\Domain\Model\Node; use TYPO3\Surf\Integration\FactoryInterface; final class DeployCommandTest extends TestCase { /** - * @var Node + * @var DeployCommand */ - protected $node; + protected $subject; /** - * @var Application + * @var FactoryInterface|ObjectProphecy */ - protected $application; - - /** - * @var Deployment - */ - protected $deployment; + private $factory; protected function setUp() { - $this->node = new Node('TestNode'); - $this->node->setHostname('hostname'); - $this->deployment = new Deployment('TestDeployment'); - $this->application = new Application('TestApplication'); - $this->application->addNode($this->node); - $this->deployment->addApplication($this->application); - $this->deployment->initialize(); - $this->deployment->setLogger($this->createMock(LoggerInterface::class)); + $this->factory = $this->prophesize(FactoryInterface::class); + $this->subject = new DeployCommand($this->factory->reveal()); } /** * @test */ - public function executeForceRun() + public function executeForceRun(): void { - $factory = $this->createMock(FactoryInterface::class); - $factory->expects($this->once())->method('getDeployment')->willReturn($this->deployment); - $command = new DeployCommand(); - $command->setFactory($factory); - $commandTester = new CommandTester($command); + $deployment = $this->prophesize(Deployment::class); + $deployment->deploy()->shouldBeCalledOnce(); + $deployment->getStatus()->willReturn(Deployment::STATUS_SUCCESS); + $this->factory->getDeployment('Foo', Argument::exact(null), Argument::exact(false), Argument::exact(true), Argument::exact(true))->willReturn($deployment); + + $commandTester = new CommandTester($this->subject); $commandTester->execute([ - 'deploymentName' => $this->deployment->getName(), + 'deploymentName' => 'Foo', '--force' => true, ]); - $this->deployment->setForceRun(true); - $this->assertEquals($this->deployment->getStatus(), Deployment::STATUS_SUCCESS); - $this->assertTrue($this->deployment->getForceRun()); } } diff --git a/tests/Unit/Command/DescribeCommandTest.php b/tests/Unit/Command/DescribeCommandTest.php index 3f5c324d..3afd3d7e 100644 --- a/tests/Unit/Command/DescribeCommandTest.php +++ b/tests/Unit/Command/DescribeCommandTest.php @@ -23,9 +23,11 @@ use TYPO3\Surf\Task\LocalShellTask; use TYPO3\Surf\Task\Transfer\RsyncTask; use TYPO3\Surf\Task\TYPO3\CMS\FlushCachesTask; +use TYPO3\Surf\Tests\Unit\KernelAwareTrait; class DescribeCommandTest extends TestCase { + use KernelAwareTrait; /** * @var Deployment @@ -45,11 +47,12 @@ class DescribeCommandTest extends TestCase protected function setUp() { $this->deployment = new Deployment('TestDeployment'); + $this->deployment->setContainer(static::getKernel()->getContainer()); $this->node = new Node('TestNode'); $this->node->setHostname('hostname'); } - protected function setUpCustomApplication() + protected function setUpCustomApplication(): void { $this->application = new Application('TestApplication'); $this->application->setOption('rsyncExcludes', ['.git', 'web/fileadmin', 'web/uploads']); @@ -105,13 +108,12 @@ protected function setUpCustomApplication() * @test * @throws Exception */ - public function describeCustomApplication() + public function describeCustomApplication(): void { $this->setUpCustomApplication(); $factory = $this->createMock(FactoryInterface::class); $factory->expects($this->once())->method('getDeployment')->willReturn($this->deployment); - $command = new DescribeCommand(); - $command->setFactory($factory); + $command = new DescribeCommand($factory); $commandTester = new CommandTester($command); $commandTester->execute([ 'deploymentName' => $this->deployment->getName(), @@ -174,7 +176,7 @@ public function describeCustomApplication() * @return string * @throws Exception */ - protected function getDescriptionOfPredefinedApplication($application, $options = []) + protected function getDescriptionOfPredefinedApplication($application, $options = []): string { $this->application = $application; $this->application->addNode($this->node); @@ -184,8 +186,7 @@ protected function getDescriptionOfPredefinedApplication($application, $options $this->deployment->addApplication($this->application)->initialize(); $factory = $this->createMock(FactoryInterface::class); $factory->expects($this->once())->method('getDeployment')->willReturn($this->deployment); - $command = new DescribeCommand(); - $command->setFactory($factory); + $command = new DescribeCommand($factory); $commandTester = new CommandTester($command); $commandTester->execute([ 'deploymentName' => $this->deployment->getName(), @@ -196,7 +197,7 @@ protected function getDescriptionOfPredefinedApplication($application, $options /** * @test */ - public function describeTypo3Cms() + public function describeTypo3Cms(): void { $application = new CMS(); $application->addSymlink( @@ -282,7 +283,7 @@ public function describeTypo3Cms() /** * @test */ - public function describeNeosNeos() + public function describeNeosNeos(): void { $this->assertEquals('Deployment TestDeployment @@ -354,7 +355,7 @@ public function describeNeosNeos() /** * @test */ - public function describeBaseApplication() + public function describeBaseApplication(): void { $this->assertEquals('Deployment TestDeployment @@ -417,7 +418,7 @@ public function describeBaseApplication() /** * @test */ - public function describeBaseApplicationWithoutLock() + public function describeBaseApplicationWithoutLock(): void { $this->assertEquals('Deployment TestDeployment @@ -477,7 +478,7 @@ public function describeBaseApplicationWithoutLock() /** * @test */ - public function describeBaseApplicationWithForceParameter() + public function describeBaseApplicationWithForceParameter(): void { $this->deployment->setForceRun(true); $this->assertEquals('Deployment TestDeployment diff --git a/tests/Unit/Domain/Model/DeploymentTest.php b/tests/Unit/Domain/Model/DeploymentTest.php index 6c41f9d3..d0a7fbdd 100644 --- a/tests/Unit/Domain/Model/DeploymentTest.php +++ b/tests/Unit/Domain/Model/DeploymentTest.php @@ -14,19 +14,24 @@ use TYPO3\Surf\Domain\Model\Deployment; use TYPO3\Surf\Domain\Model\Node; use TYPO3\Surf\Domain\Model\SimpleWorkflow; +use TYPO3\Surf\Domain\Service\TaskManager; use TYPO3\Surf\Exception; +use TYPO3\Surf\Tests\Unit\KernelAwareTrait; /** * Unit test for Deployment */ class DeploymentTest extends TestCase { + use KernelAwareTrait; + /** * @test */ public function initializeUsesSimpleWorkflowAsDefault() { $deployment = new Deployment('Test deployment'); + $deployment->setContainer(static::getKernel()->getContainer()); $deployment->initialize(); $this->assertInstanceOf(SimpleWorkflow::class, $deployment->getWorkflow()); @@ -38,6 +43,7 @@ public function initializeUsesSimpleWorkflowAsDefault() public function getNodesReturnsNodesFromApplicationsAsSet() { $deployment = new Deployment('Test deployment'); + $deployment->setContainer(static::getKernel()->getContainer()); $application1 = new Application('Test application 1'); $application2 = new Application('Test application 2'); @@ -66,7 +72,7 @@ public function getNodesReturnsNodesFromApplicationsAsSet() public function constructorCreatesReleaseIdentifier() { $deployment = new Deployment('Test deployment'); - + $deployment->setContainer(static::getKernel()->getContainer()); $releaseIdentifier = $deployment->getReleaseIdentifier(); $this->assertNotEmpty($releaseIdentifier); } @@ -74,10 +80,10 @@ public function constructorCreatesReleaseIdentifier() /** * @test */ - public function initializeIsAllowedOnlyOnce() + public function initializeIsAllowedOnlyOnce(): void { $this->expectException(Exception::class); - $workflow = new SimpleWorkflow(); + $workflow = new SimpleWorkflow($this->prophesize(TaskManager::class)->reveal()); $deployment = new Deployment('Test deployment'); $deployment->setWorkflow($workflow); $deployment->initialize(); @@ -91,17 +97,17 @@ public function initializeIsAllowedOnlyOnce() * * @param mixed $deploymentLockIdentifier */ - public function deploymentHasDefaultLockIdentifierIfNoIdentifierIsGiven($deploymentLockIdentifier) + public function deploymentHasDefaultLockIdentifierIfNoIdentifierIsGiven($deploymentLockIdentifier): void { $deployment = new Deployment('Some name', $deploymentLockIdentifier); - + $deployment->setContainer(static::getKernel()->getContainer()); $this->assertEquals($deployment->getReleaseIdentifier(), $deployment->getDeploymentLockIdentifier()); } /** * @test */ - public function deploymentHasDefinedLockIdentifier() + public function deploymentHasDefinedLockIdentifier(): void { $deploymentLockIdentifier = 'Deployment lock identifier'; $deployment = new Deployment('Some name', $deploymentLockIdentifier); @@ -112,7 +118,7 @@ public function deploymentHasDefinedLockIdentifier() /** * @test */ - public function deploymentHasLockIdentifierDefinedByEnvironmentVariable() + public function deploymentHasLockIdentifierDefinedByEnvironmentVariable(): void { $deploymentLockIdentifier = 'Deployment lock identifier'; putenv(sprintf('SURF_DEPLOYMENT_LOCK_IDENTIFIER=%s', $deploymentLockIdentifier)); @@ -123,7 +129,7 @@ public function deploymentHasLockIdentifierDefinedByEnvironmentVariable() /** * @return array */ - public function wrongDeploymentLockIdentifiersProvided() + public function wrongDeploymentLockIdentifiersProvided(): array { return [ [null], diff --git a/tests/Unit/Domain/Service/TaskFactoryTest.php b/tests/Unit/Domain/Service/TaskFactoryTest.php index 18d036ab..8d650819 100644 --- a/tests/Unit/Domain/Service/TaskFactoryTest.php +++ b/tests/Unit/Domain/Service/TaskFactoryTest.php @@ -10,6 +10,8 @@ */ use PHPUnit\Framework\TestCase; +use Prophecy\Prophecy\ObjectProphecy; +use Symfony\Component\DependencyInjection\ContainerInterface; use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; use TYPO3\Surf\Domain\Model\Node; @@ -26,9 +28,16 @@ class TaskFactoryTest extends TestCase */ protected $subject; + /** + * @var ContainerInterface|ObjectProphecy + */ + private $container; + protected function setUp() { + $this->container = $this->prophesize(ContainerInterface::class); $this->subject = new TaskFactory(); + $this->subject->setContainer($this->container->reveal()); } /** @@ -37,10 +46,11 @@ protected function setUp() public function createTaskInstance(): void { $task = new class extends Task { - public function execute(Node $node, Application $application, Deployment $deployment, array $options = []) + public function execute(Node $node, Application $application, Deployment $deployment, array $options = []): void { } }; + $this->container->get(get_class($task))->willReturn($task); $this->assertEquals($task, $this->subject->createTaskInstance(get_class($task))); } @@ -51,27 +61,19 @@ public function execute(Node $node, Application $application, Deployment $deploy public function createTaskInstanceImplementingShellCommandServiceAwareInterface(): void { $task = new class extends Task implements ShellCommandServiceAwareInterface { - public function execute(Node $node, Application $application, Deployment $deployment, array $options = []) + public function execute(Node $node, Application $application, Deployment $deployment, array $options = []): void { } - public function setShellCommandService(ShellCommandService $shellCommandService) + public function setShellCommandService(ShellCommandService $shellCommandService): void { } }; + $this->container->get(get_class($task))->willReturn($task); $this->assertEquals($task, $this->subject->createTaskInstance(get_class($task))); } - /** - * @test - */ - public function createTaskInstanceThrowsExceptionClassDoesNotExist(): void - { - $this->expectException(SurfException::class); - $this->subject->createTaskInstance('SomeFooBarBaz'); - } - /** * @test */ @@ -79,7 +81,7 @@ public function createTaskInstanceThrowsExceptionClassIsNotOfCorrectSubclass(): { $task = new class { }; - + $this->container->get(get_class($task))->willReturn($task); $this->expectException(SurfException::class); $this->subject->createTaskInstance(get_class($task)); } diff --git a/tests/Unit/Integration/FactoryTest.php b/tests/Unit/Integration/FactoryTest.php index 78822b80..e07d03e6 100644 --- a/tests/Unit/Integration/FactoryTest.php +++ b/tests/Unit/Integration/FactoryTest.php @@ -9,17 +9,20 @@ * file that was distributed with this source code. */ +use Monolog\Logger; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; use RuntimeException; -use Symfony\Component\Console\Output\ConsoleOutput; use TYPO3\Surf\Domain\Filesystem\FilesystemInterface; use TYPO3\Surf\Exception\InvalidConfigurationException; use TYPO3\Surf\Integration\Factory; +use TYPO3\Surf\Tests\Unit\KernelAwareTrait; class FactoryTest extends TestCase { + use KernelAwareTrait; + /** * @var Factory */ @@ -40,26 +43,17 @@ class FactoryTest extends TestCase */ protected $runTestInSeparateProcess = true; - protected function setUp() - { - $this->filesystem = $this->prophesize(FilesystemInterface::class); - $this->subject = new Factory($this->filesystem->reveal()); - } - /** - * @test + * @var Logger|ObjectProphecy */ - public function createCommands(): void - { - $this->assertCount(6, $this->subject->createCommands()); - } + private $logger; - /** - * @test - */ - public function createOutput(): void + protected function setUp() { - $this->assertInstanceOf(ConsoleOutput::class, $this->subject->createOutput()); + $this->filesystem = $this->prophesize(FilesystemInterface::class); + $this->logger = $this->prophesize(Logger::class); + $this->subject = new Factory($this->filesystem->reveal(), $this->logger->reveal()); + $this->subject->setContainer(static::getKernel()->getContainer()); } /** diff --git a/tests/Unit/KernelAwareTrait.php b/tests/Unit/KernelAwareTrait.php new file mode 100644 index 00000000..9954691d --- /dev/null +++ b/tests/Unit/KernelAwareTrait.php @@ -0,0 +1,32 @@ +boot(); + static::$kernel = $kernel; + } + return static::$kernel; + } +} diff --git a/tests/Unit/Task/BaseTaskTest.php b/tests/Unit/Task/BaseTaskTest.php index 3c00a1fc..0fe47d20 100644 --- a/tests/Unit/Task/BaseTaskTest.php +++ b/tests/Unit/Task/BaseTaskTest.php @@ -18,12 +18,15 @@ use TYPO3\Surf\Domain\Service\ShellCommandService; use TYPO3\Surf\Domain\Service\ShellCommandServiceAwareInterface; use TYPO3\Surf\Tests\Unit\AssertCommandExecuted; +use TYPO3\Surf\Tests\Unit\KernelAwareTrait; /** * Base unit test for tasks */ abstract class BaseTaskTest extends TestCase { + use KernelAwareTrait; + /** * Executed commands * @var array @@ -106,6 +109,7 @@ protected function setUp() $this->node = new Node('TestNode'); $this->node->setHostname('hostname'); $this->deployment = new Deployment('TestDeployment'); + $this->deployment->setContainer(static::getKernel()->getContainer()); /** @var PHPUnit_Framework_MockObject_MockObject|\Psr\Log\LoggerInterface $mockLogger */ $this->mockLogger = $this->createMock(LoggerInterface::class); $this->deployment->setLogger($this->mockLogger); diff --git a/tests/Unit/Task/CleanupReleasesTaskTest.php b/tests/Unit/Task/CleanupReleasesTaskTest.php index 428bb964..fa7de848 100644 --- a/tests/Unit/Task/CleanupReleasesTaskTest.php +++ b/tests/Unit/Task/CleanupReleasesTaskTest.php @@ -18,9 +18,12 @@ use TYPO3\Surf\Domain\Service\ShellCommandService; use TYPO3\Surf\Domain\Service\ShellCommandServiceAwareInterface; use TYPO3\Surf\Task\CleanupReleasesTask; +use TYPO3\Surf\Tests\Unit\KernelAwareTrait; class CleanupReleasesTaskTest extends BaseTaskTest { + use KernelAwareTrait; + /** * @var PHPUnit_Framework_MockObject_MockObject|ShellCommandService $shellCommandService */ @@ -48,6 +51,7 @@ protected function setUp() $this->node = new Node('TestNode'); $this->node->setHostname('hostname'); $this->deployment = new Deployment('TestDeployment'); + $this->deployment->setContainer(static::getKernel()->getContainer()); /** @var PHPUnit_Framework_MockObject_MockObject|\Psr\Log\LoggerInterface $mockLogger */ $mockLogger = $this->createMock(LoggerInterface::class); $this->deployment->setLogger($mockLogger); diff --git a/tests/Unit/Task/Test/HttpTestTaskTest.php b/tests/Unit/Task/Test/HttpTestTaskTest.php index 96b17459..53a2e6ff 100644 --- a/tests/Unit/Task/Test/HttpTestTaskTest.php +++ b/tests/Unit/Task/Test/HttpTestTaskTest.php @@ -153,7 +153,7 @@ public function responseBodyDoesNotContainsCorrectContent(): void */ protected function createTask() { - return new HttpTestTask(); + return new HttpTestTask(new Client()); } protected function assertNoExceptionThrown(array $options): void