Completed
Push — site-variables ( fc38e5...0275e0 )
by Arnaud
02:23
created

Config::getAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 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
     * Source directory.
27
     *
28
     * @var string
29
     */
30
    protected $sourceDir;
31
    /**
32
     * Destination directory.
33
     *
34
     * @var string
35
     */
36
    protected $destinationDir;
37
38
    /**
39
     * Config constructor.
40
     *
41
     * @param Config|array|null $config
42
     */
43
    public function __construct($config = null)
44
    {
45
        // default config
46
        $data = new Data(include __DIR__.'/../config/default.php');
47
        // import local config
48
        if ($config) {
49
            if ($config instanceof self) {
50
                $data->importData($config->getData());
51
            } elseif (is_array($config)) {
52
                $data->import($config);
53
            }
54
        }
55
56
        /**
57
         * Apply environment variables.
58
         */
59
        $applyEnv = function ($array) use ($data) {
60
            $iterator = new \RecursiveIteratorIterator(
61
                new \RecursiveArrayIterator($array),
62
                \RecursiveIteratorIterator::SELF_FIRST
63
            );
64
            foreach ($iterator as $leafValue) {
65
                $path = [];
66
                foreach (range(0, $iterator->getDepth()) as $depth) {
67
                    $path[] = $iterator->getSubIterator($depth)->key();
68
                }
69
                $sPath = implode('_', $path);
70
                if ($getEnv = getenv('CECIL_'.strtoupper($sPath))) {
71
                    $data->set(str_replace('_', '.', strtolower($sPath)), $getEnv);
72
                }
73
            }
74
        };
75
        $applyEnv($data->export());
76
77
        $this->setData($data);
78
    }
79
80
    /**
81
     * Import an array into the current configuration.
82
     *
83
     * @param array $config
84
     *
85
     * @return void
86
     */
87
    public function import(array $config): void
88
    {
89
        $data = $this->getData();
90
        $origin = $data->export();
91
        $data->import($config);
92
        $data->import($origin);
93
        $this->setData($data);
94
    }
95
96
    /**
97
     * Set a Data object as configuration.
98
     *
99
     * @param Data $data
100
     *
101
     * @return $this
102
     */
103
    protected function setData(Data $data): self
104
    {
105
        if ($this->data !== $data) {
106
            $this->data = $data;
107
        }
108
109
        return $this;
110
    }
111
112
    /**
113
     * Get configuration as a Data object.
114
     *
115
     * @return Data
116
     */
117
    public function getData(): Data
118
    {
119
        return $this->data;
120
    }
121
122
    /**
123
     * Get configuration as an array.
124
     *
125
     * @return array
126
     */
127
    public function getAsArray(): array
128
    {
129
        return $this->data->export();
130
    }
131
132
    /**
133
     * Is configuration's key' exists?
134
     *
135
     * @param string $key
136
     *
137
     * @return bool
138
     */
139
    public function has(string $key): bool
140
    {
141
        return $this->data->has($key);
142
    }
143
144
    /**
145
     * Get the value of a configuration's key'.
146
     *
147
     * @param string $key
148
     * @param string|null $language
149
     *
150
     * @return array|mixed|null
151
     */
152
    public function get(string $key, string $language = null)
153
    {
154
        if ($language) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $language of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
155
            $keyLang = "languages.$language.$key";
156
            if ($this->data->has($keyLang)) {
157
                return $this->data->get($keyLang);
158
            }
159
        }
160
161
        return $this->data->get($key);
162
    }
163
164
    /**
165
     * Set the source directory.
166
     *
167
     * @param string|null $sourceDir
168
     *
169
     * @throws \InvalidArgumentException
170
     *
171
     * @return $this
172
     */
173
    public function setSourceDir(string $sourceDir = null): self
174
    {
175
        if ($sourceDir === null) {
176
            $sourceDir = getcwd();
177
        }
178
        if (!is_dir($sourceDir)) {
179
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not a valid source!', $sourceDir));
180
        }
181
        $this->sourceDir = $sourceDir;
182
183
        return $this;
184
    }
185
186
    /**
187
     * Get the source directory.
188
     *
189
     * @return string
190
     */
191
    public function getSourceDir(): string
192
    {
193
        return $this->sourceDir;
194
    }
195
196
    /**
197
     * Set the destination directory.
198
     *
199
     * @param string|null $destinationDir
200
     *
201
     * @throws \InvalidArgumentException
202
     *
203
     * @return $this
204
     */
205
    public function setDestinationDir(string $destinationDir = null): self
206
    {
207
        if ($destinationDir === null) {
208
            $destinationDir = $this->sourceDir;
209
        }
210
        if (!is_dir($destinationDir)) {
211
            throw new \InvalidArgumentException(sprintf(
212
                'The directory "%s" is not a valid destination!',
213
                $destinationDir
214
            ));
215
        }
216
        $this->destinationDir = $destinationDir;
217
218
        return $this;
219
    }
220
221
    /**
222
     * Get the destination directory.
223
     *
224
     * @return string
225
     */
226
    public function getDestinationDir(): string
227
    {
228
        return $this->destinationDir;
229
    }
230
231
    /**
232
     * Paths helpers.
233
     */
234
235
    /**
236
     * Return the path of the content directory.
237
     *
238
     * @return string
239
     */
240
    public function getContentPath(): string
241
    {
242
        return $this->getSourceDir().'/'.$this->get('content.dir');
243
    }
