ArrayAccessTrait   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 16
eloc 29
c 2
b 0
f 0
dl 0
loc 97
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetUnset() 0 13 3
A offsetExists() 0 15 4
A offsetGet() 0 11 3
A offsetSet() 0 18 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Trait;
6
7
use InvalidArgumentException;
8
use Yiisoft\ActiveRecord\ActiveRecordInterface;
9
10
use function get_object_vars;
11
use function is_array;
12
use function property_exists;
13
14
/**
15
 * Trait to implement {@see ArrayAccess} interface for ActiveRecord.
16
 *
17
 * @method mixed getAttribute(string $name)
18
 * @see ActiveRecordInterface::getAttribute()
19
 *
20
 * @method bool hasAttribute(string $name)
21
 * @see ActiveRecordInterface::hasAttribute()
22
 *
23
 * @method void setAttribute(string $name, mixed $value)
24
 * @see ActiveRecordInterface::getAttribute()
25
 *
26
 * @method ActiveRecordInterface|array|null relation(string $name)
27
 * @see ActiveRecordInterface::relation()
28
 *
29
 * @method bool isRelationPopulated(string $name)
30
 * @see ActiveRecordInterface::isRelationPopulated()
31
 *
32
 * @method void populateRelation(string $name, ActiveRecordInterface|array|null $record)
33
 * @see ActiveRecordInterface::populateRelation()
34
 *
35
 * @method void resetRelation(string $name)
36
 * @see ActiveRecordInterface::resetRelation()
37
 */
38
trait ArrayAccessTrait
39
{
40
    /**
41
     * Returns whether there is an element at the specified offset.
42
     *
43
     * This method is required by the SPL interface {@see ArrayAccess}.
44
     *
45
     * It is implicitly called when you use something like `isset($model[$offset])`.
46
     *
47
     * @param string $offset the offset to check on.
48
     *
49
     * @return bool whether or not an offset exists.
50
     */
51
    public function offsetExists(mixed $offset): bool
52
    {
53
        if ($this->hasAttribute($offset)) {
54
            return $this->getAttribute($offset) !== null;
55
        }
56
57
        if (property_exists($this, $offset)) {
58
            return isset(get_object_vars($this)[$offset]);
59
        }
60
61
        if ($this->isRelationPopulated($offset)) {
62
            return $this->relation($offset) !== null;
63
        }
64
65
        return false;
66
    }
67
68
    /**
69
     * @param string $offset the offset to retrieve element.
70
     */
71
    public function offsetGet(mixed $offset): mixed
72
    {
73
        if ($this->hasAttribute($offset)) {
74
            return $this->getAttribute($offset);
75
        }
76
77
        if (property_exists($this, $offset)) {
78
            return get_object_vars($this)[$offset] ?? null;
79
        }
80
81
        return $this->relation($offset);
82
    }
83
84
    /**
85
     * Sets the element at the specified offset.
86
     *
87
     * This method is required by the SPL interface {@see ArrayAccess}.
88
     *
89
     * It is implicitly called when you use something like `$model[$offset] = $item;`.
90
     *
91
     * @param string $offset the offset to set element.
92
     */
93
    public function offsetSet(mixed $offset, mixed $value): void
94
    {
95
        if ($this->hasAttribute($offset)) {
96
            $this->setAttribute($offset, $value);
97
            return;
98
        }
99
100
        if (property_exists($this, $offset)) {
101
            $this->$offset = $value;
102
            return;
103
        }
104
105
        if ($value instanceof ActiveRecordInterface || is_array($value) || $value === null) {
106
            $this->populateRelation($offset, $value);
107
            return;
108
        }
109
110
        throw new InvalidArgumentException('Setting unknown property: ' . static::class . '::' . $offset);
111
    }
112
113
    /**
114
     * Sets the element value at the specified offset to null.
115
     *
116
     * This method is required by the SPL interface {@see ArrayAccess}.
117
     *
118
     * It is implicitly called when you use something like `unset($model[$offset])`.
119
     *
120
     * @param string $offset the offset to unset element
121
     */
122
    public function offsetUnset(mixed $offset): void
123
    {
124
        if ($this->hasAttribute($offset)) {
125
            $this->setAttribute($offset, null);
126
            return;
127
        }
128
129
        if (property_exists($this, $offset)) {
130
            $this->$offset = null;
131
            return;
132
        }
133
134
        $this->resetRelation($offset);
135
    }
136
}
137