Completed
Push — master ( 505e1e...ecfb1f )
by Vitaly
16:41
created

dbMySQL::toRecords()   D

Complexity

Conditions 13
Paths 40

Size

Total Lines 145
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 10
Bugs 3 Features 5
Metric Value
cc 13
eloc 51
c 10
b 3
f 5
nc 40
nop 4
dl 0
loc 145
rs 4.9922

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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...
Bug introduced by
There is at least one abstract method in this class. Maybe declare it as abstract, or implement the remaining methods: fetchObjectsWithJoin, insert, update
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)) {
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 . '::$_table_attributes;');
52
                // Get table name - PHP 5.2 compatible
53
                eval('$table = ' . $table . '::$_table_name;');
54
55
                // Make keys lowercase
56
                $attributes = array_change_key_case_unicode($attributes);
57
                $field = strtolower($object->$field);
58
59
                // If table does not have defined identifier field
60
                if (!array_key_exists($field, $attributes) && !in_array($field, $attributes)) {
61
                    // Add identifier field to social users table
62
                    $this->simple_query('ALTER TABLE  `' . $table . '` ADD  `' . $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
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
67
            } else { // Signal error
68
                return e('Cannot load "' . get_class($object) . '" module - no $' . $field . ' is configured');
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

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...
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
135
        // TODO: CRITICAL FOR HIGHLOAD NEEDS DECISION!
136
        $result = $this->execute($sql);
0 ignored issues
show
Unused Code introduced by
$result 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...
137
138
        // Return last inserted row identifier
139
        return $this->driver->lastInsertId();
140
    }
141
142
    public function update_old($className, &$object)
0 ignored issues
show
Coding Style introduced by
Method name "dbMySQL::update_old" is not in camel caps format
Loading history...
143
    {
144
        // ??
145
        $fields = $this->getQueryFields($className, $object, true);
146
        // Build SQL query
147
        $sql = 'UPDATE `' . $className::$_table_name . '` SET ' . implode(',',
148
                $fields) . ' WHERE ' . $className::$_table_name . '.' . $className::$_primary . '="' . $object->id . '"';
149
        $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...
150
    }
151
152
    public function delete($className, &$object)
153
    {
154
        // Build SQL query
155
        $sql = 'DELETE FROM `' . $className::$_table_name . '` WHERE ' . $className::$_primary . ' = "' . $object->id . '"';
156
        $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...
157
    }
158
159
    /**
160
     * @see idb::find()
161
     */
162
    public function &find($class_name, QueryInterface $query)
163
    {
164
        // Результат выполнения запроса
165
        $result = array();
166
167
        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...
168
            return $result;
169
        }
170
171
        // Get SQL
172
        $sql = $this->prepareSQL($class_name, $query);
173
174
        // Выполним запрос к БД
175
        $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 172 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...
176
177
        //trace($query->virtual_fields);
178
179
        // Выполним запрос к БД и создадим объекты
180
        if ((is_array($db_data)) && (sizeof($db_data) > 0)) {
181
            $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...
182
                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...
183
        }
184
185
        // Вернем коллекцию полученных объектов
186
        return $result;
187
    }
188
189
190
    /**
191
     * @see idb::find_by_id()
192
     */
193
    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...
194
    {
195
        // Получим переменные для запроса
196
        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...
197
198
        // Выполним запрос к БД
199
        $record_data = $this->fetch('SELECT ' . $_sql_select['this'] . ' FROM ' . $_sql_from['this'] . ' WHERE ' . $_table_name . '.' . $_primary . ' = "' . $id . '"');
200
201
        // Если запрос выполнился успешно и получена минимум 1-на запись из БД - создадим объект-запись из неё
202
        $db_records = $this->toRecords($class_name, $record_data);
203
204
        // Переменная для возврата
205
        $ret = null;
206
207
        // Если мы получили 1ю запись то вернем её
208
        if (sizeof($db_records) >= 1) {
209
            $ret = array_shift($db_records);
210
        }
211
212
        // Вернем переменную
213
        return $ret;
214
    }
