Completed
Push — analysis-e7NVwA ( 98d0a6 )
by Arnaud
05:46 queued 10s
created

Config::getCacheImagesThumbsPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
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 Util::joinFile([__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
            $iterator->rewind();
87
            while ($iterator->valid()) {
88
                $path = [];
89
                foreach (range(0, $iterator->getDepth()) as $depth) {
90
                    $path[] = $iterator->getSubIterator($depth)->key();
91
                }
92
                $sPath = implode('_', $path);
93
                if ($getEnv = getenv('CECIL_'.strtoupper($sPath))) {
94
                    $data->set(str_replace('_', '.', strtolower($sPath)), $getEnv);
95
                }
96
                $iterator->next();
97
            }
98
        };
99
        $applyEnv($data->export());
100
    }
101
102
    /**
103
     * Set a Data object as configuration.
104
     *
105
     * @param Data $data
106
     *
107
     * @return $this
108
     */
109
    protected function setData(Data $data): self
110
    {
111
        if ($this->data !== $data) {
112
            $this->data = $data;
113
        }
114
115
        return $this;
116
    }
117
118
    /**
119
     * Get configuration as a Data object.
120
     *
121
     * @return Data
122
     */
123
    public function getData(): Data
124
    {
125
        return $this->data;
126
    }
127
128
    /**
129
     * Get configuration as an array.
130
     *
131
     * @return array
132
     */
133
    public function getAsArray(): array
134
    {
135
        return $this->data->export();
136
    }
137
138
    /**
139
     * Is configuration's key' exists?
140
     *
141
     * @param string $key
142
     *
143
     * @return bool
144
     */
145
    public function has(string $key): bool
146
    {
147
        return $this->data->has($key);
148
    }
149
150
    /**
151
     * Get the value of a configuration's key'.
152
     *
153
     * @param string      $key
154
     * @param string|null $language
155
     *
156
     * @return array|mixed|null
157
     */
158
    public function get(string $key, string $language = null)
159
    {
160
        if ($language !== null) {
161
            $index = $this->getLanguageIndex($language);
162
            $keyLang = sprintf('languages.%s.config.%s', $index, $key);
163
            if ($this->data->has($keyLang)) {
164
                return $this->data->get($keyLang);
165
            }
166
        }
167
168
        return $this->data->get($key);
169
    }
170
171
    /**
172
     * Set the source directory.
173
     *
174
     * @param string|null $sourceDir
175
     *
176
     * @throws \InvalidArgumentException
177
     *
178
     * @return $this
179
     */
180
    public function setSourceDir(string $sourceDir = null): self
181
    {
182
        if ($sourceDir === null) {
183
            $sourceDir = getcwd();
184
        }
185
        if (!is_dir($sourceDir)) {
186
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not a valid source!', $sourceDir));
187
        }
188
        $this->sourceDir = $sourceDir;
189
190
        return $this;
191
    }
192
193
    /**
194
     * Get the source directory.
195
     *
196
     * @return string
197
     */
198
    public function getSourceDir(): string
199
    {
200
        return $this->sourceDir;
201
    }
202
203
    /**
204
     * Set the destination directory.
205
     *
206
     * @param string|null $destinationDir
207
     *
208
     * @throws \InvalidArgumentException
209
     *
210
     * @return $this
211
     */
212
    public function setDestinationDir(string $destinationDir = null): self
213
    {
214
        if ($destinationDir === null) {
215
            $destinationDir = $this->sourceDir;
216
        }
217
        if (!is_dir($destinationDir)) {
218
            throw new \InvalidArgumentException(sprintf(
219
                'The directory "%s" is not a valid destination!',
220
                $destinationDir
221
            ));
222
        }
223
        $this->destinationDir = $destinationDir;
224
225
        return $this;
226
    }
227
228
    /**
229
     * Get the destination directory.
230
     *
231
     * @return string
232
     */
233
    public function getDestinationDir(): string
234
    {
235
        return $this->destinationDir;
236
    }
237
238
    /**
239
     * Paths helpers.
240
     */
241
242
    /**
243
     * Return the path of the content directory.
244
     *
245
     * @return string
246
     */
247
    public function getContentPath(): string
248
    {
249
        return Util::joinFile([$this->getSourceDir(), (string) $this->get('content.dir')]);
250
    }
251
252
    /**
253
     * Return the path of the data directory.
254
     *
255
     * @return string
256
     */
257
    public function getDataPath(): string
258
    {
259
        return Util::joinFile([$this->getSourceDir(), (string) $this->get('data.dir')]);
260
    }
261
262
    /**
263
     * Return the path of templates directory.
264
     *
265
     * @return string
266
     */
267
    public function getLayoutsPath(): string
268
    {
269
        return Util::joinFile([$this->getSourceDir(), (string) $this->get('layouts.dir')]);
270
    }
271
272
    /**
273
     * Return the path of themes directory.
274
     *
275
     * @return string
276
     */
277
    public function getThemesPath(): string
278
    {
279
        return Util::joinFile([$this->getSourceDir(), (string) $this->get('themes.dir')]);
280
    }
281
282
    /**
283
     * Return the path of internal templates directory.
284
     *
285
     * @return string
286
     */
287
    public function getInternalLayoutsPath(): string
288
    {
289
        return Util::joinFile([__DIR__, '..', (string) $this->get('layouts.internal.dir')]);
290
    }
