Passed
Push — master ( 243250...d8ab5e )
by Max
03:50
created

AbstractDictionary::offsetSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
ccs 1
cts 1
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EasyDictionary;
6
7
use EasyDictionary\Interfaces\DataProviderInterface;
8
use EasyDictionary\Interfaces\DictionaryInterface;
9
use EasyDictionary\Interfaces\DataProviderFilterInterface;
10
use Psr\SimpleCache\CacheInterface;
11
12
/**
13
 * Class AbstractDictionary
14
 * @package EasyDictionary
15
 */
16
abstract class AbstractDictionary implements DictionaryInterface
17
{
18
    /**
19
     * @var string
20
     */
21
    protected $name = '';
22
23
    /**
24
     * @var DataProviderInterface
25
     */
26
    protected $dataProvider = null;
27
28
    /**
29
     * @var DataProviderFilterInterface
30
     */
31
    protected $dataProviderFilter = null;
32
33
    /**
34
     * @var callable
35
     */
36
    protected $view = null;
37
38
    /**
39
     * @var \Psr\SimpleCache\CacheInterface
40
     */
41
    protected $cache = null;
42
43
    /**
44
     * @var int
45
     */
46
    protected $cacheTTL = 0;
47
48
    /**
49
     * @var iterable
50
     */
51
    protected $data = [];
52
53
    /**
54
     * @var array
55
     */
56
    protected $searchFields = [];
57
58
    /**
59
     * @var bool
60
     */
61
    protected $dataLoaded = false;
62
63
    /**
64
     * AbstractDictionary constructor.
65
     * @param string $name
66
     */
67 16
    public function __construct(string $name = '')
68
    {
69 16
        $this->setName($name);
70 16
    }
71
72
    /**
73
     * @param callable|null $view
74
     * @return $this
75
     */
76 3
    public function setDefaultView(callable $view = null)
77
    {
78 3
        $this->view = $view;
79
80 3
        return $this;
81
    }
82
83
    /**
84
     * @return null|DataProviderInterface
85
     */
86 14
    public function getDataProvider(): ?DataProviderInterface
87
    {
88 14
        return $this->dataProvider;
89
    }
90
91
    /**
92
     * @param DataProviderInterface $provider
93
     * @return $this
94
     */
95 15
    public function setDataProvider(DataProviderInterface $provider)
96
    {
97 15
        $this->dataProvider = $provider;
98
99 15
        return $this;
100
    }
101
102
    /**
103
     * @param DataProviderFilterInterface $filter
104
     * @return $this|mixed
105
     */
106 2
    public function setDataProviderFilter(DataProviderFilterInterface $filter = null)
107
    {
108 2
        $this->dataProviderFilter = $filter;
109
110 2
        return $this;
111
    }
112
113
    /**
114
     * @return int
115
     */
116 1
    public function count(): int
117
    {
118 1
        return count($this->getData());
119
    }
120
121
    /**
122
     * @return mixed
123
     */
124 14
    public function getData(): iterable
125
    {
126 14
        if (false === $this->dataLoaded) {
127 14
            $cache = $this->getCache();
128
129 14
            if (is_null($cache)) {
130 12
                $this->data = $this->loadData();
131
            } else {
132 2
                $key = static::class . '_' . $this->getName();
133
134 2
                if (!is_null($this->dataProviderFilter)) {
135
                    $key .= '_' . md5($this->dataProviderFilter);
136
                }
137
138
                try {
139 2
                    if (!($this->data = $cache->get($key, []))) {
140 2
                        $this->data = $this->loadData();
141 2
                        $cache->set($key, $this->data, $this->cacheTTL);
142
                    }
143 1
                } catch (\Psr\SimpleCache\InvalidArgumentException $e) {
144 1
                    $this->data = [];
145
                }
146
            }
147
148 14
            $this->dataLoaded = true;
149
        }
150
151 14
        return $this->data;
152
    }
153
154
    /**
155
     * @return CacheInterface
156
     */
157 14
    public function getCache(): ?CacheInterface
158
    {
159 14
        return $this->cache;
160
    }
161
162
    /**
163
     * @param CacheInterface $cache
164
     * @param int $ttl
165
     * @return $this
166
     */
167 2
    public function setCache(CacheInterface $cache, int $ttl = 3600)
168
    {
169 2
        $this->cache = $cache;
170 2
        $this->cacheTTL = $ttl;
171
172 2
        return $this;
173
    }
174
175
    /**
176
     * @return iterable
177
     */
178
    abstract protected function loadData(): iterable;
179
180
    /**
181
     * @return string
182
     */
183 3
    public function getName(): string
184
    {
185 3
        return $this->name;
186
    }
187
188
    /**
189
     * @param string $name
190
     */
191 16
    public function setName(string $name)
192
    {
193 16
        $this->name = $name;
194 16
    }
195
196
    /**
197
     * @param string $pattern
198
     * @param bool $strict
199
     * @return iterable
200
     */
201 2
    public function search(string $pattern, bool $strict = false): iterable
202
    {
203 2
        $data = [];
204 2
        $searchData = [];
205 2
        $searchFields = array_filter($this->getSearchFields($strict));
206 2
        foreach ($this as $key => $value) {
207 2
            $data[$key] = $value;
208
209 2
            if (is_array($value)) {
210 1
                $searchData[$key] = (string)$key . ' ' .
211 1
                    join(' ', empty($searchFields) ? $value : array_intersect_key($value, $searchFields));
212
            } else {
213 2
                $searchData[$key] = (string)$key . ' ' . (string)$value;
214
            }
215
        }
216
217 2
        return array_intersect_key($data, preg_grep($pattern, $searchData));
218
    }
219
220
    /**
221
     * @param bool $strict
222
     * @return array
223
     */
224 2
    public function getSearchFields(bool $strict = false): array
225
    {
226 2
        return true === $strict ? array_filter($this->searchFields) : $this->searchFields;
227
    }
228
229
    /**
230
     * @param array $searchFields
231
     * @return $this
232
     */
233 3
    public function setSearchFields(array $searchFields)
234
    {
235 3
        $this->searchFields = $searchFields;
236
237 3
        return $this;
238
    }
239
240
    /**
241
     * @param mixed $offset
242
     * @param mixed $value
243
     * @return null|void
244
     */
245 1
    public function offsetSet($offset, $value)
246
    {
247 1
    }
248
249
    /**
250
     * @param mixed $offset
251
     * @return bool
252
     */
253 1
    public function offsetExists($offset)
254
    {
255 1
        $data = $this->toArray();
256
257 1
        return isset($data[$offset]);
258
    }
259
260
    /**
261
     * @param mixed $offset
262
     * @return null|void
263
     */
264 1
    public function offsetUnset($offset)
265
    {
266 1
    }
267
268
    /**
269
     * @param mixed $offset
270
     * @return mixed|null
271
     */
272 1
    public function offsetGet($offset)
273
    {
274 1
        $data = $this->toArray();
275
276 1
        return $data[$offset] ?? null;
277
    }
278
279
    /**
280
     * @param callable|null $callable
281
     * @return array
282
     */
283 4
    public function toArray(callable $callable = null)
284
    {
285 4
        $iterator = is_callable($callable)
286 1
            ? $this->withView($callable)
287 4
            : $this->getIterator();
288
289 4
        return iterator_to_array($iterator);
290
    }
291
292
    /**
293
     * @return \Iterator
294
     */
295 9
    public function getIterator(): iterable
296
    {
297 9
        $view = $this->getDefaultView();
298
299 9
        if (is_null($view)) {
0 ignored issues
show
introduced by
The condition is_null($view) is always false.
Loading history...
300 8
            foreach ($this->getData() as $key => $item) {
301 8
                yield $key => $item;
302
            }
303
        } else {
304 1
            yield from $this->withView($view);
305
        }
306 9
    }
307
308
    /**
309
     * @return callable|null
310
     */
311 9
    public function getDefaultView(): ?callable
312
    {
313 9
        return $this->view;
314
    }
315
316
    /**
317
     * @param callable $callable
318
     * @return \Generator
319
     */
320 3
    public function withView(callable $callable = null): iterable
321
    {
322 3
        if (is_callable($callable)) {
323 2
            yield from call_user_func($callable, $this->getData());
324
        } else {
325 1
            yield from $this->getIterator();
326
        }
327 3
    }
328
}
329