215
216
    /**
217
     * Выполнить защиту значения поля для его безопасного использования в запросах
218
     *
219
     * @param string $value Значения поля для запроса
220
     * @return string $value Безопасное представление значения поля для запроса
221
     */
222
    protected function protectQueryValue($value)
223
    {
224
        // If magic quotes are on - remove slashes
225
        if (get_magic_quotes_gpc()) {
226
            $value = stripslashes($value);
227
        }
228
229
        // Normally escape string
230
        $value = $this->driver->quote($value);
231
232
        // Return value in quotes
233
        return $value;
234
    }
235
236
    /** @deprecated Use execute() */
237
    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...
238
    {
239
        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...
240
    }
241
242
    /**
243
     * Prepare create & update SQL statements fields
244
     * @param string $className Entity name
245
     * @param Record $object Database object to get values(if needed)
246
     * @param bool $straight Way of forming SQL field statements
247
     * @return array Collection of key => value with SQL fields statements
248
     */
249
    protected function &getQueryFields($className, & $object = null, $straight = false)
250
    {
251
        // Результирующая коллекция
252
        $collection = array();
253
254
        // Установим флаг получения значений атрибутов из переданного объекта
255
        $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...
256
257
        // Переберем "настоящее" имена атрибутов схемы данных для объекта
258
        foreach ($className::$_table_attributes as $attribute => $map_attribute) {
259
            // Отметки времени не заполняем
260
            if ($className::$_types[$map_attribute] == 'timestamp') {
261
                continue;
262
            }
263
264
            // Основной ключ не заполняем
265
            if ($className::$_primary == $attribute) {
266
                continue;
267
            }
268
269
            // Only add attributes that have value
270
            $value = $object->$attribute !== null ?
271
                (is_numeric($object->$attribute)? $object->$attribute : $this->driver->quote($object->$attribute))
272
                : 'NULL';
273
274
            // Добавим значение поля, в зависимости от вида вывывода метода
275
            $collection[$map_attribute] = ($straight ? $className::$_table_name . '.' . $map_attribute . '=' : '') . $value;
276
        }
277
278
        // Вернем полученную коллекцию
279
        return $collection;
280
    }
281
282
    /**
283
     * Generic database migration handler
284
     * @param string $classname Class for searching migration methods
285
     * @param string $version_handler External handler for interacting with database version
286
     */
287
    public function migration($classname, $version_handler)
288
    {
289
        if (!is_callable($version_handler)) {
290
            return e('No version handler is passed', E_SAMSON_ACTIVERECORD_ERROR);
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

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...
291
        }
292
293
        // Get current database version
294
        $version = call_user_func($version_handler);
295
296
        // DB version migrating mechanism
297
        foreach (get_class_methods($classname) as $m) {
298
            // Parse migration method name to get migrating versions
299
            if (preg_match('/^migrate_(?<from>\d+)_to_(?<to>\d+)/i', $m, $matches)) {
300
                $from = $matches['from'];
301
                $to = $matches['to'];
302
303
                // If we found migration method from current db version
304
                if ($from == $version) {
305
                    // Run migration method
306
                    if (call_user_func(array($version_handler[0], $m)) !== false) {
307
                        // Save current version for further migrating
308
                        $version = $to;
309
310
                        // Call database version changing handler
311
                        call_user_func($version_handler, $to);
312
313
                        // Reload page
314
                        elapsed('Database migration from version: ' . $from . ' -> ' . $to);
315
                    } // Break and error
316
                    else {
317
                        e('Database migration from ## -> ## - has Failed', E_SAMSON_ACTIVERECORD_ERROR,
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

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...
318
                            array($from, $to));
319
                        break;
320
                    }
321
                }
322
            }
323
        }
324
    }
325
326
    /** @see idb::profiler() */
327
    public function profiler()
