Completed
Push — master ( 9ee175...c01904 )
by Boudry
02:34
created

ArrayManager::offsetExists()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 9.2
c 0
b 0
f 0
cc 4
eloc 2
nc 6
nop 1
crap 20
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 2
    public function __sleep () : array
47
    {
48 2
        $this->regularize();
49 2
        $this->clearCache();
50 2
        $this->rewind();
51
52 2
        return ['_Container','_DataHandler','_link'];
53
    }
54
55 1
    public function __wakeup ()
56
    {
57 1
        $this->resetMaxKey();
58 1
        $this->resetCounter();
59 1
    }
60
61
62
/////////// Implement ArrayAccess ///////////
63
64 99
    public function offsetSet($offset, $value) : void
65
    {
66 99
        if ($offset === null) :
67 99
            $this->_Container[++$this->_maxKey] = $value;
68 99
            ++$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 99
        $this->checkRegularize();
89 99
    }
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 82
    public function offsetGet($offset)
116
    {
117 82
        if (isset($this->_Container[$offset])) :
118 82
            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 81
    public function rewind() : void {
137 81
        $this->_cursor = null;
138 81
        $this->valid = true;
139
140 81
        reset($this->_Cache);
141 81
        reset($this->_Container);
142 81
    }
143
144 81
    public function current() {
145 81
        return $this->offsetGet($this->key());
146
    }
147
148 81
    public function key() : ?int
149
    {
150 81
        if ($this->_counter === 0) :
151
            return null;
152
        else :
153 81
            return ($this->_cursor === null) ? $this->getFirstKey() : $this->_cursor;
154
        endif;
155
    }
156
157 81
    public function next() : void
158
    {
159 81
        $oldCursor = $this->_cursor;
160
161 81
        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 69
        elseif (!$this->isUsingHandler()) :
164 68
            $this->setCursorOnNextKeyInArray($this->_Container);
165
        else :
166 2
            $this->populateCache();
167 2
            $this->setCursorOnNextKeyInArray($this->_Cache);
168
        endif;
169
170 81
        if ($this->_cursor === $oldCursor) :
171 81
            $this->valid = false;
172
        endif;
173 81
    }
174
175 69
        protected function setCursorOnNextKeyInArray (array &$array)
176
        {
177 69
            next($array);
178 69
            $arrayKey = key($array);
179
180 69
            if ($arrayKey > $this->key()) :
181 69
                return $this->_cursor = $arrayKey;
182
            endif;
183 2
        }
184
185 81
    public function valid() : bool {
186 81
        return $this->valid;
187
    }
188
189
190
/////////// Implement Countable ///////////
191
192 10
    public function count () : int {
193 10
        return $this->_counter;
194
    }
195
196
/////////// Array Methods ///////////
197
198 14
    public function getFullDataSet () : array
199
    {
200 14
        $this->regularize();
201
202 14
        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 81
    public function getFirstKey () : int
215
    {
216 81
        $r = array_keys($this->_Container);
217
218 81
        if ($this->_DataHandler !== null) :
219 2
            $r[] = $this->_DataHandler->selectMinKey();
220
        endif;
221
222 81
        return (int) min($r);
223
    }
224
225 4
    public function getContainerSize () : int
226
    {
227 4
        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 16
    public function regularize () : bool
244
    {
245 16
        if (!$this->isUsingHandler() || empty($this->_Container)) :
246 16
            return false;
247
        else :
248 3
            $this->_DataHandler->insertEntitys($this->_Container);
249 3
            $this->_Container = [];
250 3
            return true;
251
        endif;
252
    }
253
254 99
    public function checkRegularize () : bool
255
    {
256 99
        if ( $this->_DataHandler !== null && self::$MaxContainerLength <= $this->getContainerSize() ) :
257 1
            $this->regularize();
258 1
            return true;
259
        else :
260 99
            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 3
    public function clearCache () : void
280
    {
281 3
        $this->_Cache = [];
282 3
        $this->_CacheMaxKey = 0;
283 3
        $this->_CacheMinKey = 0;
284 3
    }
285
286 76
    public function isUsingHandler ()
287
    {
288 76
        return $this->_DataHandler !== null;
289
    }
290
291
/////////// HANDLER INTERRACTION ///////////
292
293 4
    public function resetCounter () : int
294
    {
295 4
        return $this->_counter = $this->getContainerSize() + ( ($this->isUsingHandler()) ? $this->_DataHandler->countEntitys() : 0 );
296
    }
297
298 4
    public function resetMaxKey () : ?int
299
    {
300 4
        $this->resetCounter();
301
302 4
        if ($this->count() < 1) :
303 3
            $this->_maxKey = -1;
304 3
            return null;
305
        else :
306 2
            $maxContainerKey = (empty($this->_Container)) ? null : max(array_keys($this->_Container));
307 2
            $maxHandlerKey = ($this->_DataHandler !== null) ? $this->_DataHandler->selectMaxKey() : null;
308
309 2
            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