Completed
Push — master ( 0ea9e7...aef2ed )
by Anton
14s
created

AbstractBuilder::setParameter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 3
dl 0
loc 11
ccs 6
cts 6
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Bluz Framework Component
4
 *
5
 * @copyright Bluz PHP Team
6
 * @link https://github.com/bluzphp/framework
7
 */
8
9
declare(strict_types=1);
10
11
namespace Bluz\Db\Query;
12
13
use Bluz\Proxy\Db;
14
15
/**
16
 * Query Builders classes is responsible to dynamically create SQL queries
17
 * Based on Doctrine QueryBuilder code
18
 *
19
 * @package Bluz\Db\Query
20
 * @link    https://github.com/bluzphp/framework/wiki/Db-Query
21
 * @link    https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Query/QueryBuilder.php
22
 */
23
abstract class AbstractBuilder
24
{
25
    /**
26
     * @var array list of table aliases
27
     */
28
    protected $aliases = [];
29
30
    /**
31
     * @var string the complete SQL string for this query
32
     */
33
    protected $sql;
34
35
    /**
36
     * @var array the array of SQL parts collected
37
     */
38
    protected $sqlParts = [
39
        'select'  => [],
40
        'from'    => [],
41
        'join'    => [],
42
        'set'     => [],
43
        'where'   => null,
44
        'groupBy' => [],
45
        'having'  => null,
46
        'orderBy' => []
47
    ];
48
49
    /**
50
     * @var array the query parameters
51
     */
52
    protected $params = [];
53
54
    /**
55
     * @var array the parameter type map of this query
56
     */
57
    protected $types = [];
58
59
    /**
60
     * Execute this query using the bound parameters and their types
61
     *
62
     * @return integer|string|array
63
     */
64 8
    public function execute()
65
    {
66 8
        return Db::query($this->getSql(), $this->params, $this->types);
67
    }
68
    
69
    /**
70
     * Return the complete SQL string formed by the current specifications
71
     *
72
     * Example
73
     * <code>
74
     *     $sb = new SelectBuilder();
75
     *     $sb
76
     *         ->select('u')
77
     *         ->from('User', 'u');
78
     *     echo $qb->getSql(); // SELECT u FROM User u
79
     * </code>
80
     *
81
     * @return string The SQL query string
82
     */
83
    abstract public function getSql();
84
85
    /**
86
     * Return the complete SQL string formed for use
87
     *
88
     * Example
89
     * <code>
90
     *     $sb = new SelectBuilder();
91
     *     $sb
92
     *         ->select('u')
93
     *         ->from('User', 'u')
94
     *         ->where('id = ?', 42);
95
     *     echo $qb->getQuery(); // SELECT u FROM User u WHERE id = "42"
96
     * </code>
97
     *
98
     * @return string
99
     */
100 7
    public function getQuery()
101
    {
102 7
        $sql = $this->getSql();
103
104 7
        $sql = str_replace('%', '%%', $sql);
105 7
        $sql = str_replace('?', '"%s"', $sql);
106
107
        // replace mask by data
108 7
        return vsprintf($sql, $this->getParameters());
109
    }
110
111
    /**
112
     * Sets a query parameter for the query being constructed
113
     *
114
     * Example
115
     * <code>
116
     *     $sb = new SelectBuilder();
117
     *     $sb
118
     *         ->select('u')
119
     *         ->from('users', 'u')
120
     *         ->where('u.id = :user_id')
121
     *         ->setParameter(':user_id', 1);
122
     * </code>
123
     *
124
     * @param  string|int $key   The parameter position or name
125
     * @param  mixed      $value The parameter value
126
     * @param  integer    $type  PDO::PARAM_*
127
     * @return $this
128
     */
129 9
    public function setParameter($key, $value, $type = \PDO::PARAM_STR)
130
    {
131 9
        if (null == $key) {
132 9
            $key = sizeof($this->params);
133
        }
134
135 9
        $this->params[$key] = $value;
136 9
        $this->types[$key] = $type;
137
138 9
        return $this;
139
    }
140
141
    /**
142
     * Sets a collection of query parameters for the query being constructed
143
     *
144
     * Example
145
     * <code>
146
     *     $sb = new SelectBuilder();
147
     *     $sb
148
     *         ->select('u')
149
     *         ->from('users', 'u')
150
     *         ->where('u.id = :user_id1 OR u.id = :user_id2')
151
     *         ->setParameters([
152
     *             ':user_id1' => 1,
153
     *             ':user_id2' => 2
154
     *         ]);
155
     * </code>
156
     *
157
     * @param  array $params The query parameters to set
158
     * @param  array $types  The query parameters types to set
159
     * @return $this
160
     */
161 1
    public function setParameters(array $params, array $types = [])
162
    {
163 1
        $this->types = $types;
164 1
        $this->params = $params;
165
166 1
        return $this;
167
    }
168
169
    /**
170
     * Gets a (previously set) query parameter of the query being constructed
171
     *
172
     * @param  mixed $key The key (index or name) of the bound parameter
173
     * @return mixed The value of the bound parameter.
174
     */
175 1
    public function getParameter($key)
176
    {
177 1
        return $this->params[$key] ?? null;
178
    }
179
180
    /**
181
     * Gets all defined query parameters for the query being constructed
182
     *
183
     * @return array The currently defined query parameters
184
     */
185 7
    public function getParameters()
186
    {
187 7
        return $this->params;
188
    }
189
190
    /**
191
     * Either appends to or replaces a single, generic query part
192
     *
193
     * The available parts are: 'select', 'from', 'set', 'where',
194
     * 'groupBy', 'having' and 'orderBy'
195
     *
196
     * @param  string       $sqlPartName
197
     * @param  string|array $sqlPart
198
     * @param  bool         $append
199
     * @return $this
200
     */
201 13
    protected function addQueryPart($sqlPartName, $sqlPart, $append = false)
202
    {
203 13
        $isArray = is_array($sqlPart);
204 13
        $isMultiple = is_array($this->sqlParts[$sqlPartName]);
205
206 13
        if ($isMultiple && !$isArray) {
207 3
            $sqlPart = [$sqlPart];
208
        }
209
210 13
        if ($append) {
211 8
            if ($sqlPartName == "orderBy" || $sqlPartName == "groupBy"
212 8
                || $sqlPartName == "select" || $sqlPartName == "set") {
213 4
                foreach ((array)$sqlPart as $part) {
214 4
                    $this->sqlParts[$sqlPartName][] = $part;
215
                }
216 6
            } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) {
217 4
                $key = key($sqlPart);
218 4
                $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key];
219 6
            } elseif ($isMultiple) {
220 6
                $this->sqlParts[$sqlPartName][] = $sqlPart;
221
            } else {
222
                $this->sqlParts[$sqlPartName] = $sqlPart;
223
            }
224
        } else {
225 13
            $this->sqlParts[$sqlPartName] = $sqlPart;
226
        }