291
292
    /**
293
     * Return the path of the output directory.
294
     *
295
     * @return string
296
     */
297
    public function getOutputPath(): string
298
    {
299
        return Util::joinFile([$this->getDestinationDir(), (string) $this->get('output.dir')]);
300
    }
301
302
    /**
303
     * Return the path of static files directory.
304
     *
305
     * @return string
306
     */
307
    public function getStaticPath(): string
308
    {
309
        return Util::joinFile([$this->getSourceDir(), (string) $this->get('static.dir')]);
310
    }
311
312
    /**
313
     * Is cache dir is absolute to systeme file
314
     * or relative to project destiantion?
315
     *
316
     * @return bool
317
     */
318
    public function isCacheDirIsAbsolute(): bool
319
    {
320
        $path = (string) $this->get('cache.dir');
321
        if (strpos($path, DIRECTORY_SEPARATOR) !== false && strpos($path, DIRECTORY_SEPARATOR) === 0) {
322
            return true;
323
        }
324
325
        return false;
326
    }
327
328
    /**
329
     * Return cache path.
330
     *
331
     * @return string
332
     */
333
    public function getCachePath(): string
334
    {
335
        if ($this->isCacheDirIsAbsolute()) {
336
            return (string) $this->get('cache.dir');
337
        }
338
339
        return Util::joinFile([$this->getDestinationDir(), (string) $this->get('cache.dir')]);
340
    }
341
342
    /**
343
     * Return the property value of an output format.
344
     *
345
     * @param string $property
346
     * @param string $name
347
     *
348
     * @return string|array|null
349
     */
350
    public function getOutputFormatProperty(string $name, string $property)
351
    {
352
        $properties = array_column((array) $this->get('output.formats'), $property, 'name');
353
354
        if (empty($properties)) {
355
            throw new Exception(sprintf(
356
                'Property "%s" is not defined for format "%s".',
357
                $property,
358
                $name
359
            ));
360
        }
361
362
        if (!array_key_exists($name, $properties)) {
363
            return null;
364
        }
365
366
        return $properties[$name];
367
    }
368
369
    /**
370
     * Theme helpers.
371
     */
372
373
    /**
374
     * Return theme(s) as an array.
375
     *
376
     * @return array|null
377
     */
378
    public function getTheme(): ?array
379
    {
380
        if ($themes = $this->get('theme')) {
381
            if (is_array($themes)) {
382
                return $themes;
383
            }
384
385
            return [$themes];
386
        }
387
388
        return null;
389
    }
390
391
    /**
392
     * Has a (valid) theme(s)?
393
     *
394
     * @throws Exception
395
     *
396
     * @return bool
397
     */
398
    public function hasTheme(): bool
399
    {
400
        if ($themes = $this->getTheme()) {
401
            foreach ($themes as $theme) {
402
                if (!Util::getFS()->exists($this->getThemeDirPath($theme, 'layouts'))) {
403
                    throw new Exception(sprintf(
404
                        "Theme directory '%s/%s/layouts' not found!",
405
                        $this->getThemesPath(),
406
                        $theme
407
                    ));
408
                }
409
            }
410
411
            return true;
412
        }
413
414
        return false;
415
    }
416
417
    /**
418
     * Return the path of a specific theme's directory.
419
     * ("layouts" by default).
420
     *
421
     * @param string $theme
422
     * @param string $dir
423
     *
424
     * @return string
425
     */
426
    public function getThemeDirPath(string $theme, string $dir = 'layouts'): string
427
    {
428
        return Util::joinFile([$this->getThemesPath(), $theme, $dir]);
429
    }
430
431
    /**
432
     * Language helpers.
433
     */
434
435
    /**
436
     * Return an array of available languages.
437
     *
438
     * @return array
439
     */
440
    public function getLanguages(): array
441
    {
442
        return $this->get('languages');
443
    }
444
445
    /**
446
     * Return the default language code (ie: "en", "fr-fr", etc.).
447
     *
448
     * @return string
449
     */
450
    public function getLanguageDefault(): string
451
    {
452
        if (!$this->get('language')) {
453
            throw new Exception('There is no default "language" in configuration.');
454
        }
455
456
        return $this->get('language');
457
    }
458
459
    /**
460
     * Return a language code index.
461
     *
462
     * @param string $code
463
     *
464
     * @return int
465
     */
466
    public function getLanguageIndex(string $code): int
467
    {
468
        $array = array_column($this->getLanguages(), 'code');
469
470
        if (!$index = array_search($code, $array)) {
471
            throw new Exception(sprintf('The language code "%s" is not defined.', $code));
472
        }
473
474
        return $index;
475
    }
476
477
    /**
478
     * Return the property value of a (specified or default) language.
479
     *
480
     * @param string      $property
481
     * @param string|null $code
482
     *
483
     * @return string|null
484
     */
485
    public function getLanguageProperty(string $property, string $code = null): ?string
486
    {
487
        $code = $code ?? $this->getLanguageDefault();
488
489
        $properties = array_column($this->getLanguages(), $property, 'code');
490
491
        if (empty($properties)) {
492
            throw new Exception(sprintf(
493
                'Property "%s" is not defined for language "%s".',
494
                $property,
495
                $code
496
            ));
497
        }
498
499
        return $properties[$code];
500
    }
501
}
502