Passed
Pull Request — master (#407)
by Kirill
06:59
created

FileSystemInfo::prepareOptions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 16
rs 9.9666
1
<?php
2
3
/**
4
 * This file is part of Spiral Framework package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Storage\Config\DTO\FileSystemInfo;
13
14
use Spiral\Storage\Exception\ConfigException;
15
use Spiral\Storage\Config\DTO\Traits\OptionsTrait;
16
use Spiral\Storage\Exception\StorageException;
17
use Spiral\Storage\Config\DTO\Traits\ClassBasedTrait;
18
19
abstract class FileSystemInfo implements
20
    FileSystemInfoInterface,
21
    ClassBasedInterface,
22
    OptionsBasedInterface
23
{
24
    use ClassBasedTrait;
25
    use OptionsTrait;
26
27
    protected const REQUIRED_OPTIONS = [];
28
29
    protected const ADDITIONAL_OPTIONS = [];
30
31
    protected const FILE_SYSTEM_INFO_TYPE = '';
32
33
    /**
34
     * @var string
35
     */
36
    protected $name;
37
38
    /**
39
     * @var string
40
     */
41
    protected $adapter;
42
43
    /**
44
     * @var string
45
     */
46
    protected $resolver;
47
48
    /**
49
     * @param string $name
50
     * @param array $info
51
     *
52
     * @throws StorageException
53
     */
54
    public function __construct(string $name, array $info)
55
    {
56
        $this->validateInfoSufficient($name, $info);
57
58
        $this->name = $name;
59
60
        $this->checkClass($info[static::ADAPTER_KEY], \sprintf('Filesystem %s adapter', $this->name));
61
        $this->adapter = $info[static::ADAPTER_KEY];
62
63
        if (array_key_exists(static::RESOLVER_KEY, $info)) {
64
            $this->checkClass($info[static::RESOLVER_KEY], \sprintf('Filesystem %s resolver', $this->name));
65
            $this->resolver = $info[static::RESOLVER_KEY];
66
        }
67
68
        $this->prepareOptions($info[OptionsBasedInterface::OPTIONS_KEY]);
69
70
        if ($this instanceof SpecificConfigurableFileSystemInfo) {
71
            $this->constructSpecific($info);
72
        }
73
    }
74
75
    /**
76
     * @inheritDoc
77
     */
78
    public function getAdapterClass(): string
79
    {
80
        return $this->adapter;
81
    }
82
83
    /**
84
     * @inheritDoc
85
     */
86
    public function getResolverClass(): string
87
    {
88
        return $this->resolver;
89
    }
90
91
    /**
92
     * @inheritDoc
93
     */
94
    public function getName(): string
95
    {
96
        return $this->name;
97
    }
98
99
    /**
100
     * @inheritDoc
101
     */
102
    public function isAdvancedUsage(): bool
103
    {
104
        foreach (static::ADDITIONAL_OPTIONS as $optionalOption => $type) {
105
            if ($this->hasOption($optionalOption)) {
106
                return true;
107
            }
108
        }
109
110
        return false;
111
    }
112
113
    /**
114
     * Validate and prepare options
115
     *
116
     * @param array $options
117
     *
118
     * @throws ConfigException
119
     */
120
    protected function prepareOptions(array $options): void
121
    {
122
        $this->validateRequiredOptions(
123
            array_keys(static::REQUIRED_OPTIONS),
124
            $options,
125
            \sprintf(' for filesystem `%s`', $this->getName())
126
        );
127
128
        foreach ($options as $optionKey => $option) {
129
            if (($type = $this->getOptionType($optionKey)) === null) {
130
                continue;
131
            }
132
133
            $this->validateOptionByType($optionKey, $type, $option);
134
135
            $this->options[$optionKey] = $this->processOptionByType($option, $type);
136
        }
137
    }
138
139
    /**
140
     * Validate if description contains all required options
141
     *
142
     * @param string $fs
143
     * @param array $info
144
     *
145
     * @throws ConfigException
146
     */
147
    protected function validateInfoSufficient(string $fs, array $info): void
148
    {
149
        if (!array_key_exists(static::ADAPTER_KEY, $info)) {
150
            throw new ConfigException(
151
                \sprintf('Filesystem `%s` needs adapter class defined', $fs)
152
            );
153
        }
154
155
        if (!array_key_exists(OptionsBasedInterface::OPTIONS_KEY, $info)) {
156
            throw new ConfigException(
157
                \sprintf('Filesystem `%s` needs options defined', $fs)
158
            );
159
        }
160
    }
161
162
    /**
163
     * Validate option type is correct
164
     *
165
     * @param string $optionLabel
166
     * @param string $optionType
167
     * @param $optionVal
168
     *
169
     * @throws ConfigException
170
     */
171
    protected function validateOptionByType(string $optionLabel, string $optionType, $optionVal): void
172
    {
173
        if (!$this->isOptionHasRequiredType($optionLabel, $optionVal, $optionType)) {
174
            throw new ConfigException(
175
                \sprintf(
176
                    'Option `%s` defined in wrong format for filesystem `%s`, %s expected',
177
                    $optionLabel,
178
                    $this->getName(),
179
                    $optionType
180
                )
181
            );
182
        }
183
    }
184
185
    /**
186
     * Get expected option type by label
187
     *
188
     * @param string $option
189
     *
190
     * @return string|null
191
     */
192
    protected function getOptionType(string $option): ?string
193
    {
194
        if (array_key_exists($option, static::REQUIRED_OPTIONS)) {
195
            return static::REQUIRED_OPTIONS[$option];
196
        }
197
198
        return static::ADDITIONAL_OPTIONS[$option] ?? null;
199
    }
200
}
201