Passed
Push — master ( ed1478...1d0673 )
by Sergey
03:10
created

Informer::checkOptionInfoAvailability()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.0312
Metric Value
dl 0
loc 14
ccs 7
cts 8
cp 0.875
rs 9.2
cc 4
eloc 7
nc 4
nop 2
crap 4.0312
1
<?php
2
/**
3
 * @author: Viskov Sergey
4
 * @date  : 3/17/16
5
 * @time  : 1:22 PM
6
 */
7
8
namespace LTDBeget\sphinx\informer;
9
10
use LTDBeget\sphinx\enums\base\eOption;
11
use LTDBeget\sphinx\enums\eSection;
12
use LTDBeget\sphinx\enums\eVersion;
13
use LTDBeget\sphinx\informer\exceptions\DocumentationSourceException;
14
use LTDBeget\sphinx\informer\exceptions\InformerRuntimeException;
15
use Symfony\Component\Yaml\Parser;
16
17
/**
18
 * Class Informer
19
 * Class for manipulating with options info
20
 *
21
 * @package LTDBeget\sphinx\informer
22
 */
23
final class Informer
24
{
25
    /**
26
     * Get informer for concrete version, and init if did not init yet
27
     *
28
     * @param eVersion $version
29
     *
30
     * @return Informer
31
     * @throws \Symfony\Component\Yaml\Exception\ParseException
32
     * @throws \LTDBeget\sphinx\informer\exceptions\DocumentationSourceException
33
     */
34 15
    public static function get(eVersion $version) : Informer
35
    {
36 15
        if (!array_key_exists("$version", self::$instances)) {
37 3
            self::$instances["$version"] = new self($version);
38
        }
39
40 15
        return self::$instances["$version"];
41
    }
42
43
    /**
44
     * return option info for concrete option of concrete section
45
     *
46
     * @param eSection $section
47
     * @param eOption  $optionName
48
     *
49
     * @return OptionInfo
50
     * @throws \LTDBeget\sphinx\informer\exceptions\InformerRuntimeException
51
     */
52 9
    public function getOptionInfo(eSection $section, eOption $optionName) : OptionInfo
53
    {
54 9
        if (!$this->isOptionInfoInit($section, $optionName)) {
55 5
            $this->makeOptionInfo($section, $optionName);
56
        }
57
58 7
        return $this->optionsInfo[(string)$section][(string)$optionName];
59
    }
60
61
    /**
62
     * check is known option for yaml documentation for concrete version
63
     *
64
     * @param eSection $section
65
     * @param eOption  $optionName
66
     *
67
     * @return bool
68
     */
69 8
    public function isKnownOption(eSection $section, eOption $optionName)
70
    {
71 8
        return array_key_exists((string)$section, $this->documentation) &&
72 8
        array_key_exists((string)$optionName, $this->documentation[(string)$section]);
73
    }
74
75
    /**
76
     * checks is this option was permanently removed in newer sphinx version
77
     *
78
     * @param eSection $section
79
     * @param eOption  $optionName
80
     *
81
     * @return bool
82
     */
83 5
    public function isRemovedOption(eSection $section, eOption $optionName)
84
    {
85 5
        return array_key_exists((string)$section, $this->removedOptions) &&
86 5
        array_key_exists((string)$optionName, $this->removedOptions[(string)$section]);
87
    }
88
89
    /**
90
     * Is this section exists in current sphinx version
91
     *
92
     * @param eSection $section
93
     *
94
     * @return bool
95
     */
96 7
    public function isSectionExist(eSection $section) : bool
97
    {
98 7
        return !$section->is(eSection::COMMON) || !version_compare((string)$this->version, eVersion::V_2_2_1, '<');
99
    }
100
101
    /**
102
     * Iterate via all option in documentation via option section type
103
     *
104
     * @param eSection $section
105
     *
106
     * @return OptionInfo[]
107
     * @throws \LogicException
108
     * @throws \InvalidArgumentException
109
     * @throws \LTDBeget\sphinx\informer\exceptions\InformerRuntimeException
110
     */
111 1
    public function iterateOptionInfo(eSection $section)
112
    {
113 1
        if (!$this->isSectionExist($section)) {
114
            throw new InformerRuntimeException("Sphinx of version {$this->version} does't have section {$section}");
115
        }
116
117 1
        foreach ($this->documentation[(string)$section] as $optionName => $optionData) {
118 1
            yield $this->getOptionInfo($section, $this->getOptionName($section, $optionName));
119
        }
120 1
    }
121
122
    /**
123
     * Get enum for given section and string name
124
     *
125
     * @internal
126
     *
127
     * @param eSection $section
128
     * @param string   $optionName
129
     *
130
     * @return eOption
131
     * @throws \LogicException
132
     * @throws \InvalidArgumentException
133
     */
134 1
    private function getOptionName(eSection $section, string $optionName) : eOption
135
    {
136 1
        $enumClassName = "LTDBeget\\sphinx\\enums\\options\\e" . ucfirst((string)$section) . 'Option';
137
138
        /**
139
         * @var eOption $enumClassName
140
         */
141 1
        return $enumClassName::get($optionName);
142
    }
143
144
    /**
145
     * Informer constructor.
146
     * Init informer for concrete sphinx version
147
     *
148
     * @param eVersion $version
149
     *
150
     * @throws \LTDBeget\sphinx\informer\exceptions\DocumentationSourceException
151
     * @throws \Symfony\Component\Yaml\Exception\ParseException
152
     */
153 3
    private function __construct(eVersion $version)
154
    {
155 3
        $this->version = $version;
156 3
        $this->loadDocumentation();
157 3
        $this->loadRemovedList();
158 3
    }
159
160
    /**
161
     * check is option info object already init
162
     *
163
     * @param eSection $section
164
     * @param eOption  $optionName
165
     *
166
     * @return bool
167
     */
168 9
    private function isOptionInfoInit(eSection $section, eOption $optionName) : bool
169
    {
170 9
        return array_key_exists((string)$section, $this->optionsInfo) &&
171 9
        array_key_exists((string)$optionName, $this->optionsInfo[(string)$section]);
172
    }
173
174
    /**
175
     * make option info object from plain data
176
     *
177
     * @param eSection $section
178
     * @param eOption  $optionName
179
     *
180
     * @throws \LTDBeget\sphinx\informer\exceptions\InformerRuntimeException
181
     */
182 5
    private function makeOptionInfo(eSection $section, eOption $optionName)
183
    {
184 5
        $this->checkOptionInfoAvailability($section, $optionName);
185
186 3
        $info_data = $this->documentation[(string)$section][(string)$optionName];
187
188 3
        $optionInfo = new OptionInfo(
189
            $optionName,
190
            $section,
191 3
            $this->version,
192 3
            $info_data['description'],
193 3
            $info_data['multi_value'],
194 3
            $info_data['link']
195
        );
196
197 3
        $this->optionsInfo[(string)$section][(string)$optionName] = $optionInfo;
198 3
    }
199
200
    /**
201
     * @param eSection $section
202
     * @param eOption  $optionName
203
     *
204
     * @throws \LTDBeget\sphinx\informer\exceptions\InformerRuntimeException
205
     */
206 5
    private function checkOptionInfoAvailability(eSection $section, eOption $optionName)
207
    {
208 5
        if (!$this->isSectionExist($section)) {
209 1
            throw new InformerRuntimeException("Sphinx of version {$this->version} does't have section {$section}");
210
        }
211
212 4
        if (!$this->isKnownOption($section, $optionName)) {
213 1
            throw new InformerRuntimeException("For sphinx v. {$this->version} option {$optionName} in {$section} isn't available");
214
        }
215
216 3
        if ($this->isRemovedOption($section, $optionName)) {
217
            throw new InformerRuntimeException("For sphinx v. {$this->version} option {$optionName} in {$section} is permanently removed");
218
        }
219 3
    }
220
221
    /**
222
     * load to object info about permanently removed options
223
     *
224
     * @throws \LTDBeget\sphinx\informer\exceptions\DocumentationSourceException
225
     * @throws \Symfony\Component\Yaml\Exception\ParseException
226
     */
227 3
    private function loadRemovedList()
228
    {
229 3
        $path = $this->getRemovedListFilePath();
230
231 3
        if ($this->isRemovedListFileExists()) {
232
            /** @noinspection PhpUndefinedClassInspection */
233 2
            $removed_list = (new Parser())->parse(file_get_contents($path));
234
235 2
            if (!is_array($removed_list)) {
236
                throw new DocumentationSourceException("Failed to parse yaml file {$path}");
237
            }
238
239 2
            $this->removedOptions = $removed_list;
240
        }
241 3
    }
242
243
    /**
244
     * loads configuration from yaml files and save as array
245
     *
246
     * @throws \LTDBeget\sphinx\informer\exceptions\DocumentationSourceException
247
     * @throws \Symfony\Component\Yaml\Exception\ParseException
248
     */
249 3
    private function loadDocumentation()
250
    {
251 3
        $path = $this->getDocumentationFilePath();
252
253 3
        if (!$this->isDocumentationExists()) {
254
            throw new DocumentationSourceException("For version {$this->version} there are no file: {$path}");
255
        }
256
257
        /** @noinspection PhpUndefinedClassInspection */
258 3
        $documentation = (new Parser())->parse(file_get_contents($path));
259
260 3
        if (!is_array($documentation)) {
261
            throw new DocumentationSourceException("Failed to parse yaml file {$path}");
262
        }
263
264 3
        $this->documentation = $documentation;
265 3
    }
266
267
    /**
268
     * check is documentation yaml file exists
269
     *
270
     * @return bool
271
     */
272 3
    private function isDocumentationExists() : bool
273
    {
274 3
        return is_file($this->getDocumentationFilePath());
275
    }
276
277
    /**
278
     * path to yaml sphinx documentation
279
     *
280
     * @return string
281
     */
282 3
    private function getDocumentationDirectoryPath() : string
283
    {
284 3
        return __DIR__ . '/../../../../sphinx/docs';
285
    }
286
287
    /**
288
     * path to yaml sphinx documentation file
289
     *
290
     * @return string
291
     */
292 3
    private function getDocumentationFilePath() : string
293
    {
294 3
        return $this->getDocumentationDirectoryPath() . "/documentation_{$this->version}.yaml";
295
    }
296
297
    /**
298
     * Return path to file with removed options list
299
     *
300
     * @return string
301
     */
302 3
    private function getRemovedListFilePath() : string
303
    {
304 3
        return $this->getDocumentationDirectoryPath() . "/permanently_removed_options_{$this->version}.yaml";
305
    }
306
307
    /**
308
     * Is file with removed options list exists
309
     *
310
     * @return bool
311
     */
312 3
    private function isRemovedListFileExists() : bool
313
    {
314 3
        return is_file($this->getRemovedListFilePath());
315
    }
316
317
    /**
318
     * @var Informer[]
319
     */
320
    private static $instances = [];
321
322
    /**
323
     * @var eVersion
324
     */
325
    private $version;
326
327
    /**
328
     * @var array
329
     */
330
    private $documentation;
331
332
    /**
333
     * @var array
334
     */
335
    private $removedOptions = [];
336
337
    /**
338
     * @var array
339
     */
340
    private $optionsInfo = [];
341
}