Completed
Push — feature-config-variables ( 3fb59a )
by Arnaud
02:13
created

Config::offsetExists()   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 1
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 implements \ArrayAccess
18
{
19
    /**
20
     * Config.
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
        $data = new Data(include __DIR__.'/../config/default.php');
46
47
        if ($config) {
48
            if ($config instanceof self) {
49
                $data->importData($config->getAll());
50
            } elseif (is_array($config)) {
51
                $data->import($config);
52
            }
53
        }
54
55
        /**
56
         * Apply environment variables.
57
         */
58
        $applyEnv = function ($array) use ($data) {
59
            $iterator = new \RecursiveIteratorIterator(
60
                new \RecursiveArrayIterator($array),
61
                \RecursiveIteratorIterator::SELF_FIRST
62
            );
63
            foreach ($iterator as $leafValue) {
64
                $path = [];
65
                foreach (range(0, $iterator->getDepth()) as $depth) {
66
                    $path[] = $iterator->getSubIterator($depth)->key();
67
                }
68
                $sPath = implode('_', $path);
69
                if ($getEnv = getenv('CECIL_'.strtoupper($sPath))) {
70
                    $data->set(str_replace('_', '.', strtolower($sPath)), $getEnv);
71
                }
72
            }
73
        };
74
        $applyEnv($data->export());
75
76
        $this->setFromData($data);
77
    }
78
79
    /**
80
     * Import array config to current config.
81
     *
82
     * @param array $config
83
     */
84
    public function import($config)
85
    {
86
        if (is_array($config)) {
87
            $data = $this->getAll();
88
            $origin = $data->export();
89
            $data->import($config);
90
            $data->import($origin);
91
            $this->setFromData($data);
92
        }
93
    }
94
95
    /**
96
     * Set config data.
97
     *
98
     * @param Data $data
99
     *
100
     * @return $this
101
     */
102
    protected function setFromData(Data $data)
103
    {
104
        if ($this->data !== $data) {
105
            $this->data = $data;
106
        }
107
108
        return $this;
109
    }
110
111
    /**
112
     * Get config data.
113
     *
114
     * @return Data
115
     */
116
    public function getAll()
117
    {
118
        return $this->data;
119
    }
120
121
    /**
122
     * Get data as array.
123
     *
124
     * @return array
125
     */
126
    public function getAllAsArray()
127
    {
128
        return $this->data->export();
129
    }
130
131
    /**
132
     * Return a config value.
133
     *
134
     * @param string $key
135
     * @param string $default
136
     *
137
     * @return array|mixed|null
138
     */
139
    public function get($key, $default = '')
140
    {
141
        return $this->data->get($key, $default);
142
    }
143
144
    /**
145
     * Implement ArrayAccess.
146
     *
147
     * @param mixed $offset
148
     *
149
     * @return bool
150
     */
151
    public function offsetExists($offset)
152
    {
153
        return $this->data->has("site.$offset");
154
    }
155
156
    /**
157
     * Implement ArrayAccess.
158
     *
159
     * @param mixed $offset
160
     *
161
     * @return null
162
     */
163
    public function offsetGet($offset)
164
    {
165
        return $this->data->get("site.$offset");
166
    }
167
168
    /**
169
     * Implement ArrayAccess.
170
     *
171
     * @param mixed $offset
172
     * @param mixed $value
173
     */
174
    public function offsetSet($offset, $value)
175
    {
176
        return $this->data->set("site.$offset", $value);
177
    }
178
179
    /**
180
     * Implement ArrayAccess.
181
     *
182
     * @param mixed $offset
183
     */
184
    public function offsetUnset($offset)
185
    {
186
        return $this->data->remove("site.$offset");
187
    }
188
189
    /**
190
     * Set source directory.
191
     *
192
     * @param null $sourceDir
193
     *
194
     * @throws Exception
195
     *
196
     * @return $this
197
     */
198 View Code Duplication
    public function setSourceDir($sourceDir = null)
199
    {
200
        if ($sourceDir === null) {
201
            $sourceDir = getcwd();
202
        }
203
        if (!is_dir($sourceDir)) {
204
            throw new \InvalidArgumentException(sprintf("'%s' is not a valid source directory.", $sourceDir));
205
        }
206
        $this->sourceDir = $sourceDir;
207
208
        return $this;
209
    }
210
211
    /**
212
     * Get source directory.
213
     *
214
     * @return string
215
     */
216
    public function getSourceDir()
217
    {
218
        return $this->sourceDir;
219
    }
220
221
    /**
222
     * Set destination directory.
223
     *
224
     * @param null $destinationDir
225
     *
226
     * @throws Exception
227
     *
228
     * @return $this
229
     */
230 View Code Duplication
    public function setDestinationDir($destinationDir = null)
231
    {
232
        if ($destinationDir === null) {
233
            $destinationDir = $this->sourceDir;
234
        }
235
        if (!is_dir($destinationDir)) {
236
            throw new \InvalidArgumentException(sprintf("'%s' is not a valid destination directory.", $destinationDir));
237
        }
238
        $this->destinationDir = $destinationDir;
239
240
        return $this;
241
    }
242
243
    /**
244
     * Get destination directory.
245
     *
246
     * @return string
247
     */
248
    public function getDestinationDir()
249
    {
250
        return $this->destinationDir;
251
    }
252
253
    /**
254
     * Path helpers.
255
     */
256
257
    /**
258
     * Return content directory path.
259
     *
260
     * @return string
261
     */
262
    public function getContentPath()
263
    {
264
        return $this->getSourceDir().'/'.$this->get('content.dir');
265
    }
