Completed
Push — master ( 1fbf10...df0b8c )
by Vitaly
02:48
created

dbMySQL::profiler()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 24
rs 8.9714
cc 3
eloc 9
nc 3
nop 0
1
<?php
2
namespace samson\activerecord;
3
4
use samsonframework\orm\QueryInterface;
5
use samsonframework\orm\ConditionInterface;
6
7
/**
8
 * Класс описывающий работу с MySQL
9
 * @author Vitaly Iegorov <[email protected]>
10
 * @author Nikita Kotenko <[email protected]>
11
 *
12
 */
13
class dbMySQL extends dbMySQLConnector
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...
14
{
15
    /**
16
     * Количество запросов класса
17
     * @var integer
18
     */
19
    private $query_count = 0;
20
21
    /** Show hide query debug information */
22
    public function debug($flag = true)
23
    {
24
        if ($flag) {
25
            $_SESSION['__AR_SHOW_QUERY__'] = true;
26
        } else {
27
            unset($_SESSION['__AR_SHOW_QUERY__']);
28
        }
29
    }
30
31
    /**
32
     * Check object $field field value as $table column
33
     * and if database table does not have it - create.
34
     * $field is not set in object - error returns
35
     *
36
     * @param object $object Pointer to object to get field names data
37
     * @param string $table Database table name
38
     * @param string $field Object field name
39
     * @param string $type Database column name
40
     *
41
     * @return bool True if database table has field or field has been created
42
     */
43
    public function createField($object, $table, $field, $type = 'INT')
44
    {
45
        // Check if db identifier field is configured
46
        if (class_exists($table, false)) {
47
            if (strlen($object->$field)) {
48
                // Variable to get all social table attributes
49
                $attributes = array();
50
                // Get table attributes - PHP 5.2 compatible
51
                eval('$attributes = ' . $table . '::$_attributes;');
52
53
                // Remove namespaces
54
                $table = classname($table);
0 ignored issues
show
Deprecated Code introduced by
The function classname() has been deprecated with message: use \samson\core\AutoLoader::getOnlyClass()

This function 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 function will be removed from the class and what other function to use instead.

Loading history...
55
56
                // Make keys lowercase
57
                $attributes = array_change_key_case_unicode($attributes);
58
59
                // If table does not have defined identifier field
60
                if (!isset($attributes[strtolower($object->$field)])) {
61
                    // Add identifier field to social users table
62
                    $this->simple_query('ALTER TABLE  `' . $table . '` ADD  `' . $object->$field . '` ' . $type . ' ');
0 ignored issues
show
Deprecated Code introduced by
The method samson\activerecord\dbMySQL::simple_query() has been deprecated with message: Use execute()

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...
63
                }
64
65
                return true;
66
67
            } else { // Signal error
68
                return e('Cannot load "' . get_class($object) . '" module - no $' . $field . ' is configured');
69
            }
70
        }
71
    }
72
73
    // TODO: Очень узкое место для совместимости с 5.2 !!!
74
    /**
75
     * Обратная совместить с PHP < 5.3 т.к. там нельзя подставлять переменное имя класса
76
     * в статическом контексте
77
     * @param unknown_type $class_name
78
     */
79
    public function __get_table_data($class_name)
0 ignored issues
show
Coding Style introduced by
Method name "dbMySQL::__get_table_data" is not in camel caps format
Loading history...
80
    {
81
        // Remove table prefix
82
        $class_name = str_replace(self::$prefix, '', $class_name);
83
84
        // Сформируем правильное имя класса
85
        $class_name = strpos($class_name, '\\') !== false ? $class_name : '\samson\activerecord\\'.$class_name;
86
87
        // Сформируем комманды на получение статических переменных определенного класса
88
        $_table_name = '$_table_name = ' . $class_name . '::$_table_name;';
89
        $_own_group = '$_own_group = ' . $class_name . '::$_own_group;';
90
        $_table_attributes = '$_table_attributes = ' . $class_name . '::$_table_attributes;';
91
        $_primary = '$_primary = ' . $class_name . '::$_primary;';
92
        $_sql_from = '$_sql_from = ' . $class_name . '::$_sql_from;';
93
        $_sql_select = '$_sql_select = ' . $class_name . '::$_sql_select;';
94
        $_attributes = '$_attributes = ' . $class_name . '::$_attributes;';
95
        $_types = '$_types = ' . $class_name . '::$_types;';
96
        $_map = '$_map = ' . $class_name . '::$_map;';
97
        $_relations = '$_relations = ' . $class_name . '::$_relations;';
98
        $_unique = '$_unique = ' . $class_name . '::$_unique;';
99
        $_relation_type = '$_relation_type = ' . $class_name . '::$_relation_type;';
100
        $_relation_alias = '$_relation_alias = ' . $class_name . '::$_relation_alias;';
101
102
        //trace($_table_name.$_primary.$_sql_from.$_sql_select.$_map.$_attributes.$_relations.$_relation_type.$_types.$_unique);
103
104
        // Выполним специальный код получения значений переменной
105
        eval($_own_group . $_table_name . $_primary . $_sql_from . $_sql_select . $_map . $_attributes . $_relations . $_relation_type . $_relation_alias . $_types . $_unique . $_table_attributes);
106
107
        // Вернем массив имен переменных и их значений
108
        return array
109
        (
110
            '_table_name' => $_table_name,
111
            '_own_group' => $_own_group,
112
            '_primary' => $_primary,
113
            '_attributes' => $_attributes,
114
            '_table_attributes' => $_table_attributes,
115
            '_types' => $_types,
116
            '_map' => $_map,
117
            '_relations' => $_relations,
118
            '_relation_type' => $_relation_type,
119
            '_relation_alias' => $_relation_alias,
120
            '_sql_from' => $_sql_from,
121
            '_sql_select' => $_sql_select,
122
            '_unique' => $_unique,
123
        );
124
    }
125
126
    public function create($className, &$object = null)
127
    {
128
        // ??
129
        $fields = $this->getQueryFields($className, $object);
130
        // Build SQL query
131
        $sql = 'INSERT INTO `' . $className::$_table_name . '` (`'
132
            . implode('`,`', array_keys($fields)) . '`)
133
            VALUES (' . implode(',', $fields) . ')';
134
        $this->query($sql);
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

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...
135
        // Return last inserted row identifier
136
        return $this->driver->lastInsertId();
137
    }
138
139
    public function update($className, &$object)
140
    {
141
        // ??
142
        $fields = $this->getQueryFields($className, $object, true);
143
        // Build SQL query
144
        $sql = 'UPDATE `' . $className::$_table_name . '` SET ' . implode(',',
145
                $fields) . ' WHERE ' . $className::$_table_name . '.' . $className::$_primary . '="' . $object->id . '"';
146
        $this->query($sql);
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

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...
147
    }
148
149
    public function delete($className, &$object)
150
    {
151
        // Build SQL query
152
        $sql = 'DELETE FROM `' . $className::$_table_name . '` WHERE ' . $className::$_primary . ' = "' . $object->id . '"';
153
        $this->query($sql);
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

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...
154
    }
155
156
    /**
157
     * @see idb::find()
158
     */
159
    public function &find($class_name, QueryInterface $query)
160
    {
161
        // Результат выполнения запроса
162
        $result = array();
163
164
        if ($query->empty) {
0 ignored issues
show
Bug introduced by
Accessing empty on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
165
            return $result;
166
        }
167
168
        // Get SQL
169
        $sql = $this->prepareSQL($class_name, $query);
170
171
        // Выполним запрос к БД
172
        $db_data = $this->fetch($sql);
0 ignored issues
show
Bug introduced by
It seems like $sql defined by $this->prepareSQL($class_name, $query) on line 169 can also be of type boolean; however, samsonframework\orm\Database::fetch() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
173
174
        //trace($query->virtual_fields);
175
176
        // Выполним запрос к БД и создадим объекты
177
        if ((is_array($db_data)) && (sizeof($db_data) > 0)) {
178
            $result = $this->toRecords($class_name, $db_data, $query->join,
0 ignored issues
show
Bug introduced by
Accessing join on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
179
                array_merge($query->own_virtual_fields, $query->virtual_fields));
0 ignored issues
show
Bug introduced by
Accessing own_virtual_fields on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing virtual_fields on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
180
        }
181
182
        // Вернем коллекцию полученных объектов
183
        return $result;
184
    }
185
186
187
    /**
188
     * @see idb::find_by_id()
189
     */
190
    public function &find_by_id($class_name, $id)
0 ignored issues
show
Coding Style introduced by
Method name "dbMySQL::find_by_id" is not in camel caps format
Loading history...
191
    {
192
        // Получим переменные для запроса
193
        extract($this->__get_table_data($class_name));
0 ignored issues
show
Bug introduced by
$this->__get_table_data($class_name) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
194
195
        // Выполним запрос к БД
196
        $record_data = $this->fetch('SELECT ' . $_sql_select['this'] . ' FROM ' . $_sql_from['this'] . ' WHERE ' . $_table_name . '.' . $_primary . ' = "' . $id . '"');
197
198
        // Если запрос выполнился успешно и получена минимум 1-на запись из БД - создадим объект-запись из неё
199
        $db_records = $this->toRecords($class_name, $record_data);
200
201
        // Переменная для возврата
202
        $ret = null;
203
204
        // Если мы получили 1ю запись то вернем её
205
        if (sizeof($db_records) >= 1) {
206
            $ret = array_shift($db_records);
207
        }
208
209
        // Вернем переменную
210
        return $ret;
211
    }
212
213
    /**
214
     * Выполнить защиту значения поля для его безопасного использования в запросах
215
     *
216
     * @param string $value Значения поля для запроса
217
     * @return string $value Безопасное представление значения поля для запроса
218
     */
219
    protected function protectQueryValue($value)
220
    {
221
        // If magic quotes are on - remove slashes
222
        if (get_magic_quotes_gpc()) {
223
            $value = stripslashes($value);
224
        }
225
226
        // Normally escape string
227
        $value = $this->driver->quote($value);
228
229
        // Return value in quotes
230
        return $value;
231
    }
232
233
    /** @deprecated Use execute() */
234
    public function &simple_query($sql)
0 ignored issues
show
Coding Style introduced by
Method name "dbMySQL::simple_query" is not in camel caps format
Loading history...
235
    {
236
        return $this->query($sql);
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Database::query() has been deprecated with message: Use execute()

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...
237
    }
238
239
    /**
240
     * Prepare create & update SQL statements fields
241
     * @param string $className Entity name
242
     * @param Record $object Database object to get values(if needed)
243
     * @param bool $straight Way of forming SQL field statements
244
     * @return array Collection of key => value with SQL fields statements
245
     */
246
    protected function &getQueryFields($className, & $object = null, $straight = false)
247
    {
248
        // Результирующая коллекция
249
        $collection = array();
250
251
        // Установим флаг получения значений атрибутов из переданного объекта
252
        $use_values = isset($object);
0 ignored issues
show
Unused Code introduced by
$use_values 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...
253
254
        // Переберем "настоящее" имена атрибутов схемы данных для объекта
255
        foreach ($className::$_table_attributes as $attribute => $map_attribute) {
256
            // Отметки времени не заполняем
257
            if ($className::$_types[$attribute] == 'timestamp') {
258
                continue;
259
            }
260
261
            // Основной ключ не заполняем
262
            if ($className::$_primary == $attribute) {
263
                continue;
264
            }
265
266
            // Only add attributes that have value
267
            if ($object->$map_attribute != null) {
268
                $value = $this->driver->quote($object->$map_attribute);
269
                // Добавим значение поля, в зависимости от вида вывывода метода
270
                $collection[$map_attribute] = ($straight ? $className::$_table_name . '.' . $map_attribute . '=' : '') . $value;
271
            }
272
        }
273
274
        // Вернем полученную коллекцию
275
        return $collection;
276
    }
277
278
    /**
279
     * Generic database migration handler
280
     * @param string $classname Class for searching migration methods
281
     * @param string $version_handler External handler for interacting with database version
282
     */
283
    public function migration($classname, $version_handler)
284
    {
285
        if (!is_callable($version_handler)) {
286
            return e('No version handler is passed', E_SAMSON_ACTIVERECORD_ERROR);
287
        }
288
289
        // Get current database version
290
        $version = call_user_func($version_handler);
291
292
        // DB version migrating mechanism
293
        foreach (get_class_methods($classname) as $m) {
294
            // Parse migration method name to get migrating versions
295
            if (preg_match('/^migrate_(?<from>\d+)_to_(?<to>\d+)/i', $m, $matches)) {
296
                $from = $matches['from'];
297
                $to = $matches['to'];
298
299
                // If we found migration method from current db version
300
                if ($from == $version) {
301
                    // Run migration method
302
                    if (call_user_func(array($version_handler[0], $m)) !== false) {
303
                        // Save current version for further migrating
304
                        $version = $to;
305
306
                        // Call database version changing handler
307
                        call_user_func($version_handler, $to);
308
309
                        // Reload page
310
                        elapsed('Database migration from version: ' . $from . ' -> ' . $to);
311
                    } // Break and error
312
                    else {
313
                        e('Database migration from ## -> ## - has Failed', E_SAMSON_ACTIVERECORD_ERROR,
314
                            array($from, $to));
315
                        break;
316
                    }
317
                }
318
            }
319
        }
320
    }
321
322
    /** @see idb::profiler() */
323
    public function profiler()
324
    {
325
        // Выведем список объектов из БД
326
        $list = array();
327
328
        // Общее кво созданных объектов
329
        $total_obj_count = 0;
330
331
        // Переберм коллекции созданных объектов
332
        foreach (dbRecord::$instances as $n => $v) {
333
            // Если для данного класса были созданы объекты
334
            if ($c = sizeof($v)) {
335
                // Увеличим общий счетчик созданных объектов
336
                $total_obj_count += $c;
337
338
                // Выведем имя класса и кво созданных объектов
339
                $list[] = '' . $n . '(' . $c . ')';
340
            }
341
        }
342
343
        // Сформируем строку профайлинга
344
        return 'DB: ' . round($this->elapsed,
345
            3) . 'с, ' . $this->query_count . ' запр., ' . $total_obj_count . ' об.(' . implode($list, ',') . ')';
346
    }
347
348
    /** Count query result */
349
    public function innerCount($className, $query)
350
    {
351
        $params = $this->__get_table_data($className);
352
353
        // Get SQL
354
        $sql = 'SELECT Count(*) as __Count FROM (' .
355
            $this->prepareInnerSQL($className, $query, $params) .
356
            ') as __table';
357
358
        $result = $this->fetch($sql);
359
360
        return $result[0]['__Count'];
361
    }
362
363
    //
364
    // Приватный контекст
365
    //
366
367
    /**
368
     * Create SQL request
369
     *
370
     * @param string $class_name Classname for request creating
371
     * @param QueryInterface $query Query with parameters
372
     * @return string SQL string
373
     */
374
    protected function prepareSQL($class_name, QueryInterface $query)
375
    {
376
        //elapsed( 'dbMySQL::find() Начало');
377
        $params = $this->__get_table_data($class_name);
0 ignored issues
show
Documentation introduced by
$class_name is of type string, but the function expects a object<samson\activerecord\unknown_type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
378
        // Получим переменные для запроса
379
        extract($params);
380
381
        // Текст выборки полей
382
        $select = '`' . $_table_name . '`.*';//$_sql_select['this'];
383
384
        // If virtual fields defined
385 View Code Duplication
        if (sizeof($query->virtual_fields)) {
0 ignored issues
show
Bug introduced by
Accessing virtual_fields on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
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...
386
            $select .= ', ' . "\n" . implode("\n" . ', ', $query->virtual_fields);
0 ignored issues
show
Bug introduced by
Accessing virtual_fields on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
387
        }
388
389
        $from = ' ( ' . $this->prepareInnerSQL($class_name, $query, $params);
390
391
        // Добавим алиас
392
        $from .= ' ) as `' . $_table_name . '`';
393
394
        //trace($query->join);
395
396
        // Iterate related tables
397
        foreach ($query->join as $relation_data) {
0 ignored issues
show
Bug introduced by
Accessing join on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
398
            $c_table = self::$prefix . $relation_data->table;
399
400
            // Если существует требуемая связь
401
            if (isset($_sql_from[$c_table])) {
402
                // Получим текст для выборки данных из связанных таблиц
403
                $select .= ',' . $_sql_select[$c_table];
404
405
                // Получим текст для привязывания таблицы к запросу
406
                $from .= "\n" . ' ' . $_sql_from[$c_table];
407
            } else {
408
                return e('Ошибка! В таблице связей для класса(##), не указана связь с классом(##)',
409
                    E_SAMSON_FATAL_ERROR, array($class_name, $c_table));
410
            }
411
        }
412
413
        // Сформируем строку запроса на поиск записи
414
        $sql = "\n" . 'SELECT ' . $select . "\n" . ' FROM ' . $from;
415
416
        // Получим все условия запроса
417
        $sql .= "\n" . ' WHERE (' . $this->getConditions($query->condition, $class_name) . ')';
0 ignored issues
show
Bug introduced by
Accessing condition on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
418
419
        // Добавим нужные сортировщики
420
        if (sizeof($query->group)) {
0 ignored issues
show
Bug introduced by
Accessing group on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
421
            $sql .= "\n" . ' GROUP BY ' . $query->group[0];
0 ignored issues
show
Bug introduced by
Accessing group on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
422
        }
423
        // Если указана сортировка результатов
424
        if (sizeof($query->order)) {
0 ignored issues
show
Bug introduced by
Accessing order on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
425
            $sql .= "\n" . ' ORDER BY ';
426
            for ($i = 0; $i < sizeof($query->order); $i++) {
0 ignored issues
show
Bug introduced by
Accessing order on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
427
                $item = &$query->order[$i];
0 ignored issues
show
Bug introduced by
Accessing order on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
428
                if (sizeof($item)) {
429
                    $sql .= $item[0] . ' ' . $item[1];
430
                }
431
                if ($i < (sizeof($query->order) - 1)) {
0 ignored issues
show
Bug introduced by
Accessing order on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
432
                    $sql .= ', ';
433
                }
434
            }
435
        }
436
        // Если нужно ограничить к-во записей в выдаче по главной таблице
437 View Code Duplication
        if (sizeof($query->limit)) {
0 ignored issues
show
Bug introduced by
Accessing limit on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
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...
438
            $sql .= "\n" . ' LIMIT ' . $query->limit[0] . (isset($query->limit[1]) ? ',' . $query->limit[1] : '');
0 ignored issues
show
Bug introduced by
Accessing limit on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
439
        }
440
441
        if (isset($GLOBALS['show_sql'])) {
442
            elapsed($sql);
443
        }
444
445
        return $sql;
446
    }
447
448
    protected function prepareInnerSQL($class_name, QueryInterface $query, $params)
449
    {
450
        //trace($class_name);
451
        //print_r($query->own_condition);
452
        // Получим текст цели запроса
453
        $from = 'SELECT ' . $params['_sql_select']['this'];
454
455
        // Если заданны виртуальные поля, добавим для них колонки
456 View Code Duplication
        if (sizeof($query->own_virtual_fields)) {
0 ignored issues
show
Bug introduced by
Accessing own_virtual_fields on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
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...
457
            $from .= ', ' . "\n" . implode("\n" . ', ', $query->own_virtual_fields);
0 ignored issues
show
Bug introduced by
Accessing own_virtual_fields on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
458
        }
459
460
        // From part
461
        $from .= "\n" . ' FROM ' . $params['_sql_from']['this'];
462
463
        // Если существуют условия для главной таблицы в запросе - получим их
464
        if ($query->own_condition->size()) {
0 ignored issues
show
Bug introduced by
Accessing own_condition on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
465
            $from .= "\n" . ' WHERE (' . $this->getConditions($query->own_condition, $class_name) . ')';
0 ignored issues
show
Bug introduced by
Accessing own_condition on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
466
        }
467
468
        // Добавим нужные групировщики
469
        $query->own_group = array_merge($params['_own_group'],
0 ignored issues
show
Bug introduced by
Accessing own_group on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
470
            is_array($query->own_group) ? $query->own_group : array());
0 ignored issues
show
Bug introduced by
Accessing own_group on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
471 View Code Duplication
        if (sizeof($query->own_group)) {
0 ignored issues
show
Bug introduced by
Accessing own_group on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
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...
472
            $from .= "\n" . 'GROUP BY ' . implode(',', $query->own_group);
0 ignored issues
show
Bug introduced by
Accessing own_group on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
473
        }
474
        // Если указана сортировка результатов
475 View Code Duplication
        if (sizeof($query->own_order)) {
0 ignored issues
show
Bug introduced by
Accessing own_order on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
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...
476
            $from .= "\n" . ' ORDER BY ' . $query->own_order[0] . ' ' . $query->own_order[1];
0 ignored issues
show
Bug introduced by
Accessing own_order on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
477
        }
478
        // Если нужно ограничить к-во записей в выдаче по главной таблице
479 View Code Duplication
        if (sizeof($query->own_limit)) {
0 ignored issues
show
Bug introduced by
Accessing own_limit on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
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...
480
            $from .= "\n" . ' LIMIT ' . $query->own_limit[0] . (isset($query->own_limit[1]) ? ',' . $query->own_limit[1] : '');
0 ignored issues
show
Bug introduced by
Accessing own_limit on the interface samsonframework\orm\QueryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
481
        }
482
483
        return $from;
484
    }
485
486
    protected function getConditions(ConditionInterface $cond_group, $class_name)
487
    {
488
        // Соберем сюда все сформированные условия для удобной "упаковки" их в строку
489
        $sql_condition = array();
490
491
        // Переберем все аргументы условий в условной группе условия
492
        foreach ($cond_group as $argument) {
493
            // Если аргумент я вляется группой аргументов, разпарсим его дополнительно
494
            if (is_a($argument, '\samsonframework\orm\ConditionInterface')) {
495
                $sql_condition[] = $this->getConditions($argument, $class_name);
496
            } else {
497
                // Если условие успешно разпознано - добавим его в коллекцию условий
498
                $sql_condition[] = $this->parseCondition($class_name, $argument);
499
            }
500
        }
501
502
        // Соберем все условия условной группы в строку
503
        if (sizeof($sql_condition)) {
504
            return '(' . implode(') ' . $cond_group->relation . ' (', $sql_condition) . ')';
0 ignored issues
show
Bug introduced by
Accessing relation on the interface samsonframework\orm\ConditionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
505
        } // Вернем то что получилось
506
        else {
507
            return '(1=1)';
508
        }
509
    }
510
511
    /**
512
     * "Правильно" разпознать переданный аргумент условия запроса к БД
513
     *
514
     * @param string $class_name Схема сущности БД для которой данные условия
515
     * @param Argument $arg Аругемнт условия для преобразования
516
     * @return string Возвращает разпознанную строку с условием для MySQL
517
     */
518
    protected function parseCondition($class_name, & $arg)
519
    {
520
        // Получим переменные для запроса
521
        extract($this->__get_table_data($class_name));
0 ignored issues
show
Bug introduced by
$this->__get_table_data($class_name) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
Documentation introduced by
$class_name is of type string, but the function expects a object<samson\activerecord\unknown_type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
522
523
        // Получим "правильное" имя аттрибута сущности и выделим постоянную часть условия
524
        $sql_cond_t = isset($_map[$arg->field]) ? $_map[$arg->field] : $arg->field;
525
526
        // Если аргумент условия - это НЕ массив - оптимизации по более частому условию
527
        if (!is_array($arg->value)) {
528
            // NULL condition
529
            if ($arg->relation === dbRelation::NOTNULL || $arg->relation === dbRelation::ISNULL) {
530
                return $sql_cond_t . $arg->relation;
531
            } // Own condition
532
            else {
533
                if ($arg->relation === dbRelation::OWN) {
534
                    return $arg->field;
535
                } // Regular condition
536
                else {
537
                    return $sql_cond_t . $arg->relation . $this->protectQueryValue($arg->value);
538
                }
539
            }
540
        } // Если аргумент условия - это массив и в нем есть значения
541
        else {
542
            if (sizeof($arg->value)) {
543
                // TODO: Add other numeric types support
544
                // TODO: Get types of joined tables fields
545
546
                // Generate list of values, integer type optimization
547
                $sql_values = isset($class_name::$_types[$arg->field]) && $class_name::$_types[$arg->field] == 'int'
548
                    ? ' IN (' . implode(',', $arg->value) . ')'
549
                    : ' IN ("' . implode('","', $arg->value) . '")';
550
551
                switch ($arg->relation) {
552
                    case dbRelation::EQUAL:
553
                        return $sql_cond_t . $sql_values;
554
                    case dbRelation::NOT_EQUAL:
555
                        return $sql_cond_t . ' NOT ' . $sql_values;
556
                }
557
            }
558
        }
559
    }
560
561
562
    /**
563
     * Create object instance by specified parameters
564
     * @param string $className Object class name
565
     * @param RelationData $metaData Object metadata for creation and filling
0 ignored issues
show
Bug introduced by
There is no parameter named $metaData. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
566
     * @param array $dbData Database record with object data
567
     *
568
     * @return idbRecord Database record object instance
569
     */
570
    public function &createObject(
571
        $className,
572
        $identifier,
573
        array & $attributes,
574
        array & $dbData,
575
        array & $virtualFields = array()
576
    )
0 ignored issues
show
Coding Style introduced by
There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found newline
Loading history...
577
    {
578
        // If this object instance is not cached
579
        if (!isset(dbRecord::$instances[$className][$identifier]) || isset($dbData['__Count']) || sizeof($virtualFields)) {
580
581
            // Create empry dbRecord ancestor and store it to cache
582
            dbRecord::$instances[$className][$identifier] = new $className();
583
584
            // Pointer to object
585
            $object = &dbRecord::$instances[$className][$identifier];
586
587
            // Set object identifier
588
            $object->id = $identifier;
589
590
            // Fix object connection with DB record
591
            $object->attached = true;
592
593
            // Fill object attributes
594
            foreach ($attributes as $lc_field => $field) {
595
                $object->$lc_field = $dbData[$field];
596
            }
597
598
            // Fill virtual fields
599
            foreach ($virtualFields as $alias => $virtual_field) {
600
                // If DB record contains virtual field data
601
                if (isset($dbData[$alias])) {
602
                    $object->$alias = $dbData[$alias];
603
                }
604
            }
605
606
            return $object;
607
608
        } else { // Get object instance from cache
609
            return dbRecord::$instances[$className][$identifier];
610
        }
611
    }
612
613
    /**
614
     * Преобразовать массив записей из БД во внутреннее представление dbRecord
615
     * @param string $class_name Имя класса
616
     * @param array $response Массив записей полученных из БД
617
     * @return array Коллекцию записей БД во внутреннем формате
618
     * @see dbRecord
619
     */
620
    protected function &toRecords($class_name, array & $response, array $join = array(), array $virtual_fields = array())
621
    {
622
        // Сформируем правильное имя класса
623
        $class_name = ns_classname($class_name, 'samson\activerecord');
0 ignored issues
show
Deprecated Code introduced by
The function ns_classname() has been deprecated with message: use \samson\core\AutoLoader::className() and pass full class name to it without splitting into class name and namespace

This function 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 function will be removed from the class and what other function to use instead.

Loading history...
624
625
        // Результирующая коллекция полученных записей из БД
626
        $collection = array();
627
628
        // Получим переменные для запроса
629
        extract($this->__get_table_data($class_name));
0 ignored issues
show
Bug introduced by
$this->__get_table_data($class_name) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
Documentation introduced by
$class_name is of type string, but the function expects a object<samson\activerecord\unknown_type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
630
631
        // Generate table metadata for joined tables
632
        $joinedTableData = array();
633
        foreach ($join as $relationData) {
634
635
            // Generate full joined table name(including prefix)
636
            $joinTable = self::$prefix . $relationData->table;
637
638
            // Get real classname of the table without alias
639
            $tableName = $_relation_alias[$joinTable];
640
641
            // Get joined table class metadata
642
            $joinedTableData[$tableName] = $this->__get_table_data($tableName);
643
        }
644
645
        // Получим имя главного
646
        $main_primary = $_primary;
647
648
        // Перебем массив полученных данных от БД - создадим для них объекты
649
        $records_count = sizeof($response);
650
651
        // Идентификатор текущего создаваемого объекта
652
        $main_id = isset($response[0]) ? $response[0][$main_primary] : 0;
653
654
        // Указатель на текущий обрабатываемый объект
655
        $main_obj = null;
656
657
        // Переберем полученные записи из БД
658
        for ($i = 0; $i < $records_count; $i++) {
659
            // Строка данных полученная из БД
660
            $db_row = &$response[$i];
661
662
            // Get object instance
663
            $collection[$main_id] = &$this->createObject($class_name, $main_id, $_attributes, $db_row, $virtual_fields);
664
665
            // Pointer to main object
666
            $main_obj = &$collection[$main_id];
667
668
            // Выполним внутренний перебор строк из БД начиная с текущей строки
669
            // Это позволит нам розабрать объекты полученные со связью один ко многим
670
            // А если это связь 1-1 то цикл выполниться только один раз
671
            for ($j = $i; $j < $records_count; $j++) {
672
                // Строка данных полученная из БД
673
                $db_inner_row = &$response[$j];
674
675
                // Получим идентфиикатор главного объекта в текущей строче БД
676
                $obj_id = $db_inner_row[$main_primary];
677
678
                // Если в строке из БД новый идентификатор
679
                if ($obj_id != $main_id) {
680
                    // Установим новый текущий идентификатор материала
681
                    $main_id = $obj_id;
682
683
                    // Установим индекс главного цикла на строку с новым главным элементом
684
                    // учтем что главный цикл сам увеличит на единицу индекс
685
                    $i = $j - 1;
686
687
                    //trace(' - Найден новый объект на строке №'.$j.'-'.$db_inner_row[$main_primary]);
688
689
                    // Прервем внутренний цикл
690
                    break;
691
                }
692
                //else trace(' + Заполняем данные из строки №'.$j);
693
694
                // Переберем все присоединенные таблицы в запросе
695
                foreach ($join as $relation_data) {
696
                    /**@var \samson\activerecord\RelationData $relation_data */
697
698
                    // If this table is not ignored
699
                    if (!$relation_data->ignore) {
700
701
                        // TODO: Prepare all data in RelationObject to speed up this method
702
703
                        $join_name = $relation_data->relation;
704
705
                        $join_table = self::$prefix . $relation_data->table;
706
707
                        //trace('Filling related table:'.$join_name.'/'.$join_table);
708
709
                        // Get real classname of the table without alias
710
                        $_relation_name = $_relation_alias[$join_table];
711
                        $join_class = str_replace(self::$prefix, '', $relation_data->table);
712
713
                        // Get joined table metadata from previously prepared object
714
                        $r_data = $joinedTableData[$_relation_name];
715
716
                        // Try to get identifier
717
                        if (isset($_relations[$join_table][$r_data['_primary']])) {
718
                            $r_obj_id_field = $_relations[$join_table][$r_data['_primary']];
719
                        } // Получим имя ключевого поля связанного объекта
720
                        else {
721
                            e('Cannot find related table(##) primary field(##) description',
722
                                E_SAMSON_ACTIVERECORD_ERROR, array($join_table, $r_data['_primary']));
723
                        }
724
725
                        // Если задано имя ключевого поля связанного объекта - создадим его
726
                        if (isset($db_inner_row[$r_obj_id_field])) {
727
                            // Получим ключевое поле связанного объекта
728
                            $r_obj_id = $db_inner_row[$r_obj_id_field];
729
730
                            // Get joined object instance
731
                            $r_obj = &$this->createObject($join_name, $r_obj_id, $_relations[$join_table],
732
                                $db_inner_row);
733
734
                            // Call handler for object filling
735
                            $r_obj->filled();
736
737
                            // TODO: Это старый подход - сохранять не зависимо от алиаса под реальным именем таблицы
738
739
                            // Если связанный объект привязан как один-к-одному - просто довами ссылку на него
740
                            if ($_relation_type[$join_table] == 0) {
741
                                $main_obj->onetoone['_' . $join_table] = $r_obj;
742
                                $main_obj->onetoone['_' . $join_class] = $r_obj;
743
                            } // Иначе создадим массив типа: идентификатор -> объект
744
                            else {
745
                                $main_obj->onetomany['_' . $join_table][$r_obj_id] = $r_obj;
746
                                $main_obj->onetomany['_' . $join_class][$r_obj_id] = $r_obj;
747
                            }
748
                        }
749
                    }
750
                }
751
            }
752
753
            // Call handler for object filling
754
            $main_obj->filled();
755
756
            // Если внутренний цикл дошел до конца остановим главный цикл
757
            if ($j == $records_count) {
758
                break;
759
            }
760
        }
761
762
        // Вернем то что у нас вышло
763
        return $collection;
764
    }
765
}
766