Passed
Push — TEST/ScrutinizerPHPAnalysisEng... ( c9e065...573acf )
by Boudry
09:25
created

PdoHandlerDriver::insertEntitys()   B

Complexity

Conditions 5
Paths 23

Size

Total Lines 33
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5.2

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 16
cts 20
cp 0.8
rs 8.439
c 0
b 0
f 0
cc 5
crap 5.2
eloc 23
nc 23
nop 1
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 19 and the first side effect is on line 219.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/*
3
    PDO DataHandler Module - From the original Condorcet PHP
4
5
    Condorcet PHP - Election manager and results calculator.
6
    Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
7
8
    By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
9
    https://github.com/julien-boudry/Condorcet
10
*/
11
declare(strict_types=1);
12
13
namespace Condorcet\DataManager\DataHandlerDrivers;
14
15
use Condorcet\DataManager\DataHandlerDrivers\DataHandlerDriverInterface;
16
use Condorcet\CondorcetException;
17
use Condorcet\CondorcetVersion;
18
19
class PdoHandlerDriver implements DataHandlerDriverInterface
20
{
21
    use CondorcetVersion;
22
23
    protected const SEGMENT = [300,100,50,10,1];
24
25
    protected $_handler;
26
    protected $_transaction = false;
27
    protected $_queryError = false;
28
29
    // Database structure
30
    protected $_struct;
31
    // Prepare Query
32
    protected $_prepare = [];
33
    // Data CallBack function
34
    public $_dataContextObject;
35
36
37 4
    public function __construct (\PDO $bdd, bool $tryCreateTable = false, array $struct = ['tableName' => 'Entitys', 'primaryColumnName' => 'id', 'dataColumnName' => 'data'])
38
    {
39 4
        if (!$this->checkStructureTemplate($struct)) :
40
            throw new CondorcetException;
41
        endif;
42
43 4
        $this->_struct = $struct;
44
45 4
        $this->_handler = $bdd;
46
47 4
        $this->_handler->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
48
49 4
        if ($tryCreateTable) :
50 4
            $this->createTable();
51
        endif;
52
53 4
        $this->initPrepareQuery();
54 4
    }
55
56 1
    public function __destruct ()
57
    {
58 1
        if ($this->_queryError) :
59
            $this->_handler->rollback();
60
            $this->_transaction = false;
61
        else :
62 1
            $this->closeTransaction();
63
        endif;
64 1
    }
65
66
67
    // INTERNAL
68
69 4
    protected function checkStructureTemplate (array &$struct) : bool
70
    {
71 4
        if (    !empty($struct['tableName']) && !empty($struct['primaryColumnName']) && !empty($struct['dataColumnName']) &&
72 4
                is_string($struct['tableName']) && is_string($struct['primaryColumnName']) && is_string($struct['dataColumnName'])
73
         ) :
74 4
            return true;
75
        else :
76
            return false;
77
        endif;
78
    }
79
80 4
    public function createTable () : void
81
    {
82
        try {
83 4
            $this->_handler->exec('CREATE TABLE IF NOT EXISTS '.$this->_struct['tableName'].' ('.$this->_struct['primaryColumnName'].' INTEGER PRIMARY KEY NOT NULL , '.$this->_struct['dataColumnName'].' BLOB NOT NULL )');
84
        } catch (\Exception $e) {
85
            throw $e;
86
        }  
87 4
    }
88
89 4
    protected function initPrepareQuery () : void
90
    {
91 4
        $template = [];
92
93
        // Base - Small query ends
94 4
        $template['end_template'] = ';';
95 4
        $template['insert_template'] = 'INSERT INTO '.$this->_struct['tableName'].' ('.$this->_struct['primaryColumnName'].', '.$this->_struct['dataColumnName'].') VALUES ';
96 4
        $template['delete_template'] = 'DELETE FROM '.$this->_struct['tableName'].' WHERE '.$this->_struct['primaryColumnName'];
97 4
        $template['select_template'] = 'SELECT '.$this->_struct['primaryColumnName'].','.$this->_struct['dataColumnName'].' FROM '.$this->_struct['tableName'].' WHERE '.$this->_struct['primaryColumnName'];
98
99
        // Select the max / min key value. Usefull if array cursor is lost on DataManager.
100 4
        $this->_prepare['selectMaxKey'] = $this->_handler->prepare('SELECT max('.$this->_struct['primaryColumnName'].') FROM '.$this->_struct['tableName'] . $template['end_template']);
101 4
        $this->_prepare['selectMinKey'] = $this->_handler->prepare('SELECT min('.$this->_struct['primaryColumnName'].') FROM '.$this->_struct['tableName'] . $template['end_template']);
102
103
        // Insert many Entitys
104 4
            $makeMany = function ($how) use (&$template) {
105 4
                $query = $template['insert_template'];
106
                
107 4
                for ($i=1; $i < $how; $i++) :
108 4
                    $query .= '(:key'.$i.', :data'.$i.'),';
109
                endfor;
110
111 4
                $query .= '(:key'.$how.', :data'.$how.')' . $template['end_template'];
112
113 4
                return $query;
114 4
            };
115
116 4
            foreach (self::SEGMENT as $value) :
117 4
                $this->_prepare['insert'.$value.'Entitys'] = $this->_handler->prepare($makeMany($value));
118
            endforeach;
119
120
        // Delete one Entity
121 4
        $this->_prepare['deleteOneEntity'] = $this->_handler->prepare($template['delete_template'] . ' = ?' . $template['end_template']);
122
123
        // Get a Entity
124 4
        $this->_prepare['selectOneEntity'] = $this->_handler->prepare($template['select_template'] . ' = ?' . $template['end_template']);
125
126
        // Get a range of Entity
127 4
        $this->_prepare['selectRangeEntitys'] = $this->_handler->prepare($template['select_template'] . ' >= :startKey order by '.$this->_struct['primaryColumnName'].' asc LIMIT :limit' . $template['end_template']);
128
129
        // Count Entitys
130 4
        $this->_prepare['countEntitys'] = $this->_handler->prepare('SELECT count('.$this->_struct['primaryColumnName'].') FROM '. $this->_struct['tableName'] . $template['end_template']);
131 4
    }
132
133 4
    protected function initTransaction () : void
134
    {
135 4
        if (!$this->_transaction) :
136 4
            $this->_transaction = $this->_handler->beginTransaction();
137
        endif;
138 4
    }
139
140 4
    public function closeTransaction () : void
141
    {
142 4
        if ($this->_transaction === true) :
143 4
            if ($this->_queryError) :
144
                throw new CondorcetException;
145
            endif;
146
147 4
            $this->_transaction = !$this->_handler->commit();
148
        endif;
149 4
    }
150
151
152
    // DATA MANAGER
153 4
    public function insertEntitys (array $input) : void
154
    {
155 4
        $this->sliceInput($input);
156
157
        try {
158 4
            $this->initTransaction();
159
160 4
            foreach ($input as $group) :
161 4
                $param = [];
162 4
                $i = 1;
163 4
                $group_count = count($group);
164
165 4
                foreach ($group as $key => &$Entity) :
166 4
                    $param['key'.$i] = $key;
167 4
                    $param['data'.$i++] = $this->_dataContextObject->dataPrepareStoringAndFormat($Entity);
168
                endforeach;
169 4
                unset($Entity);
170
171 4
                $this->_prepare['insert'.$group_count.'Entitys']->execute(
172 4
                    $param
173
                );
174
175 4
                if ($this->_prepare['insert'.$group_count.'Entitys']->rowCount() !== $group_count) :
176
                    throw new CondorcetException (0,'Tous les Entitys n\'ont pas été insérés');
177
                endif;
178
179 4
                $this->_prepare['insert'.$group_count.'Entitys']->closeCursor();
180
            endforeach;
181
182 4
            $this->closeTransaction();
183
        } catch (\Exception $e) {
184
            $this->_queryError = true;
185
            throw $e;
186
        }
187 4
    }
188
189 4
        protected function sliceInput (array &$input) : void
190
        {
191 4
            $count = count($input);
192
193 4
            foreach (self::SEGMENT as $value) :
194 4
                if ($count >= $value) :
195 4
                    $input = array_chunk($input, $value, true);
196
197 4
                    $end = end($input);
198 4
                    if (count($input) > 1 && count($end) < $value) :
199
                        $this->sliceInput($end);
200
                        unset($input[key($input)]);
201
                        $input = array_merge($input,$end);
202
                    endif;
203 4
                    break;
204
                endif;
205
            endforeach;
206 4
        }
207
208
209 2
    public function deleteOneEntity (int $key, bool $justTry) : ?int
210
    {
211
        try {
212 2
            $this->_prepare['deleteOneEntity']->bindParam(1, $key, \PDO::PARAM_INT);
213 2
            $this->_prepare['deleteOneEntity']->execute();
214
215 2
            $deleteCount = $this->_prepare['deleteOneEntity']->rowCount();
216
217 2
            if (!$justTry && $deleteCount !== 1) :
218
                throw new CondorcetException (30);
219
            endif;
220
221 2
            $this->_prepare['deleteOneEntity']->closeCursor();
222
223 2
            return $deleteCount;
224
        } catch (\Exception $e) {
225
            $this->_queryError = true;
226
            throw $e;
227
        }
228
    }
229
230 1
    public function selectMaxKey () : ?int
231
    {
232 1
        if ($this->countEntitys() === 0) :
233
            return null;
234
        endif;
235
236
        try {
237 1
            $this->_prepare['selectMaxKey']->execute();
238 1
            $r = (int) $this->_prepare['selectMaxKey']->fetch(\PDO::FETCH_NUM)[0];
239 1
            $this->_prepare['selectMaxKey']->closeCursor();
240
241 1
            return $r;
242
        } catch (\Exception $e) {
243
            throw $e;
244
        }
245
    }
246
247 3
    public function selectMinKey () : int
248
    {
249
        try {
250 3
            $this->_prepare['selectMinKey']->execute();
251 3
            $r = (int) $this->_prepare['selectMinKey']->fetch(\PDO::FETCH_NUM)[0];
252 3
            $this->_prepare['selectMinKey']->closeCursor();
253
254 3
            return $r;
255
        } catch (\Exception $e) {
256
            throw $e;
257
        }
258
    }
259
260 4
    public function countEntitys () : int
261
    {
262
        try {
263 4
            $this->_prepare['countEntitys']->execute();
264 4
            $r = (int) $this->_prepare['countEntitys']->fetch(\PDO::FETCH_NUM)[0];
265 4
            $this->_prepare['countEntitys']->closeCursor();
266
267 4
            return $r;
268
        } catch (\Exception $e) {
269
            throw $e;
270
        }
271
    }
272
273
    // return false if Entity does not exist.
274 3
    public function selectOneEntity (int $key)
275
    {
276
        try {
277 3
            $this->_prepare['selectOneEntity']->bindParam(1, $key, \PDO::PARAM_INT);
278 3
            $this->_prepare['selectOneEntity']->execute();
279
            
280 3
            $r = $this->_prepare['selectOneEntity']->fetchAll(\PDO::FETCH_NUM);
281 3
            $this->_prepare['selectOneEntity']->closeCursor();
282 3
            if (!empty($r)) :
283 3
                return $this->_dataContextObject->dataCallBack( $r[0][1] );
284
            else :
285
                return false;
286
            endif;
287
        } catch (\Exception $e) {
288
            throw $e;
289
        }
290
    }
291
292 4
    public function selectRangeEntitys (int $key, int $limit) : array
293
    {
294
        try {
295 4
            $this->_prepare['selectRangeEntitys']->bindParam(':startKey', $key, \PDO::PARAM_INT);
296 4
            $this->_prepare['selectRangeEntitys']->bindParam(':limit', $limit, \PDO::PARAM_INT);
297 4
            $this->_prepare['selectRangeEntitys']->execute();
298
            
299 4
            $r = $this->_prepare['selectRangeEntitys']->fetchAll(\PDO::FETCH_NUM);
300 4
            $this->_prepare['selectRangeEntitys']->closeCursor();
301 4
            if (!empty($r)) :
302 4
                $result = [];
303 4
                foreach ($r as $value) :
304 4
                    $result[(int) $value[0]] = $this->_dataContextObject->dataCallBack( $value[1] );
305
                endforeach ;
306
307 4
                return $result;
308
            else :
309
                return [];
310
            endif;
311
        } catch (\Exception $e) {
312
            throw $e;
313
        }
314
    }
315
316
}