Map::replaceAll()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 3
ccs 3
cts 3
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * @author hashashiyyin [email protected] / [email protected]
5
 * Date: 24/05/24
6
 * Time: 13:41
7
 *
8
 */
9
10
namespace Matecat\SubFiltering\Utils;
11
12
use ArrayAccess;
13
use ArrayIterator;
14
use Countable;
15
use DomainException;
16
use Generator;
17
use IteratorAggregate;
18
19
/**
20
 * A Java like Interface helper for key/value php arrays, with safe access to the elements (no warning for undefined index)
21
 *
22
 */
23
class Map implements ArrayAccess, IteratorAggregate, Countable {
24
25
    /**
26
     * @var array
27
     */
28
    private $map;
29
30 75
    public function __construct( array $map ) {
31 75
        if ( !empty( $map ) && Utils::array_is_list( $map ) ) {
32 1
            throw new DomainException( "Invalid map provided" );
33
        }
34 74
        $this->map = $map;
35 74
    }
36
37
    /**
38
     * @return int
39
     */
40 10
    public function count() {
41 10
        return sizeof( $this->map );
42
    }
43
44
45
    /**
46
     * @return ArrayIterator
47
     */
48 2
    public function getIterator() {
49 2
        return new ArrayIterator( $this->map );
50
    }
51
52
    /**
53
     * @param $offset
54
     *
55
     * @return bool
56
     */
57 1
    public function offsetExists( $offset ) {
58 1
        return array_key_exists( $offset, $this->map );
59
    }
60
61
    /**
62
     * @param $offset
63
     *
64
     * @return mixed|null
65
     */
66 1
    public function offsetGet( $offset ) {
67 1
        return $this->get( $offset );
68
    }
69
70
    /**
71
     * @param $offset
72
     * @param $value
73
     *
74
     * @return void
75
     */
76 1
    public function offsetSet( $offset, $value ) {
77 1
        $this->put( $offset, $value );
78 1
    }
79
80
    /**
81
     * @param $offset
82
     *
83
     * @return void
84
     */
85 1
    public function offsetUnset( $offset ) {
86 1
        $this->remove( $offset );
87 1
    }
88
89
    /**
90
     * Static helper for constructor
91
     *
92
     * @param array $map
93
     *
94
     * @return static
95
     */
96 75
    public static function instance( array $map = [] ) {
97 75
        return new static( $map );
98
    }
99
100
    /**
101
     * Safe key access. Avoid warnings.
102
     *
103
     * @param       $needle
104
     *
105
     * @return mixed|null
106
     */
107 61
    public function get( $needle ) {
108 61
        return $this->getOrDefault( $needle, null );
109
    }
110
111
    /**
112
     * @param $needle
113
     * @param $default
114
     *
115
     * @return mixed
116
     */
117 61
    public function getOrDefault( $needle, $default ) {
118 61
        return array_key_exists( $needle, $this->map ) ? $this->map [ $needle ] : $default;
119
    }
120
121
    /**
122
     * Removes all the mappings from this map.
123
     * @return void
124
     */
125 1
    public function clear() {
126 1
        $this->map = [];
127 1
    }
128
129
    /**
130
     * Returns a shallow copy of this HashMap instance: the keys and values themselves are not cloned.
131
     * @return $this
132
     */
133 1
    public function __clone() {
134 1
        return new static( $this->map );
135
    }
136
137 1
    public function containsKey( $offset ) {
138 1
        return array_key_exists( $offset, $this->map );
139
    }
140
141
    /**
142
     * Returns true if this map maps one or more keys to the specified value.
143
     * If the value is found more than once, the first matching key is returned.
144
     *
145
     * @param $value
146
     *
147
     * @return boolean
148
     */
149 1
    public function containsValue( $value ) {
150 1
        return !empty( array_search( $value, $this->map, true ) );
151
    }
152
153
    /**
154
     * Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.
155
     * Actions are performed in the order of entry set iteration.
156
     *
157
     * @param callable $callable
158
     *
159
     * @return Generator
160
     */
161 1
    public function for_each( callable $callable ) {
162 1
        foreach ( $this->map as $k => $v ) {
163 1
            $callable( $k, $v );
164
        }
165 1
    }
166
167
    /**
168
     * Returns true if this map contains no key-value mappings.
169
     *
170
     * @return bool
171
     */
172 55
    public function isEmpty() {
173 55
        return empty( $this->map );
174
    }
175
176
    /**
177
     * @return string[]
178
     */
179 1
    public function keySet() {
180 1
        return array_keys( $this->map );
181
    }
182
183
    /**
184
     * Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
185
     *
186
     * @param $offset
187
     * @param $value
188
     *
189
     * @return mixed|null the previous value associated with `key`, or null if there was no mapping for `key`.
190
     */
191 3
    public function put( $offset, $value ) {
192 3
        $previousValue        = $this->get( $offset );
193 3
        $this->map[ $offset ] = $value;
194
195 3
        return $previousValue;
196
    }
197
198
    /**
199
     * @param $map
200
     *
201
     * @return void
202
     */
203 1
    public function putAll( $map ) {
204 1
        foreach ( $map as $k => $v ) {
205 1
            $this->map[ $k ] = $v;
206
        }
207 1
    }
208
209
    /**
210
     * If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.
211
     *
212
     * @param $offset
213
     * @param $value
214
     *
215
     * @return mixed|null the previous value associated with the specified key, or null if there was no mapping for the key.
216
     *               A null return can also indicate that the map previously associated null with the `key`
217
     */
218 1
    public function putIfAbsent( $offset, $value ) {
219 1
        $previousValue = $this->get( $offset );
220 1
        if ( $previousValue === null ) {
221 1
            $this->map[ $offset ] = $value;
222
        }
223
224 1
        return $previousValue;
225
    }
226
227
    /**
228
     * Removes the mapping for the specified key from this map if present.
229
     *
230
     * @param $offset
231
     *
232
     * @return bool true if the value was removed
233
     */
234 2
    public function remove( $offset ) {
235 2
        $exists = array_key_exists( $offset, $this->map );
236 2
        if ( $exists ) {
237 2
            unset( $this->map[ $offset ] );
238
        }
239
240 2
        return $exists;
241
    }
242
243
    /**
244
     * Replaces the entry for the specified key only if it is currently mapped to some value.
245
     *
246
     * @return mixed|null the previous value associated with the specified key, or null if there was no mapping for the key.
247
     *                      A null return can also indicate that the map previously associated null with the key.
248
     */
249 1
    public function replace( $offset, $value ) {
250 1
        $exists        = array_key_exists( $offset, $this->map );
251 1
        $previousValue = $this->get( $offset );
252 1
        if ( $exists ) {
253 1
            $this->map[ $offset ] = $value;
254
        }
255
256 1
        return $previousValue;
257
    }
258
259
    /**
260
     * Replaces the entry for the specified key only if currently mapped to the specified value.
261
     *
262
     * @param $offset
263
     * @param $newValue
264
     * @param $oldValue
265
     *
266
     * @return boolean true if the value was replaced
267
     */
268 1
    public function replaceIfEquals( $offset, $newValue, $oldValue ) {
269 1
        $exists        = array_key_exists( $offset, $this->map );
270 1
        $previousValue = $this->get( $offset );
271 1
        if ( $exists && $previousValue === $oldValue ) {
272 1
            $this->map[ $offset ] = $newValue;
273
274 1
            return true;
275
        }
276
277 1
        return false;
278
    }
279
280
    /**
281
     * Replaces each entry's value with the result of invoking the given function on that entry until all entries have been processed,
282
     * or the function throws an exception.
283
     * Exceptions thrown by the function are relayed to the caller.
284
     *
285
     * @param callable $callable
286
     *
287
     * @return void
288
     */
289 1
    public function replaceAll( callable $callable ) {
290 1
        foreach ( $this->map as $offset => $value ) {
291 1
            $this->map[ $offset ] = $callable( $offset, $value );
292
        }
293 1
    }
294
295
    /**
296
     * @return int
297
     */
298 3
    public function size() {
299 3
        return sizeof( $this->map );
300
    }
301
302
    /**
303
     * @return array
304
     */
305 1
    public function values() {
306 1
        return array_values( $this->map );
307
    }
308
309
    /**
310
     * Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
311
     * For example, to either create or append a String msg to a value mapping:
312
     * <code>
313
     *     $_empty = 'EMPTY';
314
     *     $map->compute( "foo", function( $k, $v ) use ( $_empty ) { ($v == null) ? $_empty : 'NO MORE ' . $_empty  } );
315
     * </code>
316
     *
317
     * If the function returns null, the mapping is removed (or remains absent if initially absent).
318
     * If the function itself throws an (unchecked) exception, the exception is rethrown, and the current mapping is left unchanged.
319
     *
320
     * @param          $offset
321
     * @param callable $callable
322
     *
323
     * @return mixed|null the new value associated with the specified key, or null if none
324
     */
325 1
    public function compute( $offset, callable $callable ) {
326 1
        $exists = array_key_exists( $offset, $this->map );
327 1
        if ( $exists ) {
328 1
            $res = $callable( $offset, $this->get( $offset ) );
329 1
            if ( $res == null ) {
330 1
                unset( $this->map[ $offset ] );
331
            } else {
332 1
                $this->map[ $offset ] = $callable( $offset, $this->get( $offset ) );
333
334 1
                return $this->map[ $offset ];
335
            }
336
        }
337
338 1
        return null;
339
    }
340
341
    /**
342
     * If the specified key is not already associated with a value (or is mapped to null),
343
     * attempts to compute its value using the given mapping function and enters it into this map unless null.
344
     *
345
     * If the function returns null, no mapping is recorded. If the function itself throws an (unchecked) exception,
346
     * the exception is rethrown, and no mapping is recorded.
347
     *
348
     * The most common usage is to construct a new object serving as an initial mapped value or memoized result, as in:
349
     *
350
     * @param          $offset
351
     * @param callable $callable
352
     *
353
     * @return mixed|null the current (existing or computed) value associated with the specified key, or null if the computed value is null
354
     */
355 1
    public function computeIfAbsent( $offset, callable $callable ) {
356 1
        $exists        = array_key_exists( $offset, $this->map );
357 1
        $previousValue = $this->get( $offset );
358 1
        $res           = null;
359 1
        if ( !$exists || $previousValue === null ) {
360 1
            $res = $callable( $offset, $this->get( $offset ) );
361 1
            if ( $res != null ) {
362 1
                $this->map[ $offset ] = $res;
363
            }
364
365
        }
366
367 1
        return $res ?: null;
368
369
    }
370
371
    /**
372
     * If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
373
     *
374
     * If the function returns null, the mapping is removed.
375
     * If the function itself throws an (unchecked) exception, the exception is rethrown, and the current mapping is left unchanged.
376
     *
377
     * @param          $offset
378
     * @param callable $callable
379
     *
380
     * @return mixed|null the new value associated with the specified key, or null if none
381
     */
382 1
    public function computeIfPresent( $offset, callable $callable ) {
383 1
        $exists        = array_key_exists( $offset, $this->map );
384 1
        $previousValue = $this->get( $offset );
385 1
        $res           = null;
386 1
        if ( $exists && $previousValue !== null ) {
387 1
            $res = $callable( $offset, $this->map[ $offset ] );
388 1
            if ( $res == null ) {
389 1
                unset( $this->map[ $offset ] );
390
            } else {
391 1
                $this->map[ $offset ] = $res;
392
            }
393
        }
394
395 1
        return $res ?: null;
396
    }
397
398
}