Completed
Push — master ( c01904...dcbc34 )
by Boudry
02:56
created

ArrayManager::__clone()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
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) : bool
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 7
            return true;
115
        else :
116 1
            return false;
117
        endif;
118
    }
119
120 83
    public function offsetGet($offset)
121
    {
122 83
        if (isset($this->_Container[$offset])) :
123 83
            return $this->_Container[$offset];
124 2
        elseif ($this->_DataHandler !== null) :
125 2
            if (array_key_exists($offset, $this->_Cache)) :
126 2
                return $this->_Cache[$offset];
127
            else :
128 2
                $query = $this->_DataHandler->selectOneEntity($offset);
129 2
                return ($query === false) ? null : $query;
130
            endif;
131
        else :
132
            return null;
133
        endif;
134
    }
135
136
137
/////////// Implement Iterator ///////////
138
139
    protected $valid = true;
140
141 82
    public function rewind() : void {
142 82
        $this->_cursor = null;
143 82
        $this->valid = true;
144
145 82
        reset($this->_Cache);
146 82
        reset($this->_Container);
147 82
    }
148
149 82
    public function current() {
150 82
        return $this->offsetGet($this->key());
151
    }
152
153 82
    public function key() : ?int
154
    {
155 82
        if ($this->_counter === 0) :
156
            return null;
157
        else :
158 82
            return ($this->_cursor === null) ? $this->getFirstKey() : $this->_cursor;
159
        endif;
160
    }
161
162 82
    public function next() : void
163
    {
164 82
        $oldCursor = $this->_cursor;
165
166 82
        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...
167
            // Do nothing
168 70
        elseif (!$this->isUsingHandler()) :
169 69
            $this->setCursorOnNextKeyInArray($this->_Container);
170
        else :
171 2
            $this->populateCache();
172 2
            $this->setCursorOnNextKeyInArray($this->_Cache);
173
        endif;
174
175 82
        if ($this->_cursor === $oldCursor) :
176 82
            $this->valid = false;
177
        endif;
178 82
    }
179
180 70
        protected function setCursorOnNextKeyInArray (array &$array)
181
        {
182 70
            next($array);
183 70
            $arrayKey = key($array);
184
185 70
            if ($arrayKey > $this->key()) :
186 70
                return $this->_cursor = $arrayKey;
187
            endif;
188 2
        }
189
190 82
    public function valid() : bool {
191 82
        return $this->valid;
192
    }
193
194
195
/////////// Implement Countable ///////////
196
197 10
    public function count () : int {
198 10
        return $this->_counter;
199
    }
200
201
/////////// Array Methods ///////////
202
203 15
    public function getFullDataSet () : array
204
    {
205 15
        $this->regularize();
206
207 15
        return (!$this->isUsingHandler()) ? $this->_Container : $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
208
    }
209
210 7
    public function keyExist ($offset) : bool
211
    {
212 7
        if ( array_key_exists($offset, $this->_Container) || ($this->_DataHandler !== null && $this->_DataHandler->selectOneEntity($offset) !== false) ) :
213 7
            return true;
214
        else  :
215 1
            return false;
216
        endif;
217
    }
218
219 82
    public function getFirstKey () : int
220
    {
221 82
        $r = array_keys($this->_Container);
222
223 82
        if ($this->_DataHandler !== null) :
224 2
            $r[] = $this->_DataHandler->selectMinKey();
225
        endif;
226
227 82
        return (int) min($r);
228
    }
229
230 4
    public function getContainerSize () : int
231
    {
232 4
        return count($this->_Container);
233
    }
234
235 1
    public function getCacheSize () : int
236
    {
237 1
        return count($this->_Cache);
238
    }
239
240 1
    public function debugGetCache () : array
241
    {
242 1
        return $this->_Cache;
243
    }
244
245
246
/////////// HANDLER API ///////////
247
248 17
    public function regularize () : bool
