Completed
Push — master ( 5e2604...48fac3 )
by Rafał
07:45
created

Context::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
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
            if (null !== $meta) {
250
                $this[$name] = $meta;
251
            }
252
253
            return true;
254
        }
255
256
        return false;
257
    }
258
259
    /**
260
     * @return Meta[]
261
     */
262
    public function getRegisteredMeta()
263
    {
264
        return $this->registeredMeta;
265
    }
266
267
    /**
268
     * @return bool
269
     */
270
    public function isPreviewMode(): bool
271
    {
272
        return $this->previewMode;
273
    }
274
275
    /**
276
     * @param bool $previewMode
277
     */
278
    public function setPreviewMode(bool $previewMode)
279
    {
280
        $this->previewMode = $previewMode;
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286
    public function offsetSet($name, $meta)
287
    {
288
        if (array_key_exists($name, $this->registeredMeta)) {
289
            $this->$name = $meta;
290
        }
291
292
        return true;
293
    }
294
295
    /**
296
     * {@inheritdoc}
297
     */
298
    public function offsetExists($name)
299
    {
300
        return isset($this->$name);
301
    }
302
303
    /**
304
     * {@inheritdoc}
305
     */
306
    public function offsetUnset($name)
307
    {
308
        unset($this->$name);
309
310
        return true;
311
    }
312
313
    /**
314
     * {@inheritdoc}
315
     */
316
    public function offsetGet($name)
317
    {
318
        if (array_key_exists($name, $this->registeredMeta) && isset($this->$name)) {
319
            return $this->$name;
320
        }
321
322
        return false;
323
    }
324
325
    /**
326
     * @param array $keys
327
     *
328
     * @return string
329
     */
330
    public function temporaryUnset(array $keys)
331
    {
332
        $metas = [];
333
        $keysId = md5(serialize($keys));
334
335
        if (0 === count($keys)) {
336
            foreach ($this->registeredMeta as $key => $configuration) {
337
                if (isset($this[$key])) {
338
                    $metas[$key] = $this[$key];
339
                    unset($this[$key]);
340
                }
341
            }
342
        }
343
344
        foreach ($keys as $key) {
345
            if (array_key_exists($key, $this->registeredMeta)) {
346
                $metas[$key] = $this[$key];
347
                unset($this[$key]);
348
            }
349
        }
350
        $this->temporaryMeta[$keysId] = $metas;
351
352
        return $keysId;
353
    }
354
355
    /**
356
     * @param string $id
357
     *
358
     * @return null|true
359
     */
360
    public function restoreTemporaryUnset($id)
361
    {
362
        $metas = $this->temporaryMeta[$id];
363
        if (!is_array($metas)) {
364
            return;
365
        }
366
367
        foreach ($metas as $key => $value) {
368
            $this[$key] = $value;
369
        }
370
371
        return true;
372
    }
373
374
    /**
375
     *  Resets context data.
376
     */
377
    public function reset()
378
    {
379
        $this->currentPage = null;
380
        $this->registeredMeta = [];
381
        $this->availableConfigs = [];
382
        $this->previewMode = false;
383
    }
384
}
385