328
    {
329
        // Выведем список объектов из БД
330
        $list = array();
331
332
        // Общее кво созданных объектов
333
        $total_obj_count = 0;
334
335
        // Переберм коллекции созданных объектов
336
        foreach (dbRecord::$instances as $n => $v) {
337
            // Если для данного класса были созданы объекты
338
            if ($c = sizeof($v)) {
339
                // Увеличим общий счетчик созданных объектов
340
                $total_obj_count += $c;
341
342
                // Выведем имя класса и кво созданных объектов
343
                $list[] = '' . $n . '(' . $c . ')';
344
            }
345
        }
346
347
        // Сформируем строку профайлинга
348
        return 'DB: ' . round($this->elapsed,
349
            3) . 'с, ' . $this->query_count . ' запр., ' . $total_obj_count . ' об.(' . implode($list, ',') . ')';
350
    }
351
352
    /** Count query result */
353
    public function innerCount($className, $query)
354
    {
355
        $params = $this->__get_table_data($className);
356
357
        // Get SQL
358
        $sql = 'SELECT Count(*) as __Count FROM (' .
359
            $this->prepareInnerSQL($className, $query, $params) .
360
            ') as __table';
361
362
        $result = $this->fetch($sql);
363
364
        return $result[0]['__Count'];
365
    }
366
367
    //
368
    // Приватный контекст
369
    //
370
371
    /**
372
     * Create SQL request
373
     *
374
     * @param string $class_name Classname for request creating
375
     * @param QueryInterface $query Query with parameters
376
     * @return string SQL string
377
     */
378
    protected function prepareSQL($class_name, QueryInterface $query)
379
    {
380
        //elapsed( 'dbMySQL::find() Начало');
381
        $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...
382
        // Получим переменные для запроса
383
        extract($params);
384
385
        // Текст выборки полей
386
        $select = '`' . $_table_name . '`.*';//$_sql_select['this'];
387
388
        // If virtual fields defined
389 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...
390
            $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...
391
        }
392
393
        $from = ' ( ' . $this->prepareInnerSQL($class_name, $query, $params);
394
395
        // Добавим алиас
396
        $from .= ' ) as `' . $_table_name . '`';
397
398
        //trace($query->join);
399
400
        // Iterate related tables
401
        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...
402
            $c_table = self::$prefix . $relation_data->table;
403
404
            // Если существует требуемая связь
405
            if (isset($_sql_from[$c_table])) {
406
                // Получим текст для выборки данных из связанных таблиц
407
                $select .= ',' . $_sql_select[$c_table];
408
409
                // Получим текст для привязывания таблицы к запросу
410
                $from .= "\n" . ' ' . $_sql_from[$c_table];
411
            } else {
412
                return e('Ошибка! В таблице связей для класса(##), не указана связь с классом(##)',
0 ignored issues
show
Bug Best Practice introduced by
The return type of return e('Ошибка! ...class_name, $c_table)); (boolean) is incompatible with the return type of the parent method samsonframework\orm\Database::prepareSQL of type string|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

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...
413
                    E_SAMSON_FATAL_ERROR, array($class_name, $c_table));
414
            }
415
        }
416
417
        // Сформируем строку запроса на поиск записи
418
        $sql = "\n" . 'SELECT ' . $select . "\n" . ' FROM ' . $from;
419
420
        // Получим все условия запроса
421
        $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...
422
423
        // Добавим нужные сортировщики
424
        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...
425
            $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...
426
        }
427
        // Если указана сортировка результатов
428
        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...
429
            $sql .= "\n" . ' ORDER BY ';
430
            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...
431
                $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...
432
                if (sizeof($item)) {
433
                    $sql .= $item[0] . ' ' . $item[1];
434
                }
435
                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...
436
                    $sql .= ', ';
437
                }
438
            }
439
        }
440
        // Если нужно ограничить к-во записей в выдаче по главной таблице
441 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...
442
            $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...
443
        }
444
445
        if (isset($GLOBALS['show_sql'])) {
446
            elapsed($sql);
447
        }
448
449
        return $sql;
450
    }
451
452
    protected function prepareInnerSQL($class_name, QueryInterface $query, $params)
