Passed
Pull Request — 3.0 (#35)
by Rashid
02:49 queued 01:10
created

Store::closureValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 2
nc 2
nop 1
1
<?php namespace Chekote\NounStore;
2
3
use ArrayAccess;
4
use Closure;
5
use InvalidArgumentException;
6
7
class Store
8
{
9
    /** @var Key */
10
    protected $keyService;
11
12
    /** @var array */
13
    protected $nouns;
14
15
    /**
16
     * @param Key $keyService the key service to use for parsing and building keys
17
     * @codeCoverageIgnore
18
     */
19
    public function __construct(Key $keyService = null)
20
    {
21
        $this->keyService = $keyService ?: Key::getInstance();
22
    }
23
24
    /**
25
     * Removes all entries from the store.
26
     *
27
     * @return void
28
     */
29
    public function reset()
30
    {
31
        $this->nouns = [];
32
    }
33
34
    /**
35
     * Retrieves a value for the specified key.
36
     *
37
     * Each key is actually a collection. If you do not specify which item in the collection you want,
38
     * the method will return the most recent entry. You can optionally specify the entry you want by
39
     * using the plain english 1st, 2nd, 3rd etc in the $key param. For example:
40
     *
41
     * Retrieve the most recent entry "Thing" collection:
42
     *   retrieve("Thing")
43
     *
44
     * Retrieve the 1st entry in the "Thing" collection:
45
     *   retrieve("1st Thing")
46
     *
47
     * Retrieve the 3rd entry in the "Thing" collection:
48
     *   retrieve("3rd Thing")
49
     *
50
     * @see    Key::build()
51
     * @see    Key::parse()
52
     * @param  string                   $key The key to retrieve the value for. Supports nth notation.
53
     * @throws InvalidArgumentException if the key syntax is invalid.
54
     * @return mixed                    The value, or null if no value exists for the specified key/index combination.
55
     */
56
    public function get($key)
57
    {
58
        if (!$this->keyExists($key)) {
59
            return;
60
        }
61
62
        list($key, $index) = $this->keyService->parse($key);
63
        if ($this->plainKeyExists($key)) {
64
            return $index !== null ? $this->nouns[$key][$index] : end($this->nouns[$key]);
65
        }
66
67
        // Complex key
68
        list($base_key, $child_keys) = $this->keyService->parseNested($key);
69
        if (!$this->plainKeyExists($base_key)) {
70
            return;
71
        }
72
73
        return $index
74
            ? $this->data_get($this->nouns[$base_key][$index - 1], $child_keys)
75
            : $this->data_get(end($this->nouns[$base_key]), $child_keys);
76
    }
77
78
    /**
79
     * Retrieves all values for the specified key.
80
     *
81
     * @param  string $key The key to retrieve the values for. Does not support nth notation.
82
     * @return array  The values, or an empty array if no value exists for the specified key.
83
     */
84
    public function getAll($key)
85
    {
86
        return isset($this->nouns[$key]) ? $this->nouns[$key] : [];
87
    }
88
89
    /**
90
     * Determines if a value has been stored for the specified key.
91
     *
92
     * @see    Key::build()
93
     * @see    Key::parse()
94
     * @param  string                   $key The key to check. Supports nth notation.
95
     * @throws InvalidArgumentException if the key syntax is invalid.
96
     * @return bool                     True if the a value has been stored, false if not.
97
     */
98
    public function keyExists($key)
99
    {
100
        list($key, $index) = $this->keyService->parse($key);
101
        list($base_key, $unused) = $this->keyService->parseNested($key);
102
103
        return $index
104
            ? (isset($this->nouns[$key][$index]) || isset($this->nouns[$key][$index]))
105
            : (isset($this->nouns[$key]) || isset($this->nouns[$base_key]));
106
    }
107
108
    /**
109
     * Determines if a value has been stored for the specified key.
110
     *
111
     * @see    Key::build()
112
     * @see    Key::parse()
113
     * @param  string                   $key The key to check. Supports nth notation.
114
     * @throws InvalidArgumentException if the key syntax is invalid.
115
     * @return bool                     True if the a value has been stored, false if not.
116
     */
117
    public function plainKeyExists($key)
118
    {
119
        list($key, $index) = $this->keyService->parse($key);
120
121
        return $index ? isset($this->nouns[$key][$index]) : isset($this->nouns[$key]);
122
    }
123
124
    /**
125
     * Asserts that the key's value contains the specified string.
126
     *
127
     * @see    Key::build()
128
     * @see    Key::parse()
129
     * @param  string                   $key   The key to check.
130
     * @param  string                   $value The value expected to be contained within the key's value.
131
     * @throws InvalidArgumentException if the key syntax is invalid.
132
     * @return bool                     True if the key's value contains the specified string, false if not.
133
     */
134
    public function keyValueContains($key, $value)
135
    {
136
        $actual = $this->get($key);
137
138
        return is_string($actual) && strpos($actual, $value) !== false;
139
    }
140
141
    /**
142
     * Stores a value for the specified key.
143
     *
144
     * The specified value is added to the top of the "stack" for the specified key.
145
     *
146
     * @param string $key   The key to store the value under. Does not support nth notation.
147
     * @param mixed  $value The value to store.
148
     */
149
    public function set($key, $value)
150
    {
151
        $this->nouns[$key][] = $value;
152
    }
153
154
    /**
155
     * Retrieves a value from a nested array or object using array list.
156
     * (Modified version of data_get() laravel > 5.6).
157
     *
158
     * @param  mixed    $target    The target element
159
     * @param  string[] $key_parts List of nested values
160
     * @param  mixed    $default   If value doesn't exists
161
     * @return mixed
162
     */
163
    public function data_get($target, array $key_parts, $default = null)
164
    {
165
        foreach ($key_parts as $segment) {
166
            if (is_array($target)) {
167
                if (!array_key_exists($segment, $target)) {
168
                    return $this->closureValue($default);
169
                }
170
                $target = $target[$segment];
171
            } elseif ($target instanceof ArrayAccess) {
172
                if (!isset($target[$segment])) {
173
                    return $this->closureValue($default);
174
                }
175
                $target = $target[$segment];
176
            } elseif (is_object($target)) {
177
                if (!isset($target->{$segment})) {
178
                    return $this->closureValue($default);
179
                }
180
                $target = $target->{$segment};
181
            } else {
182
                return $this->closureValue($default);
183
            }
184
        }
185
186
        return $target;
187
    }
188
189
    /**
190
     * Returns value itself or Closure will be executed and return result.
191
     *
192
     * @param  string $value Closure to be evaluated
193
     * @return mixed  Result of the Closure function or $value itself
194
     */
195
    public function closureValue($value)
196
    {
197
        return $value instanceof Closure ? $value() : $value;
0 ignored issues
show
introduced by
$value is never a sub-type of Closure.
Loading history...
198
    }
199
}
200