266
267
    /**
268
     * Return templates directory path.
269
     *
270
     * @return string
271
     */
272
    public function getLayoutsPath()
273
    {
274
        return $this->getSourceDir().'/'.$this->get('layouts.dir');
275
    }
276
277
    /**
278
     * Return themes directory path.
279
     *
280
     * @return string
281
     */
282
    public function getThemesPath()
283
    {
284
        return $this->getSourceDir().'/'.$this->get('themes.dir');
285
    }
286
287
    /**
288
     * Return internal templates directory path.
289
     *
290
     * @return string
291
     */
292
    public function getInternalLayoutsPath()
293
    {
294
        return __DIR__.'/../'.$this->get('layouts.internal.dir');
295
    }
296
297
    /**
298
     * Return output directory path.
299
     *
300
     * @return string
301
     */
302
    public function getOutputPath()
303
    {
304
        return $this->getDestinationDir().'/'.$this->get('site.output.dir');
305
    }
306
307
    /**
308
     * Return static files directory path.
309
     *
310
     * @return string
311
     */
312
    public function getStaticPath()
313
    {
314
        return $this->getSourceDir().'/'.$this->get('static.dir');
315
    }
316
317
    /**
318
     * Themes helpers.
319
     */
320
321
    /**
322
     * Return theme(s).
323
     *
324
     * @return array|null
325
     */
326
    public function getTheme()
327
    {
328
        if ($themes = $this->get('theme')) {
329
            if (is_array($themes)) {
330
                return $themes;
331
            }
332
333
            return [$themes];
334
        }
335
    }
336
337
    /**
338
     * Has a (valid) theme(s)?
339
     *
340
     * @throws Exception
341
     *
342
     * @return bool
343
     */
344
    public function hasTheme()
345
    {
346
        if ($themes = $this->getTheme()) {
347
            foreach ($themes as $theme) {
348
                if (!Util::getFS()->exists($this->getThemeDirPath($theme, 'layouts'))) {
349
                    throw new Exception(sprintf(
350
                        "Theme directory '%s/%s/layouts' not found!",
351
                        $this->getThemesPath(),
352
                        $theme
353
                    ));
354
                }
355
            }
356
357
            return true;
358
        }
359
360
        return false;
361
    }
362
363
    /**
364
     * Return the path of a specific theme's directory.
365
     *
366
     * @param string $theme
367
     * @param string $dir
368
     *
369
     * @return string
370
     */
371
    public function getThemeDirPath($theme, $dir = 'layouts')
372
    {
373
        return $this->getThemesPath().'/'.$theme.'/'.$dir;
374
    }
375
376
    /**
377
     * Return "clean" array output format array.
378
     *
379
     * @param string $format
380
     *
381
     * @return array
382
     */
383
    public function getOutputFormat(string $format): array
384
    {
385
        $default = [
386
            'mediatype' => null, // 'text/html'
387
            'subpath'   => null, // ''
388
            'suffix'    => null, // '/index'
389
            'extension' => null, // 'html'
390
        ];
391
392
        $result = $this->get(sprintf('site.output.formats.%s', $format));
393
394
        return array_merge($default, $result);
395
    }
396
397
    /**
398
     * Return available languages.
399
     *
400
     * @return array
401
     */
402
    public function getLanguages(): array
403
    {
404
        return $this->get('site.languages');
405
    }
406
407
    /**
408
     * Return default language key (ie: "en", "fr-fr", etc.).
409
     *
410
     * @return string
411
     */
412
    public function getLanguageDefaultKey(): string
413
    {
414
        if ($this->get('site.language')) {
415
            return $this->get('site.language');
416
        }
417
418
        $languages = $this->getLanguages();
419
        if (!is_array($languages)) {
420
            throw new Exception('There is no default `language` in config!');
421
        }
422
        reset($languages);
423
424
        return key($languages);
425
    }
426
427
    /**
428
     * Return (specified or default) language properties.
429
     *
430
     * @return array
431
     */
432
    public function getLanguageProperties($key = null): array
433
    {
434
        $key = $key ?? $this->getLanguageDefaultKey();
435
436
        $language = $this->get(sprintf('site.languages.%s', $key));
437
        if (!is_array($language)) {
438
            throw new Exception(sprintf('Language "%s" is not correctly set in config!', $key));
439
        }
440
441
        return $language;
442
    }
443
444
    /**
445
     * Return (specified or default) language property value.
446
     *
447
     * @return string
448
     */
449
    public function getLanguageProperty($property, $key = null): string
450
    {
451
        $properties = ['name', 'locale'];
452
        $language = $this->getLanguageProperties($key);
453
454
        if (!in_array($property, $properties)) {
455
            throw new Exception(sprintf(
456
                'Property language "%s" is not available!',
457
                $property
458
            ));
459
        }
460
        if (!\array_key_exists($property, $language)) {
461
            throw new Exception(sprintf(
462
                'Property "%s" is not defined for language "%s"!',
463
                $property,
464
                $language['name']
465
            ));
466
        }
467
468
        return $language[$property];
469
    }
470
471
    /**
472
     * Language helper: return language key.
473
     */
474
    public function getLang(): string
475
    {
476
        return $this->getLanguageDefaultKey();
477
    }
478
479
    /**
480
     * Language helper: return language name.
481
     */
482
    public function getLanguage(): string
483
    {
484
        return $this->getLanguageProperty('name');
485
    }
486
487
    /**
488
     * Language helper: return language locale.
489
     */
490
    public function getLocale(): string
491
    {
492
        return $this->getLanguageProperty('locale');
493
    }
494
}
495