453
    {
454
        //trace($class_name);
455
        //print_r($query->own_condition);
456
        // Получим текст цели запроса
457
        $from = 'SELECT ' . $params['_sql_select']['this'];
458
459
        // Если заданны виртуальные поля, добавим для них колонки
460 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...
461
            $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...
462
        }
463
464
        // From part
465
        $from .= "\n" . ' FROM ' . $params['_sql_from']['this'];
466
467
        // Если существуют условия для главной таблицы в запросе - получим их
468
        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...
469
            $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...
470
        }
471
472
        // Добавим нужные групировщики
473
        $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...
474
            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...
475 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...
476
            $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...
477
        }
478
        // Если указана сортировка результатов
479 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...
480
            $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...
481
        }
482
        // Если нужно ограничить к-во записей в выдаче по главной таблице
483 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...
484
            $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...
485
        }
486
487
        return $from;
488
    }
489
490
    protected function getConditions(ConditionInterface $cond_group, $class_name)
491
    {
492
        // Соберем сюда все сформированные условия для удобной "упаковки" их в строку
493
        $sql_condition = array();
494
495
        // Переберем все аргументы условий в условной группе условия
496
        foreach ($cond_group as $argument) {
497
            // Если аргумент я вляется группой аргументов, разпарсим его дополнительно
498
            if (is_a($argument, '\samsonframework\orm\ConditionInterface')) {
499
                $sql_condition[] = $this->getConditions($argument, $class_name);
500
            } else {
501
                // Если условие успешно разпознано - добавим его в коллекцию условий
502
                $sql_condition[] = $this->parseCondition($class_name, $argument);
503
            }
504
        }
505
506
        // Соберем все условия условной группы в строку
507
        if (sizeof($sql_condition)) {
508
            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...
509
        } // Вернем то что получилось
510
        else {
511
            return '(1=1)';
512
        }
513
    }
514
515
    /**
516
     * "Правильно" разпознать переданный аргумент условия запроса к БД
517
     *
518
     * @param string $class_name Схема сущности БД для которой данные условия
519
     * @param Argument $arg Аругемнт условия для преобразования
520
     * @return string Возвращает разпознанную строку с условием для MySQL
521
     */
522
    protected function parseCondition($class_name, & $arg)
523
    {
524
        // Получим переменные для запроса
525
        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...
526
527
        // Получим "правильное" имя аттрибута сущности и выделим постоянную часть условия
528
        $sql_cond_t = isset($_map[$arg->field]) ? $_map[$arg->field] : $arg->field;
529
530
        // Если аргумент условия - это НЕ массив - оптимизации по более частому условию
531
        if (!is_array($arg->value)) {
532
            // NULL condition
533
            if ($arg->relation === dbRelation::NOTNULL || $arg->relation === dbRelation::ISNULL) {
534
                return $sql_cond_t . $arg->relation;
535
            } // Own condition
536
            else {
537
                if ($arg->relation === dbRelation::OWN) {
538
                    return $arg->field;
539
                } // Regular condition
540
                else {
541
                    return $sql_cond_t . $arg->relation . $this->protectQueryValue($arg->value);
542
                }
543
            }
544
        } // Если аргумент условия - это массив и в нем есть значения
545
        else {
546
            if (sizeof($arg->value)) {
547
                // TODO: Add other numeric types support
548
                // TODO: Get types of joined tables fields
549
550
                // Generate list of values, integer type optimization
551
                $sql_values = isset($class_name::$_types[$arg->field]) && $class_name::$_types[$arg->field] == 'int'
552
                    ? ' IN (' . implode(',', $arg->value) . ')'
553
                    : ' IN ("' . implode('","', $arg->value) . '")';
554
555
                switch ($arg->relation) {
556
                    case dbRelation::EQUAL:
557
                        return $sql_cond_t . $sql_values;
558
                    case dbRelation::NOT_EQUAL:
559
                        return $sql_cond_t . ' NOT ' . $sql_values;
560
                }
561
            } else { // If we received a condition with empty array - consider this as failing condition
562
                return '1 = 0';
563
            }
564
        }
565
    }
