Completed
Push — master ( dcbc34...facd47 )
by Boudry
02:36
created

ArrayManager::keyExist()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 2
nop 1
crap 4
1
<?php
2
/*
3
    Condorcet PHP Class, with Schulze Methods and others !
4
5
    By Julien Boudry - MIT LICENSE (Please read LICENSE.txt)
6
    https://github.com/julien-boudry/Condorcet
7
*/
8
declare(strict_types=1);
9
10
11
namespace Condorcet\DataManager;
12
13
use Condorcet\DataManager\DataContextInterface;
14
use Condorcet\DataManager\DataHandlerDrivers\DataHandlerDriverInterface;
15
use Condorcet\CondorcetException;
16
use Condorcet\CondorcetVersion;
17
18
abstract class ArrayManager implements \ArrayAccess, \Countable, \Iterator
19
{
20
    use CondorcetVersion;
21
22
        //////
23
24
    public static $CacheSize = 2000;
25
    public static $MaxContainerLength = 2000;
26
27
    protected $_Container = [];
28
    protected $_DataHandler = null;
29
    protected $_link = [];
30
31
    protected $_Cache = [];
32
    protected $_CacheMaxKey = 0;
33
    protected $_CacheMinKey = 0;
34
35
    protected $_cursor = null;
36
    protected $_counter = 0;
37
    protected $_maxKey = -1;
38
39
    public function __construct () {}
40
41 1
    public function __destruct ()
42
    {
43 1
        $this->regularize();
44 1
    }
45
46 1
    public function __clone ()
47
    {
48 1
        $this->_link = [];
49 1
    }
50
51 2
    public function __sleep () : array
52
    {
53 2
        $this->regularize();
54 2
        $this->clearCache();
55 2
        $this->rewind();
56
57 2
        return ['_Container','_DataHandler','_link'];
58
    }
59
60 1
    public function __wakeup ()
61
    {
62 1
        $this->resetMaxKey();
63 1
        $this->resetCounter();
64 1
    }
65
66
67
/////////// Implement ArrayAccess ///////////
68
69 100
    public function offsetSet($offset, $value) : void
70
    {
71 100
        if ($offset === null) :
72 100
            $this->_Container[++$this->_maxKey] = $value;
73 100
            ++$this->_counter;
74
        else :
75
            $state = !$this->keyExist($offset);
76
            $this->_Container[$offset] = $value;
77
78
            if ($state) :
79
                ++$this->_counter;
80
81
                if ($offset > $this->_maxKey) :
82
                    $this->_maxKey = $offset;
83
                endif;
84
85
                ksort($this->_Container,SORT_NUMERIC);
86
            elseif ($this->_DataHandler !== null) :
87
                $this->_DataHandler->deleteOneEntity($offset, true);
88
            endif;
89
90
            $this->clearCache();
91
        endif;
92
93 100
        $this->checkRegularize();
94 100
    }
95
96
    // Use by isset() function, must return false if offset value is null.
97
    public function offsetExists($offset) : bool
98
    {
99
        return ( isset($this->_Container[$offset]) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) ? true : false ;
100
    }
101
102 7
    public function offsetUnset($offset) : void
103
    {
104 7
        if ($this->keyExist($offset)) :
105 7
            if (array_key_exists($offset, $this->_Container)) :
106 7
                unset($this->_Container[$offset]);
107
            else :
108 1
                unset($this->_Cache[$offset]);
109
110 1
                $this->_DataHandler->deleteOneEntity($offset, false);
111
            endif;
112
113 7
            --$this->_counter;
114
        endif;
115 7
    }
116
117 83
    public function offsetGet($offset)
118
    {
119 83
        if (isset($this->_Container[$offset])) :
120 83
            return $this->_Container[$offset];
121 2
        elseif ($this->_DataHandler !== null) :
122 2
            if (array_key_exists($offset, $this->_Cache)) :
123 2
                return $this->_Cache[$offset];
124
            else :
125 2
                $query = $this->_DataHandler->selectOneEntity($offset);
126 2
                return ($query === false) ? null : $query;
127
            endif;
128
        else :
129
            return null;
130
        endif;
131
    }
132
133
134
/////////// Implement Iterator ///////////
135
136
    protected $valid = true;
137
138 82
    public function rewind() : void {
139 82
        $this->_cursor = null;
140 82
        $this->valid = true;
141
142 82
        reset($this->_Cache);
143 82
        reset($this->_Container);
144 82
    }
145
146 82
    public function current() {
147 82
        return $this->offsetGet($this->key());
148
    }
149
150 82
    public function key() : ?int
151
    {
152 82
        if ($this->_counter === 0) :
153
            return null;
154
        else :
155 82
            return ($this->_cursor === null) ? $this->getFirstKey() : $this->_cursor;
156
        endif;
157
    }
158
159 82
    public function next() : void
160
    {
161 82
        $oldCursor = $this->_cursor;
162
163 82
        if ($this->_cursor >= $this->_maxKey) :
164
            // Do nothing
165 70
        elseif (!$this->isUsingHandler()) :
166 69
            $this->setCursorOnNextKeyInArray($this->_Container);
167
        else :
168 2
            $this->populateCache();
169 2
            $this->setCursorOnNextKeyInArray($this->_Cache);
170
        endif;
171
172 82
        if ($this->_cursor === $oldCursor) :
173 82
            $this->valid = false;
174
        endif;
175 82
    }
176
177 70
        protected function setCursorOnNextKeyInArray (array &$array)
178
        {
179 70
            next($array);
180 70
            $arrayKey = key($array);
181
182 70
            if ($arrayKey > $this->key()) :
183 70
                return $this->_cursor = $arrayKey;
184
            endif;
185 1
        }
186
187 82
    public function valid() : bool {
188 82
        return $this->valid;
189
    }
190
191
192
/////////// Implement Countable ///////////
193
194 10
    public function count () : int {
195 10
        return $this->_counter;
196
    }
197
198
/////////// Array Methods ///////////
199
200 15
    public function getFullDataSet () : array
201
    {
202 15
        $this->regularize();
203
204 15
        return (!$this->isUsingHandler()) ? $this->_Container : $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
205
    }
206
207 7
    public function keyExist ($offset) : bool
208
    {
209 7
        if ( array_key_exists($offset, $this->_Container) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) :
210 7
            return true;
211
        else  :
212 1
            return false;
213
        endif;
214
    }
215
216 82
    public function getFirstKey () : int
217
    {
218 82
        $r = array_keys($this->_Container);
219
220 82
        if ($this->_DataHandler !== null) :
221 2
            $r[] = $this->_DataHandler->selectMinKey();
222
        endif;
223
224 82
        return (int) min($r);
225
    }
226
227 4
    public function getContainerSize () : int
228
    {
229 4
        return count($this->_Container);
230
    }
231
232 1
    public function getCacheSize () : int
233
    {
234 1
        return count($this->_Cache);
235
    }
236
237 1
    public function debugGetCache () : array
238
    {
239 1
        return $this->_Cache;
240
    }
241
242
243
/////////// HANDLER API ///////////
244
245 17
    public function regularize () : bool
246
    {
247 17
        if (!$this->isUsingHandler() || empty($this->_Container)) :
248 17
            return false;
249
        else :
250 3
            $this->_DataHandler->insertEntitys($this->_Container);
251 3
            $this->_Container = [];
252 3
            return true;
253
        endif;
254
    }
255
256 100
    public function checkRegularize () : bool
257
    {
258 100
        if ( $this->_DataHandler !== null && self::$MaxContainerLength <= $this->getContainerSize() ) :
259 1
            $this->regularize();
260 1
            return true;
261
        else :
262 100
            return false;
263
        endif;
264
    }
265
266 2
    protected function populateCache () : void
267
    {
268 2
        $this->regularize();
269
270 2
        $currentKey = $this->key();
271
272 2
        if ( empty($this->_Cache) || $currentKey >= $this->_CacheMaxKey || $currentKey < $this->_CacheMinKey ) :
273 2
            $this->_Cache = $this->_DataHandler->selectRangeEntitys($currentKey, self::$CacheSize);
274
275 2
            $keys = array_keys($this->_Cache);
276 2
            $this->_CacheMaxKey = max($keys);
277 2
            $this->_CacheMinKey = min($keys);
278
        endif;
279 2
    }
280
281 3
    public function clearCache () : void
282
    {
283 3
        $this->_Cache = [];
284 3
        $this->_CacheMaxKey = 0;
285 3
        $this->_CacheMinKey = 0;
286 3
    }
287
288 77
    public function isUsingHandler ()
289
    {
290 77
        return $this->_DataHandler !== null;
291
    }
292
293
/////////// HANDLER INTERRACTION ///////////
294
295 4
    public function resetCounter () : int
296
    {
297 4
        return $this->_counter = $this->getContainerSize() + ( ($this->isUsingHandler()) ? $this->_DataHandler->countEntitys() : 0 );
298
    }
299
300 4
    public function resetMaxKey () : ?int
301
    {
302 4
        $this->resetCounter();
303
304 4
        if ($this->count() < 1) :
305 3
            $this->_maxKey = -1;
306 3
            return null;
307
        else :
308 2
            $maxContainerKey = (empty($this->_Container)) ? null : max(array_keys($this->_Container));
309 2
            $maxHandlerKey = ($this->_DataHandler !== null) ? $this->_DataHandler->selectMaxKey() : null;
310
311 2
            return $this->_maxKey = max( $maxContainerKey,$maxHandlerKey );
312
        endif;
313
    }
314
315 3
    public function importHandler (DataHandlerDriverInterface $handler) : bool
316
    {
317 3
        if ($handler->countEntitys() === 0) :
318 3
            $this->_DataHandler = $handler;
319 3
            $this->_DataHandler->_dataContextObject = $this->getDataContextObject();
320
321
            try {
322 3
                $this->regularize();
323
            } catch (\Exception $e) {
324
                $this->_DataHandler = null;
325
                $this->resetCounter();
326
                $this->resetMaxKey();
327
                throw $e;
328
            }
329
330 3
            $this->resetCounter();
331 3
            $this->resetMaxKey();
332
333 3
            return true;
334
        else :
335
            throw new CondorcetException;
336
        endif;
337
    }
338
339 1
    public function closeHandler () : void
340
    {
341 1
        if ($this->_DataHandler !== null) :
342 1
            $this->regularize();
343 1
            $this->clearCache();
344
345 1
            $this->_Container = $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
346
347 1
            $this->_DataHandler = null;
348
349 1
            $this->resetCounter();
350 1
            $this->resetMaxKey();
351
        endif;
352 1
    }
353
354
    public function getDataContextObject () : DataContextInterface
355
    {
356
        return new Class implements DataContextInterface {
357
            public function dataCallBack ($data)
358
            {
359
                return $data;
360
            }
361
362
            public function dataPrepareStoringAndFormat ($data)
363
            {
364
                return $data;
365
            }
366
        };
367
    }
368
}
369