Completed
Push — master ( f036f0...b950dc )
by Rafał
02:16
created

Context::restoreTemporaryUnset()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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