Completed
Push — master ( 3be506...1c2175 )
by joanhey
01:57
created

lib/Kumbia/ActiveRecord/ActiveRecord.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
 * Implementación de patrón ActiveRecord con ayudantes de consultas sql.
24
 */
25
class ActiveRecord extends LiteRecord implements \JsonSerializable
26
{
27
28
    const BELONG_TO = 1;
29
    const HAS_MANY = 2;
30
    const HAS_ONE = 3;
31
32
    /**
33
     * Describe the relationships
34
     * @var array
35
     */
36
    protected static $relations = [];
37
38
    public static function resolver($relations, $obj)
39
    {
40
        $model = $relations->model;
41
        if ($relations->type === self::HAS_MANY) {
42
            return $model::allBy($relations->via, $obj->pk());
43
        }
44
        return $model::first($relations->via, $obj->pk());
45
    }
46
47 View Code Duplication
    public static function hasMany($name, $class, $via = null)
48
    {
49
        $str = strtolower($name);
50
        $name = static::getTable();
51
        static::$relations[$str] = (object) [
52
            'model' => $class,
53
            'type' => self::HAS_MANY,
54
            'via' => $via ? $via : "{$name}_id",
55
        ];
56
    }
57
58 View Code Duplication
    public static function hasOne($name, $class, $via = null)
0 ignored issues
show
This method seems to be duplicated in 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...
59
    {
60
        $str = strtolower($name);
61
        $name = static::getTable();
62
        static::$relations[$str] = (object) [
63
            'model' => $class,
64
            'type' => self::HAS_ONE,
65
            'via' => $via ? $via : "{$name}_id",
66
        ];
67
    }
68
69
    /**
70
     * json_encode() method
71
     */
72
    public function jsonSerialize()
73
    {
74
        return $this; //TODO: populate relations before
75
    }
76
77
    public function __get($key)
78
    {
79
80
        if ($this->$key) {
81
            return $this->$key;
82
        }
83
        //it's a relationship
84
        if (isset(static::$relations[$key])) {
85
            $this->populate($key);
86
            return $this->$key;
87
        }
88
        return null; //TODO: change for error
89
    }
90
91
    protected static function getRelationship($rel)
92
    {
93
        if (!isset(static::$relations[$rel])) {
94
            throw new \RuntimeException("Invalid relationship '$rel'", 500);
95
        }
96
97
        return static::$relations[$rel];
98
    }
99
100
    public function populate($rel)
101
    {
102
        $relations = static::getRelationship($rel);
103
        $this->$rel = static::resolver($relations, $this);
104
    }
105
106
    /**
107
     * Pagination of Results
108
     * @param  Array  $params   [description]
109
     * @param  Array  $values   [description]
110
     * @param  integer $page     [description]
111
     * @param  integer $per_page [description]
112
     * @return Paginator            [description]
113
     */
114
    public static function pagination($params = [], $values = [], $page = 1, $per_page = 10)
115
    {
116
        $model = get_called_class();
117
        unset($params['limit'], $params['offset']);
118
        $sql = QueryGenerator::select($model::getSource(), $model::getDriver(), $params);
119
        return new Paginator($model, $sql, $page, $per_page, $values);
120
    }
121
122
    /**
123
     * Actualizar registros.
124
     *
125
     * @param array  $fields
126
     * @param string $where  condiciones
127
     * @param array  $values valores para condiciones
128
     *
129
     * @return int numero de registros actualizados
130
     */
131 View Code Duplication
    public static function updateAll(array $fields, $where = null, array $values = [])
132
    {
133
        if ($values !== null && !is_array($values)) {
134
            $values = \array_slice(\func_get_args(), 2);
135
        }
136
        $sql = QueryGenerator::updateAll(\get_called_class(), $fields, $values, $where);
137
        $sth = self::prepare($sql);
138
        $sth->execute($values);
139
140
        return $sth->rowCount();
141
    }
142
143
    /**
144
     * Eliminar registro.
145
     *
146
     * @param string        $where  condiciones
147
     * @param array |string $values valores
148
     *
149
     * @return int numero de registros eliminados
150
     */
151
    public static function deleteAll($where = null, $values = null)
152
    {
153
        $source = static::getSource();
154
        $sql = QueryGenerator::deleteAll($source, $where);
155
        $sth = self::query($sql, $values);
156
157
        return $sth->rowCount();
158
    }
159
160
    /**
161
     * Elimina caracteres que podrian ayudar a ejecutar
162
     * un ataque de Inyeccion SQL.
163
     *
164
     * @param string $sqlItem
165
     *
166
     * @return string
167
     * @throw KumbiaException
168
     */
169
    public static function sqlItemSanitize($sqlItem)
170
    {
171
        $sqlItem = \trim($sqlItem);
172
        if ($sqlItem !== '' && $sqlItem !== null) {
173
            $sql_temp = \preg_replace('/\s+/', '', $sqlItem);
174
            if (!\preg_match('/^[a-zA-Z0-9_\.]+$/', $sql_temp)) {
175
                throw new \RuntimeException('Se esta tratando de ejecutar una operacion maliciosa!');
176
            }
177
        }
178
179
        return $sqlItem;
180
    }
181
182
    /**
183
     * Obtener la primera coincidencia por el campo indicado.
184
     *
185
     * @param string $field  campo
186
     * @param string $value  valor
187
     * @param array  $params parametros adicionales
188
     *                       order: criterio de ordenamiento
189
     *                       fields: lista de campos
190
     *                       join: joins de tablas
191
     *                       group: agrupar campos
192
     *                       having: condiciones de grupo
193
     *                       offset: valor offset
194
     *
195
     * @return ActiveRecord
196
     */
197 View Code Duplication
    public static function firstBy($field, $value, $params = [])
198
    {
199
        $field = self::sqlItemSanitize($field);
200
        $params['where'] = "$field = ?";
201
202
        return self::first($params, $value);
203
    }
204
205
    /**
206
     * Obtener la primera coincidencia de las condiciones indicadas.
207
     *
208
     * @param array  $params parametros adicionales
209
     *                       order: criterio de ordenamiento
210
     *                       fields: lista de campos
211
     *                       group: agrupar campos
212
     *                       join: joins de tablas
213
     *                       having: condiciones de grupo
214
     *                       offset: valor offset queda
215
     * @param array  $values valores de busqueda
216
     *
217
     * @return ActiveRecord
218
     */
219
    public static function first($params = [], $values = [])
220
    {
221
        $args = func_get_args();
222
        /*Reescribe el limit*/
223
        $args[0]['limit'] = 1;
224
        $res = self::doQuery($args);
225
226
        return $res->fetch();
227
    }
228
229
    /**
230
     * Obtener todos los registros.
231
     *
232
     * @param array $params
233
     *                      where: condiciones where
234
     *                      order: criterio de ordenamiento
235
     *                      fields: lista de campos
236
     *                      join: joins de tablas
237
     *                      group: agrupar campos
238
     *                      having: condiciones de grupo
239
     *                      limit: valor limit
240
     *                      offset: valor offset
241
     * @param array $values valores de busqueda
242
     *
243
     * @return \PDOStatement
244
     */
245
    public static function all($params = [], $values = [])
246
    {
247
        $res = self::doQuery(func_get_args());
248
249
        return $res->fetchAll();
250
    }
251
252
    /**
253
     * Do a query.
254
     *
255
     * @param array $array params of query
256
     *
257
     * @return \PDOStatement|false
258
     */
259
    protected static function doQuery(array $array)
260
    {
261
        $params = self::getParam($array);
262
        $values = self::getValues($array);
263
        $sql = QueryGenerator::select(static::getSource(), static::getDriver(), $params);
264
        $sth = static::query($sql, $values);
265
266
        return $sth;
267
    }
268
269
    /**
270
     * Retorna los parametros para el doQuery.
271
     *
272
     * @param array $array
273
     *
274
     * @return array
275
     */
276
    protected static function getParam(array &$array)
277
    {
278
        $val = array_shift($array);
279
280
        return is_null($val) ? [] : $val;
281
    }
282
283
    /**
284
     * Retorna los values para el doQuery.
285
     *
286
     * @param array $array
287
     *
288
     * @return array
289
     */
290
    protected static function getValues(array $array)
291
    {
292
        return isset($array[0]) ?
293
        is_array($array[0]) ? $array[0] : [$array[0]] : $array;
294
    }
295
296
    /**
297
     * Obtener todas las coincidencias por el campo indicado.
298
     *
299
     * @param string $field  campo
300
     * @param string $value  valor
301
     * @param array  $params
302
     *                       order: criterio de ordenamiento
303
     *                       fields: lista de campos
304
     *                       join: joins de tablas
305
     *                       group: agrupar campos
306
     *                       having: condiciones de grupo
307
     *                       limit: valor limit
308
     *                       offset: valor offset
309
     *
310
     * @return \PDOStatement
311
     */
312 View Code Duplication
    public static function allBy($field, $value, $params = [])
313
    {
314
        $field = self::sqlItemSanitize($field);
315
        $params['where'] = "$field = ?";
316
317
        return self::all($params, $value);
318
    }
319
320
    /**
321
     * Cuenta los registros que coincidan con las condiciones indicadas.
322
     *
323
     * @param string $where  condiciones
324
     * @param array  $values valores
325
     *
326
     * @return int
327
     */
328 View Code Duplication
    public static function count($where = null, $values = null)
329
    {
330
        $source = static::getSource();
331
        $sql = QueryGenerator::count($source, $where);
332
        if ($values !== null && !is_array($values)) {
333
            $values = \array_slice(\func_get_args(), 1);
334
        }
335
        $sth = static::query($sql, $values);
336
337
        return $sth->fetch()->count;
338
    }
339
340
    /**
341
     * Paginar.
342
     *
343
     * @param array $params
344
     * @param int   $page    numero de pagina
345
     * @param int   $perPage cantidad de items por pagina
346
     * @param array $values  valores
347
     *
348
     * @return Paginator
349
     */
350
    public static function paginate(array $params, $page, $perPage, $values = null)
351
    {
352
        unset($params['limit'], $params['offset']);
353
        $sql = QueryGenerator::select(static::getSource(), static::getDriver(), $params);
354
355
        // Valores para consulta
356
        if ($values !== null && !\is_array($values)) {
357
            $values = \array_slice(func_get_args(), 3);
358
        }
359
360
        return new Paginator(\get_called_class(), $sql, (int) $page, (int) $perPage, $values);
361
    }
362
363
    /**
364
     * Obtiene todos los registros de la consulta sql.
365
     *
366
     * @param string         $sql
367
     * @param string | array $values
368
     *
369
     * @return array
370
     */
371 View Code Duplication
    public static function allBySql($sql, $values = null)
372
    {
373
        if (!is_array($values)) {
374
            $values = \array_slice(\func_get_args(), 1);
375
        }
376
377
        return parent::all($sql, $values);
378
    }
379
380
    /**
381
     * Obtiene el primer registro de la consulta sql.
382
     *
383
     * @param string         $sql
384
     * @param string | array $values
385
     *
386
     * @return array
387
     */
388 View Code Duplication
    public static function firstBySql($sql, $values = null)
389
    {
390
        if (!is_array($values)) {
391
            $values = \array_slice(\func_get_args(), 1);
392
        }
393
394
        return parent::first($sql, $values);
395
    }
396
}
397