DataTrait::set()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 9.472
c 0
b 0
f 0
cc 4
nc 4
nop 0
1
<?php
2
declare(strict_types=1);
3
/*
4
 * This file is part of the php-utilities package.
5
 *
6
 * (c) Marc Aschmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Asm\Data;
13
14
use Asm\Exception\InvalidParameterException;
15
use Asm\Exception\InvalidParameterSetException;
16
17
/**
18
 * DataTrait for easier inclusion in other objects without direct inheritance
19
 *
20
 * @package Asm\Data
21
 * @author Marc Aschmann <[email protected]>
22
 */
23
trait DataTrait
24
{
25
    /**
26
     * Internal data storage.
27
     *
28
     * @var array
29
     */
30
    private $data = [];
31
32
    /**
33
     * Clears the data(!) content of the object.
34
     *
35
     * @return $this
36
     */
37
    public function clear()
38
    {
39
        $this->data = [];
40
41
        return $this;
42
    }
43
44
    /**
45
     * Generic set method for multidimensional storage.
46
     *
47
     * $this->set( $key1, $key2, $key3, ..., $val )
48
     *
49
     * @throws InvalidParameterSetException
50
     * @return $this
51
     */
52
    public function set()
53
    {
54
        $args = func_get_args();
55
        $replace = null;
56
57
        if (1 < count($args)) {
58
            // get last array element == value to set!
59
            $val = array_pop($args);
60
61
            // iterate arguments reversed to build replacement array
62
            foreach (array_reverse($args) as $key) {
63
                if (null === $replace) {
64
                    $replace = [$key => $val];
65
                } else {
66
                    $replace = [$key => $replace];
67
                }
68
            }
69
70
            // add our data to storage
71
            $this->data = array_replace_recursive($this->data, $replace);
72
        } else {
73
            throw new InvalidParameterSetException(
74
                "Data::set() - You just provided one param and need at least another param."
75
            );
76
        }
77
78
        return $this;
79
    }
80
81
    /**
82
     * Set list of key/value pairs via one dimensional array.
83
     * Careful: An empty array will just overwrite your internal storage.
84
     *
85
     * @param  array $param
86
     * @return $this
87
     */
88
    public function setByArray(array $param)
89
    {
90
        if (!empty($param)) {
91
            // reset array to explicitly start at beginning
92
            reset($param);
93
            foreach ($param as $key => $value) {
94
                $this->set($key, $value);
95
            }
96
        } else { // will overwrite content with an empty array
97
            $this->data = $param;
98
        }
99
100
        return $this;
101
    }
102
103
    /**
104
     * Adds given object's properties to self.
105
     *
106
     * @param  object $param
107
     * @return $this
108
     * @throws InvalidParameterException
109
     */
110
    public function setByObject($param)
111
    {
112
        // check for DataContainer instances - because otherwise you can't easily access virtual properties
113
        if (is_object($param)) {
114
            if (is_a($param, DataInterface::class, true)) {
115
                foreach ($param->toArray() as $key => $value) {
116
                    $this->set($key, $value);
117
                }
118
            } else {
119
                // handle as "normal" object
120
                foreach ($param as $property => $value) {
121
                    $this->set($property, $value);
122
                }
123
            }
124
        } else {
125
            throw new InvalidParameterException(
126
                "Data::setByObject() - param is a {gettype($param)},no object!"
127
            );
128
        }
129
130
        return $this;
131
    }
132
133
    /**
134
     * Fill datastore from json string.
135
     *
136
     * @param string $json
137
     * @return $this
138
     */
139
    public function setByJson(string $json)
140
    {
141
        $this->setByArray(
142
            json_decode($json, true)
143
        );
144
145
        return $this;
146
    }
147
148
    /**
149
     * Return stored data array.
150
     *
151
     * @return array
152
     */
153
    public function toArray() : array
154
    {
155
        return $this->data;
156
    }
157
158
    /**
159
     * Convert internal data to json.
160
     *
161
     * @return string
162
     */
163
    public function toJson() : string
164
    {
165
        return json_encode($this->data);
166
    }
167
168
    /**
169
     * Multidimensional getter.
170
     *
171
     * Find a key structure in a multidimensional array and return the value
172
     * params are stackable -> get( $k1, $k2, $k3, ... ).
173
     *
174
     * @return bool|mixed
175
     */
176
    public function get()
177
    {
178
        return self::searchArray(
179
            func_get_args(),
180
            $this->data
181
        );
182
    }
183
184
    /**
185
     * Return all keys of internal array's first level.
186
     *
187
     * @return array keylist
188
     */
189
    public function getKeys() : array
190
    {
191
        return array_keys($this->data);
192
    }
193
194
    /**
195
     * Remove key from container.
196
     *
197
     * @param  string $key
198
     * @return $this
199
     */
200
    public function remove(string $key)
201
    {
202
        if (array_key_exists($key, $this->data)) {
203
            unset($this->data[$key]);
204
        }
205
206
        return $this;
207
    }
208
209
    /**
210
     * Return count of all firstlevel elements.
211
     *
212
     * @return int
213
     */
214
    public function count() : int
215
    {
216
        return count($this->data);
217
    }
218
219
    /**
220
     * Find a key in an array.
221
     * example self::findInArray(array(), key1, key2, key3, ..., default_return)
222
     *
223
     * @return array|bool|mixed
224
     */
225
    public static function findInArray()
226
    {
227
        $args = func_get_args();
228
        $data = array_shift($args);
229
230
        return self::searchArray(
231
            $args,
232
            $data
233
        );
234
    }
235
236
    /**
237
     * Search an array for keys (args) and provide a default value if
238
     * last arg is some kind of empty or not numeric.
239
     *
240
     * @param array $args
241
     * @param array $data
242
     * @param bool $default
243
     * @return array|mixed
244
     */
245
    private static function searchArray(array $args, array $data, $default = false)
246
    {
247
        // check for default return value
248
        if (1 < count($args)) {
249
            $lastElm = array_pop($args);
250
            if (empty($lastElm) && !is_numeric($lastElm)) {
251
                $default = $lastElm;
252
            } else {
253
                // push the last element back into array
254
                array_push($args, $lastElm);
255
            }
256
        }
257
258
        foreach ($args as $key) {
259
            if ((is_array($data)) && (array_key_exists($key, $data))) {
260
                $data = $data[$key];
261
            } else {
262
                $data = $default;
263
                break;
264
            }
265
        }
266
267
        return $data;
268
    }
269
}
270