Completed
Push — master ( 04c69a...03a792 )
by Alberto
02:37
created

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

Severity

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 $_rs = [];
37
38
    /**
39
     * Store all information about relationship for populate methods
40
     * @var array
41
     */
42
    protected $_populate = [];
43
44
    static function resolver($rs, $obj){
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

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