YamlLoader   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 55
c 6
b 0
f 0
dl 0
loc 106
rs 10
wmc 19

4 Methods

Rating   Name   Duplication   Size   Complexity  
A enrich() 0 6 2
A getIdentifiers() 0 3 1
A __construct() 0 20 5
B initRepositories() 0 50 11
1
<?php
2
3
namespace Startwind\Forrest\Repository\Loader;
4
5
use GuzzleHttp\Client;
6
use Startwind\Forrest\Adapter\AdapterFactory;
7
use Startwind\Forrest\Adapter\EditableAdapter;
8
use Startwind\Forrest\Logger\ForrestLogger;
9
use Startwind\Forrest\Repository\Api\ApiRepository;
10
use Startwind\Forrest\Repository\Api\EditableApiRepository;
11
use Startwind\Forrest\Repository\File\EditableFileRepository;
12
use Startwind\Forrest\Repository\File\FileRepository;
13
use Startwind\Forrest\Repository\Repository;
14
use Startwind\Forrest\Repository\RepositoryCollection;
15
use Symfony\Component\Yaml\Yaml;
16
17
class YamlLoader implements RepositoryLoader
18
{
19
    public const CONFIG_ELEMENT_REPOSITORIES = 'repositories';
20
    public const CONFIG_ELEMENT_ADAPTER = 'adapter';
21
    public const CONFIG_ELEMENT_NAME = 'name';
22
    public const CONFIG_ELEMENT_CONFIG = 'config';
23
24
    public const CONFIG_ELEMENT_DESCRIPTION = 'description';
25
26
    private array $config;
27
28
    private array $repositories = [];
29
30
    public function __construct(string $userConfigFile, string $fallbackConfigFile, private readonly Client $client)
31
    {
32
        if (!file_exists($userConfigFile)) {
33
            $configFile = $fallbackConfigFile;
34
        } else {
35
            $configFile = $userConfigFile;
36
        }
37
38
        if (!file_exists($configFile)) {
39
            throw new \RuntimeException("Config file ($configFile) not found");
40
        }
41
42
        try {
43
            $this->config = Yaml::parse(file_get_contents($configFile));
44
        } catch (\Exception $exception) {
45
            throw new \RuntimeException('Unable to load YAML file ("' . $configFile . '"): ' . $exception->getMessage());
46
        }
47
48
        if (!array_key_exists(self::CONFIG_ELEMENT_REPOSITORIES, $this->config)) {
49
            throw new \RuntimeException('Config file does not contain the mandatory element "' . self::CONFIG_ELEMENT_REPOSITORIES . '".');
50
        }
51
    }
52
53
    private function initRepositories(): void
54
    {
55
        foreach ($this->config[self::CONFIG_ELEMENT_REPOSITORIES] as $repoName => $repoConfig) {
56
            if (!array_key_exists('type', $repoConfig)) {
57
                $repoType = Repository::TYPE_FILE;
58
            } else {
59
                $repoType = $repoConfig['type'];
60
            }
61
62
            /** @todo these three checks can be condensed */
63
            if (!array_key_exists(self::CONFIG_ELEMENT_NAME, $repoConfig)) {
64
                throw new \RuntimeException('No field for repository "' . $repoName . '" with value ' . self::CONFIG_ELEMENT_NAME . ' found. Fields given are: ' . implode(', ', array_keys($repoConfig)) . '.');
65
            }
66
67
            if (!array_key_exists(self::CONFIG_ELEMENT_DESCRIPTION, $repoConfig)) {
68
                throw new \RuntimeException('No field for repository "' . $repoName . '" with value ' . self::CONFIG_ELEMENT_DESCRIPTION . ' found. Fields given are: ' . implode(', ', array_keys($repoConfig)) . '.');
69
            }
70
71
            if (!array_key_exists(self::CONFIG_ELEMENT_CONFIG, $repoConfig)) {
72
                throw new \RuntimeException('No field for repository "' . $repoName . '" with value ' . self::CONFIG_ELEMENT_CONFIG . ' found. Fields given are: ' . implode(', ', array_keys($repoConfig)) . '.');
73
            }
74
75
            // @todo this should be moved to a repository factory
76
77
            if ($repoType == Repository::TYPE_API) {
78
                $repoConfig['config']['endpoint'] = str_replace('forrest.startwind.io/api', 'api.forrestcli.com', $repoConfig['config']['endpoint']);
79
                if (array_key_exists('password', $repoConfig['config'])) {
80
                    $newRepo = new EditableApiRepository($repoConfig['config']['endpoint'], $repoConfig['name'], $repoConfig['description'], $this->client);
81
                    $newRepo->setPassword($repoConfig['config']['password']);
82
                } else {
83
                    $newRepo = new ApiRepository($repoConfig['config']['endpoint'], $repoConfig['name'], $repoConfig['description'], $this->client);
84
                }
85
            } else {
86
                $adapterIdentifier = $repoConfig[self::CONFIG_ELEMENT_ADAPTER];
87
                $adapter = AdapterFactory::getAdapter($adapterIdentifier, $repoConfig['config'], $this->client);
88
                if ($adapter instanceof EditableAdapter && $adapter->isEditable()) {
89
                    $newRepo = new EditableFileRepository($adapter, $repoConfig['name'], $repoConfig['description']);
90
                } else {
91
                    $newRepo = new FileRepository($adapter, $repoConfig['name'], $repoConfig['description']);
92
                }
93
            }
94
95
            try {
96
                $newRepo->assertHealth();
97
            } catch (\Exception $exception) {
98
                ForrestLogger::error("Unable to load repository " . $repoName . ": " . $exception->getMessage() . '.');
99
                continue;
100
            }
101
102
            $this->repositories[$repoName] = $newRepo;
103
        }
104
    }
105
106
    /**
107
     * @inheritDoc
108
     */
109
    public function getIdentifiers(): array
110
    {
111
        return array_keys($this->config[self::CONFIG_ELEMENT_REPOSITORIES]);
112
    }
113
114
    /**
115
     * @inheritDoc
116
     */
117
    public function enrich(RepositoryCollection $repositoryCollection): void
118
    {
119
        $this->initRepositories();
120
121
        foreach ($this->repositories as $repoIdentifier => $repository) {
122
            $repositoryCollection->addRepository($repoIdentifier, $repository);
123
        }
124
    }
125
}
126