Completed
Push — master ( 9f5802...03a8a6 )
by Patrick
07:27 queued 05:23
created

SQLDataSet::update()   B

Complexity

Conditions 6
Paths 18

Size

Total Lines 31

Duplication

Lines 7
Ratio 22.58 %

Importance

Changes 0
Metric Value
cc 6
nc 18
nop 3
dl 7
loc 31
rs 8.8017
c 0
b 0
f 0
1
<?php
2
namespace Data;
3
4
class SQLDataSet extends DataSet
5
{
6
    protected $pdo;
7
    protected $params;
8
9
    /**
10
     * Create a new SQLDataSet
11
     *
12
     * @param array $params An array containing atleast 'dsn' and possibly 'user' and 'pass'
13
     */
14
    public function __construct($params)
15
    {
16
        $this->params = $params;
17 View Code Duplication
        if(isset($params['user']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
18
        {
19
            $this->pdo = new \PDO($params['dsn'], $params['user'], $params['pass']);
20
        }
21
        else
22
        {
23
            $this->pdo = new \PDO($params['dsn']);
24
        }
25
    }
26
27
    public function __sleep()
28
    {
29
        $this->pdo = null;
30
        return array('params');
31
    }
32
33
    public function __wakeup()
34
    {
35
        $this->connect();
36
    }
37
38
    protected function connect()
39
    {
40
        if(isset($this->params['user']))
41
        {
42
	     $this->pdo = new \PDO($this->params['dsn'], $this->params['user'], $this->params['pass']);
43
	}
44
	else
45
	{
46
	     $this->pdo = new \PDO($this->params['dsn']);
47
        }
48
    }
49
50
    /**
51
     * Get the number of rows affected by the query
52
     *
53
     * @param string $sql The SQL string
54
     *
55
     * @return integer The number of rows affected by the query
56
     */
57
    private function _get_row_count_for_query($sql)
58
    {
59
        $stmt = $this->pdo->query($sql);
60
        if($stmt === false)
61
        {
62
            return 0;
63
        }
64
        $count = $stmt->rowCount();
65
        if($count === 0)
66
        {
67
            $array = $stmt->fetchAll();
68
            $count = count($array);
69
        }
70
        return $count;
71
    }
72
73
    private function _tableExistsNoPrefix($name)
74
    {
75
        if($this->_get_row_count_for_query('SHOW TABLES LIKE '.$this->pdo->quote($name)) > 0)
76
        {
77
            return true;
78
        }
79
        else if($this->_get_row_count_for_query('SELECT * FROM sqlite_master WHERE name LIKE '.$this->pdo->quote($name)) > 0)
80
        {
81
            return true;
82
        }
83
        return false;
84
    }
85
86
    private function _tableExists($name)
87
    {
88
        return $this->_tableExistsNoPrefix('tbl'.$name);
89
    }
90
91
    private function _viewExists($name)
92
    {
93
        return $this->_tableExistsNoPrefix('v'.$name);
94
    }
95
96
    public function tableExists($name)
97
    {
98
        if($this->_tableExists($name))
99
        {
100
            return true;
101
        }
102
        if($this->_tableExistsNoPrefix($name))
103
        {
104
            return true;
105
        }
106
        if($this->_viewExists($name))
107
        {
108
            return true;
109
        }
110
        return false;
111
    }
112
113
    public function getTable($name)
114
    {
115
        if($this->_tableExists($name))
116
        {
117
            return new SQLDataTable($this, 'tbl'.$name);
118
        }
119
        if($this->_viewExists($name))
120
        {
121
            return new SQLDataTable($this, 'v'.$name);
122
        }
123
        if($this->_tableExistsNoPrefix($name))
124
        {
125
            return new SQLDataTable($this, $name);
126
        }
127
        throw new \Exception('No such table '.$name);
128
    }
129
130
    /**
131
     * @param boolean|array $sort The array to sort by or false to not sort
132
     */
133
    private function getOrderByClause($sort)
134
    {
135
        if(empty($sort))
136
        {
137
            return false;
138
        }
139
        $sql = ' ORDER BY ';
140
        $tmp = array();
141
        foreach($sort as $sort_col=>$dir)
0 ignored issues
show
Bug introduced by
The expression $sort of type boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
142
        {
143
            array_push($tmp, $sort_col.' '.($dir === 1 ? 'ASC' : 'DESC'));
144
        }
145
        $sql .= implode($tmp, ',');
146
        return $sql;
147
    }
148
149
    /**
150
     * Convert OData style $count and $skip into SQL LIMIT
151
     *
152
     * @param boolean|string $count The number of items to return
153
     * @param boolean|string $skip The number of items to skip
154
     */
155
    private function getLimitClause($count, $skip)
156
    {
157
        if($count === false)
158
        {
159
            return false;
160
        }
161
        $count = intval($count);
162
        if($skip !== false)
163
        {
164
            $skip = intval($count);
165
            return " LIMIT $skip, $count";
166
        }
167
        return ' LIMIT '.$count;
168
    }
169
170
    /**
171
     * Read data from the specified SQL table
172
     *
173
     * @param string $tablename The name of the table to read from
174
     * @param boolean|string $where The where caluse of the SQL statement
175
     * @param string $select The colums to read
176
     * @param boolean|string $count The number of rows to read
177
     * @param boolean|string $skip The number of rows to skip over
178
     * @param boolean|array $sort The array to sort by or false to not sort
179
     *
180
     * @return false|array An array of all the returned records
181
     */
182
    public function read($tablename, $where = false, $select = '*', $count = false, $skip = false, $sort = false)
183
    {
184
        if($select === false)
185
        {
186
            $select = '*';
187
        }
188
        $sql = "SELECT $select FROM `$tablename`";
189
        if($where !== false)
190
        {
191
            $sql .= ' WHERE '.$where;
192
        }
193
        $tmp = $this->getLimitClause($count, $skip);
194
        if($tmp !== false)
195
        {
196
            $sql .= $tmp;
197
        }
198
        $tmp = $this->getOrderByClause($sort);
199
        if($tmp !== false)
200
        {
201
            $sql .= $tmp;
202
        }
203
        $stmt = $this->pdo->query($sql, \PDO::FETCH_ASSOC);
204
        if($stmt === false)
205
        {
206
            return false;
207
        }
208
        $ret = $stmt->fetchAll();
209
        if(empty($ret))
210
        {
211
            return false;
212
        }
213
        return $ret;
214
    }
215
216
    /**
217
     * Perform an SQL update on the specified table
218
     *
219
     * @param string $tablename The name of the table to insert to
220
     * @param string $where The where clause in SQL format
221
     * @param mixed $data The data to write to the table
222
     *
223
     * @return boolean true if successful, false otherwise
224
     */
225
    public function update($tablename, $where, $data)
226
    {
227
        $set = array();
228
        if(is_object($data))
229
        {
230
            $data = (array)$data;
231
        }
232
        $cols = array_keys($data);
233
        $count = count($cols);
234
        for($i = 0; $i < $count; $i++)
235
        {
236
            if($data[$cols[$i]] === null)
237
            {
238
                array_push($set, $cols[$i].'=NULL');
239
            }
240
            else
241
            {
242
                array_push($set, $cols[$i].'='.$this->pdo->quote($data[$cols[$i]]));
243
            }
244
        }
245
        $set = implode(',', $set);
246
        $sql = "UPDATE $tablename SET $set WHERE $where";
247 View Code Duplication
        if($this->pdo->exec($sql) === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
        {
249
            if (php_sapi_name() !== "cli") {
250
              error_log('DB query failed. '.print_r($this->pdo->errorInfo(), true));
251
            }
252
            return false;
253
        }
254
        return true;
255
    }
256
257
    /**
258
     * Perform an SQL insert on the specified table
259
     *
260
     * @param string $tablename The name of the table to insert to
261
     * @param mixed $data The data to write to the table
262
     *
263
     * @return boolean true if successful, false otherwise
264
     */
265
    public function create($tablename, $data)
266
    {
267
        $set = array();
268
        if(is_object($data))
269
        {
270
            $data = (array)$data;
271
        }
272
        $cols = array_keys($data);
273
        $count = count($cols);
274
        for($i = 0; $i < $count; $i++)
275
        {
276
            if($data[$cols[$i]] === null)
277
            {
278
                array_push($set, 'NULL');
279
            }
280
            else
281
            {
282
                array_push($set, $this->pdo->quote($data[$cols[$i]]));
283
            }
284
        }
285
        $cols = implode(',', $cols);
286
        $set = implode(',', $set);
287
        $sql = "INSERT INTO $tablename ($cols) VALUES ($set);";
288 View Code Duplication
        if($this->pdo->exec($sql) === false)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
289
        {
290
            if (php_sapi_name() !== "cli") {
291
                error_log('DB query failed. '.print_r($this->pdo->errorInfo(), true));
292
            }
293
            return false;
294
        }
295
        return true;
296
    }
297
298
    /**
299
     * Perform an SQL delete on the specified table
300
     *
301
     * @param string $tablename The name of the table to insert to
302
     * @param string $where The where clause in SQL format
303
     *
304
     * @return boolean true if successful, false otherwise
305
     */
306
    public function delete($tablename, $where)
307
    {
308
        $sql = "DELETE FROM $tablename WHERE $where";
309
        if($this->pdo->exec($sql) === false)
310
        {
311
            return false;
312
        }
313
        return true;
314
    }
315
316
    /**
317
     * Perform an SQL query
318
     *
319
     * @param string $sql The raw SQL
320
     *
321
     * @return mixed false on a failure, an array of data otherwise
322
     */
323
    public function raw_query($sql)
324
    {
325
        $stmt = $this->pdo->query($sql, \PDO::FETCH_ASSOC);
326
        if($stmt === false)
327
        {
328
            return false;
329
        }
330
        $ret = $stmt->fetchAll();
331
        return $ret;
332
    }
333
334
    public function getLastError()
335
    {
336
        return $this->pdo->errorInfo();
337
    }
338
}
339
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
340