227 13
        return $this;
228
    }
229
230
    /**
231
     * Get a query part by its name
232
     *
233
     * @param  string $queryPartName
234
     * @return mixed
235
     */
236 3
    public function getQueryPart($queryPartName)
237
    {
238 3
        return $this->sqlParts[$queryPartName];
239
    }
240
241
    /**
242
     * Reset single SQL part
243
     *
244
     * @param  string $queryPartName
245
     * @return $this
246
     */
247
    protected function resetQueryPart($queryPartName)
248
    {
249
        $this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName])
250
            ? [] : null;
251
252
        return $this;
253
    }
254
255
    /**
256
     * setFromQueryPart
257
     *
258
     * @param  string $table
259
     * @return $this
260
     */
261 11
    protected function setFromQueryPart($table)
262
    {
263 11
        $table = Db::quoteIdentifier($table);
264 11
        return $this->addQueryPart('from', ['table' => $table], false);
265
    }
266
267
    /**
268
     * Prepare condition
269
     *
270
     * <code>
271
     *     $builder->prepareCondition("WHERE id IN (?)", [..,..]);
272
     * </code>
273
     *
274
     * @param  array $args
275
     * @return string
276
     */
277 9
    protected function prepareCondition($args = [])
278
    {
279 9
        $condition = array_shift($args);
280 9
        foreach ($args as &$value) {
281 9
            if (is_array($value)) {
282 1
                $replace = join(',', array_fill(0, sizeof($value), ':REPLACE:'));
283 1
                $condition = preg_replace('/\?/', $replace, $condition, 1);
284 1
                foreach ($value as $part) {
285 1
                    $this->setParameter(null, $part);
286
                }
287
            } else {
288 9
                $this->setParameter(null, $value);
289
            }
290
        }
291
292 9
        $condition = preg_replace('/(\:REPLACE\:)/', '?', $condition);
293
294 9
        return $condition;
295
    }
296
297
    /**
298
     * Gets a string representation of this QueryBuilder which corresponds to
299
     * the final SQL query being constructed.
300
     *
301
     * @return string The string representation of this QueryBuilder.
302
     */
303 1
    public function __toString()
304
    {
305 1
        return $this->getSql();
306
    }
307
}
308