Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config Object #14

Merged
merged 44 commits into from
May 10, 2020
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
979adff
add ext-json
l0gicgate May 1, 2020
603a6c8
add Config class
l0gicgate May 1, 2020
209c11c
add ConfigResolver
l0gicgate May 1, 2020
21eed65
add periods to error messages
l0gicgate May 1, 2020
2568df6
add getters and setters for Config object
l0gicgate May 1, 2020
6259b75
create AbstractCommand class
l0gicgate May 1, 2020
e907216
add config resolving
l0gicgate May 1, 2020
70b4b3e
rename Application to App
l0gicgate May 2, 2020
a30a337
remove setters and make constructor protected
l0gicgate May 2, 2020
c3e6c17
rename Application to App
l0gicgate May 2, 2020
e2fc479
rename APPLICATION_NAME constant to NAME
l0gicgate May 2, 2020
eaea4e3
fix code style
l0gicgate May 2, 2020
168aa57
remove setConfig
l0gicgate May 2, 2020
e72b1f2
fix typo
l0gicgate May 2, 2020
e29d7b8
move exception to its own aggregate
l0gicgate May 2, 2020
8a89b91
add json_last_error_msg() to exception description
l0gicgate May 2, 2020
c90ab34
rename instances of `Configuration` to `Config`
l0gicgate May 3, 2020
5d02287
change usage of `require_once` to `require`
l0gicgate May 3, 2020
d83aaa4
remove `mergeDefaults` method and refactor `fromEnvironment` static i…
l0gicgate May 3, 2020
542b72c
fix white spacing
l0gicgate May 3, 2020
6cb9b8f
abstract configuration parsers
l0gicgate May 3, 2020
de16735
remove rootDir and refactor validation
l0gicgate May 6, 2020
4035cdc
add micro-optimization within `attemptResolvingConfigFromSupportedFor…
l0gicgate May 6, 2020
442b9b5
add cwd
l0gicgate May 8, 2020
71ec02b
add fromDefaults method
l0gicgate May 8, 2020
4b052a2
add fallback on fromDefaults
l0gicgate May 8, 2020
9132219
refactor parsers
l0gicgate May 8, 2020
6ca9662
add tests
l0gicgate May 8, 2020
8ec4f6c
fix phpstan errors
l0gicgate May 8, 2020
7e10d3c
fix code style errors
l0gicgate May 8, 2020
b8ffb84
fix phpstan errors
l0gicgate May 8, 2020
a17bc29
add is_readable check
l0gicgate May 9, 2020
138d8a0
add more tests
l0gicgate May 9, 2020
590e5f7
remove symfony/config
l0gicgate May 9, 2020
ff8f395
change exception message to be more relevant
l0gicgate May 9, 2020
65b389f
fix docbloc definitions
l0gicgate May 9, 2020
19ad6c5
refactor directory resolving logic
l0gicgate May 9, 2020
aaea1b1
add missing file headers
l0gicgate May 9, 2020
0922b68
fix tests
l0gicgate May 9, 2020
725cecc
fix environment variable resolving logic
l0gicgate May 9, 2020
69deea9
remove unused setter
l0gicgate May 9, 2020
a7072e1
switch resolving logic to is_file instead of file_exists
l0gicgate May 9, 2020
ac0214a
remove checkMissingIterableValueType declaration
l0gicgate May 10, 2020
be36b21
fix type hints
l0gicgate May 10, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions bin/slim
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@

declare(strict_types=1);

use Slim\Console\Application;
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';
}

$app = new Application();
$config = (new ConfigResolver($cwd))->resolve();
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved

$app = new App($config);
$app->run();
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
}
],
"require": {
"ext-json": "*",
"php": "^7.2",
"symfony/console": "^5.0",
"symfony/config": "^5.0"
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved
},
"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"
},
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
parameters:
level: max
checkMissingIterableValueType: false
adriansuter marked this conversation as resolved.
Show resolved Hide resolved
inferPrivatePropertyTypeFromConstructor: true
29 changes: 25 additions & 4 deletions src/Application.php → src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,31 @@

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;
use Throwable;

class Application extends SymfonyApplication
class App extends SymfonyApplication
{
private const VERSION = '0.1';
protected const NAME = 'Slim Console';

public function __construct()
protected const VERSION = '0.1';
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved

/**
* @var Config
*/
protected $config;

/**
* @param Config $config
*/
public function __construct(Config $config)
{
parent::__construct('Slim Console', self::VERSION);
parent::__construct(static::NAME, static::VERSION);

$this->config = $config;
}

/**
Expand All @@ -48,4 +61,12 @@ public function doRun(InputInterface $input, OutputInterface $output): int

return parent::doRun($input, $output);
}

/**
* @return Config
*/
public function getConfig(): Config
{
return $this->config;
}
}
35 changes: 35 additions & 0 deletions src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Console/blob/0.x/LICENSE.md (MIT License)
*/

declare(strict_types=1);

namespace Slim\Console\Command;

use RuntimeException;
use Slim\Console\App;
use Slim\Console\Config\Config;
use Symfony\Component\Console\Command\Command;

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('Method method `getConfig()` does not exist on this type of application.');
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved
}

return $app->getConfig();
}
}
207 changes: 207 additions & 0 deletions src/Config/Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
<?php

/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Console/blob/0.x/LICENSE.md (MIT License)
*/

declare(strict_types=1);

namespace Slim\Console\Config;

use InvalidArgumentException;

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_SOURCE_DIR = 'SLIM_CONSOLE_SOURCE_DIR';
public const SLIM_CONSOLE_COMMANDS_DIR = 'SLIM_CONSOLE_COMMANDS_DIR';

/**
* @var array
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved
*/
protected static $defaults = [
'bootstrapDir' => 'app',
'indexDir' => 'public',
'indexFile' => 'index.php',
'sourceDir' => 'src',
'commandsDir' => 'src/Application/Console/Commands',
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved
];

/**
* @var string
*/
protected $bootstrapDir;

/**
* @var string
*/
protected $indexDir;

/**
* @var string
*/
protected $indexFile;

/**
* @var string
*/
protected $sourceDir;

/**
* @var string|null
*/
protected $commandsDir;

/**
* @param string $bootstrapDir
* @param string $indexDir
* @param string $indexFile
* @param string $sourceDir
* @param string|null $commandsDir
*/
protected function __construct(
string $bootstrapDir,
string $indexDir,
string $indexFile,
string $sourceDir,
?string $commandsDir = null
) {
$this->bootstrapDir = $bootstrapDir;
$this->indexDir = $indexDir;
$this->indexFile = $indexFile;
$this->sourceDir = $sourceDir;
$this->commandsDir = $commandsDir;
}

/**
* @return string
*/
public function getBootstrapDir(): string
{
return $this->bootstrapDir;
}

/**
* @return string
*/
public function getIndexDir(): string
{
return $this->indexDir;
}

/**
* @return string
*/
public function getIndexFile(): string
{
return $this->indexFile;
}

/**
* @return string
*/
public function getSourceDir(): string
{
return $this->sourceDir;
}

/**
* @return string|null
*/
public function getCommandsDir(): ?string
{
return $this->commandsDir;
}

/**
* @param array $params
adriansuter marked this conversation as resolved.
Show resolved Hide resolved
*
* @throws InvalidArgumentException
*/
protected static function validate(array $params): void
{
[
'bootstrapDir' => $bootstrapDir,
'indexDir' => $indexDir,
'indexFile' => $indexFile,
'sourceDir' => $sourceDir,
'commandsDir' => $commandsDir,
] = $params;

if (!is_string($bootstrapDir) || empty($bootstrapDir) || ctype_space($bootstrapDir)) {
throw new InvalidArgumentException('`bootstrapDir` must be a string.');
}

if (!is_string($indexDir) || empty($indexDir) || ctype_space($indexDir)) {
throw new InvalidArgumentException('`indexDir` must be a string.');
}

if (!is_string($indexFile) || empty($indexFile) || ctype_space($indexFile)) {
throw new InvalidArgumentException('`indexFile` must be a string.');
}

if (!is_string($sourceDir) || empty($sourceDir) || ctype_space($sourceDir)) {
throw new InvalidArgumentException('`sourceDir` must be a string.');
}

if (!empty($commandsDir) && (!is_string($commandsDir) || ctype_space($commandsDir))) {
adriansuter marked this conversation as resolved.
Show resolved Hide resolved
throw new InvalidArgumentException('`commandsDir` must be a string.');
}
}

/**
* @param array<mixed> $params
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't that be array<string, string>? Or is that too restrictive?

If so, there would be a phpstan complaint, as in \Slim\Console\Config\Config::fromEnvironment we have

 return self::fromArray([
            'bootstrapDir' => getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR),
/* ... */
            'commandsDir' => getenv(self::SLIM_CONSOLE_COMMANDS_DIR),
        ]);

and these getenv can be either string or false. To avoid the phpstan complaint, we would have to write

 return self::fromArray([
            'bootstrapDir' => (string)getenv(self::SLIM_CONSOLE_BOOTSTRAP_DIR),
/* ... */
            'commandsDir' => (string)getenv(self::SLIM_CONSOLE_COMMANDS_DIR),
        ]);

Of course this casting would never be necessary, as we know at this stage, that these environment variables are defined - but phpstan does apparently not know :-( that we know.

*
* @return Config
*
* @throws InvalidArgumentException
*/
public static function fromArray(array $params): Config
{
$params = array_merge(self::$defaults, $params);

self::validate($params);

return new self(
$params['bootstrapDir'],
$params['indexDir'],
$params['indexFile'],
$params['sourceDir'],
$params['commandsDir']
);
}

/**
* @return Config
*
* @throws InvalidArgumentException
*/
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),
]);
}

/**
* @return Config
*/
public static function fromDefaults(): Config
{
return new self(
self::$defaults['bootstrapDir'],
self::$defaults['indexDir'],
self::$defaults['indexFile'],
self::$defaults['sourceDir'],
self::$defaults['commandsDir']
);
}
l0gicgate marked this conversation as resolved.
Show resolved Hide resolved
}
Loading