Completed
Push — master ( 922505...49fe4c )
by Boudry
05:20
created

ArrayManager   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 349
Duplicated Lines 0 %

Test Coverage

Coverage 82.72%

Importance

Changes 0
Metric Value
wmc 3
dl 0
loc 349
ccs 134
cts 162
cp 0.8272
rs 10
c 0
b 0
f 0

33 Methods

Rating   Name   Duplication   Size   Complexity  
A hp$0 ➔ dataCallBack() 0 4 1
A hp$0 ➔ dataPrepareStoringAndFormat() 0 4 1
A __construct() 0 1 1
A __wakeup() 0 5 1
B offsetSet() 0 26 5
A offsetExists() 0 4 4
A rewind() 0 7 1
A current() 0 3 1
A key() 0 8 3
A setCursorOnNextKeyInArray() 0 9 2
A valid() 0 3 1
A count() 0 3 1
A getFullDataSet() 0 6 2
A isUsingHandler() 0 4 1
A getDataContextObject() 0 14 1
A __destruct() 0 4 1
A __sleep() 0 8 1
A offsetUnset() 0 17 3
B offsetGet() 0 15 5
A next() 0 17 4
A keyExist() 0 8 4
A getFirstKey() 0 10 2
A getContainerSize() 0 4 1
A getCacheSize() 0 4 1
A debugGetCache() 0 4 1
A regularize() 0 10 3
A checkRegularize() 0 9 3
A populateCache() 0 14 4
A clearCache() 0 6 1
A resetCounter() 0 4 2
A resetMaxKey() 0 14 4
A importHandler() 0 23 3
A closeHandler() 0 14 2
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 __sleep () : array
47
    {
48 1
        $this->regularize();
49 1
        $this->clearCache();
50 1
        $this->rewind();
51
52 1
        return ['_Container','_DataHandler','_link'];
53
    }
54
55
    public function __wakeup ()
56
    {
57
        $this->resetMaxKey();
58
        $this->resetCounter();
59
    }
60
61
62
/////////// Implement ArrayAccess ///////////
63
64 81
    public function offsetSet($offset, $value) : void
65
    {
66 81
        if ($offset === null) :
67 81
            $this->_Container[++$this->_maxKey] = $value;
68 81
            ++$this->_counter;
69
        else :
70
            $state = !$this->keyExist($offset);
71
            $this->_Container[$offset] = $value;
72
73
            if ($state) :
74
                ++$this->_counter;
75
76
                if ($offset > $this->_maxKey) :
77
                    $this->_maxKey = $offset;
78
                endif;
79
80
                ksort($this->_Container,SORT_NUMERIC);
81
            elseif ($this->_DataHandler !== null) :
82
                $this->_DataHandler->deleteOneEntity($offset, true);
83
            endif;
84
85
            $this->clearCache();
86
        endif;
87
88 81
        $this->checkRegularize();
89 81
    }
90
91
    // Use by isset() function, must return false if offset value is null.
92
    public function offsetExists($offset) : bool
93
    {
94
        return ( isset($this->_Container[$offset]) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) ? true : false ;
95
    }
96
97 7
    public function offsetUnset($offset) : bool
98
    {
99 7
        if ($this->keyExist($offset)) :
100 7
            if (array_key_exists($offset, $this->_Container)) :
101 7
                unset($this->_Container[$offset]);
102
            else :
103 1
                unset($this->_Cache[$offset]);
104
105 1
                $this->_DataHandler->deleteOneEntity($offset, false);
106
            endif;
107
108 7
            --$this->_counter;
109 7
            return true;
110
        else :
111 1
            return false;
112
        endif;
113
    }
114
115 69
    public function offsetGet($offset)
116
    {
117 69
        if (isset($this->_Container[$offset])) :
118 69
            return $this->_Container[$offset];
119 2
        elseif ($this->_DataHandler !== null) :
120 2
            if (array_key_exists($offset, $this->_Cache)) :
121 2
                return $this->_Cache[$offset];
122
            else :
123 2
                $query = $this->_DataHandler->selectOneEntity($offset);
124 2
                return ($query === false) ? null : $query;
125
            endif;
126
        else :
127
            return null;
128
        endif;
129
    }
130
131
132
/////////// Implement Iterator ///////////
133
134
    protected $valid = true;
135
136 68
    public function rewind() : void {
137 68
        $this->_cursor = null;
138 68
        $this->valid = true;
139
140 68
        reset($this->_Cache);
141 68
        reset($this->_Container);
142 68
    }
143
144 68
    public function current() {
145 68
        return $this->offsetGet($this->key());
146
    }
147
148 68
    public function key() : ?int
149
    {
150 68
        if ($this->_counter === 0) :
151
            return null;
152
        else :
153 68
            return ($this->_cursor === null) ? $this->getFirstKey() : $this->_cursor;
154
        endif;
155
    }
156
157 68
    public function next() : void
158
    {
159 68
        $oldCursor = $this->_cursor;
160
161 68
        if ($this->_cursor >= $this->_maxKey) :
1 ignored issue
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
162
            // Do nothing
163 66
        elseif (!$this->isUsingHandler()) :
164 65
            $this->setCursorOnNextKeyInArray($this->_Container);
165
        else :
166 2
            $this->populateCache();
167 2
            $this->setCursorOnNextKeyInArray($this->_Cache);
168
        endif;
169
170 68
        if ($this->_cursor === $oldCursor) :
171 68
            $this->valid = false;
172
        endif;
173 68
    }
174
175 66
        protected function setCursorOnNextKeyInArray (array &$array)
