Completed
Push — master ( 39ce43...6174f1 )
by Freek
02:09
created

Valuestore::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Spatie\Valuestore;
4
5
use ArrayAccess;
6
use Countable;
7
8
class Valuestore implements ArrayAccess, Countable
9
{
10
    /** @var string */
11
    protected $fileName;
12
13
    /**
14
     * @param string $fileName
15
     *
16
     * @return $this
17
     */
18
    public static function make(string $fileName)
19
    {
20
        return (new static())->setFileName($fileName);
21
    }
22
23
    protected function __construct()
24
    {
25
    }
26
27
    /**
28
     * Set the filename where all values will be stored.
29
     *
30
     * @param string $fileName
31
     *
32
     * @return $this
33
     */
34
    protected function setFileName(string $fileName)
35
    {
36
        $this->fileName = $fileName;
37
38
        return $this;
39
    }
40
41
    /**
42
     * Put a value in the store.
43
     *
44
     * @param string|array    $name
45
     * @param string|int|null $value
46
     *
47
     * @return $this
48
     */
49
    public function put($name, $value = null)
50
    {
51
        $newValues = $name;
52
53
        if (!is_array($name)) {
54
            $newValues = [$name => $value];
55
        }
56
57
        $newContent = array_merge($this->all(), $newValues);
58
59
        $this->setContent($newContent);
60
61
        return $this;
62
    }
63
64
    /**
65
     * Push a new value into an array.
66
     *
67
     * @param string $name
68
     * @param $pushValue
69
     *
70
     * @return $this
71
     */
72
    public function push(string $name, $pushValue)
73
    {
74
        if (!is_array($pushValue)) {
75
            $pushValue = [$pushValue];
76
        }
77
78
        if (!$this->has($name)) {
79
            $this->put($name, $pushValue);
0 ignored issues
show
Documentation introduced by
$pushValue is of type array, but the function expects a string|integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
80
81
            return $this;
82
        }
83
84
        $oldValue = $this->get($name);
85
86
        if (!is_array($oldValue)) {
87
            $oldValue = [$oldValue];
88
        }
89
90
        if (is_array($oldValue)) {
91
            $newValue = array_merge($oldValue, $pushValue);
92
        }
93
94
        $this->put($name, $newValue);
0 ignored issues
show
Bug introduced by
The variable $newValue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Documentation introduced by
$newValue is of type array, but the function expects a string|integer|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
95
96
        return $this;
97
    }
98
99
    /**
100
     * Get a value from the store.
101
     *
102
     * @param string $name
103
     * @param $default
104
     *
105
     * @return null|string
106
     */
107
    public function get(string $name, $default = null)
108
    {
109
        if (!array_key_exists($name, $this->all())) {
110
            return $default;
111
        }
112
113
        return $this->all()[$name];
114
    }
115
116
    /*
117
     * Determine if the store has a value for the given name.
118
     */
119
    public function has(string $name) : bool
120
    {
121
        return array_key_exists($name, $this->all());
122
    }
123
124
    /**
125
     * Get all values from the store.
126
     *
127
     * @param string $startingWith
128
     *
129
     * @return array
130
     */
131
    public function all(string $startingWith = '') : array
132
    {
133
        if (!file_exists($this->fileName)) {
134
            return [];
135
        }
136
137
        $values = json_decode(file_get_contents($this->fileName), true);
138
139
        if ($startingWith !== '') {
140
            return $this->filterKeysStartingWith($this->all(), $startingWith);
141
        }
142
143
        return $values;
144
    }
145
146
    /**
147
     * Forget a value from the store.
148
     *
149
     * @param string $key
150
     *
151
     * @return $this
152
     */
153
    public function forget(string $key)
154
    {
155
        $newContent = $this->all();
156
157
        unset($newContent[$key]);
158
159
        $this->setContent($newContent);
160
161
        return $this;
162
    }
163
164
    /**
165
     * Flush all values from the store.
166
     *
167
     * @param string $startingWith
168
     *
169
     * @return $this
170
     */
171
    public function flush(string $startingWith = '')
172
    {
173
        $newContent = [];
174
175
        if ($startingWith !== '') {
176
            $newContent = $this->filterKeysNotStartingWith($this->all(), $startingWith);
177
        }
178
179
        return $this->setContent($newContent);
180
    }
181
182
    /**
183
     * Get and forget a value from the store.
184
     *
185
     * @param string $name
186
     *
187
     * @return null|string
188
     */
189
    public function pull(string $name)
190
    {
191
        $value = $this->get($name);
192
193
        $this->forget($name);
194
195
        return $value;
196
    }
197
198
    /**
199
     * Increment a value from the store.
200
     *
201
     * @param string $name
202
     * @param int    $by
203
     *
204
     * @return int|null|string
205
     */
206
    public function increment(string $name, int $by = 1)
207
    {
208
        $currentValue = $this->get($name) ?? 0;
209
210
        $newValue = $currentValue + $by;
211
212
        $this->put($name, $newValue);
213
214
        return $newValue;
215
    }
216
217
    /**
218
     * Decrement a value from the store.
219
     *
220
     * @param string $name
221
     * @param int    $by
222
     *
223
     * @return int|null|string
224
     */
225
    public function decrement(string $name, int $by = 1)
226
    {
227
        return $this->increment($name, $by * -1);
228
    }
229
230
    /**
231
     * Whether a offset exists.
232
     *
233
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
234
     *
235
     * @param mixed $offset
236
     *
237
     * @return bool
238
     */
239
    public function offsetExists($offset)
240
    {
241
        return $this->has($offset);
242
    }
243
244
    /**
245
     * Offset to retrieve.
246
     *
247
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
248
     *
249
     * @param mixed $offset
250
     *
251
     * @return mixed
252
     */
253
    public function offsetGet($offset)
254
    {
255
        return $this->get($offset);
256
    }
257
258
    /**
259
     * Offset to set.
260
     *
261
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
262
     *
263
     * @param mixed $offset
264
     * @param mixed $value
265
     */
266
    public function offsetSet($offset, $value)
267
    {
268
        $this->put($offset, $value);
269
    }
270
271
    /**
272
     * Offset to unset.
273
     *
274
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
275
     *
276
     * @param mixed $offset
277
     */
278
    public function offsetUnset($offset)
279
    {
280
        $this->forget($offset);
281
    }
282
283
    protected function filterKeysStartingWith(array $values, string $startsWith) : array
284
    {
285
        return array_filter($values, function ($key) use ($startsWith) {
286
287
            return $this->startsWith($key, $startsWith);
288
289
        }, ARRAY_FILTER_USE_KEY);
290
    }
291
292
    protected function filterKeysNotStartingWith(array $values, string $startsWith) : array
293
    {
294
        return array_filter($values, function ($key) use ($startsWith) {
295
296
            return !$this->startsWith($key, $startsWith);
297
298
        }, ARRAY_FILTER_USE_KEY);
299
    }
300
301
    protected function startsWith(string $haystack, string $needle) : bool
302
    {
303
        return substr($haystack, 0, strlen($needle)) === $needle;
304
    }
305
306
    /**
307
     * @param array $values
308
     *
309
     * @return $this
310
     */
311
    protected function setContent(array $values)
312
    {
313
        file_put_contents($this->fileName, json_encode($values));
314
315
        if (! count($values)) {
316
            unlink($this->fileName);
317
        }
318
319
        return $this;
320
    }
321
322
    /**
323
     * Count elements of an object
324
     * @link http://php.net/manual/en/countable.count.php
325
     * @return int The custom count as an integer.
326
     * </p>
327
     * <p>
328
     * The return value is cast to an integer.
329
     * @since 5.1.0
330
     */
331
    public function count()
332
    {
333
        return count($this->all());
334
    }
335
}
336