Completed
Push — master ( 229d9d...1c9390 )
by Alberto
01:52
created

QueryGenerator::select()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
c 5
b 1
f 1
dl 0
loc 22
rs 9.2
cc 3
eloc 16
nc 2
nop 3
1
<?php
2
/**
3
 * KumbiaPHP web & app Framework.
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * It is also available through the world-wide-web at this URL:
10
 * http://wiki.kumbiaphp.com/Licencia
11
 * If you did not receive a copy of the license and are unable to
12
 * obtain it through the world-wide-web, please send an email
13
 * to [email protected] so we can send you a copy immediately.
14
 *
15
 * @category   Kumbia
16
 *
17
 * @copyright  2005 - 2016  Kumbia Team (http://www.kumbiaphp.com)
18
 * @license    http://wiki.kumbiaphp.com/Licencia     New BSD License
19
 */
20
namespace Kumbia\ActiveRecord;
21
22
/**
23
 * Generador de codigo SQL.
24
 */
25
class QueryGenerator
26
{
27
    /**
28
     * Construye una consulta select desde una lista de parametros.
29
     *
30
     * @param array  $params parametros de consulta select
31
     *                       where: condiciones where
32
     *                       order: criterio de ordenamiento
33
     *                       fields: lista de campos
34
     *                       join: joins de tablas
35
     *                       group: agrupar campos
36
     *                       having: condiciones de grupo
37
     *                       limit: valor limit
38
     *                       offset: valor offset
39
     * @param string $source
40
     * @param string $type
41
     *
42
     * @return string
43
     */
44
    public static function select($source, $type, array $params)
45
    {
46
        $params = array_merge([
47
            'fields' => '*',
48
            'join'   => '',
49
            'limit'  => null,
50
            'offset' => null,
51
            'where'  => null,
52
            'group'  => null,
53
            'having' => null,
54
            'order'  => null,
55
        ], $params);
56
57
        list($where, $group, $having, $order) = static::prepareParam($params);
58
        $sql = "SELECT {$params['fields']} FROM $source {$params['join']} $where $group $having $order";
59
60
        if (!is_null($params['limit']) || !is_null($params['offset'])) {
61
            $sql = self::query($type, 'limit', $sql, $params['limit'], $params['offset']);
62
        }
63
64
        return $sql;
65
    }
66
67
    /**
68
     * Permite construir el WHERE, GROUP BY, HAVING y ORDER BY de una cosnulta SQL
69
     * en base a los parametros $param.
70
     *
71
     * @param array $params
72
     */
73
    protected static function prepareParam(array $params)
74
    {
75
        return [
76
            static::where($params['where']),
77
            static::group($params['group']),
78
            static::having($params['having']),
79
            static::order($params['order']),
80
        ];
81
    }
82
83
    /**
84
     * Genera una sentencia where.
85
     *
86
     * @return string
87
     */
88
    protected static function where($where)
89
    {
90
        return empty($where)  ? '' : "WHERE $where";
91
    }
92
93
    /**
94
     * Genera una sentencia GROUP.
95
     *
96
     * @return string
97
     */
98
    protected static function group($group)
99
    {
100
        return empty($group)  ? '' : "GROUP BY $group";
101
    }
102
103
    /**
104
     * Genera una sentencia HAVING.
105
     *
106
     * @return string
107
     */
108
    protected static function having($having)
109
    {
110
        return empty($having)  ? '' : "HAVING $having";
111
    }
112
113
    /**
114
     * Genera una sentencia ORDER BY.
115
     *
116
     * @return string
117
     */
118
    protected static function order($order)
119
    {
120
        return empty($order)  ? '' : "ORDER BY $order";
121
    }
122
123
    /**
124
     * Construye una consulta INSERT.
125
     *
126
     * @param \Kumbia\ActiveRecord\LiteRecord $model Modelo a actualizar
127
     * @param array                           $data  Datos pasados a la consulta preparada
128
     *
129
     * @return string
130
     */
131
    public static function insert(\Kumbia\ActiveRecord\LiteRecord $model, &$data)
132
    {
133
        $meta = $model::metadata();
134
        $data = [];
135
        $columns = [];
136
        $values = [];
137
138
        // Preparar consulta
139
        foreach ($meta->getFieldsList() as $field) {
140
            $columns[] = $field;
141
            static::insertField($field, $model, $data, $values);
142
        }
143
        $columns = \implode(',', $columns);
144
        $values = \implode(',', $values);
145
        $source = $model::getSource();
146
147
        return "INSERT INTO $source ($columns) VALUES ($values)";
148
    }
149
150
    /**
151
     * Agrega un campo a para generar una consulta preparada para un INSERT.
152
     *
153
     * @param string     $field  Nombre del campo
154
     * @param LiteRecord $model  valor del campo
155
     * @param array      $data   array de datos
156
     * @param array      $values array de valores
157
     *
158
     * @return void
159
     */
160
    protected static function insertField($field, LiteRecord $model, array &$data, array &$values)
161
    {
162
        $meta = $model::metadata();
163
        $withDefault = $meta->getWithDefault();
0 ignored issues
show
Unused Code introduced by
$withDefault is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
164
        $autoFields = $meta->getAutoFields();
0 ignored issues
show
Unused Code introduced by
$autoFields is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
165
        if (self::haveValue($model, $field)) {
166
            $data[":$field"] = $model->$field;
167
            $values[] = ":$field";
168
        } else{//if (!\in_array($field, $withDefault) && !\in_array($field, $autoFields)) {
169
            $values[] = 'NULL';
170
        }
171
    }
172
173
    /**
174
     * Permite conocer si la columna debe definirse como nula.
175
     *
176
     * @param LiteRecord $model
177
     * @param string     $field
178
     *
179
     * @return bool
180
     */
181
    protected static function haveValue(LiteRecord $model, $field)
182
    {
183
        return isset($model->$field) && $model->$field !== '';
184
    }
185
186
    /**
187
     * Construye una consulta UPDATE.
188
     *
189
     * @param \Kumbia\ActiveRecord\LiteRecord $model Modelo a actualizar
190
     * @param array                           $data  Datos pasados a la consulta preparada
191
     *
192
     * @return string
193
     */
194
    public static function update(\Kumbia\ActiveRecord\LiteRecord $model, array &$data)
195
    {
196
        $set = [];
197
        $pk = $model::getPK();
198
        /*elimina la clave primaria*/
199
        $list = array_diff($model::metadata()->getFieldsList(), [$pk]);
200
        foreach ($list as $field) {
201
            $value = isset($model->$field) ? $model->$field : null;
202
            static::updateField($field, $value, $data, $set);
203
        }
204
        $set = \implode(', ', $set);
205
        $source = $model::getSource();
206
        $data[":$pk"] = $model->$pk;
207
208
        return "UPDATE $source SET $set WHERE $pk = :$pk";
209
    }
210
211
    /**
212
     * Generate SQL for DELETE sentence.
213
     *
214
     * @param string $source source
215
     * @param string $where  condition
216
     *
217
     * @return string SQL
218
     */
219
    public static function deleteAll($source, $where)
220
    {
221
        return "DELETE FROM $source ".static::where($where);
222
    }
223
224
    /**
225
     * Generate SQL for COUNT sentence.
226
     *
227
     * @param string $source source
228
     * @param string $where  condition
229
     *
230
     * @return string SQL
231
     */
232
    public static function count($source, $where)
233
    {
234
        return "SELECT COUNT(*) AS count FROM $source ".static::where($where);
235
    }
236
237
    /**
238
     * Agrega un campo a para generar una consulta preparada para un UPDATE.
239
     *
240
     * @param string $field Nombre del campo
241
     * @param mixed  $value valor
242
     * @param array  $data  array de datos
243
     * @param array  $set   array de valores
244
     *
245
     * @return void
246
     */
247
    protected static function updateField($field, $value, array &$data, array &$set)
248
    {
249
        if (!empty($value)) {
250
            $data[":$field"] = $value;
251
            $set[] = "$field = :$field";
252
        } else {
253
            $set[] = "$field = NULL";
254
        }
255
    }
256
257
    /**
258
     * Construye una consulta UPDATE.
259
     *
260
     * @param string      $model  nombre del modelo a actualizar
261
     * @param array       $fields campos a actualizar
262
     * @param array       $data   Datos pasados a la consulta preparada
263
     * @param string|null $where
264
     *
265
     * @todo ¿Hay que escapar los nombres de los campos?
266
     *
267
     * @return string
268
     */
269
    public static function updateAll($model, array $fields, array &$data, $where)
270
    {
271
        $set = [];
272
        //$pk = $model::getPK();
273
        /*elimina la clave primaria*/
274
        foreach ($fields as $field => $value) {
275
            static::updateField($field, $value, $data, $set);
276
        }
277
        $set = \implode(', ', $set);
278
        $source = $model::getSource();
279
        $where = static::where(['where' => $where]);
280
281
        return "UPDATE $source SET $set $where";
282
    }
283
284
    /**
285
     * Ejecuta una consulta.
286
     *
287
     * @param string $type           tipo de driver
288
     * @param string $query_function nombre de funcion
289
     *
290
     * @return mixed
291
     * @thow KumbiaException
292
     */
293
    public static function query($type, $query_function)
294
    {
295
        $query_function = "{$type}_{$query_function}";
296
297
        require_once __DIR__."/Query/{$query_function}.php";
298
299
        $args = \array_slice(\func_get_args(), 2);
300
301
        return call_user_func_array(__NAMESPACE__."\\Query\\$query_function", $args);
302
    }
303
}
304