566
567
568
    /**
569
     * Create object instance by specified parameters
570
     * @param string $className Object class name
571
     * @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...
572
     * @param array $dbData Database record with object data
573
     *
574
     * @return idbRecord Database record object instance
575
     */
576
    public function &createObject(
577
        $className,
578
        $identifier,
579
        array & $attributes,
580
        array & $dbData,
581
        array & $virtualFields = array()
582
    )
583
    {
0 ignored issues
show
Coding Style introduced by
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
584
        // If this object instance is not cached
585
        if (!isset(dbRecord::$instances[$className][$identifier]) || isset($dbData['__Count']) || sizeof($virtualFields)) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
586
587
            // Create empry dbRecord ancestor and store it to cache
588
            dbRecord::$instances[$className][$identifier] = new $className($this, new dbQuery());
589
590
            // Pointer to object
591
            $object = &dbRecord::$instances[$className][$identifier];
592
593
            // Set object identifier
594
            $object->id = $identifier;
595
596
            // Fix object connection with DB record
597
            $object->attached = true;
598
599
            // Fill object attributes
600
            foreach ($attributes as $lc_field => $field) {
601
                $object->$lc_field = $dbData[$field];
602
            }
603
604
            // Fill virtual fields
605
            foreach ($virtualFields as $alias => $virtual_field) {
606
                // If DB record contains virtual field data
607
                if (isset($dbData[$alias])) {
608
                    $object->$alias = $dbData[$alias];
609
                }
610
            }
611
612
            return $object;
613
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
614
        } else { // Get object instance from cache
615
            return dbRecord::$instances[$className][$identifier];
616
        }
617
    }
618
619
    /**
620
     * Преобразовать массив записей из БД во внутреннее представление dbRecord
621
     * @param string $class_name Имя класса
622
     * @param array $response Массив записей полученных из БД
623
     * @return array Коллекцию записей БД во внутреннем формате
624
     * @see dbRecord
625
     */
626
    protected function &toRecords($class_name, array & $response, array $join = array(), array $virtual_fields = array())
