Completed
Push — feature-data-files ( f34d72 )
by Arnaud
03:53
created

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