From c8606e42e72058c5f9867753b7114146ac27f9e9 Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Thu, 31 Jan 2019 11:15:25 -0600 Subject: [PATCH 1/9] General improvements --- bin/magento | 15 + bootstrap.php | 18 + composer.json | 11 +- composer.lock | 1054 +++++++++++++++++++++++++++++- dist/manage.php | 74 +++ magento | 78 --- src/Application.php | 105 +++ src/Application/ErrorHandler.php | 66 ++ src/Command/Context.php | 27 - src/Command/Context/Add.php | 93 ++- src/Command/Context/Get.php | 43 +- src/Command/Context/GetList.php | 56 +- src/Command/Context/Load.php | 27 - src/Command/Context/Remove.php | 53 +- src/Command/Context/Set.php | 49 +- src/Command/Remote.php | 47 +- src/Config/Reader.php | 25 + src/Config/Writer.php | 18 + src/ContextList.php | 123 ++-- 19 files changed, 1748 insertions(+), 234 deletions(-) create mode 100755 bin/magento create mode 100644 bootstrap.php create mode 100644 dist/manage.php delete mode 100755 magento create mode 100644 src/Application.php create mode 100644 src/Application/ErrorHandler.php delete mode 100644 src/Command/Context.php delete mode 100644 src/Command/Context/Load.php create mode 100644 src/Config/Reader.php create mode 100644 src/Config/Writer.php diff --git a/bin/magento b/bin/magento new file mode 100755 index 0000000..19c9cf6 --- /dev/null +++ b/bin/magento @@ -0,0 +1,15 @@ +#!/usr/bin/env php +make(\Magento\Console\Application::class, [ + 'container' => $container +])->run(); diff --git a/bootstrap.php b/bootstrap.php new file mode 100644 index 0000000..09fd1b4 --- /dev/null +++ b/bootstrap.php @@ -0,0 +1,18 @@ +=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "9f83dded91781a01c63574e387eaa769be769115" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2018-12-04T20:46:45+00:00" + }, + { + "name": "illuminate/config", + "version": "v5.7.21", + "source": { + "type": "git", + "url": "https://github.com/illuminate/config.git", + "reference": "08b6e422d62602ee5263ca2113e9f3d800e905a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/config/zipball/08b6e422d62602ee5263ca2113e9f3d800e905a4", + "reference": "08b6e422d62602ee5263ca2113e9f3d800e905a4", + "shasum": "" + }, + "require": { + "illuminate/contracts": "5.7.*", + "illuminate/support": "5.7.*", + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Config\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Config package.", + "homepage": "https://laravel.com", + "time": "2018-10-06T18:48:42+00:00" + }, + { + "name": "illuminate/container", + "version": "v5.7.20", + "source": { + "type": "git", + "url": "https://github.com/illuminate/container.git", + "reference": "53a0991e918efaace42cde526a04fdb832128a03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/container/zipball/53a0991e918efaace42cde526a04fdb832128a03", + "reference": "53a0991e918efaace42cde526a04fdb832128a03", + "shasum": "" + }, + "require": { + "illuminate/contracts": "5.7.*", + "illuminate/support": "5.7.*", + "php": "^7.1.3", + "psr/container": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Container\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Container package.", + "homepage": "https://laravel.com", + "time": "2018-12-18T14:00:02+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v5.7.20", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "758927e5e925c1d442a1faaa1356675ceba0194c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/758927e5e925c1d442a1faaa1356675ceba0194c", + "reference": "758927e5e925c1d442a1faaa1356675ceba0194c", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/container": "^1.0", + "psr/simple-cache": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "time": "2018-11-15T13:49:08+00:00" + }, + { + "name": "illuminate/filesystem", + "version": "v5.7.20", + "source": { + "type": "git", + "url": "https://github.com/illuminate/filesystem.git", + "reference": "19ba2ac5f85b7505d7c2bf6307d10633f9f3c6b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/filesystem/zipball/19ba2ac5f85b7505d7c2bf6307d10633f9f3c6b0", + "reference": "19ba2ac5f85b7505d7c2bf6307d10633f9f3c6b0", + "shasum": "" + }, + "require": { + "illuminate/contracts": "5.7.*", + "illuminate/support": "5.7.*", + "php": "^7.1.3", + "symfony/finder": "^4.1" + }, + "suggest": { + "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", + "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (^1.0).", + "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Filesystem\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Filesystem package.", + "homepage": "https://laravel.com", + "time": "2018-12-28T14:33:29+00:00" + }, + { + "name": "illuminate/support", + "version": "v5.7.20", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "ea3f30dd824bba52bcff4290dc7431b0ffb478e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/ea3f30dd824bba52bcff4290dc7431b0ffb478e1", + "reference": "ea3f30dd824bba52bcff4290dc7431b0ffb478e1", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^1.1", + "ext-mbstring": "*", + "illuminate/contracts": "5.7.*", + "nesbot/carbon": "^1.26.3", + "php": "^7.1.3" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "suggest": { + "illuminate/filesystem": "Required to use the composer class (5.7.*).", + "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "ramsey/uuid": "Required to use Str::uuid() (^3.7).", + "symfony/process": "Required to use the composer class (^4.1).", + "symfony/var-dumper": "Required to use the dd function (^4.1)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.7-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + }, + "files": [ + "helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "time": "2019-01-07T13:39:07+00:00" + }, + { + "name": "nesbot/carbon", + "version": "1.36.2", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9", + "reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/translation": "~2.6 || ~3.0 || ~4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7" + }, + "suggest": { + "friendsofphp/php-cs-fixer": "Needed for the `composer phpcs` command. Allow to automatically fix code style.", + "phpstan/phpstan": "Needed for the `composer phpstan` command. Allow to detect potential errors." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2018-12-28T10:07:33+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" + }, { "name": "symfony/console", "version": "v4.1.3", @@ -74,6 +813,181 @@ "homepage": "https://symfony.com", "time": "2018-07-26T11:24:31+00:00" }, + { + "name": "symfony/contracts", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "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": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "9094d69e8c6ee3fe186a0ec5a4f1401e506071ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/9094d69e8c6ee3fe186a0ec5a4f1401e506071ce", + "reference": "9094d69e8c6ee3fe186a0ec5a4f1401e506071ce", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "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 Finder Component", + "homepage": "https://symfony.com", + "time": "2019-01-03T09:07:35+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-08-06T14:22:27+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.9.0", @@ -132,6 +1046,138 @@ "shim" ], "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/translation", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "939fb792d73f2ce80e6ae9019d205fc480f1c9a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/939fb792d73f2ce80e6ae9019d205fc480f1c9a0", + "reference": "939fb792d73f2ce80e6ae9019d205fc480f1c9a0", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0.2", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "symfony/translation-contracts-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "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 Translation Component", + "homepage": "https://symfony.com", + "time": "2019-01-03T09:07:35+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "d0aa6c0ea484087927b49fd513383a7d36190ca6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d0aa6c0ea484087927b49fd513383a7d36190ca6", + "reference": "d0aa6c0ea484087927b49fd513383a7d36190ca6", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "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 Yaml Component", + "homepage": "https://symfony.com", + "time": "2019-01-03T09:07:35+00:00" } ], "packages-dev": [], @@ -140,6 +1186,10 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "^7.1.3", + "ext-json": "*", + "ext-curl": "*" + }, "platform-dev": [] } diff --git a/dist/manage.php b/dist/manage.php new file mode 100644 index 0000000..f1eba8d --- /dev/null +++ b/dist/manage.php @@ -0,0 +1,74 @@ +getMessage(); + exit(1); +} +ini_set('error_reporting', -1); +ini_set('display_errors', 'on'); +try { + $handler = new \Magento\Framework\App\ErrorHandler(); + set_error_handler([$handler, 'handler']); + $application = new Magento\Framework\Console\Cli('Magento CLI'); + if (isset($_GET['config'])) { + $output = new \Symfony\Component\Console\Output\BufferedOutput(); + $commands = array_map(function ($item) { + $arguments = array_map(function ($argument) { + return [ + 'name' => $argument->getName(), + 'description' => $argument->getDescription(), + 'is_array' => $argument->isArray(), + 'is_requied' => $argument->isRequired(), + 'default' => $argument->getDefault() + ]; + }, + $item->getDefinition()->getArguments() + ); + $options = array_map(function ($argument) { + return [ + 'name' => $argument->getName(), + 'description' => $argument->getDescription(), + 'shortcut' => $argument->getShortcut(), + 'default' => $argument->getDefault() + ]; + }, + $item->getDefinition()->getOptions() + ); + + return [ + 'name' => $item->getName(), + 'description' => $item->getDescription(), + 'help' => $item->getHelp(), + 'usages' => $item->getUsages(), + 'definition' => [ + 'options' => $options, + 'arguments' => $arguments + ] + ]; + }, $application->getApplicationCommands()); + echo json_encode($commands); + } else { + $inputArgs = json_decode($_POST); + $input = new \Symfony\Component\Console\Input\ArrayInput($inputArgs['arguments']); + array_walk($inputArgs['optinos'], function ($value, $key) use ($input) { + $input->setOption($key, $value); + }); + $output = new \Symfony\Component\Console\Output\StreamOutput(fopen('php://output', 'w')); + $application->setAutoExit(false); + $application->run($input, $output); + } +} catch (\Exception $e) { + while ($e) { + echo $e->getMessage(); + echo $e->getTraceAsString(); + echo "\n\n"; + $e = $e->getPrevious(); + } + exit(Magento\Framework\Console\Cli::RETURN_FAILURE); +} diff --git a/magento b/magento deleted file mode 100755 index f70ae3b..0000000 --- a/magento +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env php - $url, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FOLLOWLOCATION => true - ]); - $result = curl_exec($ch); - curl_close($ch); - return $result; -} - -$app = new Application(); -$contextList = new \Magento\Console\ContextList($homeDir); -$commands = [ - 'context' => new ContextCommand\Get($contextList), - 'context:load' => new ContextCommand\Load($contextList), - 'context:list' => new ContextCommand\GetList($contextList), - 'context:add' => new ContextCommand\Add($contextList), - 'context:remove' => new ContextCommand\Remove($contextList), - 'context:set' => new ContextCommand\Set($contextList), -]; - -if ($contextList->getCurrent()) { - $contextData = $contextList->read()[$contextList->getCurrent()]; - if (isset($contextData->commands)) { - foreach ($contextData->commands as $name => $commandData) { - $command = new \Magento\Console\Command\Remote($contextData); - $command->setDescription($commandData->description) - ->setHelp($commandData->help); - foreach ($commandData->definition->arguments as $argumentName => $argumentMeta) { - $command->addArgument( - $argumentName, - $argumentMeta->is_required ? InputArgument::REQUIRED : InputArgument::OPTIONAL, - $argumentMeta->description, - $argumentMeta->default - ); - } - foreach ($commandData->definition->options as $argumentName => $argumentMeta) { - $command->addOption( - $argumentName, - $argumentMeta->shortcut, - $argumentMeta->is_required ? InputOption::VALUE_REQUIRED : InputOption::VALUE_OPTIONAL, - $argumentMeta->description, - $argumentMeta->default - ); - } - - $commands[$commandData->name] = $command; - } - } -} - -array_walk($commands, function ($command, $name) use ($app) { - $command->setName($name); - $app->add($command); -}); - -$app->run(); diff --git a/src/Application.php b/src/Application.php new file mode 100644 index 0000000..8374dcc --- /dev/null +++ b/src/Application.php @@ -0,0 +1,105 @@ +container = $container; + $this->contextList = $contextList; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function getDefaultCommands(): array + { + $stdCommands = [ + $this->container->make(Command\Context\Get::class), + $this->container->make(Command\Context\Get::class), + $this->container->make(Command\Context\GetList::class), + $this->container->make(Command\Context\Add::class), + $this->container->make(Command\Context\Remove::class), + $this->container->make(Command\Context\Set::class) + ]; + $magentoCommands = $this->fetchMagentoCommands(); + + + return array_merge( + parent::getDefaultCommands(), + $stdCommands, + $magentoCommands + ); + } + + /** + * @return array + */ + private function fetchMagentoCommands(): array + { + $context = $this->contextList->getCurrent(); + + if (!$context) { + return []; + } + + $commands = []; + + foreach ($context->get('commands') as $data) { + /** @var Command\Remote $command */ + $command = $this->container->make(Command\Remote::class); + $command->setName($data['name']) + ->setDescription($data['description']) + ->setHelp($data['help']); + + foreach ($data['definition']['arguments'] as $aName => $aData) { + $command->addArgument( + $aName, + $aData['mode'] ?? InputArgument::OPTIONAL, + $aData['description'] ?? '' + ); + } + + foreach ($data['definition']['options'] as $oName => $oData) { + $command->addOption( + $oName, + $oData['shortcut'] ?? null, + $oData['mode'] ?? InputOption::VALUE_OPTIONAL, + $oData['description'] ?? '' + ); + } + + $commands[] = $command; + } + + return $commands; + } +} diff --git a/src/Application/ErrorHandler.php b/src/Application/ErrorHandler.php new file mode 100644 index 0000000..dbb3a1c --- /dev/null +++ b/src/Application/ErrorHandler.php @@ -0,0 +1,66 @@ + 'Error', + E_WARNING => 'Warning', + E_PARSE => 'Parse Error', + E_NOTICE => 'Notice', + E_CORE_ERROR => 'Core Error', + E_CORE_WARNING => 'Core Warning', + E_COMPILE_ERROR => 'Compile Error', + E_COMPILE_WARNING => 'Compile Warning', + E_USER_ERROR => 'User Error', + E_USER_WARNING => 'User Warning', + E_USER_NOTICE => 'User Notice', + E_STRICT => 'Strict Notice', + E_RECOVERABLE_ERROR => 'Recoverable Error', + E_DEPRECATED => 'Deprecated Functionality', + E_USER_DEPRECATED => 'User Deprecated Functionality', + ]; + + /** + * Custom error handler. + * + * @param int $errorNo + * @param string $errorStr + * @param string $errorFile + * @param int $errorLine + * @return bool + * @throws \RuntimeException + */ + public function handle(int $errorNo, string $errorStr, string $errorFile, int $errorLine): bool + { + if (strpos($errorStr, 'DateTimeZone::__construct') !== false) { + /** + * There's no way to distinguish between caught system exceptions and warnings. + */ + return false; + } + + $errorNo &= error_reporting(); + + if ($errorNo === 0) { + return false; + } + + $msg = self::$errorPhrases[$errorNo] ?? "Unknown error ({$errorNo})"; + $msg .= ": {$errorStr} in {$errorFile} on line {$errorLine}"; + + throw new \RuntimeException($msg); + } +} diff --git a/src/Command/Context.php b/src/Command/Context.php deleted file mode 100644 index 5f500d1..0000000 --- a/src/Command/Context.php +++ /dev/null @@ -1,27 +0,0 @@ -contextList = $contextList; - parent::__construct(); - } -} \ No newline at end of file diff --git a/src/Command/Context/Add.php b/src/Command/Context/Add.php index 0dffc74..18cebe2 100644 --- a/src/Command/Context/Add.php +++ b/src/Command/Context/Add.php @@ -7,23 +7,98 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\Command\Context; +use GuzzleHttp\Client; +use Magento\Console\ContextList; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use GuzzleHttp\Exception\GuzzleException; -class Add extends Context +class Add extends Command { - protected function configure() + private const ARG_NAME = 'name'; + private const ARG_URL = 'url'; + + /** + * @var ContextList + */ + private $contextList; + + /** + * @param ContextList $contextList + */ + public function __construct(ContextList $contextList) { - $this->addArgument('name', \Symfony\Component\Console\Input\InputArgument::REQUIRED); - $this->addArgument('url', \Symfony\Component\Console\Input\InputArgument::REQUIRED); + $this->contextList = $contextList; + + parent::__construct(); } + /** + * @inheritdoc + */ + protected function configure(): void + { + $this->setName('context:add') + ->setDescription('Add context') + ->addArgument(self::ARG_NAME, InputArgument::REQUIRED) + ->addArgument(self::ARG_URL, InputArgument::REQUIRED); + + parent::configure(); + } + + /** + * {@inheritdoc} + * + * @throws GuzzleException + */ protected function execute(InputInterface $input, OutputInterface $output) { - $contexts = $this->contextList->read(); + $name = $input->getArgument(self::ARG_NAME); + $url = $input->getArgument(self::ARG_URL); + $commands = $this->getCommands($url); + + if (!$commands) { + $output->writeln('Application endpoint is not correct.'); + + return; + } + + $this->contextList->add( + $name, + $url, + $commands + ); + + $output->writeln('Context added.'); + + if (!$this->contextList->getCurrentName()) { + $this->contextList->setCurrent($name); + + $output->writeln(sprintf('Context changed to %s.', $name)); + } + } + + /** + * @param string $url + * @return array + * @throws GuzzleException + */ + private function getCommands(string $url): array + { + $url .= '/manage.php?config'; + + $client = new Client(); + $response = $client->request('GET', $url); + + if ($response->getStatusCode() !== 200) { + return []; + } - $contexts[$input->getArgument('name')] = ['url' => $input->getArgument('url')]; - $this->contextList->write($contexts); + return (array)json_decode( + $response->getBody()->getContents(), + JSON_OBJECT_AS_ARRAY + ); } -} \ No newline at end of file +} diff --git a/src/Command/Context/Get.php b/src/Command/Context/Get.php index 114e4b9..8286339 100644 --- a/src/Command/Context/Get.php +++ b/src/Command/Context/Get.php @@ -7,14 +7,51 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\Command\Context; +use Magento\Console\ContextList; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class Get extends Context +class Get extends Command { + /** + * @var ContextList + */ + private $contextList; + + /** + * @param ContextList $contextList + */ + public function __construct(ContextList $contextList) + { + $this->contextList = $contextList; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure(): void + { + $this->setName('context'); + + parent::configure(); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int|null|void + */ protected function execute(InputInterface $input, OutputInterface $output) { - $output->writeln($this->contextList->getCurrent()); + if ($context = $this->contextList->getCurrentName()) { + $output->writeln($context); + + return; + } + + $output->writeln('No context set.'); } } diff --git a/src/Command/Context/GetList.php b/src/Command/Context/GetList.php index 63056ee..cc0c4a6 100644 --- a/src/Command/Context/GetList.php +++ b/src/Command/Context/GetList.php @@ -7,19 +7,59 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\Command\Context; +use Magento\Console\ContextList; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class GetList extends Context +class GetList extends Command { + /** + * @var ContextList + */ + private $contextList; + + /** + * @param ContextList $contextList + */ + public function __construct(ContextList $contextList) + { + $this->contextList = $contextList; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure(): void + { + $this->setName('context:list'); + + parent::configure(); + } + + /** + * @inheritdoc + */ protected function execute(InputInterface $input, OutputInterface $output) { - $contextList = $this->contextList->read(); - $current = $this->contextList->getCurrent(); - $strings = array_map(function ($key, $value) use ($current) { - return ($current === $key ? '* ' : ' ') . str_pad($key, 15) . $value; - }, array_keys($contextList), array_map(function ($item) { return $item->url; }, $contextList)); - $output->write(join("\n", $strings) . "\n"); + $rows = []; + + foreach ($this->contextList->getAll() as $name => $data) { + $rows[] = [$name, $data->get('url')]; + } + + if (!$rows) { + $output->writeln('No defined contexts.'); + + return; + } + + $table = new Table($output); + $table->setHeaders(['Name', 'URL']) + ->setRows($rows) + ->render(); } } diff --git a/src/Command/Context/Load.php b/src/Command/Context/Load.php deleted file mode 100644 index 97212f8..0000000 --- a/src/Command/Context/Load.php +++ /dev/null @@ -1,27 +0,0 @@ -contextList->read(); - $contextData = $contexts[$this->contextList->getCurrent()]; - $meta = json_decode(loadContextMetadata($contextData->url . "/manage.php?config")); - if (is_null($meta)) { - throw new \Exception("Could not load context metadata"); - } - $contexts[$this->contextList->getCurrent()]->commands = $meta; - $this->contextList->write($contexts); - } -} \ No newline at end of file diff --git a/src/Command/Context/Remove.php b/src/Command/Context/Remove.php index c60e976..d300824 100644 --- a/src/Command/Context/Remove.php +++ b/src/Command/Context/Remove.php @@ -7,21 +7,58 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\Command\Context; +use Magento\Console\ContextList; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class Remove extends Context +class Remove extends Command { - protected function configure() + private const ARG_NAME = 'name'; + + /** + * @var ContextList + */ + private $contextList; + + /** + * @param ContextList $contextList + */ + public function __construct(ContextList $contextList) { - $this->addArgument('name', \Symfony\Component\Console\Input\InputArgument::REQUIRED); + $this->contextList = $contextList; + + parent::__construct(); } + /** + * @inheritdoc + */ + protected function configure(): void + { + $this->setName('context:remove') + ->setDescription('Remove context') + ->addArgument(self::ARG_NAME, InputArgument::REQUIRED); + + parent::configure(); + } + + /** + * @inheritdoc + */ protected function execute(InputInterface $input, OutputInterface $output) { - $contexts = $this->contextList->read(); - unset($contexts[$input->getArgument('name')]); - $this->contextList->write($contexts); + $name = $input->getArgument(self::ARG_NAME); + + if ($this->contextList->has($name)) { + $this->contextList->remove($name); + + $output->writeln('Context removed.'); + + return; + } + + $output->writeln('No such context.'); } -} \ No newline at end of file +} diff --git a/src/Command/Context/Set.php b/src/Command/Context/Set.php index 6c78a38..fa5a433 100644 --- a/src/Command/Context/Set.php +++ b/src/Command/Context/Set.php @@ -7,24 +7,53 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\Command\Context; +use Magento\Console\ContextList; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class Set extends Context +class Set extends Command { - protected function configure() + /** + * @var ContextList + */ + private $contextList; + + /** + * @param ContextList $contextList + */ + public function __construct(ContextList $contextList) + { + $this->contextList = $contextList; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure(): void { - $this->addArgument('name', \Symfony\Component\Console\Input\InputArgument::REQUIRED); + $this->setName('context:set') + ->addArgument('name', InputArgument::REQUIRED); } + /** + * @inheritdoc + */ protected function execute(InputInterface $input, OutputInterface $output) { - $contexts = $this->contextList->read(); - if (!isset($contexts[$input->getArgument('name')])) { - $output->writeln('Context ' . $input->getArgument('name') . ' does not exist'); - } else { - $this->contextList->setCurrent($input->getArgument('name')); + $name = $input->getArgument('name'); + + if (!$this->contextList->has($name)) { + $output->writeln(sprintf('Context "%s" does not exists', $name)); + + return; } + + $this->contextList->setCurrent($input->getArgument('name')); + + $output->writeln('Context loaded'); } -} \ No newline at end of file +} diff --git a/src/Command/Remote.php b/src/Command/Remote.php index 9669c08..e923d81 100644 --- a/src/Command/Remote.php +++ b/src/Command/Remote.php @@ -5,6 +5,8 @@ */ namespace Magento\Console\Command; +use GuzzleHttp\Client; +use Magento\Console\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -12,33 +14,42 @@ class Remote extends Command { /** - * @var \stdClass + * @var ContextList */ - private $contextData; + private $contextList; /** - * @param \stdClass $contextData - * @param null $name + * @param ContextList $contextList */ - public function __construct($contextData, $name = null) + public function __construct(ContextList $contextList) { - $this->contextData = $contextData; - parent::__construct($name); + $this->contextList = $contextList; + + parent::__construct(); } + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return int|null|void + */ protected function execute(InputInterface $input, OutputInterface $output) { - $postData = json_encode(['arguments' => $input->getArguments(), 'options' => $input->getOptions()]); - $ch = curl_init(); - curl_setopt_array($ch, [ - CURLOPT_URL => $this->contextData->url . '/manage.php', - CURLOPT_RETURNTRANSFER => true, - CURLOPT_POST => true, - CURLOPT_POSTFIELDS => $postData, - CURLOPT_FOLLOWLOCATION => true + $context = $this->contextList->getCurrent(); + $url = $context['url'] . '/manage.php'; + $client = new Client(); + + $response = $client->post($url, [ + 'form_params' => [ + 'arguments' => $input->getArguments(), + 'options' => [] //$input->getOptions() + ] ]); - $result = curl_exec($ch); - $output->writeln($result); - curl_close($ch); + + $tpl = $response->getStatusCode() === 200 + ? '%s' + : '%s'; + + $output->writeln(sprintf($tpl, $response->getBody()->getContents())); } } diff --git a/src/Config/Reader.php b/src/Config/Reader.php new file mode 100644 index 0000000..10df5fc --- /dev/null +++ b/src/Config/Reader.php @@ -0,0 +1,25 @@ +reader = $reader; + $this->writer = $writer; + } /** - * @var [string] + * @param string $name + * @return bool */ - private $list = null; + public function has(string $name): bool + { + $config = $this->reader->read(); + + return isset($config['contexts'][$name]); + } /** - * @param $homeDir + * @param string $name + * @param string $url + * @param array $commands */ - public function __construct($homeDir) + public function add(string $name, string $url, array $commands): void { - $this->listPersistenceFile = $homeDir . DIRECTORY_SEPARATOR . 'contexts'; - $this->currentContextFile = $homeDir . DIRECTORY_SEPARATOR . 'context'; + $config = $this->reader->read(); + $config['contexts'][$name] = [ + 'name' => $name, + 'url' => $url, + 'commands' => $commands + ]; + + $this->writer->write($config); } /** - * Read list of contexts available to work with - * - * @return array + * @param string $name */ - public function read() : array + public function remove(string $name): void { - if ($this->list !== null) { - return $this->list; - } - $contexts = []; - if (is_readable($this->listPersistenceFile)) { - $contexts = json_decode(file_get_contents($this->listPersistenceFile)); + $config = $this->reader->read(); + + unset($config['contexts'][$name]); + + if (isset($config['current']) && $config['current'] === $name) { + unset($config['current']); } - $this->list = (array) $contexts; - return $this->list; + + $this->writer->write($config); } /** - * Persist available context list - * - * @param [string] $contexts - * @return bool + * @return null|array + */ + public function getCurrent(): ?Repository + { + $config = $this->reader->read(); + $current = $this->getCurrentName(); + + return $current ? new Repository($config['contexts'][$current]) : null; + } + + /** + * @return null|string */ - public function write(array $contexts) : bool + public function getCurrentName(): ?string { - $this->list = $contexts; - return !!file_put_contents($this->listPersistenceFile, json_encode($contexts)); + $config = $this->reader->read(); + + return $config['current'] ?? null; } /** - * @return string + * @return Repository[] */ - public function getCurrent() : ?string + public function getAll(): array { - if ($this->current !== null) { - return $this->current; + $config = $this->reader->read(); + + if (!array_key_exists('contexts', $config)) { + return []; } - if (is_readable($this->currentContextFile)) { - return json_decode(file_get_contents($this->currentContextFile)); + + $contexts = []; + + foreach ($config['contexts'] as $name => $context) { + $contexts[$name] = new Repository($context); } - return null; + + return $contexts; } /** * Set and persist current context. All following commands will be executed in this context + * * @param string $name * @return bool|int */ - public function setCurrent(string $name) : bool + public function setCurrent(string $name): bool { - $this->current = $name; - return !!file_put_contents($this->currentContextFile, json_encode($name)); + $config = $this->reader->read(); + $config['current'] = $name; + + return $this->writer->write($config); } -} \ No newline at end of file +} From 2dce9df98d71b0fff3fac433409d8bb89b5333de Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Thu, 31 Jan 2019 11:16:41 -0600 Subject: [PATCH 2/9] General improvements --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5fd7ed3..d794df0 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ Actual commands reside on Magento instances. When a new instance (context) is ad The tool itself only provides following commands: - * ```magento instance:add [name] [url]``` - register a new managed remote instance - * ```magento instance:remove [name]``` - unregister a managed instance from the tool instance list - * ```magento instance:list``` - list registered remote instances - * ```magento instance:update``` - load a list of commands supported by the instance - * ```magento context:set [name]``` - select the default instance to be used in commands + * ```./bin/magento instance:add [name] [url]``` - register a new managed remote instance + * ```./bin/magento instance:remove [name]``` - unregister a managed instance from the tool instance list + * ```./bin/magento instance:list``` - list registered remote instances + * ```./bin/magento instance:update``` - load a list of commands supported by the instance + * ```./bin/magento context:set [name]``` - select the default instance to be used in commands ### Magento instance endpoints From e316ac988004930b3f929c99125e467198d9b03d Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Thu, 21 Feb 2019 09:09:50 -0600 Subject: [PATCH 3/9] Added auth generator --- dist/manage.php | 74 ------------------------------------- src/Application.php | 12 +++--- src/Auth/Generator.php | 45 ++++++++++++++++++++++ src/Command/Context/Add.php | 67 +++++++++++++++++++++++++++------ src/Command/Remote.php | 30 ++++++++++++--- src/ContextList.php | 6 ++- 6 files changed, 135 insertions(+), 99 deletions(-) delete mode 100644 dist/manage.php create mode 100644 src/Auth/Generator.php diff --git a/dist/manage.php b/dist/manage.php deleted file mode 100644 index f1eba8d..0000000 --- a/dist/manage.php +++ /dev/null @@ -1,74 +0,0 @@ -getMessage(); - exit(1); -} -ini_set('error_reporting', -1); -ini_set('display_errors', 'on'); -try { - $handler = new \Magento\Framework\App\ErrorHandler(); - set_error_handler([$handler, 'handler']); - $application = new Magento\Framework\Console\Cli('Magento CLI'); - if (isset($_GET['config'])) { - $output = new \Symfony\Component\Console\Output\BufferedOutput(); - $commands = array_map(function ($item) { - $arguments = array_map(function ($argument) { - return [ - 'name' => $argument->getName(), - 'description' => $argument->getDescription(), - 'is_array' => $argument->isArray(), - 'is_requied' => $argument->isRequired(), - 'default' => $argument->getDefault() - ]; - }, - $item->getDefinition()->getArguments() - ); - $options = array_map(function ($argument) { - return [ - 'name' => $argument->getName(), - 'description' => $argument->getDescription(), - 'shortcut' => $argument->getShortcut(), - 'default' => $argument->getDefault() - ]; - }, - $item->getDefinition()->getOptions() - ); - - return [ - 'name' => $item->getName(), - 'description' => $item->getDescription(), - 'help' => $item->getHelp(), - 'usages' => $item->getUsages(), - 'definition' => [ - 'options' => $options, - 'arguments' => $arguments - ] - ]; - }, $application->getApplicationCommands()); - echo json_encode($commands); - } else { - $inputArgs = json_decode($_POST); - $input = new \Symfony\Component\Console\Input\ArrayInput($inputArgs['arguments']); - array_walk($inputArgs['optinos'], function ($value, $key) use ($input) { - $input->setOption($key, $value); - }); - $output = new \Symfony\Component\Console\Output\StreamOutput(fopen('php://output', 'w')); - $application->setAutoExit(false); - $application->run($input, $output); - } -} catch (\Exception $e) { - while ($e) { - echo $e->getMessage(); - echo $e->getTraceAsString(); - echo "\n\n"; - $e = $e->getPrevious(); - } - exit(Magento\Framework\Console\Cli::RETURN_FAILURE); -} diff --git a/src/Application.php b/src/Application.php index 8374dcc..afeb7bf 100644 --- a/src/Application.php +++ b/src/Application.php @@ -73,14 +73,14 @@ private function fetchMagentoCommands(): array $commands = []; - foreach ($context->get('commands') as $data) { + foreach ($context->get('commands') as $cName => $cData) { /** @var Command\Remote $command */ $command = $this->container->make(Command\Remote::class); - $command->setName($data['name']) - ->setDescription($data['description']) - ->setHelp($data['help']); + $command->setName($cName) + ->setDescription($cData['description']) + ->setHelp($cData['help']); - foreach ($data['definition']['arguments'] as $aName => $aData) { + foreach ($cData['definition']['arguments'] as $aName => $aData) { $command->addArgument( $aName, $aData['mode'] ?? InputArgument::OPTIONAL, @@ -88,7 +88,7 @@ private function fetchMagentoCommands(): array ); } - foreach ($data['definition']['options'] as $oName => $oData) { + foreach ($cData['definition']['options'] as $oName => $oData) { $command->addOption( $oName, $oData['shortcut'] ?? null, diff --git a/src/Auth/Generator.php b/src/Auth/Generator.php new file mode 100644 index 0000000..5e85ebb --- /dev/null +++ b/src/Auth/Generator.php @@ -0,0 +1,45 @@ +toString($params) . $publicKey . $privateKey); + } + + /** + * @param array $params + * @param string $string + * @return string + */ + private function toString(array $params, $string = ''): string + { + foreach ($params as $key => $value) { + if (is_array($value) && $value) { + $string .= $this->toString($value, $string); + } elseif (is_string($value) && $value) { + $string .= $key . '=' . $value; + } + } + + return $string; + } +} diff --git a/src/Command/Context/Add.php b/src/Command/Context/Add.php index 18cebe2..4e1cdb2 100644 --- a/src/Command/Context/Add.php +++ b/src/Command/Context/Add.php @@ -8,6 +8,7 @@ namespace Magento\Console\Command\Context; use GuzzleHttp\Client; +use Magento\Console\Auth\Generator; use Magento\Console\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -19,18 +20,27 @@ class Add extends Command { private const ARG_NAME = 'name'; private const ARG_URL = 'url'; + private const ARG_PUBLIC_KEY = 'public-key'; + private const ARG_PRIVATE_KEY = 'private-key'; /** * @var ContextList */ private $contextList; + /** + * @var Generator + */ + private $generator; + /** * @param ContextList $contextList + * @param Generator $generator */ - public function __construct(ContextList $contextList) + public function __construct(ContextList $contextList, Generator $generator) { $this->contextList = $contextList; + $this->generator = $generator; parent::__construct(); } @@ -43,7 +53,9 @@ protected function configure(): void $this->setName('context:add') ->setDescription('Add context') ->addArgument(self::ARG_NAME, InputArgument::REQUIRED) - ->addArgument(self::ARG_URL, InputArgument::REQUIRED); + ->addArgument(self::ARG_URL, InputArgument::REQUIRED) + ->addArgument(self::ARG_PUBLIC_KEY, InputArgument::REQUIRED) + ->addArgument(self::ARG_PRIVATE_KEY, InputArgument::REQUIRED); parent::configure(); } @@ -57,18 +69,41 @@ protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument(self::ARG_NAME); $url = $input->getArgument(self::ARG_URL); - $commands = $this->getCommands($url); - if (!$commands) { - $output->writeln('Application endpoint is not correct.'); + $sign = $this->generator->generate( + $input->getArgument(self::ARG_PUBLIC_KEY), + $input->getArgument(self::ARG_PRIVATE_KEY), + [] + ); + + $client = new Client(); + $response = $client->post($url . '/manage.php', [ + 'form_params' => [ + 'public_key' => $input->getArgument(self::ARG_PUBLIC_KEY), + 'sign' => $sign, + 'type' => 'list' + ] + ]); + + if ($response->getStatusCode() !== 200) { + throw new \RuntimeException($response->getBody()->getContents()); + } + + $commands = (array)json_decode( + $response->getBody()->getContents(), + JSON_OBJECT_AS_ARRAY + ); - return; + if (!$commands) { + throw new \RuntimeException('Commands are not defined'); } $this->contextList->add( $name, $url, - $commands + $commands, + $input->getArgument(self::ARG_PUBLIC_KEY), + $input->getArgument(self::ARG_PRIVATE_KEY) ); $output->writeln('Context added.'); @@ -85,15 +120,25 @@ protected function execute(InputInterface $input, OutputInterface $output) * @return array * @throws GuzzleException */ - private function getCommands(string $url): array + private function getCommands(string $url, InputInterface $input): array { - $url .= '/manage.php?config'; + $sign = $this->generator->generate( + $input->getArgument(self::ARG_PUBLIC_KEY), + $input->getArgument(self::ARG_PRIVATE_KEY), + [] + ); $client = new Client(); - $response = $client->request('GET', $url); + $response = $client->post($url . '/manage.php', [ + 'form_params' => [ + 'public_key' => $input->getArgument(self::ARG_PUBLIC_KEY), + 'sign' => $sign, + 'type' => 'list' + ] + ]); if ($response->getStatusCode() !== 200) { - return []; + throw new \RuntimeException($response->getBody()->getContents()); } return (array)json_decode( diff --git a/src/Command/Remote.php b/src/Command/Remote.php index e923d81..b4c340e 100644 --- a/src/Command/Remote.php +++ b/src/Command/Remote.php @@ -6,6 +6,7 @@ namespace Magento\Console\Command; use GuzzleHttp\Client; +use Magento\Console\Auth\Generator; use Magento\Console\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -18,12 +19,19 @@ class Remote extends Command */ private $contextList; + /** + * @var Generator + */ + private $generator; + /** * @param ContextList $contextList + * @param Generator $generator */ - public function __construct(ContextList $contextList) + public function __construct(ContextList $contextList, Generator $generator) { $this->contextList = $contextList; + $this->generator = $generator; parent::__construct(); } @@ -36,14 +44,24 @@ public function __construct(ContextList $contextList) protected function execute(InputInterface $input, OutputInterface $output) { $context = $this->contextList->getCurrent(); - $url = $context['url'] . '/manage.php'; + $url = $context['url'] . '/remote'; $client = new Client(); + $publicKey = $context['public_key']; + $privateKey = $context['private_key']; + + $params = [ + 'name' => $this->getName(), + 'arguments' => $input->getArguments(), + 'options' => $input->getOptions(), + 'public_key' => $publicKey, + 'type' => 'run' + ]; + + $sign = $this->generator->generate($publicKey, $privateKey, $params); + $response = $client->post($url, [ - 'form_params' => [ - 'arguments' => $input->getArguments(), - 'options' => [] //$input->getOptions() - ] + 'form_params' => $params + ['sign' => $sign] ]); $tpl = $response->getStatusCode() === 200 diff --git a/src/ContextList.php b/src/ContextList.php index 4927329..054adae 100644 --- a/src/ContextList.php +++ b/src/ContextList.php @@ -49,13 +49,15 @@ public function has(string $name): bool * @param string $url * @param array $commands */ - public function add(string $name, string $url, array $commands): void + public function add(string $name, string $url, array $commands, string $publicKey, string $privateKey): void { $config = $this->reader->read(); $config['contexts'][$name] = [ 'name' => $name, 'url' => $url, - 'commands' => $commands + 'commands' => $commands, + 'public_key' => $publicKey, + 'private_key' => $privateKey ]; $this->writer->write($config); From 27dce2cda3faddb673f5571db81c9d25e6a3d843 Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Thu, 21 Feb 2019 09:11:27 -0600 Subject: [PATCH 4/9] Update README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index d794df0..d16c94f 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,7 @@ As remote call endpoints provide wide access to magento instance, they MUST be e * Add authentication * Add install/deploy commands for standard environments (local, docker, vagrant, kubernetes) +* Create separate repository for Magento module +* Add Magento commands to mange tokens in Magento module +* Improve stability +* Fix options transfer From c12528767e832f9796cb99816addfd8d9261de16 Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Thu, 21 Feb 2019 11:43:49 -0600 Subject: [PATCH 5/9] Update README --- README.md | 1 + src/Application.php | 5 ++--- src/Command/Context/GetList.php | 9 +++++++-- src/Command/Remote.php | 4 ++-- src/ContextList.php | 18 +++++++++++++++--- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d16c94f..e7d31df 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,4 @@ As remote call endpoints provide wide access to magento instance, they MUST be e * Add Magento commands to mange tokens in Magento module * Improve stability * Fix options transfer +* Optimize IO operations diff --git a/src/Application.php b/src/Application.php index afeb7bf..e4b2e75 100644 --- a/src/Application.php +++ b/src/Application.php @@ -65,12 +65,11 @@ protected function getDefaultCommands(): array */ private function fetchMagentoCommands(): array { - $context = $this->contextList->getCurrent(); - - if (!$context) { + if (!$this->contextList->getCurrentName()) { return []; } + $context = $this->contextList->getCurrent(); $commands = []; foreach ($context->get('commands') as $cName => $cData) { diff --git a/src/Command/Context/GetList.php b/src/Command/Context/GetList.php index cc0c4a6..fc5f6aa 100644 --- a/src/Command/Context/GetList.php +++ b/src/Command/Context/GetList.php @@ -48,7 +48,12 @@ protected function execute(InputInterface $input, OutputInterface $output) $rows = []; foreach ($this->contextList->getAll() as $name => $data) { - $rows[] = [$name, $data->get('url')]; + $rows[] = [ + $name, + $data->get('url'), + $data->get('public_key'), + $data->get('private_key') + ]; } if (!$rows) { @@ -58,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $table = new Table($output); - $table->setHeaders(['Name', 'URL']) + $table->setHeaders(['Name', 'URL', 'Public key', 'Private key']) ->setRows($rows) ->render(); } diff --git a/src/Command/Remote.php b/src/Command/Remote.php index b4c340e..6b7ffa2 100644 --- a/src/Command/Remote.php +++ b/src/Command/Remote.php @@ -47,8 +47,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $url = $context['url'] . '/remote'; $client = new Client(); - $publicKey = $context['public_key']; - $privateKey = $context['private_key']; + $publicKey = $context->get('public_key'); + $privateKey = $context->get('private_key'); $params = [ 'name' => $this->getName(), diff --git a/src/ContextList.php b/src/ContextList.php index 054adae..a46af4f 100644 --- a/src/ContextList.php +++ b/src/ContextList.php @@ -80,14 +80,26 @@ public function remove(string $name): void } /** - * @return null|array + * @return Repository */ - public function getCurrent(): ?Repository + public function getCurrent(): Repository { $config = $this->reader->read(); $current = $this->getCurrentName(); - return $current ? new Repository($config['contexts'][$current]) : null; + if (!$current) { + throw new \RuntimeException('Current context not set'); + } + + return new Repository($config['contexts'][$current]); + } + + /** + * @return bool + */ + public function hasCurrent(): bool + { + return $this->getCurrentName() !== null; } /** From 09be8f0f5f39a6b9aa171f70a884d1f3c5eac1a3 Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Mon, 25 Feb 2019 19:52:15 -0600 Subject: [PATCH 6/9] Improvements - Refactored classes - Switched to JWT sign --- bin/magento | 1 + composer.json | 3 +- composer.lock | 48 +++++- src/Application.php | 16 +- src/Auth/Encoder.php | 24 +++ src/Auth/Generator.php | 45 ------ src/Client/Client.php | 55 +++++++ src/Client/ClientFactory.php | 35 ++++ src/Command/Context/Add.php | 149 ------------------ src/Command/Context/AddCommand.php | 110 +++++++++++++ .../Context/{Get.php => GetCommand.php} | 10 +- .../Context/{GetList.php => ListCommand.php} | 19 +-- .../Context/{Remove.php => RemoveCommand.php} | 11 +- .../Context/{Set.php => SetCommand.php} | 21 ++- src/Command/Remote.php | 57 +++---- src/Config/Reader.php | 19 ++- src/Config/Writer.php | 28 +++- src/{ => Context}/ContextList.php | 14 +- 18 files changed, 400 insertions(+), 265 deletions(-) create mode 100644 src/Auth/Encoder.php delete mode 100644 src/Auth/Generator.php create mode 100644 src/Client/Client.php create mode 100644 src/Client/ClientFactory.php delete mode 100644 src/Command/Context/Add.php create mode 100644 src/Command/Context/AddCommand.php rename src/Command/Context/{Get.php => GetCommand.php} (85%) rename src/Command/Context/{GetList.php => ListCommand.php} (75%) rename src/Command/Context/{Remove.php => RemoveCommand.php} (84%) rename src/Command/Context/{Set.php => SetCommand.php} (70%) rename src/{ => Context}/ContextList.php (89%) diff --git a/bin/magento b/bin/magento index 19c9cf6..a8e060f 100755 --- a/bin/magento +++ b/bin/magento @@ -10,6 +10,7 @@ $handler = new \Magento\Console\Application\ErrorHandler(); set_error_handler([$handler, 'handle']); $container = new \Illuminate\Container\Container(); +$container->instance(\Illuminate\Contracts\Container\Container::class, $container); $container->make(\Magento\Console\Application::class, [ 'container' => $container ])->run(); diff --git a/composer.json b/composer.json index 4aa1db0..3bac601 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ "illuminate/container": "^5.7", "illuminate/filesystem": "^5.7", "guzzlehttp/guzzle": "^6.3", - "illuminate/config": "^5.7" + "illuminate/config": "^5.7", + "firebase/php-jwt": "^5.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 5bdf2b4..59f6144 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": "49b0af2330e0bf383ee8c02fbcb0e66a", + "content-hash": "b30dd080dff030df2338350a11abaa8d", "packages": [ { "name": "doctrine/inflector", @@ -73,6 +73,52 @@ ], "time": "2018-01-09T20:05:19+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v5.0.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": " 4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "time": "2017-06-27T22:17:23+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.3.3", diff --git a/src/Application.php b/src/Application.php index e4b2e75..8dee20b 100644 --- a/src/Application.php +++ b/src/Application.php @@ -7,11 +7,12 @@ use Illuminate\Contracts\Container\Container; use Magento\Console\Command; +use Magento\Console\Context\ContextList; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; /** - * Class Application. + * General application */ class Application extends \Symfony\Component\Console\Application { @@ -43,16 +44,15 @@ public function __construct(Container $container, ContextList $contextList) protected function getDefaultCommands(): array { $stdCommands = [ - $this->container->make(Command\Context\Get::class), - $this->container->make(Command\Context\Get::class), - $this->container->make(Command\Context\GetList::class), - $this->container->make(Command\Context\Add::class), - $this->container->make(Command\Context\Remove::class), - $this->container->make(Command\Context\Set::class) + $this->container->make(Command\Context\GetCommand::class), + $this->container->make(Command\Context\GetCommand::class), + $this->container->make(Command\Context\ListCommand::class), + $this->container->make(Command\Context\AddCommand::class), + $this->container->make(Command\Context\RemoveCommand::class), + $this->container->make(Command\Context\SetCommand::class) ]; $magentoCommands = $this->fetchMagentoCommands(); - return array_merge( parent::getDefaultCommands(), $stdCommands, diff --git a/src/Auth/Encoder.php b/src/Auth/Encoder.php new file mode 100644 index 0000000..a406df4 --- /dev/null +++ b/src/Auth/Encoder.php @@ -0,0 +1,24 @@ +toString($params) . $publicKey . $privateKey); - } - - /** - * @param array $params - * @param string $string - * @return string - */ - private function toString(array $params, $string = ''): string - { - foreach ($params as $key => $value) { - if (is_array($value) && $value) { - $string .= $this->toString($value, $string); - } elseif (is_string($value) && $value) { - $string .= $key . '=' . $value; - } - } - - return $string; - } -} diff --git a/src/Client/Client.php b/src/Client/Client.php new file mode 100644 index 0000000..c3cbfd3 --- /dev/null +++ b/src/Client/Client.php @@ -0,0 +1,55 @@ +encoder = $encoder; + + parent::__construct([]); + } + + /** + * @param string $uri + * @param string $key + * @param string $type + * @param array $params + * @return ResponseInterface + */ + public function post( + string $uri, + string $key, + string $type, + array $params + ): ResponseInterface { + $params['type'] = $type; + + return parent::post($uri, [ + 'form_params' => [ + 'token' => $this->encoder->encode($params, $key) + ] + ]); + } +} diff --git a/src/Client/ClientFactory.php b/src/Client/ClientFactory.php new file mode 100644 index 0000000..0cc9074 --- /dev/null +++ b/src/Client/ClientFactory.php @@ -0,0 +1,35 @@ +container = $container; + } + + /** + * @return Client + */ + public function create(): Client + { + return $this->container->make(Client::class); + } +} diff --git a/src/Command/Context/Add.php b/src/Command/Context/Add.php deleted file mode 100644 index 4e1cdb2..0000000 --- a/src/Command/Context/Add.php +++ /dev/null @@ -1,149 +0,0 @@ -contextList = $contextList; - $this->generator = $generator; - - parent::__construct(); - } - - /** - * @inheritdoc - */ - protected function configure(): void - { - $this->setName('context:add') - ->setDescription('Add context') - ->addArgument(self::ARG_NAME, InputArgument::REQUIRED) - ->addArgument(self::ARG_URL, InputArgument::REQUIRED) - ->addArgument(self::ARG_PUBLIC_KEY, InputArgument::REQUIRED) - ->addArgument(self::ARG_PRIVATE_KEY, InputArgument::REQUIRED); - - parent::configure(); - } - - /** - * {@inheritdoc} - * - * @throws GuzzleException - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $name = $input->getArgument(self::ARG_NAME); - $url = $input->getArgument(self::ARG_URL); - - $sign = $this->generator->generate( - $input->getArgument(self::ARG_PUBLIC_KEY), - $input->getArgument(self::ARG_PRIVATE_KEY), - [] - ); - - $client = new Client(); - $response = $client->post($url . '/manage.php', [ - 'form_params' => [ - 'public_key' => $input->getArgument(self::ARG_PUBLIC_KEY), - 'sign' => $sign, - 'type' => 'list' - ] - ]); - - if ($response->getStatusCode() !== 200) { - throw new \RuntimeException($response->getBody()->getContents()); - } - - $commands = (array)json_decode( - $response->getBody()->getContents(), - JSON_OBJECT_AS_ARRAY - ); - - if (!$commands) { - throw new \RuntimeException('Commands are not defined'); - } - - $this->contextList->add( - $name, - $url, - $commands, - $input->getArgument(self::ARG_PUBLIC_KEY), - $input->getArgument(self::ARG_PRIVATE_KEY) - ); - - $output->writeln('Context added.'); - - if (!$this->contextList->getCurrentName()) { - $this->contextList->setCurrent($name); - - $output->writeln(sprintf('Context changed to %s.', $name)); - } - } - - /** - * @param string $url - * @return array - * @throws GuzzleException - */ - private function getCommands(string $url, InputInterface $input): array - { - $sign = $this->generator->generate( - $input->getArgument(self::ARG_PUBLIC_KEY), - $input->getArgument(self::ARG_PRIVATE_KEY), - [] - ); - - $client = new Client(); - $response = $client->post($url . '/manage.php', [ - 'form_params' => [ - 'public_key' => $input->getArgument(self::ARG_PUBLIC_KEY), - 'sign' => $sign, - 'type' => 'list' - ] - ]); - - if ($response->getStatusCode() !== 200) { - throw new \RuntimeException($response->getBody()->getContents()); - } - - return (array)json_decode( - $response->getBody()->getContents(), - JSON_OBJECT_AS_ARRAY - ); - } -} diff --git a/src/Command/Context/AddCommand.php b/src/Command/Context/AddCommand.php new file mode 100644 index 0000000..2fae5b5 --- /dev/null +++ b/src/Command/Context/AddCommand.php @@ -0,0 +1,110 @@ +contextList = $contextList; + $this->clientFactory = $clientFactory; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure(): void + { + $this->setName('context:add') + ->setDescription('Add context') + ->addArgument(self::ARG_NAME, InputArgument::REQUIRED) + ->addArgument(self::ARG_URL, InputArgument::REQUIRED) + ->addArgument(self::ARG_KEY, InputArgument::REQUIRED); + + parent::configure(); + } + + /** + * {@inheritdoc} + * + * @throws GuzzleException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $name = $input->getArgument(self::ARG_NAME); + + $client = $this->clientFactory->create(); + $response = $client->post( + $input->getArgument(self::ARG_URL), + $input->getArgument(self::ARG_KEY), + Client::TYPE_LIST, + [] + ); + + if ($response->getStatusCode() !== 200) { + throw new \RuntimeException($response->getBody()->getContents()); + } + + $commands = (array)json_decode( + $response->getBody()->getContents(), + JSON_OBJECT_AS_ARRAY + ); + + if (!$commands) { + throw new \RuntimeException('Commands are not defined'); + } + + $this->contextList->add( + $name, + $input->getArgument(self::ARG_URL), + $input->getArgument(self::ARG_KEY), + $commands + ); + + $output->writeln('Context added.'); + + if (!$this->contextList->getCurrentName()) { + $this->getApplication() + ->find(SetCommand::NAME) + ->run(new ArrayInput([SetCommand::ARG_NAME => $name]), $output); + } + } +} diff --git a/src/Command/Context/Get.php b/src/Command/Context/GetCommand.php similarity index 85% rename from src/Command/Context/Get.php rename to src/Command/Context/GetCommand.php index 8286339..e2c77fd 100644 --- a/src/Command/Context/Get.php +++ b/src/Command/Context/GetCommand.php @@ -7,12 +7,15 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\ContextList; +use Magento\Console\Context\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class Get extends Command +/** + * Display current context + */ +class GetCommand extends Command { /** * @var ContextList @@ -34,7 +37,8 @@ public function __construct(ContextList $contextList) */ protected function configure(): void { - $this->setName('context'); + $this->setName('context') + ->setDescription('Display current context'); parent::configure(); } diff --git a/src/Command/Context/GetList.php b/src/Command/Context/ListCommand.php similarity index 75% rename from src/Command/Context/GetList.php rename to src/Command/Context/ListCommand.php index fc5f6aa..52e7c68 100644 --- a/src/Command/Context/GetList.php +++ b/src/Command/Context/ListCommand.php @@ -2,18 +2,19 @@ /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. - * - * Retrieve the list of managed instances (contexts) */ namespace Magento\Console\Command\Context; -use Magento\Console\ContextList; +use Magento\Console\Context\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class GetList extends Command +/** + * Display list of contexts + */ +class ListCommand extends Command { /** * @var ContextList @@ -35,7 +36,8 @@ public function __construct(ContextList $contextList) */ protected function configure(): void { - $this->setName('context:list'); + $this->setName('context:list') + ->setDescription('Display all contexts'); parent::configure(); } @@ -51,19 +53,18 @@ protected function execute(InputInterface $input, OutputInterface $output) $rows[] = [ $name, $data->get('url'), - $data->get('public_key'), - $data->get('private_key') + $data->get('key') ]; } if (!$rows) { - $output->writeln('No defined contexts.'); + $output->writeln('No available contexts.'); return; } $table = new Table($output); - $table->setHeaders(['Name', 'URL', 'Public key', 'Private key']) + $table->setHeaders(['Name', 'URL', 'Key']) ->setRows($rows) ->render(); } diff --git a/src/Command/Context/Remove.php b/src/Command/Context/RemoveCommand.php similarity index 84% rename from src/Command/Context/Remove.php rename to src/Command/Context/RemoveCommand.php index d300824..22986fc 100644 --- a/src/Command/Context/Remove.php +++ b/src/Command/Context/RemoveCommand.php @@ -7,13 +7,16 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\ContextList; +use Magento\Console\Context\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class Remove extends Command +/** + * Remove context + */ +class RemoveCommand extends Command { private const ARG_NAME = 'name'; @@ -54,11 +57,11 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($this->contextList->has($name)) { $this->contextList->remove($name); - $output->writeln('Context removed.'); + $output->writeln('Context removed'); return; } - $output->writeln('No such context.'); + $output->writeln('No such context'); } } diff --git a/src/Command/Context/Set.php b/src/Command/Context/SetCommand.php similarity index 70% rename from src/Command/Context/Set.php rename to src/Command/Context/SetCommand.php index fa5a433..e6512cf 100644 --- a/src/Command/Context/Set.php +++ b/src/Command/Context/SetCommand.php @@ -7,14 +7,20 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\ContextList; +use Magento\Console\Context\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class Set extends Command +/** + * Switch context. + */ +class SetCommand extends Command { + public const NAME = 'context:set'; + public const ARG_NAME = 'name'; + /** * @var ContextList */ @@ -35,8 +41,9 @@ public function __construct(ContextList $contextList) */ protected function configure(): void { - $this->setName('context:set') - ->addArgument('name', InputArgument::REQUIRED); + $this->setName(self::NAME) + ->setDescription('Switch current context') + ->addArgument(self::ARG_NAME, InputArgument::REQUIRED); } /** @@ -52,8 +59,10 @@ protected function execute(InputInterface $input, OutputInterface $output) return; } - $this->contextList->setCurrent($input->getArgument('name')); + $this->contextList->setCurrent( + $input->getArgument('name') + ); - $output->writeln('Context loaded'); + $output->writeln('Context switched'); } } diff --git a/src/Command/Remote.php b/src/Command/Remote.php index 6b7ffa2..4b94464 100644 --- a/src/Command/Remote.php +++ b/src/Command/Remote.php @@ -5,33 +5,36 @@ */ namespace Magento\Console\Command; -use GuzzleHttp\Client; -use Magento\Console\Auth\Generator; -use Magento\Console\ContextList; +use Magento\Console\Client\Client; +use Magento\Console\Client\ClientFactory; +use Magento\Console\Context\ContextList; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +/** + * Generic remote command + */ class Remote extends Command { /** - * @var ContextList + * @var ClientFactory */ - private $contextList; + private $clientFactory; /** - * @var Generator + * @var ContextList */ - private $generator; + private $contextList; /** + * @param ClientFactory $clientFactory * @param ContextList $contextList - * @param Generator $generator */ - public function __construct(ContextList $contextList, Generator $generator) + public function __construct(ClientFactory $clientFactory, ContextList $contextList) { + $this->clientFactory = $clientFactory; $this->contextList = $contextList; - $this->generator = $generator; parent::__construct(); } @@ -43,31 +46,23 @@ public function __construct(ContextList $contextList, Generator $generator) */ protected function execute(InputInterface $input, OutputInterface $output) { - $context = $this->contextList->getCurrent(); - $url = $context['url'] . '/remote'; - $client = new Client(); - - $publicKey = $context->get('public_key'); - $privateKey = $context->get('private_key'); - - $params = [ - 'name' => $this->getName(), - 'arguments' => $input->getArguments(), - 'options' => $input->getOptions(), - 'public_key' => $publicKey, - 'type' => 'run' - ]; - - $sign = $this->generator->generate($publicKey, $privateKey, $params); + $client = $this->clientFactory->create(); - $response = $client->post($url, [ - 'form_params' => $params + ['sign' => $sign] - ]); + $response = $client->post( + $this->contextList->getCurrent()->get('url'), + $this->contextList->getCurrent()->get('key'), + Client::TYPE_RUN, + [ + 'name' => $this->getName(), + 'arguments' => $input->getArguments(), + 'options' => $input->getOptions() + ] + ); $tpl = $response->getStatusCode() === 200 - ? '%s' + ? '%s' : '%s'; - $output->writeln(sprintf($tpl, $response->getBody()->getContents())); + $output->write(sprintf($tpl, $response->getBody()->getContents())); } } diff --git a/src/Config/Reader.php b/src/Config/Reader.php index 10df5fc..d8e7f9e 100644 --- a/src/Config/Reader.php +++ b/src/Config/Reader.php @@ -5,10 +5,27 @@ */ namespace Magento\Console\Config; +use Illuminate\Filesystem\Filesystem; use Symfony\Component\Yaml\Yaml; +/** + * Read the application config + */ class Reader { + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @param Filesystem $filesystem + */ + public function __construct(Filesystem $filesystem) + { + $this->filesystem = $filesystem; + } + /** * @return array */ @@ -16,7 +33,7 @@ public function read(): array { $configFile = HOME_DIR . '/config.yaml'; - if (@file_exists($configFile)) { + if ($this->filesystem->exists($configFile)) { return Yaml::parseFile($configFile); } diff --git a/src/Config/Writer.php b/src/Config/Writer.php index a9b1813..d18bab0 100644 --- a/src/Config/Writer.php +++ b/src/Config/Writer.php @@ -5,14 +5,38 @@ */ namespace Magento\Console\Config; +use Illuminate\Filesystem\Filesystem; use Symfony\Component\Yaml\Yaml; +/** + * Write the application config + */ class Writer { - public function write(array $data) + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @param Filesystem $filesystem + */ + public function __construct(Filesystem $filesystem) + { + $this->filesystem = $filesystem; + } + + /** + * @param array $data + * @return int + */ + public function write(array $data): int { $configFile = HOME_DIR . '/config.yaml'; - return file_put_contents($configFile, Yaml::dump($data, 4, 2)); + return $this->filesystem->put( + $configFile, + Yaml::dump($data, 4, 2) + ); } } diff --git a/src/ContextList.php b/src/Context/ContextList.php similarity index 89% rename from src/ContextList.php rename to src/Context/ContextList.php index a46af4f..c16db48 100644 --- a/src/ContextList.php +++ b/src/Context/ContextList.php @@ -5,12 +5,15 @@ * * List of managed contexts (instances) */ -namespace Magento\Console; +namespace Magento\Console\Context; use Illuminate\Config\Repository; use Magento\Console\Config\Reader; use Magento\Console\Config\Writer; +/** + * Context repository. + */ class ContextList { /** @@ -47,17 +50,17 @@ public function has(string $name): bool /** * @param string $name * @param string $url + * @param string $key * @param array $commands */ - public function add(string $name, string $url, array $commands, string $publicKey, string $privateKey): void + public function add(string $name, string $url, string $key, array $commands): void { $config = $this->reader->read(); $config['contexts'][$name] = [ 'name' => $name, 'url' => $url, 'commands' => $commands, - 'public_key' => $publicKey, - 'private_key' => $privateKey + 'key' => $key, ]; $this->writer->write($config); @@ -133,7 +136,8 @@ public function getAll(): array } /** - * Set and persist current context. All following commands will be executed in this context + * Set and persist current context. + * All following commands will be executed in this context * * @param string $name * @return bool|int From 316bbe14126ad6b4ce8098ed452167a3cf45bdcb Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Tue, 26 Feb 2019 08:48:42 -0600 Subject: [PATCH 7/9] Update README.md --- README.md | 18 +++++++----------- composer.json | 9 +++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e7d31df..b479bb9 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,16 @@ Actual commands reside on Magento instances. When a new instance (context) is ad The tool itself only provides following commands: - * ```./bin/magento instance:add [name] [url]``` - register a new managed remote instance - * ```./bin/magento instance:remove [name]``` - unregister a managed instance from the tool instance list - * ```./bin/magento instance:list``` - list registered remote instances - * ```./bin/magento instance:update``` - load a list of commands supported by the instance - * ```./bin/magento context:set [name]``` - select the default instance to be used in commands + * `./bin/magento instance:add [name] [url] [key]` - register a new managed remote instance + * `./bin/magento instance:remove [name]` - unregister a managed instance from the tool instance list + * `./bin/magento instance:list` - list registered remote instances + * `./bin/magento instance:get` - show current context + * `./bin/magento context:set [name]` - select the default instance to be used in commands ### Magento instance endpoints -This tool only works with magento instances that support remote calls and metadata sharing +This tool only works with magento instances that support remote calls and metadata sharing. +Install and configure [Magento integration](https://github.com/shiftedreality/magento-tool-module) to be able to use this tool. #### Security @@ -24,10 +25,5 @@ As remote call endpoints provide wide access to magento instance, they MUST be e ### Evolution plan -* Add authentication * Add install/deploy commands for standard environments (local, docker, vagrant, kubernetes) -* Create separate repository for Magento module -* Add Magento commands to mange tokens in Magento module -* Improve stability -* Fix options transfer * Optimize IO operations diff --git a/composer.json b/composer.json index 3bac601..408de5f 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,14 @@ { + "name": "magento/magento-tool", "description": "Magento Console Client", + "type": "project", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "config": { + "sort-packages": true + }, "require": { "php": "^7.1.3", "symfony/console": "^4.1", From 6e31440ec05806fe285c87970fafaafff9e76426 Mon Sep 17 00:00:00 2001 From: Oleh Posyniak Date: Fri, 15 Mar 2019 08:23:24 -0500 Subject: [PATCH 8/9] Rewrite to use SSH and local calls --- README.md | 21 +- composer.json | 12 +- composer.lock | 500 ++++++++------------------ src/Application.php | 17 +- src/Client/Client.php | 55 --- src/Client/ClientFactory.php | 35 -- src/Command/Context/AddCommand.php | 58 ++- src/Command/Context/GetCommand.php | 4 +- src/Command/Context/ListCommand.php | 4 +- src/Command/Context/RemoveCommand.php | 3 +- src/Command/Remote.php | 38 +- src/Context/ContextList.php | 6 +- src/Shell/ShellFactory.php | 35 ++ 13 files changed, 260 insertions(+), 528 deletions(-) delete mode 100644 src/Client/Client.php delete mode 100644 src/Client/ClientFactory.php create mode 100644 src/Shell/ShellFactory.php diff --git a/README.md b/README.md index b479bb9..623d16e 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,31 @@ Actual commands reside on Magento instances. When a new instance (context) is ad The tool itself only provides following commands: - * `./bin/magento instance:add [name] [url] [key]` - register a new managed remote instance + * `./bin/magento instance:add [name] [type] [url]` - register a new managed remote instance * `./bin/magento instance:remove [name]` - unregister a managed instance from the tool instance list * `./bin/magento instance:list` - list registered remote instances * `./bin/magento instance:get` - show current context * `./bin/magento context:set [name]` - select the default instance to be used in commands -### Magento instance endpoints +#### Remote types -This tool only works with magento instances that support remote calls and metadata sharing. -Install and configure [Magento integration](https://github.com/shiftedreality/magento-tool-module) to be able to use this tool. +Tool works with both remote and local calls. +### Add remote context: + +```bash +./bin/magento context:add cloud remote +``` + +### Add local context: + +```bash +./bin/magento context:add local local +``` + #### Security -As remote call endpoints provide wide access to magento instance, they MUST be exposed through separate protected network interface. +The tool is using SSH for remote calls. ### Evolution plan diff --git a/composer.json b/composer.json index 408de5f..7d3ac5a 100644 --- a/composer.json +++ b/composer.json @@ -11,15 +11,15 @@ }, "require": { "php": "^7.1.3", - "symfony/console": "^4.1", - "ext-json": "*", "ext-curl": "*", - "symfony/yaml": "^4.2", + "ext-json": "*", + "firebase/php-jwt": "^5.0", + "illuminate/config": "^5.7", "illuminate/container": "^5.7", "illuminate/filesystem": "^5.7", - "guzzlehttp/guzzle": "^6.3", - "illuminate/config": "^5.7", - "firebase/php-jwt": "^5.0" + "symfony/console": "^4.1", + "symfony/process": "^4.2", + "symfony/yaml": "^4.2" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 59f6144..62836a0 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": "b30dd080dff030df2338350a11abaa8d", + "content-hash": "fdb5481dc2504bda9fe1073c27a2259f", "packages": [ { "name": "doctrine/inflector", @@ -119,212 +119,29 @@ "homepage": "https://github.com/firebase/php-jwt", "time": "2017-06-27T22:17:23+00:00" }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2018-04-22T15:46:56+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.5.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "9f83dded91781a01c63574e387eaa769be769115" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", - "reference": "9f83dded91781a01c63574e387eaa769be769115", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2018-12-04T20:46:45+00:00" - }, { "name": "illuminate/config", - "version": "v5.7.21", + "version": "v5.8.4", "source": { "type": "git", "url": "https://github.com/illuminate/config.git", - "reference": "08b6e422d62602ee5263ca2113e9f3d800e905a4" + "reference": "6dac1dee3fb51704767c69a07aead1bc75c12368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/config/zipball/08b6e422d62602ee5263ca2113e9f3d800e905a4", - "reference": "08b6e422d62602ee5263ca2113e9f3d800e905a4", + "url": "https://api.github.com/repos/illuminate/config/zipball/6dac1dee3fb51704767c69a07aead1bc75c12368", + "reference": "6dac1dee3fb51704767c69a07aead1bc75c12368", "shasum": "" }, "require": { - "illuminate/contracts": "5.7.*", - "illuminate/support": "5.7.*", + "illuminate/contracts": "5.8.*", + "illuminate/support": "5.8.*", "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7-dev" + "dev-master": "5.8-dev" } }, "autoload": { @@ -344,32 +161,32 @@ ], "description": "The Illuminate Config package.", "homepage": "https://laravel.com", - "time": "2018-10-06T18:48:42+00:00" + "time": "2019-02-14T12:51:50+00:00" }, { "name": "illuminate/container", - "version": "v5.7.20", + "version": "v5.8.4", "source": { "type": "git", "url": "https://github.com/illuminate/container.git", - "reference": "53a0991e918efaace42cde526a04fdb832128a03" + "reference": "b984960d2634c6be97b0dd368a8953e8c4e06ec7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/container/zipball/53a0991e918efaace42cde526a04fdb832128a03", - "reference": "53a0991e918efaace42cde526a04fdb832128a03", + "url": "https://api.github.com/repos/illuminate/container/zipball/b984960d2634c6be97b0dd368a8953e8c4e06ec7", + "reference": "b984960d2634c6be97b0dd368a8953e8c4e06ec7", "shasum": "" }, "require": { - "illuminate/contracts": "5.7.*", - "illuminate/support": "5.7.*", + "illuminate/contracts": "5.8.*", + "illuminate/support": "5.8.*", "php": "^7.1.3", "psr/container": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7-dev" + "dev-master": "5.8-dev" } }, "autoload": { @@ -389,20 +206,20 @@ ], "description": "The Illuminate Container package.", "homepage": "https://laravel.com", - "time": "2018-12-18T14:00:02+00:00" + "time": "2019-03-03T15:13:35+00:00" }, { "name": "illuminate/contracts", - "version": "v5.7.20", + "version": "v5.8.4", "source": { "type": "git", "url": "https://github.com/illuminate/contracts.git", - "reference": "758927e5e925c1d442a1faaa1356675ceba0194c" + "reference": "3e3a9a654adbf798e05491a5dbf90112df1effde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/758927e5e925c1d442a1faaa1356675ceba0194c", - "reference": "758927e5e925c1d442a1faaa1356675ceba0194c", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/3e3a9a654adbf798e05491a5dbf90112df1effde", + "reference": "3e3a9a654adbf798e05491a5dbf90112df1effde", "shasum": "" }, "require": { @@ -413,7 +230,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7-dev" + "dev-master": "5.8-dev" } }, "autoload": { @@ -433,27 +250,27 @@ ], "description": "The Illuminate Contracts package.", "homepage": "https://laravel.com", - "time": "2018-11-15T13:49:08+00:00" + "time": "2019-02-18T18:37:54+00:00" }, { "name": "illuminate/filesystem", - "version": "v5.7.20", + "version": "v5.8.4", "source": { "type": "git", "url": "https://github.com/illuminate/filesystem.git", - "reference": "19ba2ac5f85b7505d7c2bf6307d10633f9f3c6b0" + "reference": "8aef3ed5028eea80fa20287b776d6ec8e7eafbba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/filesystem/zipball/19ba2ac5f85b7505d7c2bf6307d10633f9f3c6b0", - "reference": "19ba2ac5f85b7505d7c2bf6307d10633f9f3c6b0", + "url": "https://api.github.com/repos/illuminate/filesystem/zipball/8aef3ed5028eea80fa20287b776d6ec8e7eafbba", + "reference": "8aef3ed5028eea80fa20287b776d6ec8e7eafbba", "shasum": "" }, "require": { - "illuminate/contracts": "5.7.*", - "illuminate/support": "5.7.*", + "illuminate/contracts": "5.8.*", + "illuminate/support": "5.8.*", "php": "^7.1.3", - "symfony/finder": "^4.1" + "symfony/finder": "^4.2" }, "suggest": { "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.0).", @@ -465,7 +282,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7-dev" + "dev-master": "5.8-dev" } }, "autoload": { @@ -485,43 +302,45 @@ ], "description": "The Illuminate Filesystem package.", "homepage": "https://laravel.com", - "time": "2018-12-28T14:33:29+00:00" + "time": "2019-02-18T18:37:54+00:00" }, { "name": "illuminate/support", - "version": "v5.7.20", + "version": "v5.8.4", "source": { "type": "git", "url": "https://github.com/illuminate/support.git", - "reference": "ea3f30dd824bba52bcff4290dc7431b0ffb478e1" + "reference": "07062f5750872a31e086ff37a7c50ac18b8c417c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/illuminate/support/zipball/ea3f30dd824bba52bcff4290dc7431b0ffb478e1", - "reference": "ea3f30dd824bba52bcff4290dc7431b0ffb478e1", + "url": "https://api.github.com/repos/illuminate/support/zipball/07062f5750872a31e086ff37a7c50ac18b8c417c", + "reference": "07062f5750872a31e086ff37a7c50ac18b8c417c", "shasum": "" }, "require": { "doctrine/inflector": "^1.1", + "ext-json": "*", "ext-mbstring": "*", - "illuminate/contracts": "5.7.*", - "nesbot/carbon": "^1.26.3", + "illuminate/contracts": "5.8.*", + "nesbot/carbon": "^1.26.3 || ^2.0", "php": "^7.1.3" }, "conflict": { "tightenco/collect": "<5.5.33" }, "suggest": { - "illuminate/filesystem": "Required to use the composer class (5.7.*).", + "illuminate/filesystem": "Required to use the composer class (5.8.*).", "moontoast/math": "Required to use ordered UUIDs (^1.1).", "ramsey/uuid": "Required to use Str::uuid() (^3.7).", - "symfony/process": "Required to use the composer class (^4.1).", - "symfony/var-dumper": "Required to use the dd function (^4.1)." + "symfony/process": "Required to use the composer class (^4.2).", + "symfony/var-dumper": "Required to use the dd function (^4.2).", + "vlucas/phpdotenv": "Required to use the env helper (^3.3)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7-dev" + "dev-master": "5.8-dev" } }, "autoload": { @@ -544,32 +363,34 @@ ], "description": "The Illuminate Support package.", "homepage": "https://laravel.com", - "time": "2019-01-07T13:39:07+00:00" + "time": "2019-03-12T13:17:00+00:00" }, { "name": "nesbot/carbon", - "version": "1.36.2", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9" + "reference": "dd16fedc022180ea4292a03aabe95e9895677911" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9", - "reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/dd16fedc022180ea4292a03aabe95e9895677911", + "reference": "dd16fedc022180ea4292a03aabe95e9895677911", "shasum": "" }, "require": { - "php": ">=5.3.9", - "symfony/translation": "~2.6 || ~3.0 || ~4.0" + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "symfony/translation": "^3.4 || ^4.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7" - }, - "suggest": { - "friendsofphp/php-cs-fixer": "Needed for the `composer phpcs` command. Allow to automatically fix code style.", - "phpstan/phpstan": "Needed for the `composer phpstan` command. Allow to detect potential errors." + "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", + "kylekatarnls/multi-tester": "^0.1", + "phpmd/phpmd": "^2.6", + "phpstan/phpstan": "^0.10.8", + "phpunit/phpunit": "^7.5 || ^8.0", + "squizlabs/php_codesniffer": "^3.4" }, "type": "library", "extra": { @@ -581,7 +402,7 @@ }, "autoload": { "psr-4": { - "": "src/" + "Carbon\\": "src/Carbon/" } }, "notification-url": "https://packagist.org/downloads/", @@ -602,7 +423,7 @@ "datetime", "time" ], - "time": "2018-12-28T10:07:33+00:00" + "time": "2019-03-12T09:31:40+00:00" }, { "name": "psr/container", @@ -653,56 +474,6 @@ ], "time": "2017-02-14T16:28:37+00:00" }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, { "name": "psr/simple-cache", "version": "1.0.1", @@ -751,68 +522,32 @@ ], "time": "2017-10-23T01:57:42+00:00" }, - { - "name": "ralouphie/getallheaders", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "~3.7.0", - "satooshi/php-coveralls": ">=1.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "time": "2016-02-11T07:05:27+00:00" - }, { "name": "symfony/console", - "version": "v4.1.3", + "version": "v4.2.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "ca80b8ced97cf07390078b29773dc384c39eee1f" + "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/ca80b8ced97cf07390078b29773dc384c39eee1f", - "reference": "ca80b8ced97cf07390078b29773dc384c39eee1f", + "url": "https://api.github.com/repos/symfony/console/zipball/9dc2299a016497f9ee620be94524e6c0af0280a9", + "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9", "shasum": "" }, "require": { "php": "^7.1.3", + "symfony/contracts": "^1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "symfony/dependency-injection": "<3.4", "symfony/process": "<3.3" }, + "provide": { + "psr/log-implementation": "1.0" + }, "require-dev": { "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", @@ -822,7 +557,7 @@ "symfony/process": "~3.4|~4.0" }, "suggest": { - "psr/log-implementation": "For using the console logger", + "psr/log": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" @@ -830,7 +565,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -857,7 +592,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:24:31+00:00" + "time": "2019-02-23T15:17:42+00:00" }, { "name": "symfony/contracts", @@ -929,16 +664,16 @@ }, { "name": "symfony/finder", - "version": "v4.2.2", + "version": "v4.2.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9094d69e8c6ee3fe186a0ec5a4f1401e506071ce" + "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9094d69e8c6ee3fe186a0ec5a4f1401e506071ce", - "reference": "9094d69e8c6ee3fe186a0ec5a4f1401e506071ce", + "url": "https://api.github.com/repos/symfony/finder/zipball/267b7002c1b70ea80db0833c3afe05f0fbde580a", + "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a", "shasum": "" }, "require": { @@ -974,7 +709,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-01-03T09:07:35+00:00" + "time": "2019-02-23T15:42:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1036,16 +771,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", - "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", "shasum": "" }, "require": { @@ -1091,20 +826,69 @@ "portable", "shim" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2018-09-21T13:07:52+00:00" + }, + { + "name": "symfony/process", + "version": "v4.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "6c05edb11fbeff9e2b324b4270ecb17911a8b7ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/6c05edb11fbeff9e2b324b4270ecb17911a8b7ad", + "reference": "6c05edb11fbeff9e2b324b4270ecb17911a8b7ad", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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 Process Component", + "homepage": "https://symfony.com", + "time": "2019-01-24T22:05:03+00:00" }, { "name": "symfony/translation", - "version": "v4.2.2", + "version": "v4.2.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "939fb792d73f2ce80e6ae9019d205fc480f1c9a0" + "reference": "748464177a77011f8f4cdd076773862ce4915f8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/939fb792d73f2ce80e6ae9019d205fc480f1c9a0", - "reference": "939fb792d73f2ce80e6ae9019d205fc480f1c9a0", + "url": "https://api.github.com/repos/symfony/translation/zipball/748464177a77011f8f4cdd076773862ce4915f8f", + "reference": "748464177a77011f8f4cdd076773862ce4915f8f", "shasum": "" }, "require": { @@ -1164,20 +948,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2019-01-03T09:07:35+00:00" + "time": "2019-02-27T03:31:50+00:00" }, { "name": "symfony/yaml", - "version": "v4.2.2", + "version": "v4.2.4", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "d0aa6c0ea484087927b49fd513383a7d36190ca6" + "reference": "761fa560a937fd7686e5274ff89dcfa87a5047df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d0aa6c0ea484087927b49fd513383a7d36190ca6", - "reference": "d0aa6c0ea484087927b49fd513383a7d36190ca6", + "url": "https://api.github.com/repos/symfony/yaml/zipball/761fa560a937fd7686e5274ff89dcfa87a5047df", + "reference": "761fa560a937fd7686e5274ff89dcfa87a5047df", "shasum": "" }, "require": { @@ -1223,7 +1007,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-01-03T09:07:35+00:00" + "time": "2019-02-23T15:17:42+00:00" } ], "packages-dev": [], @@ -1234,8 +1018,8 @@ "prefer-lowest": false, "platform": { "php": "^7.1.3", - "ext-json": "*", - "ext-curl": "*" + "ext-curl": "*", + "ext-json": "*" }, "platform-dev": [] } diff --git a/src/Application.php b/src/Application.php index 8dee20b..4878db6 100644 --- a/src/Application.php +++ b/src/Application.php @@ -5,6 +5,7 @@ */ namespace Magento\Console; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Container\Container; use Magento\Console\Command; use Magento\Console\Context\ContextList; @@ -39,7 +40,8 @@ public function __construct(Container $container, ContextList $contextList) } /** - * @inheritdoc + * @return array + * @throws BindingResolutionException */ protected function getDefaultCommands(): array { @@ -62,6 +64,7 @@ protected function getDefaultCommands(): array /** * @return array + * @throws BindingResolutionException */ private function fetchMagentoCommands(): array { @@ -72,10 +75,14 @@ private function fetchMagentoCommands(): array $context = $this->contextList->getCurrent(); $commands = []; - foreach ($context->get('commands') as $cName => $cData) { + foreach ($context->get('commands') as $cData) { + if (in_array($cData['name'], ['list', 'help'])) { + continue; + } + /** @var Command\Remote $command */ $command = $this->container->make(Command\Remote::class); - $command->setName($cName) + $command->setName($cData['name']) ->setDescription($cData['description']) ->setHelp($cData['help']); @@ -88,6 +95,10 @@ private function fetchMagentoCommands(): array } foreach ($cData['definition']['options'] as $oName => $oData) { + if (in_array($oName, ['help', 'quiet', 'verbose', 'version', 'ansi', 'no-ansi', 'no-interaction'])) { + continue; + } + $command->addOption( $oName, $oData['shortcut'] ?? null, diff --git a/src/Client/Client.php b/src/Client/Client.php deleted file mode 100644 index c3cbfd3..0000000 --- a/src/Client/Client.php +++ /dev/null @@ -1,55 +0,0 @@ -encoder = $encoder; - - parent::__construct([]); - } - - /** - * @param string $uri - * @param string $key - * @param string $type - * @param array $params - * @return ResponseInterface - */ - public function post( - string $uri, - string $key, - string $type, - array $params - ): ResponseInterface { - $params['type'] = $type; - - return parent::post($uri, [ - 'form_params' => [ - 'token' => $this->encoder->encode($params, $key) - ] - ]); - } -} diff --git a/src/Client/ClientFactory.php b/src/Client/ClientFactory.php deleted file mode 100644 index 0cc9074..0000000 --- a/src/Client/ClientFactory.php +++ /dev/null @@ -1,35 +0,0 @@ -container = $container; - } - - /** - * @return Client - */ - public function create(): Client - { - return $this->container->make(Client::class); - } -} diff --git a/src/Command/Context/AddCommand.php b/src/Command/Context/AddCommand.php index 2fae5b5..66f1875 100644 --- a/src/Command/Context/AddCommand.php +++ b/src/Command/Context/AddCommand.php @@ -7,24 +7,23 @@ */ namespace Magento\Console\Command\Context; -use Magento\Console\Client\Client; -use Magento\Console\Client\ClientFactory; use Magento\Console\Context\ContextList; +use Magento\Console\Shell\ShellFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use GuzzleHttp\Exception\GuzzleException; /** * Add new context */ class AddCommand extends Command { + private const NAME = 'context:add'; private const ARG_NAME = 'name'; + private const ARG_TYPE = 'type'; private const ARG_URL = 'url'; - private const ARG_KEY = 'key'; /** * @var ContextList @@ -32,18 +31,18 @@ class AddCommand extends Command private $contextList; /** - * @var ClientFactory + * @var ShellFactory */ - private $clientFactory; + private $sshFactory; /** * @param ContextList $contextList - * @param ClientFactory $clientFactory + * @param ShellFactory $shellFactory */ - public function __construct(ContextList $contextList, ClientFactory $clientFactory) + public function __construct(ContextList $contextList, ShellFactory $shellFactory) { $this->contextList = $contextList; - $this->clientFactory = $clientFactory; + $this->sshFactory = $shellFactory; parent::__construct(); } @@ -53,50 +52,39 @@ public function __construct(ContextList $contextList, ClientFactory $clientFacto */ protected function configure(): void { - $this->setName('context:add') + $this->setName(self::NAME) ->setDescription('Add context') - ->addArgument(self::ARG_NAME, InputArgument::REQUIRED) - ->addArgument(self::ARG_URL, InputArgument::REQUIRED) - ->addArgument(self::ARG_KEY, InputArgument::REQUIRED); + ->addArgument(self::ARG_NAME, InputArgument::REQUIRED, 'Name of context') + ->addArgument( + self::ARG_TYPE, + InputArgument::REQUIRED, + 'Type one of ' . implode(', ', [ShellFactory::TYPE_LOCAL, ShellFactory::TYPE_REMOTE])) + ->addArgument(self::ARG_URL, InputArgument::REQUIRED, 'URL address'); parent::configure(); } /** - * {@inheritdoc} + * @inheritdoc * - * @throws GuzzleException + * @throws \Exception */ protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument(self::ARG_NAME); - $client = $this->clientFactory->create(); - $response = $client->post( + $process = $this->sshFactory->create( + $input->getArgument(self::ARG_TYPE), $input->getArgument(self::ARG_URL), - $input->getArgument(self::ARG_KEY), - Client::TYPE_LIST, - [] + 'list --format=json' ); - - if ($response->getStatusCode() !== 200) { - throw new \RuntimeException($response->getBody()->getContents()); - } - - $commands = (array)json_decode( - $response->getBody()->getContents(), - JSON_OBJECT_AS_ARRAY - ); - - if (!$commands) { - throw new \RuntimeException('Commands are not defined'); - } + $process->mustRun(); $this->contextList->add( $name, + $input->getArgument(self::ARG_TYPE), $input->getArgument(self::ARG_URL), - $input->getArgument(self::ARG_KEY), - $commands + json_decode($process->getOutput(), true)['commands'] ); $output->writeln('Context added.'); diff --git a/src/Command/Context/GetCommand.php b/src/Command/Context/GetCommand.php index e2c77fd..9be71d8 100644 --- a/src/Command/Context/GetCommand.php +++ b/src/Command/Context/GetCommand.php @@ -17,6 +17,8 @@ */ class GetCommand extends Command { + private const NAME = 'context'; + /** * @var ContextList */ @@ -37,7 +39,7 @@ public function __construct(ContextList $contextList) */ protected function configure(): void { - $this->setName('context') + $this->setName(self::NAME) ->setDescription('Display current context'); parent::configure(); diff --git a/src/Command/Context/ListCommand.php b/src/Command/Context/ListCommand.php index 52e7c68..3247cb4 100644 --- a/src/Command/Context/ListCommand.php +++ b/src/Command/Context/ListCommand.php @@ -52,8 +52,8 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($this->contextList->getAll() as $name => $data) { $rows[] = [ $name, + $data->get('type'), $data->get('url'), - $data->get('key') ]; } @@ -64,7 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } $table = new Table($output); - $table->setHeaders(['Name', 'URL', 'Key']) + $table->setHeaders(['Name', 'Type', 'URL']) ->setRows($rows) ->render(); } diff --git a/src/Command/Context/RemoveCommand.php b/src/Command/Context/RemoveCommand.php index 22986fc..e224e3a 100644 --- a/src/Command/Context/RemoveCommand.php +++ b/src/Command/Context/RemoveCommand.php @@ -18,6 +18,7 @@ */ class RemoveCommand extends Command { + private const NAME = 'context:remove'; private const ARG_NAME = 'name'; /** @@ -40,7 +41,7 @@ public function __construct(ContextList $contextList) */ protected function configure(): void { - $this->setName('context:remove') + $this->setName(self::NAME) ->setDescription('Remove context') ->addArgument(self::ARG_NAME, InputArgument::REQUIRED); diff --git a/src/Command/Remote.php b/src/Command/Remote.php index 4b94464..2169304 100644 --- a/src/Command/Remote.php +++ b/src/Command/Remote.php @@ -5,9 +5,8 @@ */ namespace Magento\Console\Command; -use Magento\Console\Client\Client; -use Magento\Console\Client\ClientFactory; use Magento\Console\Context\ContextList; +use Magento\Console\Shell\ShellFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -18,23 +17,23 @@ class Remote extends Command { /** - * @var ClientFactory + * @var ContextList */ - private $clientFactory; + private $contextList; /** - * @var ContextList + * @var ShellFactory */ - private $contextList; + private $shellFactory; /** - * @param ClientFactory $clientFactory * @param ContextList $contextList + * @param ShellFactory $shellFactory */ - public function __construct(ClientFactory $clientFactory, ContextList $contextList) + public function __construct(ContextList $contextList, ShellFactory $shellFactory) { - $this->clientFactory = $clientFactory; $this->contextList = $contextList; + $this->shellFactory = $shellFactory; parent::__construct(); } @@ -46,23 +45,14 @@ public function __construct(ClientFactory $clientFactory, ContextList $contextLi */ protected function execute(InputInterface $input, OutputInterface $output) { - $client = $this->clientFactory->create(); - - $response = $client->post( + $process = $this->shellFactory->create( + $this->contextList->getCurrent()->get('type'), $this->contextList->getCurrent()->get('url'), - $this->contextList->getCurrent()->get('key'), - Client::TYPE_RUN, - [ - 'name' => $this->getName(), - 'arguments' => $input->getArguments(), - 'options' => $input->getOptions() - ] + (string)$input ); - $tpl = $response->getStatusCode() === 200 - ? '%s' - : '%s'; - - $output->write(sprintf($tpl, $response->getBody()->getContents())); + $process->mustRun(function ($type, string $buffer) use ($output) { + $output->write($buffer); + }); } } diff --git a/src/Context/ContextList.php b/src/Context/ContextList.php index c16db48..a4bf4df 100644 --- a/src/Context/ContextList.php +++ b/src/Context/ContextList.php @@ -49,18 +49,18 @@ public function has(string $name): bool /** * @param string $name + * @param string $type * @param string $url - * @param string $key * @param array $commands */ - public function add(string $name, string $url, string $key, array $commands): void + public function add(string $name, string $type, string $url, array $commands): void { $config = $this->reader->read(); $config['contexts'][$name] = [ 'name' => $name, + 'type' => $type, 'url' => $url, 'commands' => $commands, - 'key' => $key, ]; $this->writer->write($config); diff --git a/src/Shell/ShellFactory.php b/src/Shell/ShellFactory.php new file mode 100644 index 0000000..e3a860f --- /dev/null +++ b/src/Shell/ShellFactory.php @@ -0,0 +1,35 @@ + Date: Fri, 15 Mar 2019 08:39:25 -0500 Subject: [PATCH 9/9] Removed JWT --- composer.json | 1 - composer.lock | 48 +------------------------------------------- src/Auth/Encoder.php | 24 ---------------------- 3 files changed, 1 insertion(+), 72 deletions(-) delete mode 100644 src/Auth/Encoder.php diff --git a/composer.json b/composer.json index 7d3ac5a..6f92a7e 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,6 @@ "php": "^7.1.3", "ext-curl": "*", "ext-json": "*", - "firebase/php-jwt": "^5.0", "illuminate/config": "^5.7", "illuminate/container": "^5.7", "illuminate/filesystem": "^5.7", diff --git a/composer.lock b/composer.lock index 62836a0..1846e52 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": "fdb5481dc2504bda9fe1073c27a2259f", + "content-hash": "fe05cf5b44c167f47f773267e8d818bb", "packages": [ { "name": "doctrine/inflector", @@ -73,52 +73,6 @@ ], "time": "2018-01-09T20:05:19+00:00" }, - { - "name": "firebase/php-jwt", - "version": "v5.0.0", - "source": { - "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", - "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": " 4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" - } - ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", - "time": "2017-06-27T22:17:23+00:00" - }, { "name": "illuminate/config", "version": "v5.8.4", diff --git a/src/Auth/Encoder.php b/src/Auth/Encoder.php deleted file mode 100644 index a406df4..0000000 --- a/src/Auth/Encoder.php +++ /dev/null @@ -1,24 +0,0 @@ -