627
    {
628
        // Сформируем правильное имя класса
629
        $class_name = strpos($class_name, '\\') !== false ? $class_name : '\\samson\activerecord\\'.$class_name;
630
631
        // Результирующая коллекция полученных записей из БД
632
        $collection = array();
633
634
        // Получим переменные для запроса
635
        extract($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...
Bug introduced by
$this->__get_table_data($class_name) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
636
637
        // Generate table metadata for joined tables
638
        $joinedTableData = array();
639
        foreach ($join as $relationData) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
640
641
            // Generate full joined table name(including prefix)
642
            $joinTable = self::$prefix . $relationData->table;
643
644
            // Get real classname of the table without alias
645
            $tableName = $_relation_alias[$joinTable];
646
647
            // Get joined table class metadata
648
            $joinedTableData[$tableName] = $this->__get_table_data($tableName);
649
        }
650
651
        // Получим имя главного
652
        $main_primary = $_primary;
653
654
        // Перебем массив полученных данных от БД - создадим для них объекты
655
        $records_count = sizeof($response);
656
657
        // Идентификатор текущего создаваемого объекта
658
        $main_id = isset($response[0]) ? $response[0][$main_primary] : 0;
659
660
        // Указатель на текущий обрабатываемый объект
661
        $main_obj = null;
662
663
        // Переберем полученные записи из БД
664
        for ($i = 0; $i < $records_count; $i++) {
665
            // Строка данных полученная из БД
666
            $db_row = &$response[$i];
667
668
            // Get object instance
669
            $collection[$main_id] = &$this->createObject($class_name, $main_id, $_attributes, $db_row, $virtual_fields);
670
671
            // Pointer to main object
672
            $main_obj = &$collection[$main_id];
673
674
            // Выполним внутренний перебор строк из БД начиная с текущей строки
675
            // Это позволит нам розабрать объекты полученные со связью один ко многим
676
            // А если это связь 1-1 то цикл выполниться только один раз
677
            for ($j = $i; $j < $records_count; $j++) {
678
                // Строка данных полученная из БД
679
                $db_inner_row = &$response[$j];
680
681
                // Получим идентфиикатор главного объекта в текущей строче БД
682
                $obj_id = $db_inner_row[$main_primary];
683
684
                // Если в строке из БД новый идентификатор
685
                if ($obj_id != $main_id) {
686
                    // Установим новый текущий идентификатор материала
687
                    $main_id = $obj_id;
688
689
                    // Установим индекс главного цикла на строку с новым главным элементом
690
                    // учтем что главный цикл сам увеличит на единицу индекс
691
                    $i = $j - 1;
692
693
                    //trace(' - Найден новый объект на строке №'.$j.'-'.$db_inner_row[$main_primary]);
694
695
                    // Прервем внутренний цикл
696
                    break;
697
                }
698
                //else trace(' + Заполняем данные из строки №'.$j);
699
700
                // Переберем все присоединенные таблицы в запросе
701
                foreach ($join as $relation_data) {
702
                    /**@var \samson\activerecord\RelationData $relation_data */
703
704
                    // If this table is not ignored
705
                    if (!$relation_data->ignore) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
706
707
                        // TODO: Prepare all data in RelationObject to speed up this method
708
709
                        $join_name = $relation_data->relation;
710
711
                        $join_table = self::$prefix . $relation_data->table;
712
713
                        //trace('Filling related table:'.$join_name.'/'.$join_table);
714
715
                        // Get real classname of the table without alias
716
                        $_relation_name = $_relation_alias[$join_table];
717
                        $join_class = str_replace(self::$prefix, '', $relation_data->table);
718
719
                        // Get joined table metadata from previously prepared object
720
                        $r_data = $joinedTableData[$_relation_name];
721
722
                        // Try to get identifier
723
                        if (isset($_relations[$join_table][$r_data['_primary']])) {
724
                            $r_obj_id_field = $_relations[$join_table][$r_data['_primary']];
725
                        } // Получим имя ключевого поля связанного объекта
726
                        else {
727
                            e('Cannot find related table(##) primary field(##) description',
0 ignored issues
show
Deprecated Code introduced by
The function e() has been deprecated with message: Use custom exceptions

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...
728
                                E_SAMSON_ACTIVERECORD_ERROR, array($join_table, $r_data['_primary']));
729
                        }
730
731
                        // Если задано имя ключевого поля связанного объекта - создадим его
732
                        if (isset($db_inner_row[$r_obj_id_field])) {
733
                            // Получим ключевое поле связанного объекта
734
                            $r_obj_id = $db_inner_row[$r_obj_id_field];
735
736
                            // Get joined object instance
737
                            $r_obj = &$this->createObject($join_name, $r_obj_id, $_relations[$join_table],
738
                                $db_inner_row);
739
740
                            // Call handler for object filling
741
                            $r_obj->filled();
742
743
                            // TODO: Это старый подход - сохранять не зависимо от алиаса под реальным именем таблицы
744
745
                            // Если связанный объект привязан как один-к-одному - просто довами ссылку на него
746
                            if ($_relation_type[$join_table] == 0) {
747
                                $main_obj->onetoone['_' . $join_table] = $r_obj;
748
                                $main_obj->onetoone['_' . $join_class] = $r_obj;
749
                            } // Иначе создадим массив типа: идентификатор -> объект
750
                            else {
751
                                $main_obj->onetomany['_' . $join_table][$r_obj_id] = $r_obj;
752
                                $main_obj->onetomany['_' . $join_class][$r_obj_id] = $r_obj;
753
                            }
754
                        }
755
                    }
756
                }
757
            }
758
759
            // Call handler for object filling
760
            $main_obj->filled();
761
762
            // Если внутренний цикл дошел до конца остановим главный цикл
763
            if ($j == $records_count) {
764
                break;
765
            }
766
        }
767
768
        // Вернем то что у нас вышло
769
        return $collection;
770
    }
771
}
772