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

Adapt to Yii config group names convention #39

Merged
merged 17 commits into from
Feb 19, 2023
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

- Сhg #37: Remove parameters in `ApplicationRunner` methods `runBootstrap()` and `checkEvents()`, instead are used
internal container and config instances (@vjik)
- New #36: Add ability to configure container configuration group (@vjik)
- New #38: Add ability to configure config params group (@vjik)
- Chg #39: Adapt to Yii configuration groups names convention (@vjik)
- Chg #39: Remove methods `withBootstrap()`, `withoutBootstrap()`, `withCheckingEvents()`, `withoutCheckingEvents()`
from `ApplicationRunner` (@vjik)
- New #38, #39: Add ability to configure all config group names (@vjik)
- New #39: Add parameter `$checkEvents` to `ApplicationRunner` constructor (@vjik)
- Chg #39: Remove `ConfigFactory`, instead it move code to `ApplicationRunner::createDefaultConfig()` method (@vjik)
- Enh #39: Make methods `ApplicationRunner::getConfig()` and `ApplicationRunner::getContainer()` public (@vjik)

## 1.2.1 November 07, 2022

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ use Yiisoft\Yii\Runner\Http\HttpApplicationRunner;

require_once __DIR__ . '/autoload.php';

(new HttpApplicationRunner(__DIR__, $_ENV['YII_DEBUG'], $_ENV['YII_ENV']))->run();
(new HttpApplicationRunner(
rootPath: __DIR__,
debug: $_ENV['YII_DEBUG'],
environment: $_ENV['YII_ENV']
))->run();
```

## Testing
Expand Down
2 changes: 2 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0"?>
<psalm
errorLevel="1"
findUnusedBaselineEntry="true"
findUnusedCode="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
Expand Down
152 changes: 74 additions & 78 deletions src/ApplicationRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use Yiisoft\Config\Config;
use Yiisoft\Config\ConfigInterface;
use Yiisoft\Config\ConfigPaths;
use Yiisoft\Config\Modifier\RecursiveMerge;
use Yiisoft\Config\Modifier\ReverseMerge;
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Di\Container;
use Yiisoft\Di\ContainerConfig;
Expand All @@ -22,81 +24,54 @@
*/
abstract class ApplicationRunner implements RunnerInterface
{
protected ?ConfigInterface $config = null;
protected ?ContainerInterface $container = null;
protected ?string $bootstrapGroup = null;
protected ?string $eventsGroup = null;
private ?ConfigInterface $config = null;
private ?ContainerInterface $container = null;

/**
* @param string $rootPath The absolute path to the project root.
* @param bool $debug Whether the debug mode is enabled.
* @param string $paramsConfigGroup The config parameters group name.
* @param string $containerConfigGroup The container configuration group name.
* @param bool $checkEvents Whether to check events' configuration.
* @param string|null $environment The environment name.
* @param string $bootstrapGroup The bootstrap configuration group name.
* @param string $eventsGroup The events' configuration group name.
* @param string $diGroup The container definitions' configuration group name.
* @param string $diProvidersGroup The container providers' configuration group name.
* @param string $diDelegatesGroup The container delegates' configuration group name.
* @param string $diTagsGroup The container tags' configuration group name.
* @param string $paramsGroup The configuration parameters group name.
* @param array $nestedParamsGroups Configuration group names that are included into configuration parameters group.
* This is needed for recursive merging of parameters.
* @param array $nestedEventsGroups Configuration group names that are included into events' configuration group.
* This is needed for reverse and recursive merge of events' configurations.
*
vjik marked this conversation as resolved.
Show resolved Hide resolved
* @psalm-param list<string> $nestedParamsGroups
* @psalm-param list<string> $nestedEventsGroups
*/
public function __construct(
protected string $rootPath,
protected bool $debug,
protected string $paramsConfigGroup,
protected string $containerConfigGroup,
protected ?string $environment
protected bool $checkEvents,
protected ?string $environment,
protected string $bootstrapGroup,
protected string $eventsGroup,
protected string $diGroup,
protected string $diProvidersGroup,
protected string $diDelegatesGroup,
protected string $diTagsGroup,
protected string $paramsGroup,
protected array $nestedParamsGroups,
samdark marked this conversation as resolved.
Show resolved Hide resolved
protected array $nestedEventsGroups,
) {
}

abstract public function run(): void;

/**
* Returns a new instance with the specified bootstrap configuration group name.
*
* @param string $bootstrapGroup The bootstrap configuration group name.
*/
public function withBootstrap(string $bootstrapGroup): static
{
$new = clone $this;
$new->bootstrapGroup = $bootstrapGroup;
return $new;
}

/**
* Returns a new instance with bootstrapping disabled.
*/
public function withoutBootstrap(): static
{
$new = clone $this;
$new->bootstrapGroup = null;
return $new;
}

/**
* Returns a new instance with the specified name of event configuration group to check.
*
* Note: The configuration of events is checked in debug mode only.
*
* @param string $eventsGroup Name of event configuration group to check.
*/
public function withCheckingEvents(string $eventsGroup): static
{
$new = clone $this;
$new->eventsGroup = $eventsGroup;
return $new;
}

/**
* Returns a new instance with disabled event configuration check.
*/
public function withoutCheckingEvents(): static
{
$new = clone $this;
$new->eventsGroup = null;
return $new;
}

/**
* Returns a new instance with the specified config instance {@see ConfigInterface}.
*
* @param ConfigInterface $config The config instance.
*/
public function withConfig(ConfigInterface $config): static
final public function withConfig(ConfigInterface $config): static
{
$new = clone $this;
$new->config = $config;
Expand All @@ -108,7 +83,7 @@ public function withConfig(ConfigInterface $config): static
*
* @param ContainerInterface $container The container instance.
*/
public function withContainer(ContainerInterface $container): static
final public function withContainer(ContainerInterface $container): static
{
$new = clone $this;
$new->container = $container;
Expand All @@ -118,40 +93,46 @@ public function withContainer(ContainerInterface $container): static
/**
* @throws ErrorException|RuntimeException
*/
protected function runBootstrap(): void
final protected function runBootstrap(): void
{
if ($this->bootstrapGroup !== null) {
(new BootstrapRunner($this->getContainer(), $this->getConfig()->get($this->bootstrapGroup)))->run();
$bootstrapList = $this->getConfiguration($this->bootstrapGroup);
if (empty($bootstrapList)) {
return;
}

(new BootstrapRunner($this->getContainer(), $bootstrapList))->run();
}

/**
* @throws ContainerExceptionInterface|ErrorException|NotFoundExceptionInterface
*/
protected function checkEvents(): void
final protected function checkEvents(): void
{
if ($this->debug && $this->eventsGroup !== null) {
if (
$this->checkEvents
&& null !== $configuration = $this->getConfiguration($this->eventsGroup)
) {
/** @psalm-suppress MixedMethodCall */
$this->getContainer()
->get(ListenerConfigurationChecker::class)
->check($this->getConfig()->get($this->eventsGroup));
->check($configuration);
}
}

/**
* @throws ErrorException
*/
protected function getConfig(): ConfigInterface
final public function getConfig(): ConfigInterface
{
return $this->config ??= $this->createDefaultConfig();
}

/**
* @throws ErrorException|InvalidConfigException
*/
protected function getContainer(): ContainerInterface
final public function getContainer(): ContainerInterface
{
$this->container ??= $this->createDefaultContainer($this->getConfig(), $this->containerConfigGroup);
$this->container ??= $this->createDefaultContainer();
samdark marked this conversation as resolved.
Show resolved Hide resolved

if ($this->container instanceof Container) {
return $this->container->get(ContainerInterface::class);
Expand All @@ -160,39 +141,54 @@ protected function getContainer(): ContainerInterface
return $this->container;
}

final protected function getConfiguration(string $name): ?array
{
$config = $this->getConfig();
return $config->has($name) ? $config->get($name) : null;
}

/**
* @throws ErrorException
*/
protected function createDefaultConfig(): Config
private function createDefaultConfig(): Config
{
return ConfigFactory::create(
$paramsGroups = [$this->paramsGroup, ...$this->nestedParamsGroups];
samdark marked this conversation as resolved.
Show resolved Hide resolved
$eventsGroups = [$this->eventsGroup, ...$this->nestedEventsGroups];

return new Config(
new ConfigPaths($this->rootPath, 'config'),
$this->environment,
$this->paramsConfigGroup,
[
ReverseMerge::groups(...$eventsGroups),
RecursiveMerge::groups(...$paramsGroups, ...$eventsGroups),
],
$this->paramsGroup,
);
}

/**
* @throws ErrorException|InvalidConfigException
*/
protected function createDefaultContainer(ConfigInterface $config, string $definitionEnvironment): Container
private function createDefaultContainer(): Container
{
$containerConfig = ContainerConfig::create()->withValidate($this->debug);

if ($config->has($definitionEnvironment)) {
$containerConfig = $containerConfig->withDefinitions($config->get($definitionEnvironment));
$config = $this->getConfig();

if (null !== $definitions = $this->getConfiguration($this->diGroup)) {
$containerConfig = $containerConfig->withDefinitions($definitions);
}

if ($config->has("providers-$definitionEnvironment")) {
$containerConfig = $containerConfig->withProviders($config->get("providers-$definitionEnvironment"));
if (null !== $providers = $this->getConfiguration($this->diProvidersGroup)) {
$containerConfig = $containerConfig->withProviders($providers);
}

if ($config->has("delegates-$definitionEnvironment")) {
$containerConfig = $containerConfig->withDelegates($config->get("delegates-$definitionEnvironment"));
if (null !== $delegates = $this->getConfiguration($this->diDelegatesGroup)) {
$containerConfig = $containerConfig->withDelegates($delegates);
}

if ($config->has("tags-$definitionEnvironment")) {
$containerConfig = $containerConfig->withTags($config->get("tags-$definitionEnvironment"));
if (null !== $tags = $this->getConfiguration($this->diTagsGroup)) {
$containerConfig = $containerConfig->withTags($tags);
}

$containerConfig = $containerConfig->withDefinitions(
Expand Down
16 changes: 10 additions & 6 deletions src/BootstrapRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
*/
final class BootstrapRunner implements RunnerInterface
{
public function __construct(private ContainerInterface $container, private array $bootstrapList = [])
{
public function __construct(
private ContainerInterface $container,
private array $bootstrapList = [],
) {
}

/**
Expand All @@ -27,10 +29,12 @@ public function run(): void
{
foreach ($this->bootstrapList as $callback) {
if (!is_callable($callback)) {
throw new RuntimeException(sprintf(
'Bootstrap callback must be callable, "%s" given.',
get_debug_type($callback),
));
throw new RuntimeException(
sprintf(
'Bootstrap callback must be callable, "%s" given.',
get_debug_type($callback),
)
);
}

$callback($this->container);
Expand Down
44 changes: 0 additions & 44 deletions src/ConfigFactory.php

This file was deleted.

Loading