Completed
Push — master ( 300c6d...8b6eac )
by Mathieu
08:24
created

AbstractEntity::setWithSeparator()   C

Complexity

Conditions 7
Paths 9

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 25
nc 9
nop 2
1
<?php
2
3
namespace Charcoal\Config;
4
5
// Dependencies from `PHP`
6
use ArrayAccess;
7
use InvalidArgumentException;
8
9
/**
10
 * Default Charcoal core entity (data container).
11
 */
12
abstract class AbstractEntity implements EntityInterface
13
{
14
15
    /**
16
     * Keep a list of all config keys available.
17
     * @var array $keys
18
     */
19
    protected $keys = [];
20
21
    /**
22
     * Get the configuration's available keys.
23
     *
24
     * @return array
25
     */
26
    public function keys()
27
    {
28
        return array_keys($this->keys);
29
    }
30
31
    /**
32
     * Gets the entity data, as associative array map.
33
     *
34
     * @param array $filters Optional. Property filters.
35
     * @return array The data map.
36
     */
37
    public function data(array $filters = null)
38
    {
39
        unset($filters);
40
        $ret = [];
41
        $keys = $this->keys();
42
        foreach ($keys as $k) {
43
            if ($k == 'data') {
44
                // Avoid recursive call
45
                continue;
46
            }
47
            if (isset($this[$k])) {
48
                $ret[$k] = $this[$k];
49
            }
50
        }
51
        return $ret;
52
    }
53
54
    /**
55
     * Sets the entity data, from associative array map.
56
     *
57
     * This function takes an array and fill the property with its value.
58
     *
59
     * @param array $data The entity data. Will call setters.
60
     * @return self
61
     * @see self::offsetSet()
62
     */
63
    public function setData(array $data)
64
    {
65
        foreach ($data as $prop => $val) {
66
            $this[$prop] = $val;
67
        }
68
        return $this;
69
    }
70
71
    /**
72
     * Returns true if the container can return an entry for the given identifier.
73
     * Returns false otherwise.
74
     *
75
     * `has($key)` returning true does not mean that `get($key)` will not throw an exception.
76
     * It does however mean that `get($id)` will not throw a `NotFoundException`.
77
     *
78
     * @param string $key Identifier of the entry to look for.
79
     * @return boolean
80
     */
81
    public function has($key)
82
    {
83
        return isset($this[$key]);
84
    }
85
86
    /**
87
     * Find an entry of the configuration by its key and retrieve it.
88
     *
89
     * @see self::offsetGet()
90
     * @param string $key The key of the configuration item to look for.
91
     * @return mixed
92
     */
93
    public function get($key)
94
    {
95
        return $this[$key];
96
    }
97
98
    /**
99
     * Assign a value to the specified key of the configuration.
100
     *
101
     * Public method variant of setting by array key.
102
     *
103
     * @see self::offsetSet()
104
     * @param string $key   The key to assign $value to.
105
     * @param mixed  $value Value to assign to $key.
106
     * @return self
107
     */
108
    public function set($key, $value)
109
    {
110
        $this[$key] = $value;
111
        return $this;
112
    }
113
114
    /**
115
     * Determine if a configuration key exists.
116
     *
117
     * @see ArrayAccess::offsetExists()
118
     * @param string $key The key of the configuration item to look for.
119
     * @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value.
120
     * @return boolean
121
     */
122
    public function offsetExists($key)
123
    {
124
        if (is_numeric($key)) {
125
            throw new InvalidArgumentException(
126
                'Entity array access only supports non-numeric keys.'
127
            );
128
        }
129
130
        $key = $this->camelize($key);
131 View Code Duplication
        if (is_callable([$this, $key])) {
0 ignored issues
show
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...
132
            $value = $this->{$key}();
133
        } else {
134
            if (!isset($this->{$key})) {
135
                return false;
136
            }
137
            $value = $this->{$key};
138
        }
139
        return ($value !== null);
140
    }
141
142
    /**
143
     * Find an entry of the configuration by its key and retrieve it.
144
     *
145
     * @see ArrayAccess::offsetGet()
146
     * @param string $key The key of the configuration item to look for.
147
     * @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value.
148
     * @return mixed The value (or null)
149
     */
150
    public function offsetGet($key)
151
    {
152
        if (is_numeric($key)) {
153
            throw new InvalidArgumentException(
154
                'Entity array access only supports non-numeric keys.'
155
            );
156
        }
157
158
        $key = $this->camelize($key);
159
160 View Code Duplication
        if (is_callable([$this, $key])) {
0 ignored issues
show
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...
161
            return $this->{$key}();
162
        } else {
163
            if (isset($this->{$key})) {
164
                return $this->{$key};
165
            } else {
166
                return null;
167
            }
168
        }
169
    }
170
171
    /**
172
     * Assign a value to the specified key of the configuration.
173
     *
174
     * Set the value either by:
175
     * - a setter method (`set_{$key}()`)
176
     * - setting (or overriding)
177
     *
178
     * @see ArrayAccess::offsetSet()
179
     * @param string $key   The key to assign $value to.
180
     * @param mixed  $value Value to assign to $key.
181
     * @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value.
182
     * @return void
183
     */
184
    public function offsetSet($key, $value)
185
    {
186
        if (is_numeric($key)) {
187
            throw new InvalidArgumentException(
188
                'Entity array access only supports non-numeric keys.'
189
            );
190
        }
191
192
        $key = $this->camelize($key);
193
        $setter = 'set'.ucfirst($key);
194
195
        // Case: url.com?_=something
196
        if ($setter === 'set') {
197
            return;
198
        }
199
200 View Code Duplication
        if (is_callable([$this, $setter])) {
0 ignored issues
show
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...
201
            $this->{$setter}($value);
202
        } else {
203
            $this->{$key} = $value;
204
        }
205
        $this->keys[$key] = true;
206
    }
207
208
    /**
209
     * ArrayAccess > offsetUnset()
210
     *
211
     * @param string $key The key of the configuration item to remove.
212
     * @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value.
213
     * @return void
214
     */
215
    public function offsetUnset($key)
216
    {
217
        if (is_numeric($key)) {
218
            throw new InvalidArgumentException(
219
                'Entity array access only supports non-numeric keys.'
220
            );
221
        }
222
        $key = $this->camelize($key);
223
        $this[$key] = null;
224
        unset($this->keys[$key]);
225
    }
226
    /**
227
     * JsonSerializable > jsonSerialize()
228
     *
229
     * @return array
230
     */
231
    public function jsonSerialize()
232
    {
233
        return $this->data();
234
    }
235
236
    /**
237
     * Serializable > serialize()
238
     *
239
     * @return string
240
     */
241
    public function serialize()
242
    {
243
        return serialize($this->data());
244
    }
245
246
    /**
247
     * Serializable > unserialize()
248
     *
249
     * @param string $serialized The serialized data (with `serialize()`).
250
     * @return void
251
     */
252
    public function unserialize($serialized)
253
    {
254
        $unserialized = unserialize($serialized);
255
        $this->setData($unserialized);
0 ignored issues
show
Unused Code introduced by
The call to the method Charcoal\Config\AbstractEntity::setData() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
256
    }
257
258
    /**
259
     * Transform a snake_case string to camelCase.
260
     *
261
     * @param string $str The snake_case string to camelize.
262
     * @return string The camelcase'd string.
263
     */
264
    final protected function camelize($str)
265
    {
266
        if (strstr($str, '_') === false) {
267
            return $str;
268
        }
269
        return lcfirst(implode('', array_map('ucfirst', explode('_', $str))));
270
    }
271
}
272