Passed
Pull Request — master (#12)
by Donald
01:39
created

Store::__construct()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
1
<?php namespace Chekote\NounStore;
2
3
use InvalidArgumentException;
4
use OutOfBoundsException;
5
use RuntimeException;
6
7
class Store
8
{
9
    /** @var array */
10
    protected $nouns;
11
12
    /** @var Key */
13
    protected $keyService;
14
15 59
    public function __construct(Key $keyService = null)
16
    {
17 59
        $this->keyService = $keyService ?: Key::getInstance();
18 59
    }
19
20
    /**
21
     * Asserts that a value has been stored for the specified key.
22
     *
23
     * @param  string                   $key   The key to check. @see self::get() for formatting options.
24
     * @param  int                      $index [optional] The index of the key entry to check. If not specified, the
25
     *                                         method will ensure that at least one item is stored for the key.
26
     * @throws OutOfBoundsException     if a value has not been stored for the specified key.
27
     * @throws InvalidArgumentException if both an $index and $key are provided, but the $key contains an nth value
28
     *                                        that does not match the index.
29
     * @return mixed                    The value.
30
     */
31 23 View Code Duplication
    public function assertKeyExists($key, $index = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
32
    {
33 23
        list($key, $index) = $this->keyService->parse($key, $index);
34
35 22
        if (!$this->keyExists($key, $index)) {
36 6
            throw new OutOfBoundsException("Entry '{$this->buildKey($key, $index)}' was not found in the store.");
37
        }
38
39 16
        return $this->get($key, $index);
40
    }
41
42
    /**
43
     * Asserts that the key's value matches the specified value.
44
     *
45
     * @param  string                   $key   The key to check. @see self::get() for formatting options.
46
     * @param  mixed                    $value The expected value.
47
     * @param  int                      $index [optional] The index of the key entry to retrieve. If not specified, the
48
     *                                         method will check the most recent value stored under the key.
49
     * @throws OutOfBoundsException     If a value has not been stored for the specified key.
50
     * @throws InvalidArgumentException if both an $index and $key are provided, but the $key contains an nth value
51
     *                                        that does not match the index.
52
     */
53 10
    public function assertKeyValueIs($key, $value, $index = null)
54
    {
55 10
        list($key, $index) = $this->keyService->parse($key, $index);
56
57 9
        $this->assertKeyExists($key, $index);
58
59 7
        if ($this->get($key, $index) != $value) {
60 2
            throw new RuntimeException(
61 2
                "Entry '{$this->buildKey($key, $index)}' does not match '" . print_r($value, true) . "'"
62
            );
63
        }
64 5
    }
65
66
    /**
67
     * Asserts that the key's value contains the specified string.
68
     *
69
     * @param  string                   $key   The key to check. @see self::get() for formatting options.
70
     * @param  string                   $value The value expected to be contained within the key's value.
71
     * @param  int                      $index [optional] The index of the key entry to retrieve. If not specified, the
72
     *                                         method will check the most recent value stored under the key.
73
     * @throws OutOfBoundsException     If a value has not been stored for the specified key.
74
     * @throws InvalidArgumentException if both an $index and $key are provided, but the $key contains an nth value
75
     *                                        that does not match the index.
76
     */
77 10 View Code Duplication
    public function assertKeyValueContains($key, $value, $index = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
78
    {
79 10
        list($key, $index) = $this->keyService->parse($key, $index);
80
81 9
        $this->assertKeyExists($key, $index);
82
83 7
        if (!$this->keyValueContains($key, $value, $index)) {
84 2
            throw new RuntimeException(
85 2
                "Entry '{$this->buildKey($key, $index)}' does not contain '$value'"
86
            );
87
        }
88 5
    }
89
90
    /**
91
     * Removes all entries from the store.
92
     *
93
     * @return void
94
     */
95 1
    public function reset()
96
    {
97 1
        $this->nouns = [];
98 1
    }
99
100
    /**
101
     * Retrieves a value for the specified key.
102
     *
103
     * Each key is actually a collection. If you do not specify which item in the collection you want,
104
     * the method will return the most recent entry. You can specify the entry you want by either
105
     * using the plain english 1st, 2nd, 3rd etc in the $key param, or by specifying 0, 1, 2 etc in
106
     * the $index param. For example:
107
     *
108
     * Retrieve the most recent entry "Thing" collection:
109
     *   retrieve("Thing")
110
     *
111
     * Retrieve the 1st entry in the "Thing" collection:
112
     *   retrieve("1st Thing")
113
     *   retrieve("Thing", 0)
114
     *
115
     * Retrieve the 3rd entry in the "Thing" collection:
116
     *   retrieve("3rd Thing")
117
     *   retrieve("Thing", 2)
118
     *
119
     * Please note: The nth value in the string key is indexed from 1. In that "1st" is the first item stored.
120
     * The index parameter is indexed from 0. In that 0 is the first item stored.
121
     *
122
     * Please Note: If you specify both an $index param and an nth in the $key, they must both reference the same index.
123
     * If they do not, the method will throw an InvalidArgumentException.
124
     *
125
     * retrieve("1st Thing", 1);
126
     *
127
     * @param  string                   $key   The key to retrieve the value for. Can be prefixed with an nth descriptor.
128
     * @param  int                      $index [optional] The index of the key entry to retrieve. If not specified, the
129
     *                                         method will return the most recent value stored under the key.
130
     * @throws InvalidArgumentException if both an $index and $key are provided, but the $key contains an nth value
131
     *                                        that does not match the index.
132
     * @return mixed                    The value, or null if no value exists for the specified key/index combination.
133
     */
134 32
    public function get($key, $index = null)
135
    {
136 32
        list($key, $index) = $this->keyService->parse($key, $index);
137
138 31
        if (!$this->keyExists($key, $index)) {
139 5
            return;
140
        }
141
142 26
        return $index !== null ? $this->nouns[$key][$index] : end($this->nouns[$key]);
143
    }
144
145
    /**
146
     * Retrieves all values for the specified key.
147
     *
148
     * @param  string               $key The key to retrieve the values for.
149
     * @throws OutOfBoundsException if the specified $key does not exist in the store.
150
     * @return array                The values.
151
     */
152 2
    public function getAll($key)
153
    {
154 2
        if (!isset($this->nouns[$key])) {
155 1
            throw new OutOfBoundsException("'$key' does not exist in the store");
156
        }
157
158 1
        return $this->nouns[$key];
159
    }
160
161
    /**
162
     * Determines if a value has been stored for the specified key.
163
     *
164
     * @param  string                   $key   The key to check.
165
     * @param  int                      $index [optional] The index of the key entry to check. If not specified, the
166
     *                                         method will ensure that at least one item is stored for the key.
167
     * @throws InvalidArgumentException if both an $index and $key are provided, but the $key contains an nth value
168
     *                                        that does not match the index.
169
     * @return bool                     True if the a value has been stored, false if not.
170
     */
171 42
    public function keyExists($key, $index = null)
172
    {
173 42
        list($key, $index) = $this->keyService->parse($key, $index);
174
175 41
        return $index !== null ? isset($this->nouns[$key][$index]) : isset($this->nouns[$key]);
176
    }
177
178
    /**
179
     * Asserts that the key's value contains the specified string.
180
     *
181
     * @param  string                   $key   The key to check. @see self::get() for formatting options.
182
     * @param  string                   $value The value expected to be contained within the key's value.
183
     * @param  int                      $index [optional] The index of the key entry to retrieve. If not specified, the
184
     *                                         method will check the most recent value stored under the key.
185
     * @throws InvalidArgumentException if both an $index and $key are provided, but the $key contains an nth value
186
     *                                        that does not match the index.
187
     * @return bool                     True if the key's value contains the specified string, false if not.
188
     */
189 17
    public function keyValueContains($key, $value, $index = null)
190
    {
191 17
        list($key, $index) = $this->keyService->parse($key, $index);
192
193 16
        $actual = $this->get($key, $index);
194
195 16
        return is_string($actual) && strpos($actual, $value) !== false;
196
    }
197
198
    /**
199
     * Stores a value for the specified key.
200
     *
201
     * @param string $key   The key to store the value under.
202
     * @param mixed  $value The value to store.
203
     */
204 59
    public function set($key, $value)
205
    {
206 59
        $this->nouns[$key][] = $value;
207 59
    }
208
209
    /**
210
     * Builds a key from it's separate key and index values.
211
     *
212
     * @example buildKey("Item", null): "Item"
213
     * @example buildKey("Item", 0): "1st Item"
214
     * @example buildKey("Item", 1): "2nd Item"
215
     * @example buildKey("Item", 2): "3rd Item"
216
     *
217
     * @param  string                   $key   The key to check.
218
     * @param  int                      $index The index (zero indexed) value for the key. If not specified, the method
219
     *                                         will not add an index notation to the key.
220
     * @throws InvalidArgumentException if $key is not a string.
221
     * @throws InvalidArgumentException if $index is not an int.
222
     * @return string                   the key with the index, or just the key if index is null.
223
     */
224 17
    protected function buildKey($key, $index)
225
    {
226 17
        if ($index === null) {
227 3
            return $key;
228
        }
229
230 14
        $nth = $index + 1;
231
232 14
        return $nth . $this->keyService->getOrdinal($nth) . ' ' . $key;
233
    }
234
}
235