Completed
Push — analysis-D2M1DL ( 825c2b )
by Arnaud
06:16 queued 11s
created

Config::getCacheImagesThumbsPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 11
rs 10
1
<?php
2
/*
3
 * Copyright (c) Arnaud Ligny <[email protected]>
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Cecil;
10
11
use Cecil\Exception\Exception;
12
use Dflydev\DotAccessData\Data;
13
14
/**
15
 * Class Config.
16
 */
17
class Config
18
{
19
    /**
20
     * Configuration is a Data object.
21
     *
22
     * @var Data
23
     */
24
    protected $data;
25
    /**
26
     * Local configuration.
27
     *
28
     * @var Config|array
29
     */
30
    protected $localConfig;
31
    /**
32
     * Source directory.
33
     *
34
     * @var string
35
     */
36
    protected $sourceDir;
37
    /**
38
     * Destination directory.
39
     *
40
     * @var string
41
     */
42
    protected $destinationDir;
43
44
    /**
45
     * Config constructor.
46
     *
47
     * @param Config|array|null $config
48
     */
49
    public function __construct($config = null)
50
    {
51
        // default config
52
        $this->data = new Data(include __DIR__.'/../config/default.php');
53
        // import local config
54
        $this->localConfig = $config;
55
        $this->import($this->localConfig);
56
    }
57
58
    /**
59
     * Import config data into the current configuration.
60
     *
61
     * @param Config|array|null $config
62
     *
63
     * @return void
64
     */
65
    public function import($config): void
66
    {
67
        if ($config instanceof self) {
68
            $this->data->importData($config->getData());
69
        } elseif (is_array($config)) {
70
            $this->data->import($config);
71
        }
72
        // re-import local config
73
        if ($config !== $this->localConfig) {
74
            $this->import($this->localConfig);
75
        }
76
77
        /**
78
         * Apply environment variables.
79
         */
80
        $data = $this->getData();
81
        $applyEnv = function ($array) use ($data) {
82
            $iterator = new \RecursiveIteratorIterator(
83
                new \RecursiveArrayIterator($array),
84
                \RecursiveIteratorIterator::SELF_FIRST
85
            );
86
            foreach ($iterator as $leafValue) {
87
                $path = [];
88
                foreach (range(0, $iterator->getDepth()) as $depth) {
89
                    $path[] = $iterator->getSubIterator($depth)->key();
90
                }
91
                $sPath = implode('_', $path);
92
                if ($getEnv = getenv('CECIL_'.strtoupper($sPath))) {
93
                    $data->set(str_replace('_', '.', strtolower($sPath)), $getEnv);
94
                }
95
            }
96
        };
97
        $applyEnv($data->export());
98
    }
99
100
    /**
101
     * Set a Data object as configuration.
102
     *
103
     * @param Data $data
104
     *
105
     * @return $this
106
     */
107
    protected function setData(Data $data): self
108
    {
109
        if ($this->data !== $data) {
110
            $this->data = $data;
111
        }
112
113
        return $this;
114
    }
115
116
    /**
117
     * Get configuration as a Data object.
118
     *
119
     * @return Data
120
     */
121
    public function getData(): Data
122
    {
123
        return $this->data;
124
    }
125
126
    /**
127
     * Get configuration as an array.
128
     *
129
     * @return array
130
     */
131
    public function getAsArray(): array
132
    {
133
        return $this->data->export();
134
    }
135
136
    /**
137
     * Is configuration's key' exists?
138
     *
139
     * @param string $key
140
     *
141
     * @return bool
142
     */
143
    public function has(string $key): bool
144
    {
145
        return $this->data->has($key);
146
    }
147
148
    /**
149
     * Get the value of a configuration's key'.
150
     *
151
     * @param string      $key
152
     * @param string|null $language
153
     *
154
     * @return array|mixed|null
155
     */
156
    public function get(string $key, string $language = null)
157
    {
158
        if ($language !== null) {
159
            $index = $this->getLanguageIndex($language);
160
            $keyLang = sprintf('languages.%s.config.%s', $index, $key);
161
            if ($this->data->has($keyLang)) {
162
                return $this->data->get($keyLang);
163
            }
164
        }
165
166
        return $this->data->get($key);
167
    }
168
169
    /**
170
     * Set the source directory.
171
     *
172
     * @param string|null $sourceDir
173
     *
174
     * @throws \InvalidArgumentException
175
     *
176
     * @return $this
177
     */
178
    public function setSourceDir(string $sourceDir = null): self
179
    {
180
        if ($sourceDir === null) {
181
            $sourceDir = getcwd();
182
        }
183
        if (!is_dir($sourceDir)) {
184
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not a valid source!', $sourceDir));
185
        }
186
        $this->sourceDir = $sourceDir;
187
188
        return $this;
189
    }
190
191
    /**
192
     * Get the source directory.
193
     *
194
     * @return string
195
     */
196
    public function getSourceDir(): string
197
    {
198
        return $this->sourceDir;
199
    }
200
201
    /**
202
     * Set the destination directory.
203
     *
204
     * @param string|null $destinationDir
205
     *
206
     * @throws \InvalidArgumentException
207
     *
208
     * @return $this
209
     */
210
    public function setDestinationDir(string $destinationDir = null): self
211
    {
212
        if ($destinationDir === null) {
213
            $destinationDir = $this->sourceDir;
214
        }
215
        if (!is_dir($destinationDir)) {
216
            throw new \InvalidArgumentException(sprintf(
217
                'The directory "%s" is not a valid destination!',
218
                $destinationDir
219
            ));
220
        }
221
        $this->destinationDir = $destinationDir;
222
223
        return $this;
224
    }
225
226
    /**
227
     * Get the destination directory.
228
     *
229
     * @return string
230
     */
231
    public function getDestinationDir(): string
232
    {
233
        return $this->destinationDir;
234
    }
235
236
    /**
237
     * Paths helpers.
238
     */
239
240
    /**
241
     * Return the path of the content directory.
242
     *
243
     * @return string
244
     */
245
    public function getContentPath(): string
246
    {
247
        return $this->getSourceDir().'/'.$this->get('content.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('content.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

247
        return $this->getSourceDir().'/'./** @scrutinizer ignore-type */ $this->get('content.dir');
Loading history...
248
    }
249
250
    /**
251
     * Return the path of the data directory.
252
     *
253
     * @return string
254
     */
255
    public function getDataPath(): string
256
    {
257
        return $this->getSourceDir().'/'.$this->get('data.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('data.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

257
        return $this->getSourceDir().'/'./** @scrutinizer ignore-type */ $this->get('data.dir');
Loading history...
258
    }
259
260
    /**
261
     * Return the path of templates directory.
262
     *
263
     * @return string
264
     */
265
    public function getLayoutsPath(): string
266
    {
267
        return $this->getSourceDir().'/'.$this->get('layouts.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('layouts.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

267
        return $this->getSourceDir().'/'./** @scrutinizer ignore-type */ $this->get('layouts.dir');
Loading history...
268
    }
269
270
    /**
271
     * Return the path of themes directory.
272
     *
273
     * @return string
274
     */
275
    public function getThemesPath(): string
276
    {
277
        return $this->getSourceDir().'/'.$this->get('themes.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('themes.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

277
        return $this->getSourceDir().'/'./** @scrutinizer ignore-type */ $this->get('themes.dir');
Loading history...
278
    }
279
280
    /**
281
     * Return the path of internal templates directory.
282
     *
283
     * @return string
284
     */
285
    public function getInternalLayoutsPath(): string
286
    {
287
        return __DIR__.'/../'.$this->get('layouts.internal.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('layouts.internal.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

287
        return __DIR__.'/../'./** @scrutinizer ignore-type */ $this->get('layouts.internal.dir');
Loading history...
288
    }
289
290
    /**
291
     * Return the path of the output directory.
292
     *
293
     * @return string
294
     */
295
    public function getOutputPath(): string
296
    {
297
        return $this->getDestinationDir().'/'.$this->get('output.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('output.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

297
        return $this->getDestinationDir().'/'./** @scrutinizer ignore-type */ $this->get('output.dir');
Loading history...
298
    }
299
300
    /**
301
     * Return the path of static files directory.
302
     *
303
     * @return string
304
     */
305
    public function getStaticPath(): string
306
    {
307
        return $this->getSourceDir().'/'.$this->get('static.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('static.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

307
        return $this->getSourceDir().'/'./** @scrutinizer ignore-type */ $this->get('static.dir');
Loading history...
308
    }
309
310
    /**
311
     * Return the path to images/thumbs cache dir.
312
     *
313
     * @return string
314
     */
315
    public function getCacheImagesThumbsPath(): string
316
    {
317
        $path = (string) $this->get('cache.dir').'/'
318
            .$this->get('cache.images.dir').'/'
0 ignored issues
show
Bug introduced by
Are you sure $this->get('cache.images.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

318
            ./** @scrutinizer ignore-type */ $this->get('cache.images.dir').'/'
Loading history...
319
            .$this->get('cache.images.thumbs.dir');
0 ignored issues
show
Bug introduced by
Are you sure $this->get('cache.images.thumbs.dir') of type array|mixed|null can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

319
            ./** @scrutinizer ignore-type */ $this->get('cache.images.thumbs.dir');
Loading history...
320
321
        if ($this->get('cache.external')) {
322
            return $path;
323
        }
324
325
        return $this->getDestinationDir().'/'.$path;
326
    }
327
328
    /**
329
     * Return the property value of an output format.
330
     *
331
     * @param string $property
332
     * @param string $name
333
     *
334
     * @return string|array|null
335
     */
336
    public function getOutputFormatProperty(string $name, string $property)
337
    {
338
        $properties = array_column($this->get('output.formats'), $property, 'name');
0 ignored issues
show
Bug introduced by
It seems like $this->get('output.formats') can also be of type null; however, parameter $input of array_column() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

338
        $properties = array_column(/** @scrutinizer ignore-type */ $this->get('output.formats'), $property, 'name');
Loading history...
339
340
        if (empty($properties)) {
341
            throw new Exception(sprintf(
342
                'Property "%s" is not defined for format "%s".',
343
                $property,
344
                $name
345
            ));
346
        }
347
348
        if (!array_key_exists($name, $properties)) {
349
            return null;
350
        }
351
352
        return $properties[$name];
353
    }
354
355
    /**
356
     * Theme helpers.
357
     */
358
359
    /**
360
     * Return theme(s) as an array.
361
     *
362
     * @return array|null
363
     */
364
    public function getTheme(): ?array
365
    {
366
        if ($themes = $this->get('theme')) {
367
            if (is_array($themes)) {
368
                return $themes;
369
            }
370
371
            return [$themes];
372
        }
373
374
        return null;
375
    }
376
377
    /**
378
     * Has a (valid) theme(s)?
379
     *
380
     * @throws Exception
381
     *
382
     * @return bool
383
     */
384
    public function hasTheme(): bool
385
    {
386
        if ($themes = $this->getTheme()) {
387
            foreach ($themes as $theme) {
388
                if (!Util::getFS()->exists($this->getThemeDirPath($theme, 'layouts'))) {
389
                    throw new Exception(sprintf(
390
                        "Theme directory '%s/%s/layouts' not found!",
391
                        $this->getThemesPath(),
392
                        $theme
393
                    ));
394
                }
395
            }
396
397
            return true;
398
        }
399
400
        return false;
401
    }
402
403
    /**
404
     * Return the path of a specific theme's directory.
405
     * ("layouts" by default).
406
     *
407
     * @param string $theme
408
     * @param string $dir
409
     *
410
     * @return string
411
     */
412
    public function getThemeDirPath(string $theme, string $dir = 'layouts'): string
413
    {
414
        return $this->getThemesPath().'/'.$theme.'/'.$dir;
415
    }
416
417
    /**
418
     * Language helpers.
419
     */
420
421
    /**
422
     * Return an array of available languages.
423
     *
424
     * @return array
425
     */
426
    public function getLanguages(): array
427
    {
428
        return $this->get('languages');
429
    }
430
431
    /**
432
     * Return the default language code (ie: "en", "fr-fr", etc.).
433
     *
434
     * @return string
435
     */
436
    public function getLanguageDefault(): string
437
    {
438
        if (!$this->get('language')) {
439
            throw new Exception('There is no default "language" in configuration.');
440
        }
441
442
        return $this->get('language');
443
    }
444
445
    /**
446
     * Return a language code index.
447
     *
448
     * @param string $code
449
     *
450
     * @return int
451
     */
452
    public function getLanguageIndex(string $code): int
453
    {
454
        $array = array_column($this->getLanguages(), 'code');
455
456
        if (!$index = array_search($code, $array)) {
457
            throw new Exception(sprintf('The language code "%s" is not defined.', $code));
458
        }
459
460
        return $index;
461
    }
462
463
    /**
464
     * Return the property value of a (specified or default) language.
465
     *
466
     * @param string      $property
467
     * @param string|null $code
468
     *
469
     * @return string|null
470
     */
471
    public function getLanguageProperty(string $property, string $code = null): ?string
472
    {
473
        $code = $code ?? $this->getLanguageDefault();
474
475
        $properties = array_column($this->getLanguages(), $property, 'code');
476
477
        if (empty($properties)) {
478
            throw new Exception(sprintf(
479
                'Property "%s" is not defined for language "%s".',
480
                $property,
481
                $code
482
            ));
483
        }
484
485
        return $properties[$code];
486
    }
487
}
488