Record::offsetUnset()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php declare(strict_types=1);
2
namespace samsonframework\orm;
3
4
use samsonframework\core\RenderInterface;
5
6
/**
7
 * ORM Active record class.
8
 *
9
 * @author Vitaly Iegorov <[email protected]>
10
 * @author Nikita Kotenko <[email protected]>
11
 *
12
 * TODO: Remove render interface
13
 * TODO: Remove ArrayAccess interface
14
 * TODO: Remove activerecord pattern from entity
15
 */
16
class Record implements RenderInterface, \ArrayAccess, RecordInterface
17
{
18
    /**
19
     * @var array Collection of instances for caching
20
     * @deprecated
21
     */
22
    public static $instances = array();
23
24
    /**
25
     * Collection of class fields that would not be passed to module view
26
     * @deprecated
27
     */
28
    public static $restricted = array('attached', 'oneToOne', 'oneToMany', 'value');
29
30
    /**
31
     * @var array Collection of joined entities
32
     * @deprecated
33
     */
34
    public $joined = [];
35
    /**
36
     * @var string Entity class name
37
     * @deprecated
38
     */
39
    public $className;
40
    /**
41
     * @var array Related OTO records grouped by entity class name
42
     * @deprecated
43
     */
44
    public $oneToOne = array();
45
    /**
46
     * @var array Related OTM records grouped by entity class name
47
     * @deprecated
48
     */
49
    public $oneToMany = array();
50
    /**
51
     * @var bool Flag if this object has a database record
52
     * @deprecated
53
     */
54
    public $attached = false;
55
56
    /** @var DatabaseInterface Database layer */
57
    protected $database;
58
    /** @var TableMetadata */
59
    protected $metadata;
60
    /** @var int Identifier */
61
    public $id;
62
63
    /**
64
     * Record constructor.
65
     *
66
     * @param DatabaseInterface|null $database
67
     */
68
    public function __construct(DatabaseInterface $database = null, TableMetadata $metadata = null)
69
    {
70
        // Get database layer
71
        $this->database = $database;
72
73
        // TODO: !IMPORTANT THIS NEEDS TO BE REMOVED!
74
        // FIXME: Dependency resolving
75
        if (array_key_exists('__core', $GLOBALS)) {
76
            $this->database = $GLOBALS['__core']->getContainer()->get('database');
77
        }
78
79
        // Get current class name if none is passed
80
        $this->className = get_class($this);
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$className has been deprecated.

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

Loading history...
81
82
        // Get table metadata
83
        // FIXME: Dependency resolving
84
        $this->metadata = $metadata ?? TableMetadata::fromClassName($this->className);
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\TableMetadata::fromClassName() has been deprecated with message: This is temporary old approach

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...
Deprecated Code introduced by
The property samsonframework\orm\Record::$className has been deprecated.

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

Loading history...
85
    }
86
87
    /**
88
     * Find database record by primary key value.
89
     * This is generic method that should be used in nested classes to find its
90
     * records by some its primary key value.
91
     *
92
     * @param QueryInterface $query Query object instance
93
     * @param string $identifier Primary key value
94
     * @param mixed $return Variable to return found database record
95
     * @return bool|null|self  Record instance or null if 3rd parameter not passed
96
     * @deprecated Record should not be queryable, query class ancestor must be used
97
     */
98
    public static function byID(QueryInterface $query, $identifier, &$return = null)
99
    {
100
        /** @var Field $record Cache field object */
101
        $return = isset(self::$instances[$identifier])
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$instances has been deprecated.

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

Loading history...
102
            // Get record from cache by identifier
103
            ? self::$instances[$identifier]
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$instances has been deprecated.

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

Loading history...
104
            // Find record by identifier
105
            : self::$instances[$identifier] = static::oneByColumn(
0 ignored issues
show
Deprecated Code introduced by
The method samsonframework\orm\Record::oneByColumn() has been deprecated with message: Record should not be queryable, query class ancestor must be used

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...
Deprecated Code introduced by
The property samsonframework\orm\Record::$instances has been deprecated.

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

Loading history...
106
                $query,
107
                static::$_primary,
108
                $identifier
109
            );
110
111
        // Return bool or record depending on parameters passed
112
        return func_num_args() > 2 ? isset($return) : $return;
113
    }
114
115
    /**
116
     * Find database record by column name and its value.
117
     * This is generic method that should be used in nested classes to find its
118
     * records by some its column values.
119
     *
120
     * @param QueryInterface $query Query object instance
121
     * @param string $columnValue Column name for searching in calling class
122
     * @param string $columnName Column value
123
     * @return null|self  Record instance if it was found and 4th variable has NOT been passed,
124
     *                      NULL if record has NOT been found and 4th variable has NOT been passed
125
     * @deprecated Record should not be queryable, query class ancestor must be used
126
     */
127
    public static function oneByColumn(QueryInterface $query, $columnName, $columnValue)
128
    {
129
        // Perform db request and get materials
130
        return $query->entity(get_called_class())
131
            ->where($columnName, $columnValue)
132
            ->first();
133
    }
134
135
    /**
136
     * Find database record collection by column name and its value.
137
     * This is generic method that should be used in nested classes to find its
138
     * records by some its column values.
139
     *
140
     * @param QueryInterface $query Query object instance
141
     * @param string $columnName Column name for searching in calling class
142
     * @param mixed $columnValue Column value
143
     * @return self[]  Record instance if it was found and 4th variable has NOT been passed,
144
     *                      NULL if record has NOT been found and 4th variable has NOT been passed
145
     * @deprecated Record should not be queryable, query class ancestor must be used
146
     */
147
    public static function collectionByColumn(QueryInterface $query, $columnName, $columnValue)
148
    {
149
        // Perform db request and get materials
150
        return $query->className(get_called_class())
151
            ->cond($columnName, $columnValue)
152
            ->exec();
153
    }
154
155
    /**    @see idbRecord::delete() */
156
    public function delete()
157
    {
158
        // Если запись привязана к БД то удалим её оттуда
159
        if ($this->attached) {
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$attached has been deprecated.

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

Loading history...
160
            $this->database->delete($this->className, $this);
0 ignored issues
show
Bug introduced by
The method delete() does not seem to exist on object<samsonframework\orm\DatabaseInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Deprecated Code introduced by
The property samsonframework\orm\Record::$className has been deprecated.

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

Loading history...
161
        }
162
    }
163
164
    /** Special method called when object has been filled with data */
165
    public function filled()
166
    {
167
168
    }
169
170
    /**
171
     * Обработчик клонирования записи
172
     * Этот метод выполняется при системном вызове функции clone
173
     * и выполняет создание записи в БД и привязку клонированного объекта к ней
174
     * @deprecated Data entites should be cloned normally
175
     */
176
    public function __clone()
177
    {
178
        // Выполним создание записи в БД
179
        $this->id = $this->database->create($this->className, $this);
0 ignored issues
show
Bug introduced by
The method create() does not seem to exist on object<samsonframework\orm\DatabaseInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Deprecated Code introduced by
The property samsonframework\orm\Record::$className has been deprecated.

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

Loading history...
180
181
        // Установим флаг что мы привязались к БД
182
        $this->attached = true;
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$attached has been deprecated.

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

Loading history...
183
184
        // Сохраним запись в БД
185
        $this->save();
186
    }
187
188
    /**
189
     * @see idbRecord::save()
190
     */
191
    public function save()
192
    {
193
        $attributes = [];
194
        foreach ($this->metadata->columnAliases as $columnAlias => $columnName) {
195
            $attributes[$columnName] = $this->$columnAlias;
196
        }
197
198
        if ($this->attached) {
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$attached has been deprecated.

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

Loading history...
199
            $this->database->update($this->metadata, $attributes);
200
        } else {
201
            $newIdentifier = $this->database->insert($this->metadata, $attributes);
202
203
            $rows = $this->database->fetchArray(
204
                'SELECT * FROM `' . $this->metadata->tableName . '` WHERE ' .
205
                '`' . $this->metadata->tableName . '`.`' . $this->metadata->primaryField . '` = ' . $newIdentifier
206
            );
207
208
            if (count($rows)) {
209
                foreach ($this->metadata->columnAliases as $columnAlias => $columnName) {
210
                    $this->$columnAlias = $rows[0][$columnName];
211
                }
212
            } else {
213
                throw new \InvalidArgumentException('Failed ' . get_class($this) . ' entoty creation');
214
            }
215
        }
216
217
        // Store instance in cache
218
        self::$instances[$this->className][$this->id] = &$this;
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$instances has been deprecated.

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

Loading history...
Deprecated Code introduced by
The property samsonframework\orm\Record::$className has been deprecated.

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

Loading history...
219
    }
220
221
    /**
222
     * @see idbRecord::create()
223
     * @deprecated
224
     */
225
    public function create()
226
    {
227
    }
228
229
    /**
230
     * @see \samson\core\iModuleViewable::toView()
231
     * @deprecated
232
     */
233
    public function toView($prefix = null, array $restricted = array())
234
    {
235
        // Create resulting view data array, add identifier field
236
        $values = array($prefix . 'id' => $this->id);
237
238
        // Учтем поля которые не нужно превращать в массив
239
        $restricted = array_merge(self::$restricted, $restricted);
0 ignored issues
show
Deprecated Code introduced by
The property samsonframework\orm\Record::$restricted has been deprecated.

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

Loading history...
240
241
        // Пробежимся по переменным класса
242
        foreach (get_object_vars($this) as $var => $value) {
243
            // Если это не системное поле записи - запишем его значение
244
            if (!in_array($var, $restricted)) {
245
                $values[$prefix . $var] = is_string($value) ? trim($value) : $value;
246
            }
247
        }
248
249
        // Вернем массив атрибутов представляющий запись БД
250
        return $values;
251
    }
252
253
    /**
254
     * Create full entity copy from
255
     * @param mixed $object Variable to return copied object
256
     * @return Record New copied object
257
     * @deprecated Not supported yet
258
     */
259
    public function &copy(&$object = null)
260
    {
261
        // Get current entity class
262
        $entity = get_class($this);
263
264
        // Create object instance
265
        $object = new $entity(false);
266
267
        // PHP 5.2 compliant get attributes
268
        $attributes = array();
269
        eval('$attributes = ' . $entity . '::$_attributes;');
270
271
        // Iterate all object attributes
272
        foreach ($attributes as $attribute) {
273
            // If we have this attribute set
274
            if (isset($this[$attribute])) {
275
                // Store it in copied object
276
                $object[$attribute] = $this[$attribute];
277
            }
278
        }
279
280
        // Save object in database
281
        $object->save();
282
283
        // Return created copied object
284
        return $object;
285
    }
286
287
    public function __isset($name)
288
    {
289
        return $this->offsetExists($name);
290
    }
291
292
    public function __set($name, $value)
293
    {
294
        $this->offsetSet($name, $value);
295
    }
296
297
    public function __get($name)
298
    {
299
        return $this->offsetGet($name);
300
    }
301
302
    /**
303
     * @see ArrayAccess::offsetSet()
304
     * @throws \InvalidArgumentException
305
     */
306
    public function offsetSet($offset, $value)
307
    {
308
        if ($this->metadata->isColumnExists($offset)) {
309
            $fieldName = $this->metadata->getTableColumnAlias($offset);
310
            $this->$fieldName = $value;
311
        } else {
312
            $this->$offset = $value;
313
        }
314
    }
315
316
    /**
317
     * @see ArrayAccess::offsetGet()
318
     * @throws \InvalidArgumentException
319
     */
320
    public function offsetGet($offset)
321
    {
322
        if ($this->metadata->isColumnExists($offset)) {
323
            $fieldName = $this->metadata->getTableColumnAlias($offset);
324
            return $this->$fieldName;
325
        }
326
327
        return $this->$offset;
328
    }
329
330
    /** @see ArrayAccess::offsetUnset() */
331
    public function offsetUnset($offset)
332
    {
333
        unset($this->$offset);
334
    }
335
336
    /** @see ArrayAccess::offsetExists() */
337
    public function offsetExists($offset)
338
    {
339
        return property_exists($this, $offset) || $this->metadata->isColumnExists($offset);
340
    }
341
}
342