Completed
Push — master ( d35622...5e2604 )
by Rafał
06:46
created

Context::loadConfigsFromPath()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 13
nc 5
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Superdesk Web Publisher Templates System.
5
 *
6
 * Copyright 2015 Sourcefabric z.ú. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace SWP\Component\TemplatesSystem\Gimme\Context;
16
17
use Doctrine\Common\Cache\Cache;
18
use SWP\Component\TemplatesSystem\Gimme\Meta\Meta;
19
use Symfony\Component\Finder\Finder;
20
use Symfony\Component\Yaml\Parser;
21
22
class Context implements \ArrayAccess
23
{
24
    /**
25
     * Array with current page information's.
26
     *
27
     * @var Meta
28
     */
29
    protected $currentPage;
30
31
    /**
32
     * Array will all registered meta types.
33
     *
34
     * @var Meta[]
35
     */
36
    protected $registeredMeta = [];
37
38
    /**
39
     * Array with available meta configs.
40
     *
41
     * @var array
42
     */
43
    protected $availableConfigs = [];
44
45
    /**
46
     * @var Cache
47
     */
48
    protected $metadataCache;
49
50
    /**
51
     * @var string
52
     */
53
    protected $configsPath;
54
55
    /**
56
     * @var array
57
     */
58
    private $temporaryMeta = [];
59
60
    /**
61
     * @var bool
62
     */
63
    private $previewMode = false;
64
65
    /**
66
     * Context constructor.
67
     *
68
     * @param Cache  $metadataCache
69
     * @param string $configsPath
70
     */
71
    public function __construct(Cache $metadataCache, $configsPath = null)
72
    {
73
        $this->metadataCache = $metadataCache;
74
        $this->configsPath = $configsPath;
75
    }
76
77
    /**
78
     * @return array
79
     */
80
    public function getAvailableConfigs()
81
    {
82
        if (0 === count($this->availableConfigs)) {
83
            $this->loadConfigsFromPath($this->configsPath);
84
        }
85
86
        return $this->availableConfigs;
87
    }
88
89
    /**
90
     * @param array $configuration
91
     *
92
     * @return bool
93
     */
94
    public function addAvailableConfig(array $configuration)
95
    {
96
        if (isset($configuration['class']) && !isset($this->availableConfigs[$configuration['class']])) {
97
            $this->availableConfigs[$configuration['class']] = $configuration;
98
99
            return true;
100
        }
101
102
        return false;
103
    }
104
105
    /**
106
     * @param array $availableConfigs
107
     *
108
     * @return Context
109
     */
110
    public function setAvailableConfigs(array $availableConfigs)
111
    {
112
        $this->availableConfigs = $availableConfigs;
113
114
        return $this;
115
    }
116
117
    /**
118
     * @param string $configsPath
119
     */
120
    public function loadConfigsFromPath($configsPath)
121
    {
122
        if (file_exists($configsPath)) {
123
            if (!$this->metadataCache->contains('metadata_config_files')) {
124
                $finder = new Finder();
125
                $finder->in($configsPath)->files()->name('*.yml');
126
                $files = [];
127
                foreach ($finder as $file) {
128
                    $files[] = $file->getRealPath();
129
                    $this->addNewConfig($file->getRealPath());
130
                }
131
                $this->metadataCache->save('metadata_config_files', $files);
132
            } else {
133
                foreach ($this->metadataCache->fetch('metadata_config_files') as $file) {
134
                    $this->addNewConfig($file);
135
                }
136
            }
137
        }
138
    }
139
140
    /**
141
     * @param mixed $value
142
     *
143
     * @return array
144
     *
145
     * @throws \Exception
146
     */
147
    public function getConfigurationForValue($value)
148
    {
149
        if (false === is_object($value)) {
150
            throw new \Exception('Context supports configuration loading only for objects');
151
        }
152
153
        foreach ($this->getAvailableConfigs() as $class => $configuration) {
154
            if ($value instanceof $class) {
155
                return $configuration;
156
            }
157
        }
158
159
        return [];
160
    }
161
162
    /**
163
     * @param mixed $value
164
     *
165
     * @return Meta
166
     */
167
    public function getMetaForValue($value)
168
    {
169
        return new Meta($this, $value, $this->getConfigurationForValue($value));
170
    }
171
172
    /**
173
     * @param mixed $value
174
     *
175
     * @return bool
176
     */
177
    public function isSupported($value)
178
    {
179
        if (!is_object($value)) {
180
            return false;
181
        }
182
183
        return count($this->getConfigurationForValue($value)) > 0 ? true : false;
184
    }
185
186
    /**
187
     * @param string $filePath
188
     *
189
     * @return $this
190
     */
191
    public function addNewConfig($filePath)
192
    {
193
        $cacheKey = md5($filePath);
194
        if (!$this->metadataCache->contains($cacheKey)) {
195
            if (!is_readable($filePath)) {
196
                throw new \InvalidArgumentException('Configuration file is not readable for parser');
197
            }
198
            $parser = new Parser();
199
            $configuration = $parser->parse(file_get_contents($filePath));
200
            $this->metadataCache->save($cacheKey, $configuration);
201
        } else {
202
            $configuration = $this->metadataCache->fetch($cacheKey);
203
        }
204
205
        $this->addAvailableConfig($configuration);
206
207
        return $configuration;
208
    }
209
210
    /**
211
     * Set current context page information's.
212
     *
213
     * @param Meta $currentPage
214
     *
215
     * @return self
216
     */
217
    public function setCurrentPage(Meta $currentPage)
218
    {
219
        $this->currentPage = $currentPage;
220
221
        return $this;
222
    }
223
224
    /**
225
     * Get current context page information's.
226
     *
227
     * @return Meta
228
     */
229
    public function getCurrentPage()
230
    {
231
        return $this->currentPage;
232
    }
233
234
    /**
235
     * Register new meta type, registration is required before setting new value for meta.
236
     *
237
     * @param Meta|null $meta Meta object
238
     *
239
     * @throws \Exception if already registered
240
     *
241
     * @return bool if registered successfully
242
     */
243
    public function registerMeta(Meta $meta = null)
244
    {
245
        $configuration = $meta->getConfiguration();
0 ignored issues
show
Bug introduced by
It seems like $meta is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
246
        $name = $configuration['name'];
247
        if (!array_key_exists($name, $this->registeredMeta)) {
248
            $this->registeredMeta[$name] = $configuration;
249
250
            if (null !== $meta) {
251
                $this[$name] = $meta;
252
            }
253
254
            return true;
255
        }
256
257
        return false;
258
    }
259
260
    /**
261
     * @return Meta[]
262
     */
263
    public function getRegisteredMeta()
264
    {
265
        return $this->registeredMeta;
266
    }
267
268
    /**
269
     * @return bool
270
     */
271
    public function isPreviewMode(): bool
272
    {
273
        return $this->previewMode;
274
    }
275
276
    /**
277
     * @param bool $previewMode
278
     */
279
    public function setPreviewMode(bool $previewMode)
280
    {
281
        $this->previewMode = $previewMode;
282
    }
283
284
    /**
285
     * {@inheritdoc}
286
     */
287
    public function offsetSet($name, $meta)
288
    {
289
        if (array_key_exists($name, $this->registeredMeta)) {
290
            $this->$name = $meta;
291
        }
292
293
        return true;
294
    }
295
296
    /**
297
     * {@inheritdoc}
298
     */
299
    public function offsetExists($name)
300
    {
301
        return isset($this->$name);
302
    }
303
304
    /**
305
     * {@inheritdoc}
306
     */
307
    public function offsetUnset($name)
308
    {
309
        unset($this->$name);
310
311
        return true;
312
    }
313
314
    /**
315
     * {@inheritdoc}
316
     */
317
    public function offsetGet($name)
318
    {
319
        if (array_key_exists($name, $this->registeredMeta) && isset($this->$name)) {
320
            return $this->$name;
321
        }
322
323
        return false;
324
    }
325
326
    /**
327
     * @param array $keys
328
     *
329
     * @return string
330
     */
331
    public function temporaryUnset(array $keys)
332
    {
333
        $metas = [];
334
        $keysId = md5(serialize($keys));
335
336
        if (0 === count($keys)) {
337
            foreach ($this->registeredMeta as $key => $configuration) {
338
                if (isset($this[$key])) {
339
                    $metas[$key] = $this[$key];
340
                    unset($this[$key]);
341
                }
342
            }
343
        }
344
345
        foreach ($keys as $key) {
346
            if (array_key_exists($key, $this->registeredMeta)) {
347
                $metas[$key] = $this[$key];
348
                unset($this[$key]);
349
            }
350
        }
351
        $this->temporaryMeta[$keysId] = $metas;
352
353
        return $keysId;
354
    }
355
356
    /**
357
     * @param string $id
358
     *
359
     * @return null|true
360
     */
361
    public function restoreTemporaryUnset($id)
362
    {
363
        $metas = $this->temporaryMeta[$id];
364
        if (!is_array($metas)) {
365
            return;
366
        }
367
368
        foreach ($metas as $key => $value) {
369
            $this[$key] = $value;
370
        }
371
372
        return true;
373
    }
374
}
375