Passed
Push — master ( ad6b2a...b41ca0 )
by Caen
07:45 queued 14s
created

LoadYamlConfiguration::mergeParsedConfiguration()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 6
nc 5
nop 0
dl 0
loc 13
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Foundation\Internal;
6
7
use Hyde\Enums\Feature;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Str;
10
use Hyde\Foundation\Application;
11
use Illuminate\Config\Repository;
12
use Hyde\Framework\Features\Blogging\Models\PostAuthor;
0 ignored issues
show
Bug introduced by
The type Hyde\Framework\Features\Blogging\Models\PostAuthor was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Hyde\Framework\Exceptions\InvalidConfigurationException;
14
15
use function tap;
16
use function array_merge;
17
18
/**
19
 * @internal Bootstrap service that loads the YAML configuration file.
20
 *
21
 * @see docs/digging-deeper/customization.md#yaml-configuration
22
 *
23
 * It also supports loading multiple configuration namespaces, where a configuration namespace is defined
24
 * as a firs level entry in the service container configuration repository array, and corresponds
25
 * one-to-one with a file in the config directory, and a root-level key in the YAML file.
26
 *
27
 * The namespace feature by design, requires a top-level configuration entry to be present as 'hyde' in the YAML file.
28
 * Existing config files will be parsed as normal, but can be migrated by indenting all entries by one level,
29
 * and adding a top-level 'hyde' key. Then additional namespaces can be added underneath as needed.
30
 */
31
class LoadYamlConfiguration
32
{
33
    protected YamlConfigurationRepository $yaml;
34
35
    /** @var array<string, array<string, null|scalar|array>> */
36
    protected array $config;
37
38
    public function bootstrap(Application $app): void
39
    {
40
        $this->yaml = $app->make(YamlConfigurationRepository::class);
41
42
        if ($this->yaml->hasYamlConfigFile()) {
43
            /** @var Repository $config */
44
            $config = $app->make('config');
45
46
            tap($config, function (Repository $config): void {
47
                $this->config = $config->all();
48
                $this->mergeParsedConfiguration();
49
            })->set($this->config);
50
        }
51
    }
52
53
    protected function mergeParsedConfiguration(): void
54
    {
55
        foreach ($this->yaml->getData() as $namespace => $data) {
56
            if ($namespace === 'hyde' && isset($data['authors'])) {
57
                // Todo: We may not actually need this, since the parser in the kernel can handle this. See https://github.com/hydephp/develop/pull/1824/commits/6a076b831b3cf07341605c314f0c29bfa4c0a8da
58
                $data['authors'] = $this->parseAuthors($data['authors']);
59
            }
60
61
            if ($namespace === 'hyde' && isset($data['features'])) {
62
                $data['features'] = $this->parseFeatures($data['features']);
63
            }
64
65
            $this->mergeConfiguration($namespace, Arr::undot($data ?: []));
66
        }
67
    }
68
69
    protected function mergeConfiguration(string $namespace, array $yaml): void
70
    {
71
        $this->config[$namespace] = array_merge($this->config[$namespace] ?? [], $yaml);
72
    }
73
74
    /**
75
     * @param  array<string, array{username?: string, name?: string, website?: string, bio?: string, avatar?: string, socials?: array<string, string>}>  $authors
76
     * @return array<string, \Hyde\Framework\Features\Blogging\Models\PostAuthor>
77
     */
78
    protected function parseAuthors(array $authors): array
79
    {
80
        return Arr::mapWithKeys($authors, function (array $author, string $username): array {
81
            $message = 'Invalid author configuration detected in the YAML config file. Please double check the syntax.';
82
83
            return InvalidConfigurationException::try(fn () => [$username => PostAuthor::create($author)], $message);
84
        });
85
    }
86
87
    /**
88
     * @param  array<string>  $features
89
     * @return array<\Hyde\Enums\Feature>
90
     */
91
    protected function parseFeatures(array $features): array
92
    {
93
        return array_map(function (string $feature): Feature {
94
            $name = Str::studly($feature);
95
            $case = Feature::fromName($name);
96
97
            if (! $case) {
98
                throw new InvalidConfigurationException("Invalid feature '$feature' specified in the YAML config file. (Feature::$name does not exist)");
99
            }
100
101
            return $case;
102
        }, $features);
103
    }
104
}
105