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