249
    {
250 17
        if (!$this->isUsingHandler() || empty($this->_Container)) :
251 17
            return false;
252
        else :
253 3
            $this->_DataHandler->insertEntitys($this->_Container);
254 3
            $this->_Container = [];
255 3
            return true;
256
        endif;
257
    }
258
259 100
    public function checkRegularize () : bool
260
    {
261 100
        if ( $this->_DataHandler !== null && self::$MaxContainerLength <= $this->getContainerSize() ) :
262 1
            $this->regularize();
263 1
            return true;
264
        else :
265 100
            return false;
266
        endif;
267
    }
268
269 2
    protected function populateCache () : void
270
    {
271 2
        $this->regularize();
272
273 2
        $currentKey = $this->key();
274
275 2
        if ( empty($this->_Cache) || $currentKey >= $this->_CacheMaxKey || $currentKey < $this->_CacheMinKey ) :
276 2
            $this->_Cache = $this->_DataHandler->selectRangeEntitys($currentKey, self::$CacheSize);
277
278 2
            $keys = array_keys($this->_Cache);
279 2
            $this->_CacheMaxKey = max($keys);
280 2
            $this->_CacheMinKey = min($keys);
281
        endif;
282 2
    }
283
284 3
    public function clearCache () : void
285
    {
286 3
        $this->_Cache = [];
287 3
        $this->_CacheMaxKey = 0;
288 3
        $this->_CacheMinKey = 0;
289 3
    }
290
291 77
    public function isUsingHandler ()
292
    {
293 77
        return $this->_DataHandler !== null;
294
    }
295
296
/////////// HANDLER INTERRACTION ///////////
297
298 4
    public function resetCounter () : int
299
    {
300 4
        return $this->_counter = $this->getContainerSize() + ( ($this->isUsingHandler()) ? $this->_DataHandler->countEntitys() : 0 );
301
    }
302
303 4
    public function resetMaxKey () : ?int
304
    {
305 4
        $this->resetCounter();
306
307 4
        if ($this->count() < 1) :
308 3
            $this->_maxKey = -1;
309 3
            return null;
310
        else :
311 2
            $maxContainerKey = (empty($this->_Container)) ? null : max(array_keys($this->_Container));
312 2
            $maxHandlerKey = ($this->_DataHandler !== null) ? $this->_DataHandler->selectMaxKey() : null;
313
314 2
            return $this->_maxKey = max( $maxContainerKey,$maxHandlerKey );
315
        endif;
316
    }
317
318 3
    public function importHandler (DataHandlerDriverInterface $handler) : bool
319
    {
320 3
        if ($handler->countEntitys() === 0) :
321 3
            $this->_DataHandler = $handler;
322 3
            $this->_DataHandler->_dataContextObject = $this->getDataContextObject();
323
324
            try {
325 3
                $this->regularize();
326
            } catch (\Exception $e) {
327
                $this->_DataHandler = null;
328
                $this->resetCounter();
329
                $this->resetMaxKey();
330
                throw $e;
331
            }
332
333 3
            $this->resetCounter();
334 3
            $this->resetMaxKey();
335
336 3
            return true;
337
        else :
338
            throw new CondorcetException;
339
        endif;
340
    }
341
342 1
    public function closeHandler () : void
343
    {
344 1
        if ($this->_DataHandler !== null) :
345 1
            $this->regularize();
346 1
            $this->clearCache();
347
348 1
            $this->_Container = $this->_DataHandler->selectRangeEntitys(0,$this->_maxKey + 1);
349
350 1
            $this->_DataHandler = null;
351
352 1
            $this->resetCounter();
353 1
            $this->resetMaxKey();
354
        endif;
355 1
    }
356
357
    public function getDataContextObject () : DataContextInterface
358
    {
359
        return new Class implements DataContextInterface {
360
            public function dataCallBack ($data)
361
            {
362
                return $data;
363
            }
364
365
            public function dataPrepareStoringAndFormat ($data)
366
            {
367
                return $data;
368
            }
369
        };
370
    }
371
}
372