Completed
Push — master ( 898b1d...88e766 )
by Paweł
10:35
created

Context::getConfigurationForValue()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 4
cts 4
cp 1
rs 8.7624
c 0
b 0
f 0
cc 5
eloc 11
nc 5
nop 1
crap 5
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 128
     * @var array
67
     */
68 128
    private $supportedCache = [];
69 128
70 128
    /**
71
     * @var array
72
     */
73
    private $configurationCache = [];
74
75 20
    /**
76
     * Context constructor.
77 20
     *
78 19
     * @param Cache  $metadataCache
79
     * @param string $configsPath
80
     */
81 20
    public function __construct(Cache $metadataCache, $configsPath = null)
82
    {
83
        $this->metadataCache = $metadataCache;
84
        $this->configsPath = $configsPath;
85
    }
86
87
    /**
88
     * @return array
89 20
     */
90
    public function getAvailableConfigs()
91 20
    {
92 20
        if (0 === count($this->availableConfigs)) {
93
            $this->loadConfigsFromPath($this->configsPath);
94 20
        }
95
96
        return $this->availableConfigs;
97
    }
98
99
    /**
100
     * @param array $configuration
101
     *
102
     * @return bool
103
     */
104
    public function addAvailableConfig(array $configuration)
105
    {
106
        if (isset($configuration['class']) && !isset($this->availableConfigs[$configuration['class']])) {
107
            $this->availableConfigs[$configuration['class']] = $configuration;
108
109
            return true;
110
        }
111
112
        return false;
113
    }
114
115 19
    /**
116
     * @param array $availableConfigs
117 19
     *
118 18
     * @return Context
119 18
     */
120
    public function setAvailableConfigs(array $availableConfigs)
121 18
    {
122 18
        $this->availableConfigs = $availableConfigs;
123
124
        return $this;
125 19
    }
126
127
    /**
128
     * @param string $configsPath
129
     */
130
    public function loadConfigsFromPath($configsPath)
131
    {
132
        if (file_exists($configsPath)) {
133
            if (!$this->metadataCache->contains('metadata_config_files')) {
134 18
                $finder = new Finder();
135
                $finder->in($configsPath)->files()->name('*.yml');
136 18
                $files = [];
137
                foreach ($finder as $file) {
138
                    $files[] = $file->getRealPath();
139
                    $this->addNewConfig($file->getRealPath());
140 18
                }
141 18
                $this->metadataCache->save('metadata_config_files', $files);
142 18
            } else {
143
                foreach ($this->metadataCache->fetch('metadata_config_files') as $file) {
144
                    $this->addNewConfig($file);
145
                }
146 10
            }
147
        }
148
    }
149
150
    /**
151
     * @param mixed $value
152
     *
153
     * @return array
154 10
     *
155
     * @throws \Exception
156 10
     */
157
    public function getConfigurationForValue($value)
158
    {
159
        if (false === is_object($value)) {
160
            throw new \Exception('Context supports configuration loading only for objects');
161
        }
162
163
        $objectClassName = get_class($value);
164 20
        if (array_key_exists($objectClassName, $this->configurationCache)) {
165
            return $this->configurationCache[$objectClassName];
166 20
        }
167 19
168
        foreach ($this->getAvailableConfigs() as $class => $configuration) {
169
            if ($value instanceof $class) {
170 10
                $this->configurationCache[$objectClassName] = $configuration;
171
172
                return $configuration;
173
            }
174
        }
175
176
        return [];
177
    }
178 20
179
    /**
180 20
     * @param mixed $value
181 20
     *
182 20
     * @return Meta
183
     */
184
    public function getMetaForValue($value)
185 20
    {
186 20
        return new Meta($this, $value, $this->getConfigurationForValue($value));
187 20
    }
188
189
    /**
190
     * @param mixed $value
191
     *
192 20
     * @return bool
193
     */
194 20
    public function isSupported($value)
195
    {
196
        if (!is_object($value)) {
197
            return false;
198
        }
199
200
        $objectClassName = get_class($value);
201
        if (array_key_exists($objectClassName, $this->supportedCache)) {
202
            return $this->supportedCache[$objectClassName];
203
        }
204 13
205
        $result = count($this->getConfigurationForValue($value)) > 0 ? true : false;
206 13
        $this->supportedCache[$objectClassName] = $result;
207
208 13
        return $result;
209
    }
210
211
    /**
212
     * @param string $filePath
213
     *
214
     * @return $this
215
     */
216 2
    public function addNewConfig($filePath)
