ChainableArray_ArrayAccess_Trait::offsetSet()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
namespace JClaveau\Arrays;
3
4
/**
5
 * This Trait gathers methods related to the ArrayAccess interface for
6
 * the Table Helper.
7
 *
8
 * @see http://php.net/manual/en/class.arrayaccess.php
9
 */
10
trait ChainableArray_ArrayAccess_Trait
11
{
12
    // protected $defaultRowGenerator;
13
14
    /**
15
     * ArrayAccess interface
16
     */
17
    public function offsetSet($offset, $value)
18
    {
19
        if (is_null($offset)) {
20
            $this->data[] = $value;
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
21
        }
22
        else {
23
            $this->data[$offset] = $value;
24
        }
25
    }
26
27
    /**
28
     * ArrayAccess interface
29
     */
30
    public function offsetExists($offset)
31
    {
32
        try {
33
            return isset($this->data[$offset]);
34
        }
35
        catch (\Exception $e) {
36
            if (property_exists($this, 'defaultRowGenerator')) {
37
                return true;
38
            }
39
40
            $this->throwUsageException(
0 ignored issues
show
Bug introduced by
It seems like throwUsageException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

40
            $this->/** @scrutinizer ignore-call */ 
41
                   throwUsageException(
Loading history...
41
                $e->getMessage().': '.var_export($offset, true)
42
            );
43
        }
44
    }
45
46
    /**
47
     * ArrayAccess interface
48
     */
49
    public function offsetUnset($offset)
50
    {
51
        unset($this->data[$offset]);
52
    }
53
54
    /**
55
     * ArrayAccess interface. Method called if isset() or empty() is called.
56
     *
57
     * /!\ We need the reference here to have the line below working
58
     *      $this['key']['sub_key'] = 'lalala'
59
     *
60
     * @throws \Exception The same as for a classical array with
61
     *                         "Undefined index" having the good trace end.
62
     */
63
    public function &offsetGet($offset)
64
    {
65
        try {
66
            if ( ! array_key_exists($offset, $this->data)
67
                && $this->hasDefaultRowValue()
68
            ) {
69
                $this->data[$offset] = $this->generateDefaultRow($offset);
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
70
            }
71
72
            // This line simply triggers the exception. It's odd but wanted.
73
            // If we do not do that, it could create an null entry in the array
74
            // instead of throw "Undefined index".
75
            $this->data[$offset];
76
            // This one returns the expected value as reference for foreach
77
            // support but wouldn't throw exception if it doesn't exist
78
            $returnValue = &$this->data[$offset];
79
            return $returnValue;
80
        }
81
        catch (\Exception $e) {
82
            // here we simply move the Exception location at the one
83
            // of the caller as the isset() method is called at its
84
            // location.
85
86
            // The true location of the throw is still available through
87
            // $e->getTrace()
88
            $trace_location  = $e->getTrace()[1];
89
            $reflectionClass = new \ReflectionClass( get_class($e) );
90
91
            //file
92
            if (isset($trace_location['file'])) {
93
                $reflectionProperty = $reflectionClass->getProperty('file');
94
                $reflectionProperty->setAccessible(true);
95
                $reflectionProperty->setValue($e, $trace_location['file']);
96
            }
97
98
            // line
99
            if (isset($trace_location['line'])) {
100
                $reflectionProperty = $reflectionClass->getProperty('line');
101
                $reflectionProperty->setAccessible(true);
102
                $reflectionProperty->setValue($e, $trace_location['line']);
103
            }
104
105
            throw $e;
106
        }
107
    }
108
109
    /**
110
     * Defines a default row or a callback to generate it.
111
     *
112
     * @param  mixed
113
     * @return $this
114
     */
115
    public function setDefaultRow($row)
116
    {
117
        unset($this->defaultRowGenerator);
118
        $this->defaultRow = $row;
0 ignored issues
show
Bug Best Practice introduced by
The property defaultRow does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
119
        return $this;
120
    }
121
122
    /**
123
     * Defines a default row or a callback to generate it.
124
     *
125
     * @param  mixed
126
     * @return $this
127
     */
128
    public function setDefaultRowGenerator(callable $row_generator)
129
    {
130
        unset($this->defaultRow);
131
        $this->defaultRowGenerator = $row_generator;
0 ignored issues
show
Bug Best Practice introduced by
The property defaultRowGenerator does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
132
        return $this;
133
    }
134
135
    /**
136
     * Undefines the default row or a callback to generate it.
137
     *
138
     * @return $this
139
     */
140
    public function unsetDefaultRow()
141
    {
142
        unset($this->defaultRow);
143
        unset($this->defaultRowGenerator);
144
        return $this;
145
    }
146
147
    /**
148
     * Checks if a default row generator exists.
149
     *
150
     * @return bool
151
     */
152
    public function hasDefaultRowValue()
153
    {
154
        return property_exists($this, 'defaultRow')
155
            || property_exists($this, 'defaultRowGenerator');
156
    }
157
158
    /**
159
     * Undefines the default row or a callback to generate it.
160
     *
161
     * @return $this
162
     */
163
    protected function generateDefaultRow($offset)
164
    {
165
        if (property_exists($this, 'defaultRow'))
166
            return $this->defaultRow;
167
        elseif (property_exists($this, 'defaultRowGenerator'))
168
            return call_user_func($this->defaultRowGenerator, $offset);
169
    }
170
171
    /**/
172
}
173