176
        {
177 66
            next($array);
178 66
            $arrayKey = key($array);
179
180 66
            if ($arrayKey > $this->key()) :
181 66
                return $this->_cursor = $arrayKey;
182
            endif;
183 2
        }
184
185 68
    public function valid() : bool {
186 68
        return $this->valid;
187
    }
188
189
190
/////////// Implement Countable ///////////
191
192 15
    public function count () : int {
193 15
        return $this->_counter;
194
    }
195
196
/////////// Array Methods ///////////
197
198 12
    public function getFullDataSet () : array
199
    {
200 12
        $this->regularize();
201
202 12
        return (!$this->isUsingHandler()) ? $this->_Container : $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
203
    }
204
205 7
    public function keyExist ($offset) : bool
206
    {
207 7
        if ( array_key_exists($offset, $this->_Container) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) :
208 7
            return true;
209
        else  :
210 1
            return false;
211
        endif;
212
    }
213
214 68
    public function getFirstKey () : int
215
    {
216 68
        $r = array_keys($this->_Container);
217
218 68
        if ($this->_DataHandler !== null) :
219 2
            $r[] = $this->_DataHandler->selectMinKey();
220
        endif;
221
222 68
        return (int) min($r);
223
    }
224
225 3
    public function getContainerSize () : int
226
    {
227 3
        return count($this->_Container);
228
    }
229
230 1
    public function getCacheSize () : int
231
    {
232 1
        return count($this->_Cache);
233
    }
234
235 1
    public function debugGetCache () : array
236
    {
237 1
        return $this->_Cache;
238
    }
239
240
241
/////////// HANDLER API ///////////
242
243 14
    public function regularize () : bool
244
    {
245 14
        if (!$this->isUsingHandler() || empty($this->_Container)) :
246 14
            return false;
247
        else :
248 3
            $this->_DataHandler->insertEntitys($this->_Container);
249 3
            $this->_Container = [];
250 3
            return true;
251
        endif;
252
    }
253
254 81
    public function checkRegularize () : bool
255
    {
256 81
        if ( $this->_DataHandler !== null && self::$MaxContainerLength <= $this->getContainerSize() ) :
257 1
            $this->regularize();
258 1
            return true;
259
        else :
260 81
            return false;
261
        endif;
262
    }
263
264 2
    protected function populateCache () : void
265
    {
266 2
        $this->regularize();
267
268 2
        $currentKey = $this->key();
269
270 2
        if ( empty($this->_Cache) || $currentKey >= $this->_CacheMaxKey || $currentKey < $this->_CacheMinKey ) :
271 2
            $this->_Cache = $this->_DataHandler->selectRangeEntitys($currentKey, self::$CacheSize);
272
273 2
            $keys = array_keys($this->_Cache);
274 2
            $this->_CacheMaxKey = max($keys);
275 2
            $this->_CacheMinKey = min($keys);
276
        endif;
277 2
    }
278
279 2
    public function clearCache () : void
280
    {
281 2
        $this->_Cache = [];
282 2
        $this->_CacheMaxKey = 0;
283 2
        $this->_CacheMinKey = 0;
284 2
    }
285
286 72
    public function isUsingHandler ()
287
    {
288 72
        return $this->_DataHandler !== null;
289
    }
290
291
/////////// HANDLER INTERRACTION ///////////
292
293 3
    public function resetCounter () : int
294
    {
295 3
        return $this->_counter = $this->getContainerSize() + ( ($this->isUsingHandler()) ? $this->_DataHandler->countEntitys() : 0 );
296
    }
297
298 3
    public function resetMaxKey () : ?int
299
    {
300 3
        $this->resetCounter();
301
302 3
        if ($this->count() < 1) :
303 3
            $this->_maxKey = -1;
304 3
            return null;
305
        else :
306 1
            $maxContainerKey = (empty($this->_Container)) ? null : max(array_keys($this->_Container));
307 1
            $maxHandlerKey = ($this->_DataHandler !== null) ? $this->_DataHandler->selectMaxKey() : null;
308
309 1
            return $this->_maxKey = max( $maxContainerKey,$maxHandlerKey );
310
        endif;
311
    }
312
313 3
    public function importHandler (DataHandlerDriverInterface $handler) : bool
314
    {
315 3
        if ($handler->countEntitys() === 0) :
316 3
            $this->_DataHandler = $handler;
317 3
            $this->_DataHandler->_dataContextObject = $this->getDataContextObject();
318
319
            try {
320 3
                $this->regularize();
321
            } catch (\Exception $e) {
322
                $this->_DataHandler = null;
323
                $this->resetCounter();
324
                $this->resetMaxKey();
325
                throw $e;
326
            }
327
328 3
            $this->resetCounter();
329 3
            $this->resetMaxKey();
330
331 3
            return true;
332
        else :
333
            throw new CondorcetException;
334
        endif;
335
    }
336
337 1
    public function closeHandler () : void
338
    {
339 1
        if ($this->_DataHandler !== null) :
340 1
            $this->regularize();
341 1
            $this->clearCache();
342
343 1
            $this->_Container = $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
344
345 1
            $this->_DataHandler = null;
346
347 1
            $this->resetCounter();
348 1
            $this->resetMaxKey();
349
        endif;
350 1
    }
351
352
    public function getDataContextObject () : DataContextInterface
353
    {
354
        return new Class implements DataContextInterface {
355
            public function dataCallBack ($data)
356
            {
357
                return $data;
358
            }
359
360
            public function dataPrepareStoringAndFormat ($data)
361
            {
362
                return $data;
363
            }
364
        };
365
    }
366
}
367