217
    {
218 2
        $cacheKey = md5($filePath);
219
        if (!$this->metadataCache->contains($cacheKey)) {
220
            if (!is_readable($filePath)) {
221
                throw new \InvalidArgumentException('Configuration file is not readable for parser');
222
            }
223
            $parser = new Parser();
224
            $configuration = $parser->parse(file_get_contents($filePath));
225
            $this->metadataCache->save($cacheKey, $configuration);
226
        } else {
227
            $configuration = $this->metadataCache->fetch($cacheKey);
228
        }
229
230 20
        $this->addAvailableConfig($configuration);
231
        $this->supportedCache = [];
232 20
233 20
        return $configuration;
234 20
    }
235 20
236
    /**
237 20
     * Set current context page information's.
238 20
     *
239
     * @param Meta $currentPage
240
     *
241 20
     * @return self
242
     */
243
    public function setCurrentPage(Meta $currentPage)
244 14
    {
245
        $this->currentPage = $currentPage;
246
247
        return $this;
248
    }
249
250 3
    /**
251
     * Get current context page information's.
252 3
     *
253
     * @return Meta
254
     */
255
    public function getCurrentPage()
256
    {
257
        return $this->currentPage;
258 20
    }
259
260 20
    /**
261 20
     * Register new meta type, registration is required before setting new value for meta.
262
     *
263
     * @param Meta|null $meta Meta object
264 20
     *
265
     * @throws \Exception if already registered
266
     *
267
     * @return bool if registered successfully
268
     */
269
    public function registerMeta(Meta $meta = null)
270 11
    {
271
        $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...
272 11
        $name = $configuration['name'];
273
        if (!array_key_exists($name, $this->registeredMeta)) {
274
            $this->registeredMeta[$name] = $configuration;
275
            if (null !== $meta) {
276
                $this[$name] = $meta;
277
            }
278 1
279
            return true;
280 1
        }
281
282 1
        return false;
283
    }
284
285
    /**
286
     * @return Meta[]
287
     */
288 10
    public function getRegisteredMeta()
289
    {
290 10
        return $this->registeredMeta;
291 10
    }
292
293
    /**
294
     * @return bool
295
     */
296
    public function isPreviewMode(): bool
297
    {
298
        return $this->previewMode;
299
    }
300
301
    /**
302 1
     * @param bool $previewMode
303
     */
304 1
    public function setPreviewMode(bool $previewMode)
305 1
    {
306
        $this->previewMode = $previewMode;
307 1
    }
308
309
    /**
310
     * {@inheritdoc}
311
     */
312
    public function offsetSet($name, $meta)
313
    {
314
        if (array_key_exists($name, $this->registeredMeta)) {
315
            $this->$name = $meta;
316 1
        }
317 1
318 1
        return true;
319 1
    }
320
321
    /**
322 1
     * {@inheritdoc}
323
     */
324 1
    public function offsetExists($name)
325
    {
326
        return isset($this->$name);
327
    }
328
329
    /**
330
     * {@inheritdoc}
331
     */
332 1
    public function offsetUnset($name)
333
    {
334 1
        unset($this->$name);
335 1
336
        return true;
337
    }
338
339 1
    /**
340 1
     * {@inheritdoc}
341
     */
342
    public function offsetGet($name)
343 1
    {
344
        if (array_key_exists($name, $this->registeredMeta) && isset($this->$name)) {
345
            return $this->$name;
346
        }
347
348
        return false;
349
    }
350
351
    /**
352
     * @param array $keys
353
     *
354
     * @return string
355
     */
356
    public function temporaryUnset(array $keys)
357
    {
358
        $metas = [];
359
        $keysId = md5(serialize($keys));
360
361
        if (0 === count($keys)) {
362
            foreach ($this->registeredMeta as $key => $configuration) {
363
                if (isset($this[$key])) {
364
                    $metas[$key] = $this[$key];
365
                    unset($this[$key]);
366
                }
367
            }
368
        }
369
370
        foreach ($keys as $key) {
371
            if (array_key_exists($key, $this->registeredMeta)) {
372
                $metas[$key] = $this[$key];
373
                unset($this[$key]);
374
            }
375
        }
376
        $this->temporaryMeta[$keysId] = $metas;
377
378
        return $keysId;
379
    }
380
381
    /**
382
     * @param string $id
383
     *
384
     * @return null|true
385
     */
386
    public function restoreTemporaryUnset($id)
387
    {
388
        $metas = $this->temporaryMeta[$id];
389
        if (!is_array($metas)) {
390
            return;
391
        }
392
393
        foreach ($metas as $key => $value) {
394
            $this[$key] = $value;
395
        }
396
397
        return true;
398
    }
399
400
    /**
401
     *  Resets context data.
402
     */
403
    public function reset()
404
    {
405
        $this->currentPage = null;
406
        $this->registeredMeta = [];
407
        $this->availableConfigs = [];
408
        $this->previewMode = false;
409
    }
410
}
411