Completed
Push — master ( 9978ee...7d1f83 )
by Vitaly
10:49
created

dbQuery::__call()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 2
Metric Value
c 4
b 0
f 2
dl 0
loc 25
rs 8.439
cc 5
eloc 16
nc 5
nop 2
1
<?php 
2
namespace samson\activerecord;
3
4
//TODO: Написать метод ALL()
5
//TODO: Поддержка нескольких подключений
6
/**
7
 * Запрос для БД
8
 * Класс собирает в себя все необходимые параметры для 
9
 * формирования "правильного" запроса на самом низком уровне
10
 * работы с БД
11
 * @author Vitaly Iegorov <[email protected]> 
12
 *
13
 */
14
class dbQuery extends \samsonframework\orm\Query
0 ignored issues
show
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
15
{
16
    /**
17
     * Указатель на текущую группу условий с которой работает запрос
18
     *
19
     * @var Condition
20
     */
21
    public $cConditionGroup;
22
23
    /**
24
     * Указатель на соединение с БД
25
     * @var resource
26
     */
27
    public $link;
28
29
    /**
30
     * Указатель на группу условий для текущего объекта с которой работает запрос
31
     *
32
     * @var Condition
33
     */
34
    public $own_condition;
35
36
    /** Limiting filter for base table */
37
    public $own_limit;
38
39
    /** Grouping filter for base table */
40
    public $own_group;
41
42
    /** Sorting filter for base table */
43
    public $own_order;
44
45
    /** Virtual field for base table */
46
    public $own_virtual_fields = array();
47
48
    /** Virtual fields */
49
    public $virtual_fields = array();
50
51
    public $empty = false;
52
53
    /** @var bool True to show requests */
54
    protected $debug = false;
55
56
    /**
57
     * Коллекция условных групп для запроса
58
     * @var dbConditionGroup
59
     */
60
    public $condition;
61
62
    /**
63
     * Параметры ограничения результатов запроса к БД
64
     * @var array
65
     */
66
    public $limit  = array();
67
68
    /**
69
     * Параметры сортировки результатов запроса к БД
70
     * @var array
71
     */
72
    public $order  = array();
73
74
    /**
75
     * Параметры группировки результатов запроса к БД
76
     * @var array
77
     */
78
    public $group  = array();
79
80
    /**
81
     * Коллекция параметров для запроса к связанным объектам
82
     * @var array
83
     */
84
    public $join = array();
85
86
87
    /** */
88
    public function own_limit($st, $en = NULL)
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::own_limit" is not in camel caps format
Loading history...
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
89
    {
90
        $this->own_limit = array($st, $en);
91
        return $this;
92
    }
93
94
    /** */
95
    public function own_group_by($params)
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::own_group_by" is not in camel caps format
Loading history...
96
    {
97
        $this->own_group[] = $params;
98
        return $this;
99
    }
100
101
    /** */
102
    public function own_order_by($field, $direction = 'ASC')
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::own_order_by" is not in camel caps format
Loading history...
103
    {
104
        $this->own_order = array($field,$direction);
105
        return $this;
106
    }
107
108
    /** @see idbQuery::flush() */
109
    public function flush()
110
    {
111
        // Очистим параметры запроса
112
        $this->condition = new Condition();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \samson\activerecord\Condition() of type object<samson\activerecord\Condition> is incompatible with the declared type object<samson\activerecord\dbConditionGroup> of property $condition.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Deprecated Code introduced by
The class samson\activerecord\Condition has been deprecated with message: use \samsonframework\orm\Condition

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
113
        $this->limit = array();
114
        $this->order = array();
115
        $this->group = array();
116
        $this->join = array();
117
118
        $this->own_condition = new Condition();
0 ignored issues
show
Deprecated Code introduced by
The class samson\activerecord\Condition has been deprecated with message: use \samsonframework\orm\Condition

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
119
        $this->own_group = array();
120
        $this->own_virtual_fields = array();
121
        $this->own_limit = array();
122
        $this->own_order = array();
123
124
        $this->cConditionGroup = &$this->condition;
125
    }
126
127
    /** @see idbQuery::random() */
128
    public function random(& $return_value = null)
129
    {
130
        // Add random ordering
131
        $this->order_by('', 'RAND()');
132
133
        // Correctly perform db request for multiple data
134
        return func_num_args() ? $this->exec($return_value) : $this->exec();
135
    }
136
137
138
    /**
139
     * @see idbQuery::or_()
140
     * @deprecated
141
     */
142
    public function or_($relation = 'OR')
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::or_" is not in camel caps format
Loading history...
143
    {
144
        // Получим либо переданную группу условий, либо создадим новую, потом добавим её в массив групп условий запроса
145
        $cond_group = new Condition($relation);
0 ignored issues
show
Deprecated Code introduced by
The class samson\activerecord\Condition has been deprecated with message: use \samsonframework\orm\Condition

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
146
147
        // Установим текущую группу условий с которой работает запрос
148
        $this->cConditionGroup = &$cond_group;
149
150
        // Добавим нову группу условий в коллекцию групп
151
        $this->condition->arguments[] = $cond_group;
152
153
        // Вернем себя для цепирования
154
        return $this;
155
    }
156
157
    /**
158
     * Set debug query mode
159
     * @param bool $value Debug status, true - active
160
     *
161
     * @return $this Chaining
162
     */
163
    public function debug($value = true)
164
    {
165
        db()->debug($this->debug = $value);
166
167
        return $this;
168
    }
169
170
    public function isnull($attribute)
171
    {
172
        return $this->cond($attribute, '', dbRelation::ISNULL);
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::cond() has been deprecated with message: @see self::where()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
173
    }
174
    public function notnull($attribute)
175
    {
176
        return $this->cond($attribute, '', dbRelation::NOTNULL);
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::cond() has been deprecated with message: @see self::where()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
177
    }
178
    public function notempty($attribute)
179
    {
180
        return $this->cond($attribute, '', dbRelation::NOT_EQUAL);
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::cond() has been deprecated with message: @see self::where()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
181
    }
182
    public function like($attribute, $value = '')
183
    {
184
        return $this->cond($attribute, $value, dbRelation::LIKE);
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::cond() has been deprecated with message: @see self::where()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
185
    }
186
187
188
189
    /** @deprecated Use self::fields() */
190
    public function fieldsNew($fieldName, & $return = null)
0 ignored issues
show
Unused Code introduced by
The parameter $fieldName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $return is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
191
    {
192
        return call_user_func_array(array($this, 'fields'), func_get_args());
193
    }
194
195
    /** @see idbQuery::join() */
196
    public function join($tableName, $className = null, $ignore = false)
197
    {
198
        // Добавим имя класса в коллекцию присоединения
199
        $this->join[] = new RelationData($this->class_name, $tableName, $className, $ignore);
200
201
        // Вернем себя для цепирования
202
        return $this;
203
    }
204
205
    /** @see idbQuery::group_by() */
206
    public function group_by($field)
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::group_by" is not in camel caps format
Loading history...
207
    {
208
        // Default grouping array
209
        $destination = &$this->group;
210
211
        // If this field belongs to query main class
212
        //if (property_exists( $this->class_name, $field )) $destination = & $this->own_group;
213
214
        $destination[] = $field;
215
216
        // Вернем себя для цепирования
217
        return $this;
218
    }
219
220
    /** @see idbQuery::limit() */
221
    public function limit($st, $en = NULL, $own = false)
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
222
    {
223
        // Select base table or whole query destination
224
        if ($own) {
225
            $this->own_limit = array($st, $en);
226
        } else {
227
            $this->limit = array($st, $en);
228
        }
229
230
        // Вернем себя для цепирования
231
        return $this;
232
    }
233
234
    /** @see idbQuery::order_by() */
235
    public function order_by($field, $direction = 'ASC')
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::order_by" is not in camel caps format
Loading history...
236
    {
237
        $this->order[] = array($field, $direction);
238
239
        // Вернем себя для цепирования
240
        return $this;
241
    }
242
243
    /** @see idbQuery::add_field() */
244
    public function add_field($field, $alias = null, $own = true)
0 ignored issues
show
Coding Style introduced by
Method name "dbQuery::add_field" is not in camel caps format
Loading history...
245
    {
246
        // Если передан псевдоним для поля, то подставим его
247
        if (isset($alias)) {
248
            $field = $field . ' as ' . $alias;
249
        } else {
250
            $alias = $field;
251
        }
252
253
        // Добавим виртуальное поле
254
        if ($own) {
255
            $this->own_virtual_fields[$alias] = $field;
256
        } else {
257
            $this->virtual_fields[$alias] = $field;
258
        }
259
260
        // Вернем себя для цепирования
261
        return $this;
262
    }
263
264
    /** @see idbQuery::count() */
265
    public function count($field = '*')
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
266
    {
267
        return db()->count($this->class_name, $this);
268
    }
269
270
    /** @see idbQuery::innerCount() */
271
    public function innerCount($field = '*')
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
272
    {
273
        return db()->innerCount($this->class_name, $this);
274
    }
275
276
    /**	@see idbQuery::parse() */
0 ignored issues
show
Coding Style introduced by
Spaces must be used for alignment; tabs are not allowed
Loading history...
277
    public function parse($queryText, array $args = null)
278
    {
279
        // Преобразуем текст в нижний регистр
280
        //$query_text = mb_strtolower( $query_text, 'UTF-8' );
281
282
        // Паттерн для определения метода динамического запроса
283
        $sortingPattern = '
284
		/(?:^(?<method>find_by|find_all_by|all|first|last)_)
285
			|_order_by_  (?P<order>[a-zа-я0-9]+) _ (?P<order_dir>(?:asc|desc))
286
			|_limit_ (?P<limit_start>\d+) (?:_(?P<limit_end>\d+))?
287
			|_group_by_(?P<group>.+)
288
			|_join_ (?<join>.+)
289
		/iux';
290
291
        // Это внутренний счетчик для аргументов запроса для того чтобы не сбиться при их подставлении
292
        // в условие запроса к БД
293
        $argsCnt = 0;
294
295
        // Выполним первоначальный парсинг проверяющий правильность указанного метода
296
        // выборки данных и поиск возможных модификаторов запроса
297
        if (preg_match_all($sortingPattern, $queryText, $globalMatches)) {
298
            // Удалим все пустые группы полученные послке разпознования
299
            $globalMatches = array_filter_recursive($globalMatches);
300
301
            // Получим текст условий самого запроса, убрав из него все возможные модификаторы и параметры
302
            // и переберем только полученные группы условий запроса
303
            foreach (explode('_or_', str_ireplace($globalMatches[0], '', $queryText)) as $groupText) {
304
                // Добавим группу условий к запросу
305
                $this->or_('AND');
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::or_() has been deprecated.

This method has been deprecated.

Loading history...
306
307
                // Переберем поля которые формируют условия запроса - создание объекты-условия запроса
308
                foreach (explode('_and_', $groupText) as $conditionText) {
309
                    $this->cond($conditionText, $args[$argsCnt++]);
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbQuery::cond() has been deprecated with message: @see self::where()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
310
                }
311
            }
312
313
            // Получим сортировку запроса
314
            if (isset($globalMatches['order'])) {
315
                $this->order = array($globalMatches['order'][0], $globalMatches['order_dir'][0]);
316
            }
317
            // Получим ограничения запроса
318
            if (isset($globalMatches['limit_start'])) {
319
                $this->limit = array($globalMatches['limit_start'][0], $globalMatches['limit_end'][0]);
320
            }
321
            // Получим групировку запроса
322 View Code Duplication
            if (isset($globalMatches['group'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
323
                $this->group = explode('_and_', $globalMatches['group'][0]);
324
            }
325
            // Получим имена таблиц для "объединения" в запросе
326 View Code Duplication
            if (isset($globalMatches['join'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
327
                foreach (explode('_and_', $globalMatches['join'][0]) as $join) {
328
                    $this->join($join);
329
                }
330
            }
331
        }
332
333
        // Вернем полученный объект-запрос
334
        return $this;
335
    }
336
337
    /**
338
     * Function to reconfigure dbQuery to work with multiple Entities
339
     *
340
     * @param string $className Entity name
341
     * @deprecated @see \samsonframework\orm\QueryInterface::entity(), full class name with namespace
342
     *                 should be passed.
343
     * @return self|string Chaining or current class name if nothing is passed
344
     */
345
    public function className($className = null)
346
    {
347
        // Old support for not full class names
348
        if (strpos($className, '\\') === false) {
349
            // Add generic namespace
350
            $className = '\samson\activerecord\\'.$className;
351
        }
352
353
        return func_num_args() > 0 ? $this->entity($className) : $this->entity();
354
    }
355
356
    /**
357
     * Add condition by primary field
358
     *
359
     * @param string $value Primary field value
360
     * @return self Chaining
361
     * @deprecated Use direct query with where('PRIMARY_FIELD',...)
362
     */
363
    public function id($value)
364
    {
365
        // PHP 5.2 get primary field
366
        $_primary = null;
367
        eval('$_primary = ' . $this->class_name . '::$_primary;');
368
369
        // Set primary field value
370
        return $this->where($_primary, $value);
371
    }
372
373
    /**
374
     * Add condition to current query.
375
     * This method supports receives three possible types for $fieldName,
376
     * this is deprecated logic and this should be changed to use separate methods
377
     * for each argument type.
378
     *
379
     * @param string|ConditionInterface|ArgumentInterface $fieldName Entity field name
380
     * @param string $fieldValue Value
381
     * @param string $relation Relation between field name and its value
382
     * @deprecated @see self::where()
383
     * @return self Chaining
384
     */
385
    public function cond($fieldName, $fieldValue = null, $relation = '=')
386
    {
387
        // If empty array is passed
388
        if (is_string($fieldName)) {
389
            return $this->where($fieldName, $fieldValue, $relation);
390
        } elseif (is_array($fieldValue) && !sizeof($fieldValue)) {
391
            $this->empty = true;
392
            return $this;
393
        } elseif (is_a($fieldName, __NAMESPACE__.'\ConditionInterface')) {
394
            $this->whereCondition($fieldName);
395
        } elseif (is_a($fieldName, __NAMESPACE__.'\ArgumentInterface')) {
396
            $this->getConditionGroup($fieldName->field)->addArgument($fieldName);
397
        }
398
399
        return $this;
400
    }
401
402
    /**
403
     * Query constructor.
404
     * @param string|null $entity Entity identifier
405
     * @throws EntityNotFound
406
     */
407
    public function __construct($entity = null)
408
    {
409
        // Old support for not full class names
410
        if (strpos($entity, '\\') === false) {
411
            // Add generic namespace
412
            $entity = '\samson\activerecord\\'.$entity;
413
        }
414
415
        // Call parent constructor
416
        parent::__construct($entity, db());
417
    }
418
}
419