Completed
Push — master ( 5cd377...9fa01f )
by Dmytro
03:17
created

DBPreparedQuery::debug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 1
1
<?php
2
3
namespace Asymptix\db;
4
5
use Asymptix\core\Tools;
6
7
/**
8
 * Complex DB query object for Prepared Statement.
9
 *
10
 * @category Asymptix PHP Framework
11
 * @author Dmytro Zarezenko <[email protected]>
12
 * @copyright (c) 2015 - 2016, Dmytro Zarezenko
13
 *
14
 * @git https://github.com/Asymptix/Framework
15
 * @license http://opensource.org/licenses/MIT
16
 */
17
class DBPreparedQuery extends DBQuery {
18
19
    /**
20
     * DB query template.
21
     *
22
     * @var string
23
     */
24
    public $query = "";
25
26
    /**
27
     * Parameters SQL types string ("idsb").
28
     *
29
     * @var string
30
     */
31
    public $types = "";
32
33
    /**
34
     * List of the DB SQL query parameters.
35
     *
36
     * @var array
37
     */
38
    public $params = [];
39
40
41
    /* Service variables */
42
43
    /**
44
     * Creates and initialize DBPreparedQuery object.
45
     *
46
     * @param string $query DB SQL query template.
47
     * @param string $types Parameters SQL types string ("idsb").
48
     * @param array $params List of the DB SQL query parameters.
49
     */
50
    public function __construct($query = "", $types = "", $params = []) {
51
        $this->query = $query;
52
        $this->types = $types;
53
        $this->params = $params;
54
55
        if (!empty($this->query)) {
56
            $this->type = $this->detectType();
57
        }
58
        parent::__construct($this->type);
59
    }
60
61
    /**
62
     * Verify if current DBPreparedQuery is have parameters for binding.
63
     *
64
     * @return bool
65
     */
66
    public function isBindable() {
67
        return ($this->params != null && count($this->params) > 0);
68
    }
69
70
    /**
71
     * Verify if current DBPreparedQuery is valid for the execution.
72
     *
73
     * @return bool
74
     */
75
    public function isValid() {
76
        self::checkParameterTypes($this->params, $this->types);
77
78
        return true;
79
    }
80
81
    /**
82
     * Executes SQL query.
83
     *
84
     * @param bool $debug Debug mode flag.
85
     *
86
     * @return mixed Statement object or FALSE if an error occurred if SELECT
87
     *           query executed or number of affected rows on success if other
88
     *           type of query executed.
89
     */
90
    public function go($debug = false) {
91
        if ($debug) {
92
            $this->debug();
93
        } else {
94
            if ($this->isSelector()) {
95
                return DBCore::doSelectQuery($this);
96
            }
97
98
            return DBCore::doUpdateQuery($this);
0 ignored issues
show
Documentation introduced by
$this is of type this<Asymptix\db\DBPreparedQuery>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
99
        }
100
    }
101
102
    /**
103
     * Shows debug information for the SQL query without execution.
104
     */
105
    public function debug() {
106
        self::showQueryDebugInfo($this->query, $this->types, $this->params);
107
    }
108
109
    /**
110
     * Checks query parameters types correspondence.
111
     *
112
     * @param array $params Parameters of the query.
113
     * @param string $types Types of the parameters ("idsb").
114
     *
115
     * @throws DBCoreException
116
     */
117
    private static function checkParameterTypes($params, $types) {
118
        if (count($params) != strlen($types)) {
119
            throw new DBCoreException(
120
                "Number of types is not equal parameters number"
121
            );
122
        }
123
124
        foreach ($params as $key => $value) {
125
            $type = $types[$key];
126
127
            if (!in_array($type, ['i', 'd', 's', 'b'])) {
128
                throw new DBCoreException(
129
                    "Invalid query parameters types string (type '" . $type .
130
                    "' is undefined, only 'i', 'd', 's' and 'b' types are acceptable)"
131
                );
132
            }
133
134
            $typeByValue = DBField::getType($value);
135
            if ($typeByValue != 's') {
136
                if ($type != $typeByValue && !(
137
                       ($type == 'd' && $typeByValue == 'i') || // We can put integer as double
138
                       ($type == 's' && $typeByValue == 'i') // We can put integer as string
139
                   )
140
                ) {
141
                    throw new DBCoreException(
142
                        "Invalid query parameters types string ('" . $value .
143
                        "' is not '" . $type . "' type but '" . $typeByValue . "' detected)"
144
                    );
145
                }
146
            } else { // in case if we try send non-string parameters as a string value
147
                switch ($type) {
148
                    case 'i':
149
                        if (!(Tools::isNumeric($value) && ((string)(int)$value === $value))) {
150
                            throw new DBCoreException(
151
                                "Invalid query parameters types string ('" . $value . "' is not '" . $type . ")"
152
                            );
153
                        }
154
                        break;
155
                    case 'd':
156
                        if (!Tools::isDoubleString($value)) {
157
                            throw new DBCoreException(
158
                                "Invalid query parameters types string ('" . $value . "' is not '" . $type . ")"
159
                            );
160
                        }
161
                        break;
162
                    case 'b':
163
                        if (!in_array(strtolower($value), ['true', 'false'])) {
164
                            throw new DBCoreException(
165
                                "Invalid query parameters types string ('" . $value . "' is not '" . $type . ")"
166
                            );
167
                        }
168
                        break;
169
                }
170
            }
171
        }
172
    }
173
174
    /**
175
     * Return qwestion marks string for IN(...) SQL construction.
176
     *
177
     * @param int $length Length of the result string.
178
     *
179
     * @return string
180
     */
181
    public static function sqlQMString($length) {
182
        return implode(",", array_fill(0, $length, "?"));
183
    }
184
185
    /**
186
     * Return fields and qwestion marks string for SET field1=?, ... SQL construction.
187
     *
188
     * @param array<mixed> $fieldsList List of the table fields (syntax: array[fieldName] = fieldValue)
189
     * @param string $idFieldName Name of the primary key field.
190
     *
191
     * @return string
192
     */
193
    public static function sqlQMValuesString($fieldsList, $idFieldName = "") {
194
        $chunks = [];
195
        foreach (array_keys($fieldsList) as $fieldName) {
196
            if ($fieldName != $idFieldName) {
197
                $chunks[] = "`" . $fieldName . "` = ?";
198
            }
199
        }
200
201
        return implode(", ", $chunks);
202
    }
203
204
    /**
205
     * Return fields and values string for SET field1=value1, ... SQL construction.
206
     *
207
     * @param array<mixed> $fieldsList List of the table fields (syntax: array[fieldName] = fieldValue)
208
     * @param string $idFieldName Name of the primary key field.
209
     *
210
     * @return string
211
     */
212
    public static function sqlValuesString($fieldsList, $idFieldName) {
213
        $chunks = [];
214
        foreach ($fieldsList as $fieldName => $fieldValue) {
215
            if ($fieldName != $idFieldName) {
216
                $chunks[]= "`" . $fieldName . "` = '" . $fieldValue . "'";
217
            }
218
        }
219
220
        return implode(", ", $chunks);
221
    }
222
223
    /**
224
     * Returns SQL types string.
225
     * Type specification chars:
226
     *    i - corresponding variable has type integer
227
     *    d - corresponding variable has type double
228
     *    s - corresponding variable has type string
229
     *    b - corresponding variable is a blob and will be sent in packets.
230
     *
231
     * @param array<mixed> $fieldsList List of the table fields (syntax: array[fieldName] = fieldValue)
232
     * @param string $idFieldName Name of the primary key field.
233
     * @return string
234
     */
235
    public static function sqlTypesString($fieldsList, $idFieldName = "") {
236
        $typesString = "";
237
        foreach ($fieldsList as $fieldName => $fieldValue) {
238
            if ($fieldName != $idFieldName) {
239
                if (Tools::isDouble($fieldValue)) {
240
                    $typesString.= "d";
241
                } elseif (Tools::isInteger($fieldValue)) {
242
                    $typesString.= "i";
243
                } else {
244
                    $typesString.= "s";
245
                }
246
            }
247
        }
248
249
        return $typesString;
250
    }
251
252
    /**
253
     * Returns SQL types string of single type.
254
     *
255
     * @param string $type SQL type.
256
     * @param int $length Length of the SQL types string.
257
     *
258
     * @return string
259
     * @throws DBFieldTypeException If invalid type passed.
260
     */
261
    public static function sqlSingleTypeString($type, $length) {
262
        $type = DBField::castType($type);
263
        $typesString = "";
264
        while ($length > 0) {
265
            $typesString.= $type;
266
            $length--;
267
        }
268
269
        return $typesString;
270
    }
271
272
    /**
273
     * Push values to the DBPreparedQuery SQL query field end.
274
     *
275
     * @param array $values List of pairs key => value or SQL query parts with
276
     *           parameters.
277
     * @param string $separator Join separator.
278
     */
279
    public function sqlPushValues($values, $separator = ", ") {
280
        $chunks = [];
281
        foreach ($values as $fieldName => $fieldValue) {
282
            if (!is_array($fieldValue)) {
283
                if (!is_null($fieldValue)) {
284
                    $chunks[] = $fieldName . " = ?";
285
                    $this->types.= DBField::getType($fieldValue);
286
                    $this->params[] = $fieldValue;
287
                } else {
288
                    $chunks[] = $fieldName;
289
                }
290
            } else {
291
                $condition = $fieldName;
292
                $localParams = $fieldValue;
293
294
                $chunks[] = $condition;
295
                foreach ($localParams as $param) {
296
                    $this->types.= DBField::getType($param);
297
                    $this->params[] = $param;
298
                }
299
            }
300
        }
301
        $this->query.= implode($separator, $chunks);
302
    }
303
304
}
305