244
245
    /**
246
     * Return the path of templates directory.
247
     *
248
     * @return string
249
     */
250
    public function getLayoutsPath(): string
251
    {
252
        return $this->getSourceDir().'/'.$this->get('layouts.dir');
253
    }
254
255
    /**
256
     * Return the path of themes directory.
257
     *
258
     * @return string
259
     */
260
    public function getThemesPath(): string
261
    {
262
        return $this->getSourceDir().'/'.$this->get('themes.dir');
263
    }
264
265
    /**
266
     * Return the path of internal templates directory.
267
     *
268
     * @return string
269
     */
270
    public function getInternalLayoutsPath(): string
271
    {
272
        return __DIR__.'/../'.$this->get('layouts.internal.dir');
273
    }
274
275
    /**
276
     * Return the path of the output directory.
277
     *
278
     * @return string
279
     */
280
    public function getOutputPath(): string
281
    {
282
        return $this->getDestinationDir().'/'.$this->get('output.dir');
283
    }
284
285
    /**
286
     * Return the path of static files directory.
287
     *
288
     * @return string
289
     */
290
    public function getStaticPath(): string
291
    {
292
        return $this->getSourceDir().'/'.$this->get('static.dir');
293
    }
294
295
    /**
296
     * Return a "clean" array of an output format.
297
     *
298
     * @param string $format
299
     *
300
     * @return array
301
     */
302
    public function getOutputFormat(string $format): array
303
    {
304
        $default = [
305
            'mediatype' => null, // 'text/html'
306
            'subpath'   => null, // ''
307
            'suffix'    => null, // '/index'
308
            'extension' => null, // 'html'
309
        ];
310
311
        $result = $this->get(sprintf('output.formats.%s', $format));
312
313
        return array_merge($default, $result);
314
    }
315
316
    /**
317
     * Theme helpers.
318
     */
319
320
    /**
321
     * Return theme(s) as an array.
322
     *
323
     * @return array|null
324
     */
325
    public function getTheme(): ?array
326
    {
327
        if ($themes = $this->get('theme')) {
328
            if (is_array($themes)) {
329
                return $themes;
330
            }
331
332
            return [$themes];
333
        }
334
    }
335
336
    /**
337
     * Has a (valid) theme(s)?
338
     *
339
     * @throws Exception
340
     *
341
     * @return bool
342
     */
343
    public function hasTheme(): bool
344
    {
345
        if ($themes = $this->getTheme()) {
346
            foreach ($themes as $theme) {
347
                if (!Util::getFS()->exists($this->getThemeDirPath($theme, 'layouts'))) {
348
                    throw new Exception(sprintf(
349
                        "Theme directory '%s/%s/layouts' not found!",
350
                        $this->getThemesPath(),
351
                        $theme
352
                    ));
353
                }
354
            }
355
356
            return true;
357
        }
358
359
        return false;
360
    }
361
362
    /**
363
     * Return the path of a specific theme's directory.
364
     * ("layouts" by default).
365
     *
366
     * @param string $theme
367
     * @param string $dir
368
     *
369
     * @return string
370
     */
371
    public function getThemeDirPath(string $theme, string $dir = 'layouts'): string
372
    {
373
        return $this->getThemesPath().'/'.$theme.'/'.$dir;
374
    }
375
376
    /**
377
     * Language helpers.
378
     */
379
380
    /**
381
     * Return an array of available languages.
382
     *
383
     * @return array
384
     */
385
    public function getLanguages(): array
386
    {
387
        return $this->get('languages');
388
    }
389
390
    /**
391
     * Return the default language key (ie: "en", "fr-fr", etc.).
392
     *
393
     * @return string
394
     */
395
    public function getLanguageDefaultKey(): string
396
    {
397
        if ($this->get('language')) {
398
            return $this->get('language');
399
        }
400
401
        $languages = $this->getLanguages();
402
        if (!is_array($languages)) {
403
            throw new Exception('There is no default "language" in configuration!');
404
        }
405
        reset($languages);
406
407
        return key($languages);
408
    }
409
410
    /**
411
     * Return properties of a (specified or default) language.
412
     *
413
     * @param string|null $key
414
     *
415
     * @return array
416
     */
417
    public function getLanguageProperties(string $key = null): array
418
    {
419
        $key = $key ?? $this->getLanguageDefaultKey();
420
421
        $languageProperties = $this->get(sprintf('languages.%s', $key));
422
        if (!is_array($languageProperties)) {
423
            throw new Exception(sprintf('Language "%s" is not correctly set in config!', $key));
424
        }
425
426
        return $languageProperties;
427
    }
428
429
    /**
430
     * Return the property value of a (specified or default) language.
431
     *
432
     * @param string $property
433
     * @param string|null $key
434
     *
435
     * @return string
436
     */
437
    public function getLanguageProperty($property, $key = null): string
438
    {
439
        $properties = ['name', 'locale'];
440
        $languageProperties = $this->getLanguageProperties($key);
441
442
        if (!in_array($property, $properties)) {
443
            throw new Exception(sprintf(
444
                'Property language "%s" is not available!',
445
                $property
446
            ));
447
        }
448
        if (!\array_key_exists($property, $languageProperties)) {
449
            throw new Exception(sprintf(
450
                'Property "%s" is not defined for language "%s"!',
451
                $property,
452
                $languageProperties['name']
453
            ));
454
        }
455
456
        return $languageProperties[$property];
457
    }
458
}
459