From 979adff5821f1bfa40f11a870472eb91cdabcca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 1 May 2020 14:45:50 -0600 Subject: [PATCH 01/44] add ext-json --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 1a124ca..47493dd 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ } ], "require": { + "ext-json": "*", "php": "^7.2", "symfony/console": "^5.0", "symfony/config": "^5.0" From 603a6c8988f2ea087ff693b1ef960217d2693ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 1 May 2020 14:46:21 -0600 Subject: [PATCH 02/44] add Config class --- src/Config/Config.php | 303 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 src/Config/Config.php diff --git a/src/Config/Config.php b/src/Config/Config.php new file mode 100644 index 0000000..68c620a --- /dev/null +++ b/src/Config/Config.php @@ -0,0 +1,303 @@ +boostrapDir = $boostrapDir; + $this->indexDir = $indexDir; + $this->indexFile = $indexFile; + $this->rootDir = $rootDir; + $this->sourceDir = $sourceDir; + $this->commandsDir = $commandsDir; + } + + /** + * @return string + */ + public function getBoostrapDir(): string + { + return $this->boostrapDir; + } + + /** + * @param string $boostrapDir + * + * @return static + */ + public function setBoostrapDir(string $boostrapDir) + { + $this->boostrapDir = $boostrapDir; + + return $this; + } + + /** + * @return string + */ + public function getIndexDir(): string + { + return $this->indexDir; + } + + /** + * @param string $indexDir + * + * @return static + */ + public function setIndexDir(string $indexDir) + { + $this->indexDir = $indexDir; + + return $this; + } + + /** + * @return string + */ + public function getIndexFile(): string + { + return $this->indexFile; + } + + /** + * @param string $indexFile + * + * @return static + */ + public function setIndexFile(string $indexFile) + { + $this->indexFile = $indexFile; + + return $this; + } + + /** + * @return string + */ + public function getRootDir(): string + { + return $this->rootDir; + } + + /** + * @param string $rootDir + * + * @return static + */ + public function setRootDir(string $rootDir) + { + $this->rootDir = $rootDir; + + return $this; + } + + /** + * @return string + */ + public function getSourceDir(): string + { + return $this->sourceDir; + } + + /** + * @param string $sourceDir + * + * @return static + */ + public function setSourceDir(string $sourceDir) + { + $this->sourceDir = $sourceDir; + + return $this; + } + + /** + * @return string|null + */ + public function getCommandsDir(): ?string + { + return $this->commandsDir; + } + + /** + * @param string|null $commandsDir + * + * @return static + */ + public function setCommandsDir(?string $commandsDir) + { + $this->commandsDir = $commandsDir; + + return $this; + } + + /** + * @param array $params + * + * @return array + */ + protected static function mergeDefaults(array $params): array + { + $defaults = [ + 'bootstrapDir' => 'app', + 'indexDir' => 'public', + 'indexFile' => 'index.php', + 'rootDir' => null, + 'sourceDir' => 'src', + 'commandsDir' => null, + ]; + + return $defaults + $params; + } + + /** + * @param array $params + * + * @throws InvalidArgumentException + */ + protected static function validate(array $params): void + { + [ + 'bootstrapDir' => $bootstrapDir, + 'indexDir' => $indexDir, + 'indexFile' => $indexFile, + 'rootDir' => $rootDir, + 'sourceDir' => $sourceDir, + 'commandsDir' => $commandsDir, + ] = $params; + + $error = null; + + if (!is_string($bootstrapDir) || empty($bootstrapDir)) { + $error = '`bootstrapDir` must be a string'; + } elseif (!is_string($indexDir) || empty($indexDir)) { + $error = '`indexDir` must be a string'; + } elseif (!is_string($indexFile) || empty($indexFile)) { + $error = '`indexFile` must be a string'; + } elseif (!is_string($rootDir) || empty($rootDir)) { + $error = '`rootDir` must be a string'; + } elseif (!is_string($sourceDir) || empty($sourceDir)) { + $error = '`sourceDir` must be a string'; + } elseif (!empty($commandsDir) && !is_string($commandsDir)) { + $error = '`commandsDir` must be a string'; + } + + if ($error) { + throw new InvalidArgumentException($error); + } + } + + /** + * @param array $params + * + * @return Config + * + * @throws InvalidArgumentException + */ + public static function fromArray(array $params): Config + { + $params = self::mergeDefaults($params); + self::validate($params); + + return new self( + $params['bootstrapDir'], + $params['indexDir'], + $params['indexFile'], + $params['rootDir'], + $params['sourceDir'], + $params['commandsDir'] + ); + } + + /** + * @return Config + * + * @throws InvalidArgumentException + */ + public static function fromEnvironment(): Config + { + $params = self::mergeDefaults([ + 'bootstrapDir' => getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR), + 'indexDir' => getenv(self::SLIM_CONSOLE_INDEX_DIR), + 'indexFile' => getenv(self::SLIM_CONSOLE_INDEX_FILE), + 'rootDir' => getenv(self::SLIM_CONSOLE_ROOT_DIR), + 'sourceDir' => getenv(self::SLIM_CONSOLE_SOURCE_DIR), + 'commandsDir' => getenv(self::SLIM_CONSOLE_COMMANDS_DIR), + ]); + + self::validate($params); + + return new self( + $params['bootstrapDir'], + $params['indexDir'], + $params['indexFile'], + $params['rootDir'], + $params['sourceDir'], + $params['commandsDir'] + ); + } +} From 209c11ce7e157f793728fa0f4c84d9eae7f2a603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 1 May 2020 14:46:31 -0600 Subject: [PATCH 03/44] add ConfigResolver --- .../CannotResolveConfigurationException.php | 18 +++ src/Config/ConfigResolver.php | 113 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/Config/CannotResolveConfigurationException.php create mode 100644 src/Config/ConfigResolver.php diff --git a/src/Config/CannotResolveConfigurationException.php b/src/Config/CannotResolveConfigurationException.php new file mode 100644 index 0000000..f6a9bdf --- /dev/null +++ b/src/Config/CannotResolveConfigurationException.php @@ -0,0 +1,18 @@ +rootDir = $rootDir; + } + + /** + * @return Config + * + * @throws CannotResolveConfigurationException + * @throws InvalidArgumentException + * @throws RuntimeException + */ + public function resolve(): Config + { + try { + return Config::fromEnvironment(); + } catch (InvalidArgumentException $e) { + return $this->attemptResolvingConfigurationFromSupportedFormats(); + } + } + + /** + * @return Config + * + * @throws CannotResolveConfigurationException + * @throws InvalidArgumentException + * @throws RuntimeException + */ + protected function attemptResolvingConfigurationFromSupportedFormats(): Config + { + foreach ($this->supportedFormats as $format) { + $path = $this->rootDir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME . ".{$format}"; + if (file_exists($path)) { + return $this->attemptParsingConfigurationFromFile($path, $format); + } + } + + throw new CannotResolveConfigurationException(); + } + + /** + * @param string $path + * @param string $format + * + * @return Config + * + * @throws InvalidArgumentException + * @throws RuntimeException + */ + protected function attemptParsingConfigurationFromFile(string $path, string $format): Config + { + switch ($format) { + case self::FORMAT_PHP: + $parsed = require_once $path; + + if (!is_array($parsed)) { + throw new InvalidArgumentException('Slim Console configuration should be an array'); + } + + return Config::fromArray($parsed); + + case self::FORMAT_JSON: + $contents = file_get_contents($path); + $parsed = json_decode($contents); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration'); + } else if (!is_array($parsed)) { + throw new InvalidArgumentException('Slim Console: configuration should be an array'); + } + + return Config::fromArray($parsed); + + default: + throw new RuntimeException("Invalid configuration format: {$format}"); + } + } +} From 21eed65fa2d41ed4803572c1e3e1c3ab8bd54d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=83=C2=A9rub=C3=83=C2=A9?= Date: Fri, 1 May 2020 15:05:27 -0600 Subject: [PATCH 04/44] add periods to error messages --- src/Config/Config.php | 12 ++++++------ src/Config/ConfigResolver.php | 21 +++++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 68c620a..5a04e75 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -233,17 +233,17 @@ protected static function validate(array $params): void $error = null; if (!is_string($bootstrapDir) || empty($bootstrapDir)) { - $error = '`bootstrapDir` must be a string'; + $error = '`bootstrapDir` must be a string.'; } elseif (!is_string($indexDir) || empty($indexDir)) { - $error = '`indexDir` must be a string'; + $error = '`indexDir` must be a string.'; } elseif (!is_string($indexFile) || empty($indexFile)) { - $error = '`indexFile` must be a string'; + $error = '`indexFile` must be a string.'; } elseif (!is_string($rootDir) || empty($rootDir)) { - $error = '`rootDir` must be a string'; + $error = '`rootDir` must be a string.'; } elseif (!is_string($sourceDir) || empty($sourceDir)) { - $error = '`sourceDir` must be a string'; + $error = '`sourceDir` must be a string.'; } elseif (!empty($commandsDir) && !is_string($commandsDir)) { - $error = '`commandsDir` must be a string'; + $error = '`commandsDir` must be a string.'; } if ($error) { diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 7cc1054..738fc38 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -14,15 +14,18 @@ use RuntimeException; class ConfigResolver { - public const FORMAT_PHP = 'PHP'; - public const FORMAT_JSON = 'JSON'; - public const FORMAT_YAML = 'YAML'; public const CONFIG_FILENAME = 'slim-console.config'; + public const FORMAT_PHP = 'php'; + + public const FORMAT_JSON = 'json'; + + /** + * @var string[] + */ protected $supportedFormats = [ self::FORMAT_PHP, self::FORMAT_JSON, - //self::FORMAT_YAML, ]; /** @@ -39,6 +42,8 @@ public function __construct(string $rootDir) } /** + * Resolve configuration. Environment takes precedence over configuration file. + * * @return Config * * @throws CannotResolveConfigurationException @@ -89,7 +94,7 @@ protected function attemptParsingConfigurationFromFile(string $path, string $for $parsed = require_once $path; if (!is_array($parsed)) { - throw new InvalidArgumentException('Slim Console configuration should be an array'); + throw new InvalidArgumentException('Slim Console configuration should be an array.'); } return Config::fromArray($parsed); @@ -99,15 +104,15 @@ protected function attemptParsingConfigurationFromFile(string $path, string $for $parsed = json_decode($contents); if (json_last_error() !== JSON_ERROR_NONE) { - throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration'); + throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration.'); } else if (!is_array($parsed)) { - throw new InvalidArgumentException('Slim Console: configuration should be an array'); + throw new InvalidArgumentException('Slim Console configuration should be an array.'); } return Config::fromArray($parsed); default: - throw new RuntimeException("Invalid configuration format: {$format}"); + throw new RuntimeException("Invalid configuration format `{$format}`."); } } } From 2568df609e3b218c0bb9260dd3608a0d1f474877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=83=C2=A9rub=C3=83=C2=A9?= Date: Fri, 1 May 2020 15:05:27 -0600 Subject: [PATCH 05/44] add getters and setters for Config object --- src/Application.php | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Application.php b/src/Application.php index 5f85abe..8a886a1 100644 --- a/src/Application.php +++ b/src/Application.php @@ -10,6 +10,7 @@ namespace Slim\Console; +use Slim\Console\Config\Config; use Symfony\Component\Console\Application as SymfonyApplication; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -17,11 +18,23 @@ class Application extends SymfonyApplication { - private const VERSION = '0.1'; + protected const APPLICATION_NAME = 'Slim Console'; - public function __construct() + protected const VERSION = '0.1'; + + /** + * @var Config + */ + protected $config; + + /** + * @param Config $config + */ + public function __construct(Config $config) { - parent::__construct('Slim Console', self::VERSION); + parent::__construct(static::APPLICATION_NAME, static::VERSION); + + $this->config = $config; } /** @@ -48,4 +61,24 @@ public function doRun(InputInterface $input, OutputInterface $output): int return parent::doRun($input, $output); } + + /** + * @return Config + */ + public function getConfig(): Config + { + return $this->config; + } + + /** + * @param Config $config + * + * @return static + */ + public function setConfig(Config $config) + { + $this->config = $config; + + return $this; + } } From 6259b75c5033cdcf3139e1c1a99830267ff2aa1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=83=C2=A9rub=C3=83=C2=A9?= Date: Fri, 1 May 2020 15:05:27 -0600 Subject: [PATCH 06/44] create AbstractCommand class --- src/Command/AbstractCommand.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/Command/AbstractCommand.php diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php new file mode 100644 index 0000000..48ca7df --- /dev/null +++ b/src/Command/AbstractCommand.php @@ -0,0 +1,33 @@ +getApplication(); + + if ($app instanceof Application === false) { + throw new RuntimeException('Cannot call method `getConfig()` on ' . get_class($app)); + } + + return $app->getConfig(); + } +} From e907216dbbe8826e4dff1453c817ccec94d20055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=83=C2=A9rub=C3=83=C2=A9?= Date: Fri, 1 May 2020 15:05:27 -0600 Subject: [PATCH 07/44] add config resolving --- bin/slim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/slim b/bin/slim index 9896594..5176fad 100755 --- a/bin/slim +++ b/bin/slim @@ -10,6 +10,7 @@ declare(strict_types=1); use Slim\Console\Application; +use Slim\Console\Config\ConfigResolver; if (file_exists(__DIR__ . '/../../../autoload.php')) { require __DIR__ . '/../../../autoload.php'; @@ -17,5 +18,7 @@ if (file_exists(__DIR__ . '/../../../autoload.php')) { require __DIR__ . '/../vendor/autoload.php'; } -$app = new Application(); +$config = (new ConfigResolver())->resolve(); + +$app = new Application($config); $app->run(); From 70b4b3eac764a3c1acce0b088f2a28ebc22b081b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 1 May 2020 18:31:08 -0600 Subject: [PATCH 08/44] rename Application to App --- src/{Application.php => App.php} | 2 +- src/Command/AbstractCommand.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/{Application.php => App.php} (97%) diff --git a/src/Application.php b/src/App.php similarity index 97% rename from src/Application.php rename to src/App.php index 8a886a1..6b70424 100644 --- a/src/Application.php +++ b/src/App.php @@ -16,7 +16,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Throwable; -class Application extends SymfonyApplication +class App extends SymfonyApplication { protected const APPLICATION_NAME = 'Slim Console'; diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index 48ca7df..fe705ba 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -11,7 +11,7 @@ namespace Slim\Console\Command; use RuntimeException; -use Slim\Console\Application; +use Slim\Console\App; use Slim\Console\Config\Config; use Symfony\Component\Console\Command\Command; @@ -24,7 +24,7 @@ public function getConfig(): ?Config { $app = $this->getApplication(); - if ($app instanceof Application === false) { + if ($app instanceof App === false) { throw new RuntimeException('Cannot call method `getConfig()` on ' . get_class($app)); } From a30a337c877b0b5beda8c0fe734b21c04e3cd2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 1 May 2020 18:32:16 -0600 Subject: [PATCH 09/44] remove setters and make constructor protected --- src/Config/Config.php | 75 +------------------------------------------ 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 5a04e75..4b18e02 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -51,7 +51,6 @@ class Config { protected $commandsDir; /** - * Config constructor. * @param string $boostrapDir * @param string $indexDir * @param string $indexFile @@ -59,7 +58,7 @@ class Config { * @param string $sourceDir * @param string|null $commandsDir */ - public function __construct( + protected function __construct( string $boostrapDir, string $indexDir, string $indexFile, @@ -83,18 +82,6 @@ public function getBoostrapDir(): string return $this->boostrapDir; } - /** - * @param string $boostrapDir - * - * @return static - */ - public function setBoostrapDir(string $boostrapDir) - { - $this->boostrapDir = $boostrapDir; - - return $this; - } - /** * @return string */ @@ -103,18 +90,6 @@ public function getIndexDir(): string return $this->indexDir; } - /** - * @param string $indexDir - * - * @return static - */ - public function setIndexDir(string $indexDir) - { - $this->indexDir = $indexDir; - - return $this; - } - /** * @return string */ @@ -123,18 +98,6 @@ public function getIndexFile(): string return $this->indexFile; } - /** - * @param string $indexFile - * - * @return static - */ - public function setIndexFile(string $indexFile) - { - $this->indexFile = $indexFile; - - return $this; - } - /** * @return string */ @@ -143,18 +106,6 @@ public function getRootDir(): string return $this->rootDir; } - /** - * @param string $rootDir - * - * @return static - */ - public function setRootDir(string $rootDir) - { - $this->rootDir = $rootDir; - - return $this; - } - /** * @return string */ @@ -163,18 +114,6 @@ public function getSourceDir(): string return $this->sourceDir; } - /** - * @param string $sourceDir - * - * @return static - */ - public function setSourceDir(string $sourceDir) - { - $this->sourceDir = $sourceDir; - - return $this; - } - /** * @return string|null */ @@ -183,18 +122,6 @@ public function getCommandsDir(): ?string return $this->commandsDir; } - /** - * @param string|null $commandsDir - * - * @return static - */ - public function setCommandsDir(?string $commandsDir) - { - $this->commandsDir = $commandsDir; - - return $this; - } - /** * @param array $params * From c3e6c173e1351000d4625481d1c138435b717b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:42:54 -0600 Subject: [PATCH 10/44] rename Application to App --- bin/slim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/slim b/bin/slim index 5176fad..5fbaef6 100755 --- a/bin/slim +++ b/bin/slim @@ -9,7 +9,7 @@ declare(strict_types=1); -use Slim\Console\Application; +use Slim\Console\App; use Slim\Console\Config\ConfigResolver; if (file_exists(__DIR__ . '/../../../autoload.php')) { @@ -20,5 +20,5 @@ if (file_exists(__DIR__ . '/../../../autoload.php')) { $config = (new ConfigResolver())->resolve(); -$app = new Application($config); +$app = new App($config); $app->run(); From e2fc479f7baebd8ba0be068d5f1c294fb1fe70cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:43:36 -0600 Subject: [PATCH 11/44] rename APPLICATION_NAME constant to NAME --- src/App.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App.php b/src/App.php index 6b70424..9a93c07 100644 --- a/src/App.php +++ b/src/App.php @@ -18,7 +18,7 @@ class App extends SymfonyApplication { - protected const APPLICATION_NAME = 'Slim Console'; + protected const NAME = 'Slim Console'; protected const VERSION = '0.1'; @@ -32,7 +32,7 @@ class App extends SymfonyApplication */ public function __construct(Config $config) { - parent::__construct(static::APPLICATION_NAME, static::VERSION); + parent::__construct(static::NAME, static::VERSION); $this->config = $config; } From eaea4e3015d99c6f36772fb522fb1bb0c17a956f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:44:29 -0600 Subject: [PATCH 12/44] fix code style --- src/Config/Config.php | 3 ++- src/Config/ConfigResolver.php | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 4b18e02..2842746 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -12,7 +12,8 @@ use InvalidArgumentException; -class Config { +class Config +{ public const SLIM_CONSOLE_BOOTSTRAP_DIR = 'SLIM_CONSOLE_BOOTSTRAP_DIR'; public const SLIM_CONSOLE_INDEX_DIR = 'SLIM_CONSOLE_INDEX_DIR'; public const SLIM_CONSOLE_INDEX_FILE = 'SLIM_CONSOLE_INDEX_FILE'; diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 738fc38..bd92995 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -13,7 +13,8 @@ use InvalidArgumentException; use RuntimeException; -class ConfigResolver { +class ConfigResolver +{ public const CONFIG_FILENAME = 'slim-console.config'; public const FORMAT_PHP = 'php'; @@ -105,7 +106,7 @@ protected function attemptParsingConfigurationFromFile(string $path, string $for if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration.'); - } else if (!is_array($parsed)) { + } elseif (!is_array($parsed)) { throw new InvalidArgumentException('Slim Console configuration should be an array.'); } From 168aa57925fdea8e63d314dffdd1669c1e4f0b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:45:05 -0600 Subject: [PATCH 13/44] remove setConfig --- src/App.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/App.php b/src/App.php index 9a93c07..2d27487 100644 --- a/src/App.php +++ b/src/App.php @@ -69,16 +69,4 @@ public function getConfig(): Config { return $this->config; } - - /** - * @param Config $config - * - * @return static - */ - public function setConfig(Config $config) - { - $this->config = $config; - - return $this; - } } From e72b1f24af5900832c64617c12ecbe28fb2e995f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:46:06 -0600 Subject: [PATCH 14/44] fix typo --- src/Config/Config.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 2842746..7e6d324 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -24,7 +24,7 @@ class Config /** * @var string */ - protected $boostrapDir; + protected $bootstrapDir; /** * @var string @@ -52,7 +52,7 @@ class Config protected $commandsDir; /** - * @param string $boostrapDir + * @param string $bootstrapDir * @param string $indexDir * @param string $indexFile * @param string $rootDir @@ -60,14 +60,14 @@ class Config * @param string|null $commandsDir */ protected function __construct( - string $boostrapDir, + string $bootstrapDir, string $indexDir, string $indexFile, string $rootDir, string $sourceDir, ?string $commandsDir = null ) { - $this->boostrapDir = $boostrapDir; + $this->bootstrapDir = $bootstrapDir; $this->indexDir = $indexDir; $this->indexFile = $indexFile; $this->rootDir = $rootDir; @@ -78,9 +78,9 @@ protected function __construct( /** * @return string */ - public function getBoostrapDir(): string + public function getBootstrapDir(): string { - return $this->boostrapDir; + return $this->bootstrapDir; } /** From e29d7b80b317404671ee8054e6f66bd4e184d71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:53:48 -0600 Subject: [PATCH 15/44] move exception to its own aggregate --- .../CannotResolveConfigurationException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{Config => Exception}/CannotResolveConfigurationException.php (90%) diff --git a/src/Config/CannotResolveConfigurationException.php b/src/Exception/CannotResolveConfigurationException.php similarity index 90% rename from src/Config/CannotResolveConfigurationException.php rename to src/Exception/CannotResolveConfigurationException.php index f6a9bdf..8a5125e 100644 --- a/src/Config/CannotResolveConfigurationException.php +++ b/src/Exception/CannotResolveConfigurationException.php @@ -8,7 +8,7 @@ declare(strict_types=1); -namespace Slim\Console\Config; +namespace Slim\Console\Exception; use Exception; From 8a89b910e7375c10f83f8a1b67d2287011f240d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 2 May 2020 10:54:13 -0600 Subject: [PATCH 16/44] add json_last_error_msg() to exception description --- src/Config/ConfigResolver.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index bd92995..7803590 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -12,6 +12,7 @@ use InvalidArgumentException; use RuntimeException; +use Slim\Console\Exception\CannotResolveConfigurationException; class ConfigResolver { @@ -105,7 +106,7 @@ protected function attemptParsingConfigurationFromFile(string $path, string $for $parsed = json_decode($contents); if (json_last_error() !== JSON_ERROR_NONE) { - throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration.'); + throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration. ' . json_last_error_msg()); } elseif (!is_array($parsed)) { throw new InvalidArgumentException('Slim Console configuration should be an array.'); } From c90ab3489f73114f2fe0c3fc3f55fa3a07348d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sun, 3 May 2020 17:13:35 -0600 Subject: [PATCH 17/44] rename instances of `Configuration` to `Config` --- src/Config/ConfigResolver.php | 16 ++++++++-------- ...tion.php => CannotResolveConfigException.php} | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) rename src/Exception/{CannotResolveConfigurationException.php => CannotResolveConfigException.php} (83%) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 7803590..4ac6338 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -12,7 +12,7 @@ use InvalidArgumentException; use RuntimeException; -use Slim\Console\Exception\CannotResolveConfigurationException; +use Slim\Console\Exception\CannotResolveConfigException; class ConfigResolver { @@ -48,7 +48,7 @@ public function __construct(string $rootDir) * * @return Config * - * @throws CannotResolveConfigurationException + * @throws CannotResolveConfigException * @throws InvalidArgumentException * @throws RuntimeException */ @@ -57,27 +57,27 @@ public function resolve(): Config try { return Config::fromEnvironment(); } catch (InvalidArgumentException $e) { - return $this->attemptResolvingConfigurationFromSupportedFormats(); + return $this->attemptResolvingConfigFromSupportedFormats(); } } /** * @return Config * - * @throws CannotResolveConfigurationException + * @throws CannotResolveConfigException * @throws InvalidArgumentException * @throws RuntimeException */ - protected function attemptResolvingConfigurationFromSupportedFormats(): Config + protected function attemptResolvingConfigFromSupportedFormats(): Config { foreach ($this->supportedFormats as $format) { $path = $this->rootDir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME . ".{$format}"; if (file_exists($path)) { - return $this->attemptParsingConfigurationFromFile($path, $format); + return $this->attemptParsingConfigFromFile($path, $format); } } - throw new CannotResolveConfigurationException(); + throw new CannotResolveConfigException(); } /** @@ -89,7 +89,7 @@ protected function attemptResolvingConfigurationFromSupportedFormats(): Config * @throws InvalidArgumentException * @throws RuntimeException */ - protected function attemptParsingConfigurationFromFile(string $path, string $format): Config + protected function attemptParsingConfigFromFile(string $path, string $format): Config { switch ($format) { case self::FORMAT_PHP: diff --git a/src/Exception/CannotResolveConfigurationException.php b/src/Exception/CannotResolveConfigException.php similarity index 83% rename from src/Exception/CannotResolveConfigurationException.php rename to src/Exception/CannotResolveConfigException.php index 8a5125e..c8cb78f 100644 --- a/src/Exception/CannotResolveConfigurationException.php +++ b/src/Exception/CannotResolveConfigException.php @@ -12,7 +12,7 @@ use Exception; -class CannotResolveConfigurationException extends Exception +class CannotResolveConfigException extends Exception { public $message = 'Cannot resolve Slim Console configuration file.'; } From 5d02287b7b323a7b3380f9603177f3d39bf4c115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sun, 3 May 2020 17:14:00 -0600 Subject: [PATCH 18/44] change usage of `require_once` to `require` --- src/Config/ConfigResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 4ac6338..b16c76e 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -93,7 +93,7 @@ protected function attemptParsingConfigFromFile(string $path, string $format): C { switch ($format) { case self::FORMAT_PHP: - $parsed = require_once $path; + $parsed = require $path; if (!is_array($parsed)) { throw new InvalidArgumentException('Slim Console configuration should be an array.'); From d83aaa407f2990dea1c90414143484e76b24588b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sun, 3 May 2020 17:16:27 -0600 Subject: [PATCH 19/44] remove `mergeDefaults` method and refactor `fromEnvironment` static instantiator --- src/Config/Config.php | 46 +++++++++++++------------------------------ 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 7e6d324..6d5a42e 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -21,6 +21,18 @@ class Config public const SLIM_CONSOLE_SOURCE_DIR = 'SLIM_CONSOLE_SOURCE_DIR'; public const SLIM_CONSOLE_COMMANDS_DIR = 'SLIM_CONSOLE_COMMANDS_DIR'; + /** + * @var array + */ + protected static $defaults = [ + 'bootstrapDir' => 'app', + 'indexDir' => 'public', + 'indexFile' => 'index.php', + 'rootDir' => null, + 'sourceDir' => 'src', + 'commandsDir' => null, + ]; + /** * @var string */ @@ -123,25 +135,6 @@ public function getCommandsDir(): ?string return $this->commandsDir; } - /** - * @param array $params - * - * @return array - */ - protected static function mergeDefaults(array $params): array - { - $defaults = [ - 'bootstrapDir' => 'app', - 'indexDir' => 'public', - 'indexFile' => 'index.php', - 'rootDir' => null, - 'sourceDir' => 'src', - 'commandsDir' => null, - ]; - - return $defaults + $params; - } - /** * @param array $params * @@ -188,7 +181,7 @@ protected static function validate(array $params): void */ public static function fromArray(array $params): Config { - $params = self::mergeDefaults($params); + $params = self::$defaults + $params; self::validate($params); return new self( @@ -208,7 +201,7 @@ public static function fromArray(array $params): Config */ public static function fromEnvironment(): Config { - $params = self::mergeDefaults([ + return self::fromArray([ 'bootstrapDir' => getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR), 'indexDir' => getenv(self::SLIM_CONSOLE_INDEX_DIR), 'indexFile' => getenv(self::SLIM_CONSOLE_INDEX_FILE), @@ -216,16 +209,5 @@ public static function fromEnvironment(): Config 'sourceDir' => getenv(self::SLIM_CONSOLE_SOURCE_DIR), 'commandsDir' => getenv(self::SLIM_CONSOLE_COMMANDS_DIR), ]); - - self::validate($params); - - return new self( - $params['bootstrapDir'], - $params['indexDir'], - $params['indexFile'], - $params['rootDir'], - $params['sourceDir'], - $params['commandsDir'] - ); } } From 542b72cc52efea975b0f673a1ab7c85d62474bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sun, 3 May 2020 17:33:43 -0600 Subject: [PATCH 20/44] fix white spacing --- src/Config/Config.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Config/Config.php b/src/Config/Config.php index 6d5a42e..97485ca 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -182,6 +182,7 @@ protected static function validate(array $params): void public static function fromArray(array $params): Config { $params = self::$defaults + $params; + self::validate($params); return new self( From 6cb9b8f18d4902dd0ba5227e0a5b3d02f0df3c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sun, 3 May 2020 17:43:05 -0600 Subject: [PATCH 21/44] abstract configuration parsers --- src/Config/ConfigResolver.php | 21 +++--------- src/Config/Parser/AbstractConfigParser.php | 27 ++++++++++++++++ src/Config/Parser/ConfigParserInterface.php | 24 ++++++++++++++ src/Config/Parser/JSONConfigParser.php | 36 +++++++++++++++++++++ src/Config/Parser/PHPConfigParser.php | 31 ++++++++++++++++++ 5 files changed, 122 insertions(+), 17 deletions(-) create mode 100644 src/Config/Parser/AbstractConfigParser.php create mode 100644 src/Config/Parser/ConfigParserInterface.php create mode 100644 src/Config/Parser/JSONConfigParser.php create mode 100644 src/Config/Parser/PHPConfigParser.php diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index b16c76e..4c420ac 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -12,6 +12,8 @@ use InvalidArgumentException; use RuntimeException; +use Slim\Console\Config\Parser\JSONConfigParser; +use Slim\Console\Config\Parser\PHPConfigParser; use Slim\Console\Exception\CannotResolveConfigException; class ConfigResolver @@ -93,25 +95,10 @@ protected function attemptParsingConfigFromFile(string $path, string $format): C { switch ($format) { case self::FORMAT_PHP: - $parsed = require $path; - - if (!is_array($parsed)) { - throw new InvalidArgumentException('Slim Console configuration should be an array.'); - } - - return Config::fromArray($parsed); + return (new PHPConfigParser($path))->parse(); case self::FORMAT_JSON: - $contents = file_get_contents($path); - $parsed = json_decode($contents); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new InvalidArgumentException('Invalid JSON parsed from Slim Console configuration. ' . json_last_error_msg()); - } elseif (!is_array($parsed)) { - throw new InvalidArgumentException('Slim Console configuration should be an array.'); - } - - return Config::fromArray($parsed); + return (new JSONConfigParser($path))->parse(); default: throw new RuntimeException("Invalid configuration format `{$format}`."); diff --git a/src/Config/Parser/AbstractConfigParser.php b/src/Config/Parser/AbstractConfigParser.php new file mode 100644 index 0000000..2d84d7a --- /dev/null +++ b/src/Config/Parser/AbstractConfigParser.php @@ -0,0 +1,27 @@ +path = $path; + } +} diff --git a/src/Config/Parser/ConfigParserInterface.php b/src/Config/Parser/ConfigParserInterface.php new file mode 100644 index 0000000..e1193b9 --- /dev/null +++ b/src/Config/Parser/ConfigParserInterface.php @@ -0,0 +1,24 @@ +path); + $parsed = json_decode($contents); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new InvalidArgumentException( + 'Invalid JSON parsed from Slim Console configuration. ' . json_last_error_msg() + ); + } elseif (!is_array($parsed)) { + throw new InvalidArgumentException('Slim Console configuration should be an array.'); + } + + return Config::fromArray($parsed); + } +} diff --git a/src/Config/Parser/PHPConfigParser.php b/src/Config/Parser/PHPConfigParser.php new file mode 100644 index 0000000..bb42bc8 --- /dev/null +++ b/src/Config/Parser/PHPConfigParser.php @@ -0,0 +1,31 @@ +path; + + if (!is_array($parsed)) { + throw new InvalidArgumentException('Slim Console configuration should be an array.'); + } + + return Config::fromArray($parsed); + } +} From de16735bcfab97d9eb79c7415ebf5dc50f2d6e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Wed, 6 May 2020 11:11:47 -0600 Subject: [PATCH 22/44] remove rootDir and refactor validation --- src/Config/Config.php | 53 +++++++++++++------------------------------ 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 97485ca..ebfc738 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -17,7 +17,6 @@ class Config public const SLIM_CONSOLE_BOOTSTRAP_DIR = 'SLIM_CONSOLE_BOOTSTRAP_DIR'; public const SLIM_CONSOLE_INDEX_DIR = 'SLIM_CONSOLE_INDEX_DIR'; public const SLIM_CONSOLE_INDEX_FILE = 'SLIM_CONSOLE_INDEX_FILE'; - public const SLIM_CONSOLE_ROOT_DIR = 'SLIM_CONSOLE_ROOT_DIR'; public const SLIM_CONSOLE_SOURCE_DIR = 'SLIM_CONSOLE_SOURCE_DIR'; public const SLIM_CONSOLE_COMMANDS_DIR = 'SLIM_CONSOLE_COMMANDS_DIR'; @@ -28,9 +27,8 @@ class Config 'bootstrapDir' => 'app', 'indexDir' => 'public', 'indexFile' => 'index.php', - 'rootDir' => null, 'sourceDir' => 'src', - 'commandsDir' => null, + 'commandsDir' => 'src/Application/Console/Commands', ]; /** @@ -48,11 +46,6 @@ class Config */ protected $indexFile; - /** - * @var string - */ - protected $rootDir; - /** * @var string */ @@ -67,7 +60,6 @@ class Config * @param string $bootstrapDir * @param string $indexDir * @param string $indexFile - * @param string $rootDir * @param string $sourceDir * @param string|null $commandsDir */ @@ -75,14 +67,12 @@ protected function __construct( string $bootstrapDir, string $indexDir, string $indexFile, - string $rootDir, string $sourceDir, ?string $commandsDir = null ) { $this->bootstrapDir = $bootstrapDir; $this->indexDir = $indexDir; $this->indexFile = $indexFile; - $this->rootDir = $rootDir; $this->sourceDir = $sourceDir; $this->commandsDir = $commandsDir; } @@ -111,14 +101,6 @@ public function getIndexFile(): string return $this->indexFile; } - /** - * @return string - */ - public function getRootDir(): string - { - return $this->rootDir; - } - /** * @return string */ @@ -146,29 +128,28 @@ protected static function validate(array $params): void 'bootstrapDir' => $bootstrapDir, 'indexDir' => $indexDir, 'indexFile' => $indexFile, - 'rootDir' => $rootDir, 'sourceDir' => $sourceDir, 'commandsDir' => $commandsDir, ] = $params; - $error = null; - if (!is_string($bootstrapDir) || empty($bootstrapDir)) { - $error = '`bootstrapDir` must be a string.'; - } elseif (!is_string($indexDir) || empty($indexDir)) { - $error = '`indexDir` must be a string.'; - } elseif (!is_string($indexFile) || empty($indexFile)) { - $error = '`indexFile` must be a string.'; - } elseif (!is_string($rootDir) || empty($rootDir)) { - $error = '`rootDir` must be a string.'; - } elseif (!is_string($sourceDir) || empty($sourceDir)) { - $error = '`sourceDir` must be a string.'; - } elseif (!empty($commandsDir) && !is_string($commandsDir)) { - $error = '`commandsDir` must be a string.'; + throw new InvalidArgumentException('`bootstrapDir` must be a string.'); + } + + if (!is_string($indexDir) || empty($indexDir)) { + throw new InvalidArgumentException('`indexDir` must be a string.'); + } + + if (!is_string($indexFile) || empty($indexFile)) { + throw new InvalidArgumentException('`indexFile` must be a string.'); + } + + if (!is_string($sourceDir) || empty($sourceDir)) { + throw new InvalidArgumentException('`sourceDir` must be a string.'); } - if ($error) { - throw new InvalidArgumentException($error); + if (!empty($commandsDir) && !is_string($commandsDir)) { + throw new InvalidArgumentException('`commandsDir` must be a string.'); } } @@ -189,7 +170,6 @@ public static function fromArray(array $params): Config $params['bootstrapDir'], $params['indexDir'], $params['indexFile'], - $params['rootDir'], $params['sourceDir'], $params['commandsDir'] ); @@ -206,7 +186,6 @@ public static function fromEnvironment(): Config 'bootstrapDir' => getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR), 'indexDir' => getenv(self::SLIM_CONSOLE_INDEX_DIR), 'indexFile' => getenv(self::SLIM_CONSOLE_INDEX_FILE), - 'rootDir' => getenv(self::SLIM_CONSOLE_ROOT_DIR), 'sourceDir' => getenv(self::SLIM_CONSOLE_SOURCE_DIR), 'commandsDir' => getenv(self::SLIM_CONSOLE_COMMANDS_DIR), ]); From 4035cdceb668ebe1f8a8c35e1e43d9c0db6bc80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Wed, 6 May 2020 11:21:14 -0600 Subject: [PATCH 23/44] add micro-optimization within `attemptResolvingConfigFromSupportedFormats()` method --- src/Config/ConfigResolver.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 4c420ac..1d477bf 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -72,8 +72,10 @@ public function resolve(): Config */ protected function attemptResolvingConfigFromSupportedFormats(): Config { + $basePath = $this->rootDir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME; + foreach ($this->supportedFormats as $format) { - $path = $this->rootDir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME . ".{$format}"; + $path = $basePath . ".{$format}"; if (file_exists($path)) { return $this->attemptParsingConfigFromFile($path, $format); } From 442b9b5550d7ce7bf7b9174294e1270fd45e4415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 12:56:00 -0600 Subject: [PATCH 24/44] add cwd --- bin/slim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/slim b/bin/slim index 5fbaef6..35f6d42 100755 --- a/bin/slim +++ b/bin/slim @@ -12,13 +12,15 @@ declare(strict_types=1); use Slim\Console\App; use Slim\Console\Config\ConfigResolver; +$cwd = getcwd(); + if (file_exists(__DIR__ . '/../../../autoload.php')) { require __DIR__ . '/../../../autoload.php'; } else { require __DIR__ . '/../vendor/autoload.php'; } -$config = (new ConfigResolver())->resolve(); +$config = (new ConfigResolver($cwd))->resolve(); $app = new App($config); $app->run(); From 71ec02bedd984033c50b7b9f6718734ef3ac7c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 12:56:14 -0600 Subject: [PATCH 25/44] add fromDefaults method --- src/Config/Config.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Config/Config.php b/src/Config/Config.php index ebfc738..e954aae 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -190,4 +190,20 @@ public static function fromEnvironment(): Config 'commandsDir' => getenv(self::SLIM_CONSOLE_COMMANDS_DIR), ]); } + + /** + * @return Config + * + * @throws InvalidArgumentException + */ + public static function fromDefaults(): Config + { + return new self( + self::$defaults['bootstrapDir'], + self::$defaults['indexDir'], + self::$defaults['indexFile'], + self::$defaults['sourceDir'], + self::$defaults['commandsDir'] + ); + } } From 4b052a2f93ee5beecc21e4c3c47a03850da4a296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 12:56:37 -0600 Subject: [PATCH 26/44] add fallback on fromDefaults --- src/Config/ConfigResolver.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 1d477bf..dbde774 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -35,14 +35,14 @@ class ConfigResolver /** * @var string */ - protected $rootDir; + protected $cwd; /** - * @param string $rootDir + * @param string $cwd */ - public function __construct(string $rootDir) + public function __construct(string $cwd) { - $this->rootDir = $rootDir; + $this->cwd = $cwd; } /** @@ -50,7 +50,6 @@ public function __construct(string $rootDir) * * @return Config * - * @throws CannotResolveConfigException * @throws InvalidArgumentException * @throws RuntimeException */ @@ -59,7 +58,11 @@ public function resolve(): Config try { return Config::fromEnvironment(); } catch (InvalidArgumentException $e) { - return $this->attemptResolvingConfigFromSupportedFormats(); + try { + return $this->attemptResolvingConfigFromSupportedFormats(); + } catch (CannotResolveConfigException $e) { + return Config::fromDefaults(); + } } } @@ -72,7 +75,7 @@ public function resolve(): Config */ protected function attemptResolvingConfigFromSupportedFormats(): Config { - $basePath = $this->rootDir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME; + $basePath = $this->cwd . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME; foreach ($this->supportedFormats as $format) { $path = $basePath . ".{$format}"; From 91322192db0f0858b8e743cd70d39d964ee4e474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 15:19:30 -0600 Subject: [PATCH 27/44] refactor parsers --- src/Config/ConfigResolver.php | 28 ++++++++++++++++++--- src/Config/Parser/AbstractConfigParser.php | 27 -------------------- src/Config/Parser/ConfigParserInterface.php | 4 ++- src/Config/Parser/JSONConfigParser.php | 10 +++++--- src/Config/Parser/PHPConfigParser.php | 8 +++--- 5 files changed, 38 insertions(+), 39 deletions(-) delete mode 100644 src/Config/Parser/AbstractConfigParser.php diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index dbde774..68156e4 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -56,8 +56,8 @@ public function __construct(string $cwd) public function resolve(): Config { try { - return Config::fromEnvironment(); - } catch (InvalidArgumentException $e) { + return $this->attemptResolvingConfigFromEnvironment(); + } catch (CannotResolveConfigException $e) { try { return $this->attemptResolvingConfigFromSupportedFormats(); } catch (CannotResolveConfigException $e) { @@ -66,6 +66,26 @@ public function resolve(): Config } } + /** + * @return Config + * + * @throws CannotResolveConfigException + */ + protected function attemptResolvingConfigFromEnvironment(): Config + { + if ( + getenv(Config::SLIM_CONSOLE_BOOTSTRAP_DIR) + || getenv(Config::SLIM_CONSOLE_COMMANDS_DIR) + || getenv(Config::SLIM_CONSOLE_INDEX_DIR) + || getenv(Config::SLIM_CONSOLE_INDEX_FILE) + || getenv(Config::SLIM_CONSOLE_SOURCE_DIR) + ) { + return Config::fromEnvironment(); + } + + throw new CannotResolveConfigException(); + } + /** * @return Config * @@ -100,10 +120,10 @@ protected function attemptParsingConfigFromFile(string $path, string $format): C { switch ($format) { case self::FORMAT_PHP: - return (new PHPConfigParser($path))->parse(); + return PHPConfigParser::parse($path); case self::FORMAT_JSON: - return (new JSONConfigParser($path))->parse(); + return JSONConfigParser::parse($path); default: throw new RuntimeException("Invalid configuration format `{$format}`."); diff --git a/src/Config/Parser/AbstractConfigParser.php b/src/Config/Parser/AbstractConfigParser.php deleted file mode 100644 index 2d84d7a..0000000 --- a/src/Config/Parser/AbstractConfigParser.php +++ /dev/null @@ -1,27 +0,0 @@ -path = $path; - } -} diff --git a/src/Config/Parser/ConfigParserInterface.php b/src/Config/Parser/ConfigParserInterface.php index e1193b9..44e44a8 100644 --- a/src/Config/Parser/ConfigParserInterface.php +++ b/src/Config/Parser/ConfigParserInterface.php @@ -16,9 +16,11 @@ interface ConfigParserInterface { /** + * @param string $path + * * @return Config * * @throws InvalidArgumentException */ - public function parse(): Config; + public static function parse(string $path): Config; } diff --git a/src/Config/Parser/JSONConfigParser.php b/src/Config/Parser/JSONConfigParser.php index f46db74..8ed84d8 100644 --- a/src/Config/Parser/JSONConfigParser.php +++ b/src/Config/Parser/JSONConfigParser.php @@ -13,15 +13,17 @@ use InvalidArgumentException; use Slim\Console\Config\Config; -class JSONConfigParser extends AbstractConfigParser +class JSONConfigParser implements ConfigParserInterface { /** + * @param string $path + * * @return Config */ - public function parse(): Config + public static function parse(string $path): Config { - $contents = file_get_contents($this->path); - $parsed = json_decode($contents); + $contents = file_get_contents($path); + $parsed = json_decode($contents, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidArgumentException( diff --git a/src/Config/Parser/PHPConfigParser.php b/src/Config/Parser/PHPConfigParser.php index bb42bc8..d79e71e 100644 --- a/src/Config/Parser/PHPConfigParser.php +++ b/src/Config/Parser/PHPConfigParser.php @@ -13,14 +13,16 @@ use InvalidArgumentException; use Slim\Console\Config\Config; -class PHPConfigParser extends AbstractConfigParser +class PHPConfigParser implements ConfigParserInterface { /** + * @param string $path + * * @return Config */ - public function parse(): Config + public static function parse(string $path): Config { - $parsed = require $this->path; + $parsed = require $path; if (!is_array($parsed)) { throw new InvalidArgumentException('Slim Console configuration should be an array.'); From 6ca9662d3b2de4c777576a1aef9100dd83916f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 15:37:28 -0600 Subject: [PATCH 28/44] add tests --- src/Config/Config.php | 14 +-- src/Config/Parser/JSONConfigParser.php | 4 +- tests/Config/ConfigResolverTest.php | 104 ++++++++++++++++ tests/Config/ConfigTest.php | 112 ++++++++++++++++++ tests/Config/Parser/JSONConfigParserTest.php | 58 +++++++++ tests/Config/Parser/PHPConfigParserTest.php | 44 +++++++ tests/TestCase.php | 61 ++++++++++ .../examples/invalid-json/invalid-format.json | 1 + .../examples/invalid-json/invalid-syntax.json | 3 + tests/examples/invalid-php/invalid-format.php | 2 + tests/examples/json/slim-console.config.json | 7 ++ tests/examples/php/slim-console.config.php | 8 ++ 12 files changed, 409 insertions(+), 9 deletions(-) create mode 100644 tests/Config/ConfigResolverTest.php create mode 100644 tests/Config/ConfigTest.php create mode 100644 tests/Config/Parser/JSONConfigParserTest.php create mode 100644 tests/Config/Parser/PHPConfigParserTest.php create mode 100644 tests/TestCase.php create mode 100644 tests/examples/invalid-json/invalid-format.json create mode 100644 tests/examples/invalid-json/invalid-syntax.json create mode 100644 tests/examples/invalid-php/invalid-format.php create mode 100644 tests/examples/json/slim-console.config.json create mode 100644 tests/examples/php/slim-console.config.php diff --git a/src/Config/Config.php b/src/Config/Config.php index e954aae..d6d6a81 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -132,23 +132,23 @@ protected static function validate(array $params): void 'commandsDir' => $commandsDir, ] = $params; - if (!is_string($bootstrapDir) || empty($bootstrapDir)) { + if (!is_string($bootstrapDir) || empty($bootstrapDir) || ctype_space($bootstrapDir)) { throw new InvalidArgumentException('`bootstrapDir` must be a string.'); } - if (!is_string($indexDir) || empty($indexDir)) { + if (!is_string($indexDir) || empty($indexDir) || ctype_space($indexDir)) { throw new InvalidArgumentException('`indexDir` must be a string.'); } - if (!is_string($indexFile) || empty($indexFile)) { + if (!is_string($indexFile) || empty($indexFile) || ctype_space($indexFile)) { throw new InvalidArgumentException('`indexFile` must be a string.'); } - if (!is_string($sourceDir) || empty($sourceDir)) { + if (!is_string($sourceDir) || empty($sourceDir) || ctype_space($sourceDir)) { throw new InvalidArgumentException('`sourceDir` must be a string.'); } - if (!empty($commandsDir) && !is_string($commandsDir)) { + if (!empty($commandsDir) && (!is_string($commandsDir) || ctype_space($commandsDir))) { throw new InvalidArgumentException('`commandsDir` must be a string.'); } } @@ -162,7 +162,7 @@ protected static function validate(array $params): void */ public static function fromArray(array $params): Config { - $params = self::$defaults + $params; + $params = array_merge(self::$defaults, $params); self::validate($params); @@ -193,8 +193,6 @@ public static function fromEnvironment(): Config /** * @return Config - * - * @throws InvalidArgumentException */ public static function fromDefaults(): Config { diff --git a/src/Config/Parser/JSONConfigParser.php b/src/Config/Parser/JSONConfigParser.php index 8ed84d8..f1c6bc3 100644 --- a/src/Config/Parser/JSONConfigParser.php +++ b/src/Config/Parser/JSONConfigParser.php @@ -29,7 +29,9 @@ public static function parse(string $path): Config throw new InvalidArgumentException( 'Invalid JSON parsed from Slim Console configuration. ' . json_last_error_msg() ); - } elseif (!is_array($parsed)) { + } + + if (!is_array($parsed)) { throw new InvalidArgumentException('Slim Console configuration should be an array.'); } diff --git a/tests/Config/ConfigResolverTest.php b/tests/Config/ConfigResolverTest.php new file mode 100644 index 0000000..003f106 --- /dev/null +++ b/tests/Config/ConfigResolverTest.php @@ -0,0 +1,104 @@ +setupEnvConfig(); + + $exampleJsonConfigPath = $this->getExampleConfigPath(ConfigResolver::FORMAT_JSON); + $configResolver = new ConfigResolver($exampleJsonConfigPath); + + $config = $configResolver->resolve(); + + $this->assertSame($this->envParams['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($this->envParams['commandsDir'], $config->getCommandsDir()); + $this->assertSame($this->envParams['indexDir'], $config->getIndexDir()); + $this->assertSame($this->envParams['indexFile'], $config->getIndexFile()); + $this->assertSame($this->envParams['sourceDir'], $config->getSourceDir()); + } + + /** + * @dataProvider supportedFormatsProvider + * + * @param string $format + * @param Closure $parser + */ + public function testAttemptResolvingConfigFromSupportedFormats(string $format, Closure $parser): void + { + $example = $parser($this->getExampleConfigPath($format) . DIRECTORY_SEPARATOR . ConfigResolver::CONFIG_FILENAME . '.' . $format); + + $exampleConfigPath = $this->getExampleConfigPath($format); + $configResolver = new ConfigResolver($exampleConfigPath); + + $config = $configResolver->resolve(); + + $this->assertSame($example['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($example['commandsDir'], $config->getCommandsDir()); + $this->assertSame($example['indexDir'], $config->getIndexDir()); + $this->assertSame($example['indexFile'], $config->getIndexFile()); + $this->assertSame($example['sourceDir'], $config->getSourceDir()); + } + + public function testAttemptParsingConfigFromFileThrowsRuntimeException(): void + { + $attemptParsingConfigFromFileMethod = new ReflectionMethod(ConfigResolver::class, 'attemptParsingConfigFromFile'); + $attemptParsingConfigFromFileMethod->setAccessible(true); + + $invalidFormat = 'invalid'; + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage("Invalid configuration format `{$invalidFormat}`."); + + $configResolver = new ConfigResolver($this->examplesConfigBasePath); + + $attemptParsingConfigFromFileMethod->invoke($configResolver, $this->examplesConfigBasePath, $invalidFormat); + } + + public function testResolveFallbackOnDefaults(): void + { + $defaultsReflection = new ReflectionProperty(Config::class, 'defaults'); + $defaultsReflection->setAccessible(true); + + $defaults = $defaultsReflection->getValue(); + + $configResolver = new ConfigResolver($this->examplesConfigBasePath); + $config = $configResolver->resolve(); + + $this->assertSame($defaults['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($defaults['commandsDir'], $config->getCommandsDir()); + $this->assertSame($defaults['indexDir'], $config->getIndexDir()); + $this->assertSame($defaults['indexFile'], $config->getIndexFile()); + $this->assertSame($defaults['sourceDir'], $config->getSourceDir()); + } +} diff --git a/tests/Config/ConfigTest.php b/tests/Config/ConfigTest.php new file mode 100644 index 0000000..90c9c3b --- /dev/null +++ b/tests/Config/ConfigTest.php @@ -0,0 +1,112 @@ + $bootstrapDir, + 'commandsDir' => $commandsDir, + 'indexDir' => $indexDir, + 'indexFile' => $indexFile, + 'sourceDir' => $sourceDir, + ]); + + $this->assertSame($bootstrapDir, $config->getBootstrapDir()); + $this->assertSame($commandsDir, $config->getCommandsDir()); + $this->assertSame($indexDir, $config->getIndexDir()); + $this->assertSame($indexFile, $config->getIndexFile()); + $this->assertSame($sourceDir, $config->getSourceDir()); + } + + public function testFromEnvironment(): void + { + $this->setupEnvConfig(); + + $config = Config::fromEnvironment(); + + $this->assertSame($this->envParams['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($this->envParams['commandsDir'], $config->getCommandsDir()); + $this->assertSame($this->envParams['indexDir'], $config->getIndexDir()); + $this->assertSame($this->envParams['indexFile'], $config->getIndexFile()); + $this->assertSame($this->envParams['sourceDir'], $config->getSourceDir()); + } + + public function testFromDefaults(): void + { + $defaultsReflection = new ReflectionProperty(Config::class, 'defaults'); + $defaultsReflection->setAccessible(true); + + $defaults = $defaultsReflection->getValue(); + $config = Config::fromDefaults(); + + $this->assertSame($defaults['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($defaults['commandsDir'], $config->getCommandsDir()); + $this->assertSame($defaults['indexDir'], $config->getIndexDir()); + $this->assertSame($defaults['indexFile'], $config->getIndexFile()); + $this->assertSame($defaults['sourceDir'], $config->getSourceDir()); + } + + public function invalidDataProvider(): array + { + return [ + ['bootstrapDir', ''], + ['bootstrapDir', ' '], + ['commandsDir', ' '], + ['indexDir', ''], + ['indexDir', ' '], + ['indexFile', ''], + ['indexFile', ' '], + ['sourceDir', ''], + ['sourceDir', ' '], + ]; + } + + /** + * @dataProvider invalidDataProvider + * + * @param string $param + * @param string $value + */ + public function testValidate(string $param, string $value): void + { + $configReflection = new ReflectionClass(Config::class); + + $defaultsReflection = $configReflection->getProperty('defaults'); + $defaultsReflection->setAccessible(true); + + $defaults = $defaultsReflection->getValue(); + + $validateMethod = $configReflection->getMethod('validate'); + $validateMethod->setAccessible(true); + + $params = array_merge($defaults, [$param => $value]); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("`{$param}` must be a string."); + + $validateMethod->invoke(null, $params); + } +} diff --git a/tests/Config/Parser/JSONConfigParserTest.php b/tests/Config/Parser/JSONConfigParserTest.php new file mode 100644 index 0000000..1868f4b --- /dev/null +++ b/tests/Config/Parser/JSONConfigParserTest.php @@ -0,0 +1,58 @@ +getExampleConfigPath(ConfigResolver::FORMAT_JSON); + $jsonConfigPath = $exampleJsonConfigPath . DIRECTORY_SEPARATOR . ConfigResolver::CONFIG_FILENAME . '.' . ConfigResolver::FORMAT_JSON; + $jsonConfig = json_decode(file_get_contents($jsonConfigPath), true); + + $config = JSONConfigParser::parse($jsonConfigPath); + + $this->assertSame($jsonConfig['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($jsonConfig['commandsDir'], $config->getCommandsDir()); + $this->assertSame($jsonConfig['indexDir'], $config->getIndexDir()); + $this->assertSame($jsonConfig['indexFile'], $config->getIndexFile()); + $this->assertSame($jsonConfig['sourceDir'], $config->getSourceDir()); + } + + /** + * @dataProvider invalidConfigurationProvider + * + * @param string $fileName + * @param string $expectedExceptionMessage + */ + public function testParseThrowsInvalidArgumentException(string $fileName, string $expectedExceptionMessage): void + { + $invalidJsonConfigPath = $this->examplesConfigBasePath . DIRECTORY_SEPARATOR . 'invalid-json' . DIRECTORY_SEPARATOR . $fileName; + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($expectedExceptionMessage); + + JSONConfigParser::parse($invalidJsonConfigPath); + } +} diff --git a/tests/Config/Parser/PHPConfigParserTest.php b/tests/Config/Parser/PHPConfigParserTest.php new file mode 100644 index 0000000..c6b6f39 --- /dev/null +++ b/tests/Config/Parser/PHPConfigParserTest.php @@ -0,0 +1,44 @@ +getExampleConfigPath(ConfigResolver::FORMAT_PHP); + $phpConfigPath = $exampleJsonConfigPath . DIRECTORY_SEPARATOR . ConfigResolver::CONFIG_FILENAME . '.' . ConfigResolver::FORMAT_PHP; + $phpConfig = require $phpConfigPath; + + $config = PHPConfigParser::parse($phpConfigPath); + + $this->assertSame($phpConfig['bootstrapDir'], $config->getBootstrapDir()); + $this->assertSame($phpConfig['commandsDir'], $config->getCommandsDir()); + $this->assertSame($phpConfig['indexDir'], $config->getIndexDir()); + $this->assertSame($phpConfig['indexFile'], $config->getIndexFile()); + $this->assertSame($phpConfig['sourceDir'], $config->getSourceDir()); + } + + public function testParseThrowsInvalidArgumentException(): void + { + $invalidJsonConfigPath = $this->examplesConfigBasePath . DIRECTORY_SEPARATOR . 'invalid-php' . DIRECTORY_SEPARATOR . 'invalid-format.php'; + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Slim Console configuration should be an array.'); + + PHPConfigParser::parse($invalidJsonConfigPath); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..ac97c02 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,61 @@ +examplesConfigBasePath . DIRECTORY_SEPARATOR . $format; + } + + /** + * @var string[] + */ + protected $envParams = [ + 'bootstrapDir' => 'envCustomDir', + 'commandsDir' => 'envCustomCommands', + 'indexDir' => 'envCustomIndexDir', + 'indexFile' => 'envCustom.php', + 'sourceDir' => 'envCustomSrc', + ]; + + protected function setupEnvConfig(): void + { + putenv(Config::SLIM_CONSOLE_BOOTSTRAP_DIR . '=' . $this->envParams['bootstrapDir']); + putenv(Config::SLIM_CONSOLE_COMMANDS_DIR . '=' . $this->envParams['commandsDir']); + putenv(Config::SLIM_CONSOLE_INDEX_DIR . '=' . $this->envParams['indexDir']); + putenv(Config::SLIM_CONSOLE_INDEX_FILE . '=' . $this->envParams['indexFile']); + putenv(Config::SLIM_CONSOLE_SOURCE_DIR . '=' . $this->envParams['sourceDir']); + } +} diff --git a/tests/examples/invalid-json/invalid-format.json b/tests/examples/invalid-json/invalid-format.json new file mode 100644 index 0000000..50a269a --- /dev/null +++ b/tests/examples/invalid-json/invalid-format.json @@ -0,0 +1 @@ +"invalid" diff --git a/tests/examples/invalid-json/invalid-syntax.json b/tests/examples/invalid-json/invalid-syntax.json new file mode 100644 index 0000000..cee1564 --- /dev/null +++ b/tests/examples/invalid-json/invalid-syntax.json @@ -0,0 +1,3 @@ +{ + invalid: 'json', +} diff --git a/tests/examples/invalid-php/invalid-format.php b/tests/examples/invalid-php/invalid-format.php new file mode 100644 index 0000000..c3a0a2e --- /dev/null +++ b/tests/examples/invalid-php/invalid-format.php @@ -0,0 +1,2 @@ + 'customBootstrapDir', + 'commandsDir' => 'customCommandsDir', + 'indexDir' => 'customIndexDir', + 'indexFile' => 'customIndexFile.php', + 'sourceDir' => 'customSourceDir', +]; From 8ec4f6c16b365ff0fcddc73b9a262db1f96bdb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 15:40:47 -0600 Subject: [PATCH 29/44] fix phpstan errors --- src/Command/AbstractCommand.php | 4 +++- src/Config/Parser/JSONConfigParser.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index fe705ba..6c03b1b 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -19,13 +19,15 @@ abstract class AbstractCommand extends Command { /** * @return Config|null + * + * @throws RuntimeException */ public function getConfig(): ?Config { $app = $this->getApplication(); if ($app instanceof App === false) { - throw new RuntimeException('Cannot call method `getConfig()` on ' . get_class($app)); + throw new RuntimeException('Method method `getConfig()` does not exist on this type of application.'); } return $app->getConfig(); diff --git a/src/Config/Parser/JSONConfigParser.php b/src/Config/Parser/JSONConfigParser.php index f1c6bc3..220f104 100644 --- a/src/Config/Parser/JSONConfigParser.php +++ b/src/Config/Parser/JSONConfigParser.php @@ -22,7 +22,7 @@ class JSONConfigParser implements ConfigParserInterface */ public static function parse(string $path): Config { - $contents = file_get_contents($path); + $contents = (string) file_get_contents($path); $parsed = json_decode($contents, true); if (json_last_error() !== JSON_ERROR_NONE) { From 7e10d3c7801758344b7a75cb918ff49267d3939d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 15:44:00 -0600 Subject: [PATCH 30/44] fix code style errors --- tests/Config/ConfigResolverTest.php | 10 ++++++++-- tests/Config/Parser/JSONConfigParserTest.php | 8 ++++++-- tests/Config/Parser/PHPConfigParserTest.php | 8 ++++++-- tests/examples/invalid-php/invalid-format.php | 1 + tests/examples/php/slim-console.config.php | 1 + 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tests/Config/ConfigResolverTest.php b/tests/Config/ConfigResolverTest.php index 003f106..0405ac8 100644 --- a/tests/Config/ConfigResolverTest.php +++ b/tests/Config/ConfigResolverTest.php @@ -56,7 +56,10 @@ public function testResolvePrioritizesEnvironment(): void */ public function testAttemptResolvingConfigFromSupportedFormats(string $format, Closure $parser): void { - $example = $parser($this->getExampleConfigPath($format) . DIRECTORY_SEPARATOR . ConfigResolver::CONFIG_FILENAME . '.' . $format); + $configPath = $this->getExampleConfigPath($format) + . DIRECTORY_SEPARATOR + . ConfigResolver::CONFIG_FILENAME . '.' . $format; + $example = $parser($configPath); $exampleConfigPath = $this->getExampleConfigPath($format); $configResolver = new ConfigResolver($exampleConfigPath); @@ -72,7 +75,10 @@ public function testAttemptResolvingConfigFromSupportedFormats(string $format, C public function testAttemptParsingConfigFromFileThrowsRuntimeException(): void { - $attemptParsingConfigFromFileMethod = new ReflectionMethod(ConfigResolver::class, 'attemptParsingConfigFromFile'); + $attemptParsingConfigFromFileMethod = new ReflectionMethod( + ConfigResolver::class, + 'attemptParsingConfigFromFile' + ); $attemptParsingConfigFromFileMethod->setAccessible(true); $invalidFormat = 'invalid'; diff --git a/tests/Config/Parser/JSONConfigParserTest.php b/tests/Config/Parser/JSONConfigParserTest.php index 1868f4b..c192dff 100644 --- a/tests/Config/Parser/JSONConfigParserTest.php +++ b/tests/Config/Parser/JSONConfigParserTest.php @@ -28,7 +28,9 @@ public function invalidConfigurationProvider(): array public function testParse(): void { $exampleJsonConfigPath = $this->getExampleConfigPath(ConfigResolver::FORMAT_JSON); - $jsonConfigPath = $exampleJsonConfigPath . DIRECTORY_SEPARATOR . ConfigResolver::CONFIG_FILENAME . '.' . ConfigResolver::FORMAT_JSON; + $jsonConfigPath = $exampleJsonConfigPath + . DIRECTORY_SEPARATOR + . ConfigResolver::CONFIG_FILENAME . '.' . ConfigResolver::FORMAT_JSON; $jsonConfig = json_decode(file_get_contents($jsonConfigPath), true); $config = JSONConfigParser::parse($jsonConfigPath); @@ -48,7 +50,9 @@ public function testParse(): void */ public function testParseThrowsInvalidArgumentException(string $fileName, string $expectedExceptionMessage): void { - $invalidJsonConfigPath = $this->examplesConfigBasePath . DIRECTORY_SEPARATOR . 'invalid-json' . DIRECTORY_SEPARATOR . $fileName; + $invalidJsonConfigPath = $this->examplesConfigBasePath + . DIRECTORY_SEPARATOR . 'invalid-json' + . DIRECTORY_SEPARATOR . $fileName; $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage($expectedExceptionMessage); diff --git a/tests/Config/Parser/PHPConfigParserTest.php b/tests/Config/Parser/PHPConfigParserTest.php index c6b6f39..d9e5254 100644 --- a/tests/Config/Parser/PHPConfigParserTest.php +++ b/tests/Config/Parser/PHPConfigParserTest.php @@ -20,7 +20,9 @@ class PHPConfigParserTest extends TestCase public function testParse(): void { $exampleJsonConfigPath = $this->getExampleConfigPath(ConfigResolver::FORMAT_PHP); - $phpConfigPath = $exampleJsonConfigPath . DIRECTORY_SEPARATOR . ConfigResolver::CONFIG_FILENAME . '.' . ConfigResolver::FORMAT_PHP; + $phpConfigPath = $exampleJsonConfigPath + . DIRECTORY_SEPARATOR + . ConfigResolver::CONFIG_FILENAME . '.' . ConfigResolver::FORMAT_PHP; $phpConfig = require $phpConfigPath; $config = PHPConfigParser::parse($phpConfigPath); @@ -34,7 +36,9 @@ public function testParse(): void public function testParseThrowsInvalidArgumentException(): void { - $invalidJsonConfigPath = $this->examplesConfigBasePath . DIRECTORY_SEPARATOR . 'invalid-php' . DIRECTORY_SEPARATOR . 'invalid-format.php'; + $invalidJsonConfigPath = $this->examplesConfigBasePath + . DIRECTORY_SEPARATOR . 'invalid-php' + . DIRECTORY_SEPARATOR . 'invalid-format.php'; $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Slim Console configuration should be an array.'); diff --git a/tests/examples/invalid-php/invalid-format.php b/tests/examples/invalid-php/invalid-format.php index c3a0a2e..faafbbc 100644 --- a/tests/examples/invalid-php/invalid-format.php +++ b/tests/examples/invalid-php/invalid-format.php @@ -1,2 +1,3 @@ 'customBootstrapDir', 'commandsDir' => 'customCommandsDir', From b8ffb8438f66867eb4154d3d9be5dc8ff8dc9939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Fri, 8 May 2020 15:50:47 -0600 Subject: [PATCH 31/44] fix phpstan errors --- composer.json | 2 +- phpstan.neon.dist | 1 + src/Config/Config.php | 2 +- src/Exception/CannotResolveConfigException.php | 3 +++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 47493dd..881cacf 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "require-dev": { "adriansuter/php-autoload-override": "^1.0", "phpspec/prophecy": "^1.10", - "phpstan/phpstan": "^0.12.19", + "phpstan/phpstan": "^0.12.23", "phpunit/phpunit": "^8.5", "squizlabs/php_codesniffer": "^3.5" }, diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 036e5a5..b55137a 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,3 +1,4 @@ parameters: level: max + checkMissingIterableValueType: false inferPrivatePropertyTypeFromConstructor: true diff --git a/src/Config/Config.php b/src/Config/Config.php index d6d6a81..871abaf 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -154,7 +154,7 @@ protected static function validate(array $params): void } /** - * @param array $params + * @param array $params * * @return Config * diff --git a/src/Exception/CannotResolveConfigException.php b/src/Exception/CannotResolveConfigException.php index c8cb78f..451c989 100644 --- a/src/Exception/CannotResolveConfigException.php +++ b/src/Exception/CannotResolveConfigException.php @@ -14,5 +14,8 @@ class CannotResolveConfigException extends Exception { + /** + * @var string + */ public $message = 'Cannot resolve Slim Console configuration file.'; } From a17bc298211030fd2e3ebdea1b2150df67f64d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 12:16:53 -0600 Subject: [PATCH 32/44] add is_readable check --- src/Config/ConfigResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 68156e4..fc5e408 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -99,7 +99,7 @@ protected function attemptResolvingConfigFromSupportedFormats(): Config foreach ($this->supportedFormats as $format) { $path = $basePath . ".{$format}"; - if (file_exists($path)) { + if (file_exists($path) && is_readable($path)) { return $this->attemptParsingConfigFromFile($path, $format); } } From 138d8a07802b2a4014067be1d1f25c24c4000024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 13:01:26 -0600 Subject: [PATCH 33/44] add more tests --- tests/AppTest.php | 96 +++++++++++++++++++++++++++ tests/Command/AbstractCommandTest.php | 42 ++++++++++++ tests/Mocks/MockCommand.php | 57 ++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 tests/AppTest.php create mode 100644 tests/Command/AbstractCommandTest.php create mode 100644 tests/Mocks/MockCommand.php diff --git a/tests/AppTest.php b/tests/AppTest.php new file mode 100644 index 0000000..40e8860 --- /dev/null +++ b/tests/AppTest.php @@ -0,0 +1,96 @@ +add($mockCommand); + + $inputInterfaceProphecy = $this->prophesize(InputInterface::class); + + $inputInterfaceProphecy + ->hasParameterOption(['--help', '-h'], true) + ->willReturn(false) + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->hasParameterOption(['--help', '-h']) + ->willReturn(true) + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->isInteractive() + ->willReturn(true) + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->hasArgument('command') + ->willReturn(false) + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->validate() + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->hasParameterOption(['--version', '-V'], true) + ->willReturn(false) + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->getFirstArgument() + ->willReturn(MockCommand::getDefaultName()) + ->shouldBeCalledOnce(); + + $inputInterfaceProphecy + ->bind(Argument::any()) + ->shouldBeCalledTimes(2); + + $outputInterfaceProphecy = $this->prophesize(OutputInterface::class); + + $outputInterfaceProphecy + ->writeln($app->getLongVersion()) + ->shouldBeCalledOnce(); + + $outputInterfaceProphecy + ->writeln('') + ->shouldBeCalledOnce(); + + $outputInterfaceProphecy + ->writeln($mockCommand->getMockOutput()) + ->shouldBeCalledOnce(); + + $app->doRun($inputInterfaceProphecy->reveal(), $outputInterfaceProphecy->reveal()); + } + + public function testGetConfig(): void + { + $config = Config::fromDefaults(); + + $app = new App($config); + + $this->assertSame($config, $app->getConfig()); + } +} diff --git a/tests/Command/AbstractCommandTest.php b/tests/Command/AbstractCommandTest.php new file mode 100644 index 0000000..babaeaf --- /dev/null +++ b/tests/Command/AbstractCommandTest.php @@ -0,0 +1,42 @@ +add($mockCommand); + + $this->assertSame($config, $mockCommand->getConfig()); + } + + public function testGetConfigThrowsRuntimeExceptionWithIncompatibleApp(): void + { + $mockCommand = new MockCommand(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Method method `getConfig()` does not exist on this type of application.'); + + $mockCommand->getConfig(); + } +} diff --git a/tests/Mocks/MockCommand.php b/tests/Mocks/MockCommand.php new file mode 100644 index 0000000..7a283b0 --- /dev/null +++ b/tests/Mocks/MockCommand.php @@ -0,0 +1,57 @@ +writeln($this->getMockOutput()); + return 1; + } + + /** + * @return string + */ + public function getMockOutput(): string + { + return $this->output; + } + + /** + * @param string $output + * @return self + */ + public function setMockOutput(string $output): self + { + $this->output = $output; + return $this; + } +} From 590e5f7658e1ccf2d8cb5287aacbc75013e522ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 17:08:34 -0600 Subject: [PATCH 34/44] remove symfony/config --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 881cacf..c3857f2 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,7 @@ "require": { "ext-json": "*", "php": "^7.2", - "symfony/console": "^5.0", - "symfony/config": "^5.0" + "symfony/console": "^5.0" }, "require-dev": { "adriansuter/php-autoload-override": "^1.0", From ff8f39561eccda72ac21e0969a24ee7ecd72ce62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 17:08:48 -0600 Subject: [PATCH 35/44] change exception message to be more relevant --- src/Command/AbstractCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index 6c03b1b..949c360 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -27,7 +27,9 @@ public function getConfig(): ?Config $app = $this->getApplication(); if ($app instanceof App === false) { - throw new RuntimeException('Method method `getConfig()` does not exist on this type of application.'); + throw new RuntimeException( + 'Usage of the method `getConfig()` requires the parent application to be a Slim Console Application.' + ); } return $app->getConfig(); From 65b389f74a3b2fe49faf55b3aece9f9a65a4d984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 17:09:05 -0600 Subject: [PATCH 36/44] fix docbloc definitions --- src/Config/Config.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Config/Config.php b/src/Config/Config.php index 871abaf..8a80dd8 100644 --- a/src/Config/Config.php +++ b/src/Config/Config.php @@ -21,14 +21,20 @@ class Config public const SLIM_CONSOLE_COMMANDS_DIR = 'SLIM_CONSOLE_COMMANDS_DIR'; /** - * @var array + * @var array */ protected static $defaults = [ 'bootstrapDir' => 'app', 'indexDir' => 'public', 'indexFile' => 'index.php', 'sourceDir' => 'src', - 'commandsDir' => 'src/Application/Console/Commands', + 'commandsDir' => 'src' + . DIRECTORY_SEPARATOR + . 'Application' + . DIRECTORY_SEPARATOR + . 'Console' + . DIRECTORY_SEPARATOR + . 'Commands', ]; /** @@ -118,7 +124,7 @@ public function getCommandsDir(): ?string } /** - * @param array $params + * @param array $params * * @throws InvalidArgumentException */ @@ -154,7 +160,7 @@ protected static function validate(array $params): void } /** - * @param array $params + * @param array $params * * @return Config * @@ -183,11 +189,11 @@ public static function fromArray(array $params): Config public static function fromEnvironment(): Config { return self::fromArray([ - 'bootstrapDir' => getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR), - 'indexDir' => getenv(self::SLIM_CONSOLE_INDEX_DIR), - 'indexFile' => getenv(self::SLIM_CONSOLE_INDEX_FILE), - 'sourceDir' => getenv(self::SLIM_CONSOLE_SOURCE_DIR), - 'commandsDir' => getenv(self::SLIM_CONSOLE_COMMANDS_DIR), + 'bootstrapDir' => (string) getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR), + 'indexDir' => (string) getenv(self::SLIM_CONSOLE_INDEX_DIR), + 'indexFile' => (string) getenv(self::SLIM_CONSOLE_INDEX_FILE), + 'sourceDir' => (string) getenv(self::SLIM_CONSOLE_SOURCE_DIR), + 'commandsDir' => (string) getenv(self::SLIM_CONSOLE_COMMANDS_DIR), ]); } From 19ad6c5d6747f9386006b425c600bd60c4f5f222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=83=3F=C3=82=C2=A9rub=C3=83=3F=C3=82=C2=A9?= Date: Sat, 9 May 2020 17:09:25 -0600 Subject: [PATCH 37/44] refactor directory resolving logic --- bin/slim | 2 +- src/Config/ConfigResolver.php | 44 ++++++++------------ src/Config/Parser/ConfigParserInterface.php | 4 +- src/Config/Parser/JSONConfigParser.php | 4 +- src/Config/Parser/PHPConfigParser.php | 8 ++-- src/Exception/CannotParseConfigException.php | 17 ++++++++ 6 files changed, 42 insertions(+), 37 deletions(-) create mode 100644 src/Exception/CannotParseConfigException.php diff --git a/bin/slim b/bin/slim index 35f6d42..036fc1c 100755 --- a/bin/slim +++ b/bin/slim @@ -20,7 +20,7 @@ if (file_exists(__DIR__ . '/../../../autoload.php')) { require __DIR__ . '/../vendor/autoload.php'; } -$config = (new ConfigResolver($cwd))->resolve(); +$config = (new ConfigResolver())->resolve($cwd); $app = new App($config); $app->run(); diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index fc5e408..7cfcd67 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -10,10 +10,10 @@ namespace Slim\Console\Config; -use InvalidArgumentException; use RuntimeException; use Slim\Console\Config\Parser\JSONConfigParser; use Slim\Console\Config\Parser\PHPConfigParser; +use Slim\Console\Exception\CannotParseConfigException; use Slim\Console\Exception\CannotResolveConfigException; class ConfigResolver @@ -32,34 +32,23 @@ class ConfigResolver self::FORMAT_JSON, ]; - /** - * @var string - */ - protected $cwd; - - /** - * @param string $cwd - */ - public function __construct(string $cwd) - { - $this->cwd = $cwd; - } - /** * Resolve configuration. Environment takes precedence over configuration file. * + * @param string $dir + * * @return Config * - * @throws InvalidArgumentException + * @throws CannotParseConfigException * @throws RuntimeException */ - public function resolve(): Config + public function resolve(string $dir): Config { try { return $this->attemptResolvingConfigFromEnvironment(); } catch (CannotResolveConfigException $e) { try { - return $this->attemptResolvingConfigFromSupportedFormats(); + return $this->attemptResolvingConfigFromSupportedFormats($dir); } catch (CannotResolveConfigException $e) { return Config::fromDefaults(); } @@ -74,11 +63,11 @@ public function resolve(): Config protected function attemptResolvingConfigFromEnvironment(): Config { if ( - getenv(Config::SLIM_CONSOLE_BOOTSTRAP_DIR) - || getenv(Config::SLIM_CONSOLE_COMMANDS_DIR) - || getenv(Config::SLIM_CONSOLE_INDEX_DIR) - || getenv(Config::SLIM_CONSOLE_INDEX_FILE) - || getenv(Config::SLIM_CONSOLE_SOURCE_DIR) + is_string(getenv(Config::SLIM_CONSOLE_BOOTSTRAP_DIR)) + || is_string(getenv(Config::SLIM_CONSOLE_COMMANDS_DIR)) + || is_string(getenv(Config::SLIM_CONSOLE_INDEX_DIR)) + || is_string(getenv(Config::SLIM_CONSOLE_INDEX_FILE)) + || is_string(getenv(Config::SLIM_CONSOLE_SOURCE_DIR)) ) { return Config::fromEnvironment(); } @@ -87,15 +76,18 @@ protected function attemptResolvingConfigFromEnvironment(): Config } /** + * @param string|null $dir + * * @return Config * * @throws CannotResolveConfigException - * @throws InvalidArgumentException + * @throws CannotParseConfigException * @throws RuntimeException */ - protected function attemptResolvingConfigFromSupportedFormats(): Config + protected function attemptResolvingConfigFromSupportedFormats(string $dir = null): Config { - $basePath = $this->cwd . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME; + $dir = $dir ?? getcwd(); + $basePath = $dir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME; foreach ($this->supportedFormats as $format) { $path = $basePath . ".{$format}"; @@ -113,7 +105,7 @@ protected function attemptResolvingConfigFromSupportedFormats(): Config * * @return Config * - * @throws InvalidArgumentException + * @throws CannotParseConfigException * @throws RuntimeException */ protected function attemptParsingConfigFromFile(string $path, string $format): Config diff --git a/src/Config/Parser/ConfigParserInterface.php b/src/Config/Parser/ConfigParserInterface.php index 44e44a8..3b11003 100644 --- a/src/Config/Parser/ConfigParserInterface.php +++ b/src/Config/Parser/ConfigParserInterface.php @@ -10,8 +10,8 @@ namespace Slim\Console\Config\Parser; -use InvalidArgumentException; use Slim\Console\Config\Config; +use Slim\Console\Exception\CannotParseConfigException; interface ConfigParserInterface { @@ -20,7 +20,7 @@ interface ConfigParserInterface * * @return Config * - * @throws InvalidArgumentException + * @throws CannotParseConfigException */ public static function parse(string $path): Config; } diff --git a/src/Config/Parser/JSONConfigParser.php b/src/Config/Parser/JSONConfigParser.php index 220f104..8702e70 100644 --- a/src/Config/Parser/JSONConfigParser.php +++ b/src/Config/Parser/JSONConfigParser.php @@ -16,9 +16,7 @@ class JSONConfigParser implements ConfigParserInterface { /** - * @param string $path - * - * @return Config + * {@inheritdoc} */ public static function parse(string $path): Config { diff --git a/src/Config/Parser/PHPConfigParser.php b/src/Config/Parser/PHPConfigParser.php index d79e71e..c6a13ff 100644 --- a/src/Config/Parser/PHPConfigParser.php +++ b/src/Config/Parser/PHPConfigParser.php @@ -10,22 +10,20 @@ namespace Slim\Console\Config\Parser; -use InvalidArgumentException; use Slim\Console\Config\Config; +use Slim\Console\Exception\CannotParseConfigException; class PHPConfigParser implements ConfigParserInterface { /** - * @param string $path - * - * @return Config + * {@inheritdoc} */ public static function parse(string $path): Config { $parsed = require $path; if (!is_array($parsed)) { - throw new InvalidArgumentException('Slim Console configuration should be an array.'); + throw new CannotParseConfigException('Slim Console configuration should be an array.'); } return Config::fromArray($parsed); diff --git a/src/Exception/CannotParseConfigException.php b/src/Exception/CannotParseConfigException.php new file mode 100644 index 0000000..c469703 --- /dev/null +++ b/src/Exception/CannotParseConfigException.php @@ -0,0 +1,17 @@ + Date: Sat, 9 May 2020 17:09:25 -0600 Subject: [PATCH 38/44] add missing file headers --- tests/examples/invalid-php/invalid-format.php | 8 ++++++++ tests/examples/php/slim-console.config.php | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/examples/invalid-php/invalid-format.php b/tests/examples/invalid-php/invalid-format.php index faafbbc..ce6a0b9 100644 --- a/tests/examples/invalid-php/invalid-format.php +++ b/tests/examples/invalid-php/invalid-format.php @@ -1,3 +1,11 @@ 'customBootstrapDir', 'commandsDir' => 'customCommandsDir', From 0922b68ea0b22a797955e265d6bf5b44dd2d8e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=83=3F=C3=82=C2=A9rub=C3=83=3F=C3=82=C2=A9?= Date: Sat, 9 May 2020 17:09:25 -0600 Subject: [PATCH 39/44] fix tests --- tests/Command/AbstractCommandTest.php | 4 +++- tests/Config/ConfigResolverTest.php | 14 +++++++------- tests/Config/Parser/PHPConfigParserTest.php | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/Command/AbstractCommandTest.php b/tests/Command/AbstractCommandTest.php index babaeaf..ef9116b 100644 --- a/tests/Command/AbstractCommandTest.php +++ b/tests/Command/AbstractCommandTest.php @@ -35,7 +35,9 @@ public function testGetConfigThrowsRuntimeExceptionWithIncompatibleApp(): void $mockCommand = new MockCommand(); $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Method method `getConfig()` does not exist on this type of application.'); + $this->expectExceptionMessage( + 'Usage of the method `getConfig()` requires the parent application to be a Slim Console Application.' + ); $mockCommand->getConfig(); } diff --git a/tests/Config/ConfigResolverTest.php b/tests/Config/ConfigResolverTest.php index 0405ac8..8472f7c 100644 --- a/tests/Config/ConfigResolverTest.php +++ b/tests/Config/ConfigResolverTest.php @@ -37,9 +37,9 @@ public function testResolvePrioritizesEnvironment(): void $this->setupEnvConfig(); $exampleJsonConfigPath = $this->getExampleConfigPath(ConfigResolver::FORMAT_JSON); - $configResolver = new ConfigResolver($exampleJsonConfigPath); + $configResolver = new ConfigResolver(); - $config = $configResolver->resolve(); + $config = $configResolver->resolve($exampleJsonConfigPath); $this->assertSame($this->envParams['bootstrapDir'], $config->getBootstrapDir()); $this->assertSame($this->envParams['commandsDir'], $config->getCommandsDir()); @@ -62,9 +62,9 @@ public function testAttemptResolvingConfigFromSupportedFormats(string $format, C $example = $parser($configPath); $exampleConfigPath = $this->getExampleConfigPath($format); - $configResolver = new ConfigResolver($exampleConfigPath); + $configResolver = new ConfigResolver(); - $config = $configResolver->resolve(); + $config = $configResolver->resolve($exampleConfigPath); $this->assertSame($example['bootstrapDir'], $config->getBootstrapDir()); $this->assertSame($example['commandsDir'], $config->getCommandsDir()); @@ -86,7 +86,7 @@ public function testAttemptParsingConfigFromFileThrowsRuntimeException(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage("Invalid configuration format `{$invalidFormat}`."); - $configResolver = new ConfigResolver($this->examplesConfigBasePath); + $configResolver = new ConfigResolver(); $attemptParsingConfigFromFileMethod->invoke($configResolver, $this->examplesConfigBasePath, $invalidFormat); } @@ -98,8 +98,8 @@ public function testResolveFallbackOnDefaults(): void $defaults = $defaultsReflection->getValue(); - $configResolver = new ConfigResolver($this->examplesConfigBasePath); - $config = $configResolver->resolve(); + $configResolver = new ConfigResolver(); + $config = $configResolver->resolve($this->examplesConfigBasePath); $this->assertSame($defaults['bootstrapDir'], $config->getBootstrapDir()); $this->assertSame($defaults['commandsDir'], $config->getCommandsDir()); diff --git a/tests/Config/Parser/PHPConfigParserTest.php b/tests/Config/Parser/PHPConfigParserTest.php index d9e5254..27e2bb6 100644 --- a/tests/Config/Parser/PHPConfigParserTest.php +++ b/tests/Config/Parser/PHPConfigParserTest.php @@ -10,9 +10,9 @@ namespace Slim\Tests\Console\Config\Parser; -use InvalidArgumentException; use Slim\Console\Config\ConfigResolver; use Slim\Console\Config\Parser\PHPConfigParser; +use Slim\Console\Exception\CannotParseConfigException; use Slim\Tests\Console\TestCase; class PHPConfigParserTest extends TestCase @@ -34,13 +34,13 @@ public function testParse(): void $this->assertSame($phpConfig['sourceDir'], $config->getSourceDir()); } - public function testParseThrowsInvalidArgumentException(): void + public function testParseThrowsExceptionWithInvalidConfigFormat(): void { $invalidJsonConfigPath = $this->examplesConfigBasePath . DIRECTORY_SEPARATOR . 'invalid-php' . DIRECTORY_SEPARATOR . 'invalid-format.php'; - $this->expectException(InvalidArgumentException::class); + $this->expectException(CannotParseConfigException::class); $this->expectExceptionMessage('Slim Console configuration should be an array.'); PHPConfigParser::parse($invalidJsonConfigPath); From 725cecc46c3cdbdf4341a6f4a8181e2add7cdbcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 17:19:21 -0600 Subject: [PATCH 40/44] fix environment variable resolving logic --- src/Config/ConfigResolver.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 7cfcd67..216f689 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -35,14 +35,14 @@ class ConfigResolver /** * Resolve configuration. Environment takes precedence over configuration file. * - * @param string $dir + * @param string|null $dir * * @return Config * * @throws CannotParseConfigException * @throws RuntimeException */ - public function resolve(string $dir): Config + public function resolve(string $dir = null): Config { try { return $this->attemptResolvingConfigFromEnvironment(); @@ -62,12 +62,18 @@ public function resolve(string $dir): Config */ protected function attemptResolvingConfigFromEnvironment(): Config { + $bootstrapDir = getenv(Config::SLIM_CONSOLE_BOOTSTRAP_DIR); + $commandsDir = getenv(Config::SLIM_CONSOLE_COMMANDS_DIR); + $indexDir = getenv(Config::SLIM_CONSOLE_INDEX_DIR); + $indexFile = getenv(Config::SLIM_CONSOLE_INDEX_FILE); + $sourceDir = getenv(Config::SLIM_CONSOLE_SOURCE_DIR); + if ( - is_string(getenv(Config::SLIM_CONSOLE_BOOTSTRAP_DIR)) - || is_string(getenv(Config::SLIM_CONSOLE_COMMANDS_DIR)) - || is_string(getenv(Config::SLIM_CONSOLE_INDEX_DIR)) - || is_string(getenv(Config::SLIM_CONSOLE_INDEX_FILE)) - || is_string(getenv(Config::SLIM_CONSOLE_SOURCE_DIR)) + (is_string($bootstrapDir) && !empty($bootstrapDir) && !ctype_space($bootstrapDir)) + || (is_string($commandsDir) && !empty($commandsDir) && !ctype_space($commandsDir)) + || (is_string($indexDir) && !empty($indexDir) && !ctype_space($indexDir)) + || (is_string($indexFile) && !empty($indexFile) && !ctype_space($indexFile)) + || (is_string($sourceDir) && !empty($sourceDir) && !ctype_space($sourceDir)) ) { return Config::fromEnvironment(); } From 69deea9cac1c0ded595279d94497bcfb6109f49d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 17:21:20 -0600 Subject: [PATCH 41/44] remove unused setter --- tests/Mocks/MockCommand.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/Mocks/MockCommand.php b/tests/Mocks/MockCommand.php index 7a283b0..b1bfc72 100644 --- a/tests/Mocks/MockCommand.php +++ b/tests/Mocks/MockCommand.php @@ -44,14 +44,4 @@ public function getMockOutput(): string { return $this->output; } - - /** - * @param string $output - * @return self - */ - public function setMockOutput(string $output): self - { - $this->output = $output; - return $this; - } } From a7072e19eb1eb59239255902d150f9067bc8e9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 17:22:54 -0600 Subject: [PATCH 42/44] switch resolving logic to is_file instead of file_exists --- src/Config/ConfigResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index 216f689..ecf4ce9 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -97,7 +97,7 @@ protected function attemptResolvingConfigFromSupportedFormats(string $dir = null foreach ($this->supportedFormats as $format) { $path = $basePath . ".{$format}"; - if (file_exists($path) && is_readable($path)) { + if (is_file($path) && is_readable($path)) { return $this->attemptParsingConfigFromFile($path, $format); } } From ac0214ae0f0f88b31927ef4f4e9aa28f2b49a858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sat, 9 May 2020 18:39:12 -0600 Subject: [PATCH 43/44] remove checkMissingIterableValueType declaration --- phpstan.neon.dist | 1 - 1 file changed, 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b55137a..036e5a5 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,4 +1,3 @@ parameters: level: max - checkMissingIterableValueType: false inferPrivatePropertyTypeFromConstructor: true From be36b21e2b30789b4733fca2adaaa765c36506d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20B=C3=A9rub=C3=A9?= Date: Sun, 10 May 2020 11:49:44 -0600 Subject: [PATCH 44/44] fix type hints --- src/Config/ConfigResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Config/ConfigResolver.php b/src/Config/ConfigResolver.php index ecf4ce9..f779553 100644 --- a/src/Config/ConfigResolver.php +++ b/src/Config/ConfigResolver.php @@ -42,7 +42,7 @@ class ConfigResolver * @throws CannotParseConfigException * @throws RuntimeException */ - public function resolve(string $dir = null): Config + public function resolve(?string $dir = null): Config { try { return $this->attemptResolvingConfigFromEnvironment(); @@ -90,7 +90,7 @@ protected function attemptResolvingConfigFromEnvironment(): Config * @throws CannotParseConfigException * @throws RuntimeException */ - protected function attemptResolvingConfigFromSupportedFormats(string $dir = null): Config + protected function attemptResolvingConfigFromSupportedFormats(?string $dir = null): Config { $dir = $dir ?? getcwd(); $basePath = $dir . DIRECTORY_SEPARATOR . self::CONFIG_FILENAME;