Passed
Push — master ( 6a4583...107afa )
by Jean
02:44
created

ChainableArray_Utils_Trait::generateGroupId()   C

Complexity

Conditions 14
Paths 58

Size

Total Lines 61
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 34
nc 58
nop 2
dl 0
loc 61
rs 6.2666
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A ChainableArray_Utils_Trait::firstKey() 0 16 3
A ChainableArray_Utils_Trait::last() 0 15 3
A ChainableArray_Utils_Trait::lastKey() 0 16 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace JClaveau\Arrays;
3
4
/**
5
 * Custom functions that can be used on arrays.
6
 */
7
trait ChainableArray_Utils_Trait
8
{
9
    /**
10
     * Same as $this->groupByTransformed() without the transformer to
11
     * improve the readability in some cases.
12
     *
13
     * @param  callable $indexGenerator   Can return a scalar or an array.
14
     *         Multiple indexes allow to add a row to multiple groups.
15
     * @param  callable $conflictResolver
16
     *
17
     * @throws Missing conflict resolver
18
     *
19
     * @return array The array containing the grouped rows.
20
     */
21
    public function groupBy( callable $indexGenerator, callable $conflictResolver=null )
22
    {
23
        // todo : this doesn't work
24
        // return $this->groupByTransformed($indexGenerator, null, $conflictResolver);
25
26
        $out = [];
27
        foreach ($this->data as $key => $row) {
28
29
            if (!$row)
30
                continue;
31
32
            $newIndexes     = call_user_func($indexGenerator, $key, $row);
33
            if (!is_array($newIndexes))
34
                $newIndexes = [$newIndexes];
35
36
            foreach ($newIndexes as $newIndex) {
37
                if (!isset($out[$newIndex])) {
38
                    $out[$newIndex] = $row;
39
                }
40
                else {
41
                    if ($conflictResolver === null) {
42
                        self::throwUsageException(
43
                            "A 'group by' provoking a conflict"
44
                            ." has no conflict resolver defined:\n"
45
                            ." + key: ".$key."\n"
46
                            ." + existing: ".var_export($out[$newIndex], true)."\n"
47
                            ." + conflict: ".var_export($row, true)."\n"
48
                        );
49
                    }
50
51
                    $out[$newIndex] = call_user_func(
52
                        $conflictResolver,
53
                        $newIndex,
54
                        $out[$newIndex],
55
                        $row
56
                    );
57
                }
58
            }
59
        }
60
61
        return $this->returnConstant($out);
0 ignored issues
show
Bug introduced by
It seems like returnConstant() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

61
        return $this->/** @scrutinizer ignore-call */ returnConstant($out);
Loading history...
62
    }
63
64
    /**
65
     * Group rows in arrays indexed by the index generated by $indexGenerator
66
     *
67
     * @param  callable $indexGenerator   Can return a scalar or an array.
68
     *         Multiple indexes allow to add a row to multiple groups.
69
     *
70
     * @return array The array containing the grouped rows.
71
     */
72
    public function groupInArrays( callable $indexGenerator )
73
    {
74
        $out = [];
75
        foreach ($this->data as $key => $row) {
76
77
            if (!$row)
78
                continue;
79
80
            $new_keys = call_user_func($indexGenerator, $row, $key);
81
            if (!is_array($new_keys))
82
                $new_keys = [$new_keys];
83
84
            foreach ($new_keys as $new_key) {
85
                if (!isset($out[ $new_key ])) {
86
                    $out[ $new_key ] = [
87
                        $key => $row
88
                    ];
89
                }
90
                else {
91
                    $out[ $new_key ][ $key ] = $row;
92
                }
93
            }
94
        }
95
96
        return $this->returnConstant($out);
97
    }
98
99
    /**
100
     * Parses an array and group it rows by index. This index is generated
101
     * by the first parameter.
102
     * The row corresponding to the new index can be different from the
103
     * grouped ones so the second parameter allows us to transform them.
104
     * Finally, the third parameter is used to resolve the conflict e.g.
105
     * when two rows generate the same index.
106
     *
107
     * @paramb callable $indexGenerator
108
     * @paramb callable $rowTransformer
109
     * @paramb callable $conflictResolver
110
     *
111
     * @return array The array containing the grouped rows.
112
     */
113
    public function groupByTransformed(
114
        callable $indexGenerator,
115
        callable $rowTransformer,      // todo check this behavior
116
        callable $conflictResolver )
117
    {
118
        // The goal here is to remove the second parameter has it makes the
119
        // grouping process too complicated
120
        // if (!$conflictResolver) {
121
            // $conflictResolver = $rowTransformer;
122
            // $rowTransformer   = null;
123
        // }
124
125
        $out = [];
126
        foreach ($this->data as $key => $row) {
127
128
            if (!$row)
129
                continue;
130
131
            $newIndex       = call_user_func($indexGenerator, $key, $row);
132
133
            $transformedRow = $rowTransformer
134
                            ? call_user_func($rowTransformer, $row)
135
                            : $row;
136
137
            if (!isset($out[$newIndex])) {
138
                $out[$newIndex] = $transformedRow;
139
            }
140
            else {
141
                $out[$newIndex] = call_user_func(
142
                    $conflictResolver,
143
                    $newIndex,
144
                    $out[$newIndex],
145
                    $transformedRow,
146
                    $row
147
                );
148
            }
149
        }
150
151
        return $this->returnConstant($out);
152
    }
153
154
    /**
155
     * Merge a table into another one
156
     *
157
     * @param static $otherTable       The table to merge into
158
     * @param callable     $conflictResolver Defines what to do if two
159
     *                                       rows have the same index.
160
     * @return static
161
     */
162
    public function mergeWith( $otherTable, callable $conflictResolver=null )
163
    {
164
        if (is_array($otherTable))
0 ignored issues
show
introduced by
The condition is_array($otherTable) is always false.
Loading history...
165
            $otherTable = new static($otherTable);
166
167
        if (!$otherTable instanceof static) {
0 ignored issues
show
introduced by
$otherTable is always a sub-type of static.
Loading history...
168
            self::throwUsageException(
169
                '$otherTable must be an array or an instance of '.static::class.' instead of: '
170
                .var_export($otherTable, true)
171
            );
172
        }
173
174
        $out = $this->data;
175
        foreach ($otherTable->getArray() as $key => $row) {
0 ignored issues
show
Bug introduced by
It seems like getArray() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

175
        foreach ($otherTable->/** @scrutinizer ignore-call */ getArray() as $key => $row) {
Loading history...
176
177
            if (!isset($out[$key])) {
178
                $out[$key] = $row;
179
            }
180
            else {
181
                if ($conflictResolver === null)
182
                    self::throwUsageException('No conflict resolver for a merge provoking one');
183
184
                $arguments = [
185
                    &$key,
186
                    $out[$key],
187
                    $row
188
                ];
189
190
                $out[$key] = call_user_func_array(
191
                    $conflictResolver,
192
                    $arguments
193
                );
194
            }
195
        }
196
197
        return $this->returnConstant($out);
198
    }
199
200
    /**
201
     * Merge the table $otherTable into the current table.
202
     * (same as self::mergeWith with the other table as $this)
203
     * @return static
204
     */
205
    public function mergeIn( $otherTable, callable $conflictResolver=null )
206
    {
207
        $otherTable->mergeWith($this, $conflictResolver);
208
        return $this;
209
    }
210
211
    /**
212
     * The same as self::mergeWith with an array of tables.
213
     *
214
     * @param array $othersTable array of HelperTable
215
     * @param func  $conflictResolver callback resolver
0 ignored issues
show
Bug introduced by
The type JClaveau\Arrays\func was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
216
     */
217
    public function mergeSeveralWith(array $othersTable, callable $conflictResolver = null)
218
    {
219
        foreach ($othersTable as $otherTable) {
220
            $this->mergeWith($otherTable, $conflictResolver);
221
        }
222
223
        return $this;
224
    }
225
226
    /**
227
     *
228
     */
229
    public function each(callable $rowTransformer)
230
    {
231
        $out  = [];
232
        foreach ($this->data as $key => $row) {
233
            $out[$key] = call_user_func_array(
234
                $rowTransformer,
235
                [$row, &$key, $this->data]
236
            );
237
        }
238
239
        return $this->returnConstant($out);
240
    }
241
242
    /**
243
     * Rename a column on every row.
244
     *
245
     * @todo remove this method and force the usage of $this->renameColumns()?
246
     * @deprecated use $this->renameColumns(Array) instead]
247
     *
248
     */
249
    public function renameColumn($old_name, $new_name)
250
    {
251
        return $this->renameColumns([$old_name => $new_name]);
252
    }
253
254
    /**
255
     * Rename a column on every row.
256
     *
257
     * @return static
258
     */
259
    public function renameColumns(array $old_to_new_names)
260
    {
261
        $out  = [];
262
        foreach ($this->data as $key => $row) {
263
            try {
264
                foreach ($old_to_new_names as $old_name => $new_name) {
265
                    $row[$new_name] = $row[$old_name];
266
                    unset($row[$old_name]);
267
                }
268
            }
269
            catch (\Exception $e) {
270
                self::throwUsageException( $e->getMessage() );
271
            }
272
273
            $out[$key] = $row;
274
        }
275
276
        return $this->returnConstant($out);
277
    }
278
279
    /**
280
     * Limits the size of the array.
281
     *
282
     * @param  int         $max
283
     * @return Heper_Table $this
0 ignored issues
show
Bug introduced by
The type JClaveau\Arrays\Heper_Table was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
284
     *
285
     * @todo implement other parameters for this function like in SQL
286
     */
287
    public function limit()
288
    {
289
        $arguments = func_get_args();
290
        if (count($arguments) == 1 && is_numeric($arguments[0]))
291
            $max = $arguments[0];
292
        else
293
            self::throwUsageException("Bad arguments type and count for limit()");
294
295
        $out   = [];
296
        $count = 0;
297
        foreach ($this->data as $key => $row) {
298
299
            if ($max <= $count)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $max does not seem to be defined for all execution paths leading up to this point.
Loading history...
300
                break;
301
302
            $out[$key] = $row;
303
304
            $count++;
305
        }
306
307
        return $this->returnConstant($out);
308
    }
309
310
    /**
311
     * Appends an array to the current one.
312
     *
313
     * @param  array|static $new_rows to append
314
     * @param  callable           $conflict_resolver to use if a new row as the
315
     *                            same key as an existing row. By default, the new
316
     *                            key will be lost and the row appended as natively.
317
     *
318
     * @throws UsageException     If the $new_rows parameter is neither an array
319
     *                            nor a static.
320
     * @return static       $this
321
     */
322
    public function append($new_rows, callable $conflict_resolver=null)
323
    {
324
        if ($new_rows instanceof static)
325
            $new_rows = $new_rows->getArray();
326
327
        if (!is_array($new_rows)) {
328
            $this->throwUsageException(
0 ignored issues
show
Bug introduced by
It seems like throwUsageException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

328
            $this->/** @scrutinizer ignore-call */ 
329
                   throwUsageException(
Loading history...
329
                "\$new_rows parameter must be an array or an instance of " . __CLASS__
330
            );
331
        }
332
333
        if (!$conflict_resolver) {
334
            // default conflict resolver: append with numeric key
335
            $conflict_resolver = function (&$data, $existing_row, $confliuct_row, $key) {
336
                $data[] = $confliuct_row;
337
            };
338
        }
339
340
        foreach ($new_rows as $key => $new_row) {
341
            if (isset($this->data[$key])) {
342
                $arguments = [
343
                    &$this->data,
344
                    $existing_row,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $existing_row seems to be never defined.
Loading history...
345
                    $confliuct_row,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $confliuct_row seems to be never defined.
Loading history...
346
                    $key
347
                ];
348
349
                call_user_func_array($conflict_resolver, $arguments);
350
            }
351
            else {
352
                $this->data[$key] = $new_row;
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
353
            }
354
        }
355
356
        return $this;
357
    }
358
359
    /**
360
     * @param $columnNames scalar[] The names of the newly created columns.
361
     * @param $options     array    Unsed presently
362
     *
363
     * @see self::dimensionsAsColumns_recurser()
364
     *
365
     * @return static
366
     */
367
    public function dimensionsAsColumns(array $columnNames, array $options=null)
368
    {
369
        $out = $this->dimensionsAsColumns_recurser($this->data, $columnNames);
370
        return $this->returnConstant($out);
371
    }
372
373
    /**
374
     *
375
     * @todo Fix case of other columns
376
     *
377
     * Example:
378
     *  dimensionsAsColumns_recurser([
379
     *      [
380
     *          0,
381
     *          'me',
382
     *      ],
383
     *      [
384
     *          1,
385
     *          'me_too',
386
     *      ],
387
     *  ],
388
     *  [
389
     *      'id',
390
     *      'name',
391
     *  ]
392
     *
393
     * => [
394
     *      'id:0-name:me'     => [
395
     *          'id'   => 0,
396
     *          'name' => 'me',
397
     *      ],
398
     *      'id:1-name:me_too' => [
399
     *          'id'   => 1,
400
     *          'name' => 'me_too',
401
     *      ],
402
     * ]
403
     */
404
    protected function dimensionsAsColumns_recurser(array $data, $columnNames, $rowIdParts=[])
405
    {
406
        $out = [];
407
        // if (!$columnNames)
408
            // return $data;
409
        $no_more_column = !(bool) $columnNames;
0 ignored issues
show
Unused Code introduced by
The assignment to $no_more_column is dead and can be removed.
Loading history...
410
411
        // If all the names have been given to the dimensions
412
        // we compile the index key of the row at the current level
413
        if (empty($columnNames)) {
414
            // echo json_encode([
415
                // 'columnNames' => $columnNames,
416
                // 'rowIdParts'  => $rowIdParts,
417
                // 'data'        => $data,
418
            // ]);
419
            // exit;
420
421
            $indexParts = [];
422
            foreach ($rowIdParts as $name => $value) {
423
                $indexParts[] = $name.':'.$value;
424
            }
425
            $row_id = implode('-', $indexParts);
426
427
            // If we are at a "leaf" of the tree
428
            foreach ($rowIdParts as $name => $value) {
429
                if (isset($data[$name]) && $data[$name] !== $value) {
430
                    self::throwUsageException(
431
                         "Trying to populate a column '$name' that "
432
                        ."already exists with a different value "
433
                        .var_export($data[$name], true). " => '$value'"
434
                    );
435
                }
436
                $data[$name] = $value;
437
            }
438
439
            $out = [
440
                $row_id => $data,
441
            ];
442
443
            return $out;
444
        }
445
446
        $currentDimensionName = array_shift($columnNames);
447
448
        foreach ($data as $key => $row) {
449
450
            // if (!$no_more_column)
451
                $rowIdParts[$currentDimensionName] = $key;
452
            // else
453
                // $rowIdParts[] = $key;
454
455
456
            if (is_array($row)) {
457
                $rows = $this->dimensionsAsColumns_recurser($row, $columnNames, $rowIdParts);
458
                foreach ($rows as $row_id => $joined_row) {
459
                    $out[$row_id] = $joined_row;
460
                }
461
            }
462
            else {
463
464
                if (!isset($rows)) {
465
                    echo json_encode([
466
                        '$rowIdParts' => $rowIdParts,
467
                        '$row' => $row,
468
                    ]);
469
                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
470
                }
471
472
                foreach ($rowIdParts as $rowIdPartName => $rowIdPartValue)
473
                    $row[$rowIdPartName] = $rowIdPartValue;
474
475
                $indexParts = [];
476
                foreach ($rowIdParts as $name => $value) {
477
                    $indexParts[] = $name.':'.$value;
478
                }
479
                $row_id = implode('-', $indexParts);
480
481
                $out[$row_id] = $row;
482
            }
483
484
        }
485
486
        return $out;
487
    }
488
489
    /**
490
     * Returns the first element of the array
491
     */
492
    public function first($strict=false)
493
    {
494
        if (!$this->count()) {
0 ignored issues
show
Bug introduced by
It seems like count() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

494
        if (!$this->/** @scrutinizer ignore-call */ count()) {
Loading history...
495
            if ($strict)
496
                throw new \ErrorException("No first element found in this array");
497
            else
498
                $first = null;
499
        }
500
        else {
501
            $key   = key($this->data);
502
            $first = reset($this->data);
503
            $this->move($key);
504
        }
505
506
        return $first;
507
    }
508
509
    /**
510
     * Returns the last element of the array
511
     *
512
     * @todo Preserve the offset
513
     */
514
    public function last($strict=false)
515
    {
516
        if (!$this->count()) {
517
            if ($strict)
518
                throw new \ErrorException("No last element found in this array");
519
            else
520
                $last = null;
521
        }
522
        else {
523
            $key  = key($this->data);
524
            $last = end($this->data);
525
            $this->move($key);
526
        }
527
528
        return $last;
529
    }
530
531
    /**
532
     *
533
     */
534
    public function firstKey($strict=false)
535
    {
536
        if (!$this->count()) {
537
            if ($strict)
538
                throw new \ErrorException("No last element found in this array");
539
            else
540
                $firstKey = null;
541
        }
542
        else {
543
            $key      = key($this->data);
544
            reset($this->data);
545
            $firstKey = key($this->data);
546
            $this->move($key);
547
        }
548
549
        return $firstKey;
550
    }
551
552
    /**
553
     *
554
     */
555
    public function lastKey($strict=false)
556
    {
557
        if (!$this->count()) {
558
            if ($strict)
559
                throw new \ErrorException("No last element found in this array");
560
            else
561
                $lastKey = null;
562
        }
563
        else {
564
            $key  = key($this->data);
565
            end($this->data);
566
            $lastKey = key($this->data);
567
            $this->move($key);
568
        }
569
570
        return $lastKey;
571
    }
572
573
    /**
574
     * Move the internal pointer of the array to the key given as parameter
575
     */
576
    public function move($key, $strict=true)
577
    {
578
        if (array_key_exists($key, $this->data)) {
579
            foreach ($this->data as $i => &$value) {
580
                if ($i === $key) {
581
                    prev($this->data);
582
                    break;
583
                }
584
            }
585
        }
586
        elseif ($strict) {
587
            throw new \ErrorException("Unable to move the internal pointer to a key that doesn't exist.");
588
        }
589
590
        return $this;
591
    }
592
593
    /**
594
     * Chained equivalent of in_array().
595
     * @return bool
596
     */
597
    public function contains($value)
598
    {
599
        return in_array($value, $this->data);
600
    }
601
602
    /**
603
     * Checks if the array is associative or not.
604
     * @return bool
605
     */
606
    public function isAssoc()
607
    {
608
        return Arrays::isAssoc($this->getArray());
0 ignored issues
show
Bug introduced by
The method isAssoc() does not exist on JClaveau\Arrays\Arrays. Did you maybe mean isAssociative()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

608
        return Arrays::/** @scrutinizer ignore-call */ isAssoc($this->getArray());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
609
    }
610
611
    /**
612
     * Checks if the array is empty or not.
613
     * @return bool
614
     */
615
    public function isEmpty()
616
    {
617
        return empty($this->getArray());
618
    }
619
620
    /**
621
     * Computes the weighted mean of the values of a column weighted
622
     * by the values of a second one.
623
     *
624
     * @param  string $valueColumnName
625
     * @param  string $weightColumnName
626
     *
627
     * @return float The calculated weighted mean.
628
     */
629
    public function weightedMean($valueColumnName, $weightColumnName)
630
    {
631
        $values  = array_column($this->data, $valueColumnName);
632
        $weights = array_column($this->data, $weightColumnName);
633
634
        return Arrays::weightedMean($values, $weights);
635
    }
636
637
    /**
638
     * Equivalent of var_dump().
639
     *
640
     * @see http://php.net/manual/fr/function.var-dump.php
641
     * @todo Handle xdebug dump formatting
642
     */
643
    public function dump($exit=false)
644
    {
645
        $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
646
        $caller = $bt[0];
647
648
        var_export([
649
            'location' => $caller['file'] . ':' . $caller['line'],
650
            'data'     => $this->data,
651
        ]);
652
653
        if ($exit)
654
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
655
656
        return $this;
657
    }
658
659
    /**
660
     * Scans the array recursivelly (until the max depthis reached) and replaces
661
     * the entries with the callback;
662
     *
663
     * @todo move it to an Arrays class storing static methods
664
     */
665
    public static function replaceEntries(
666
        array $array, callable $replacer, $max_depth=null
667
    ) {
668
        foreach ($array as $key => &$row) {
669
            $arguments = [&$row, $key];
670
            call_user_func_array($replacer, $arguments);
671
672
            if (is_array($row) && $max_depth !== 0) { // allowing null to have no depth limit
673
                $row = self::replaceEntries(
674
                    $row, $replacer, $max_depth ? $max_depth-1 : $max_depth
675
                );
676
            }
677
        }
678
679
        return $array;
680
    }
681
682
    /**
683
     * Equivalent of ->filter() but removes the matching values
684
     *
685
     * @param  callable|array $callback The filter logic with $value and $key
686
     *                            as parameters.
687
     *
688
     * @return static $this or a new static.
689
     */
690
    public function extract($callback=null)
691
    {
692
        if ($callback) {
693
694
            if (is_array($callback)) {
695
                $callback = new \JClaveau\LogicalFilter\LogicalFilter($callback);
0 ignored issues
show
Bug introduced by
The type JClaveau\LogicalFilter\LogicalFilter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
696
            }
697
698
            if (!is_callable($callback)) {
699
                $this->throwUsageException(
700
                    "\$callback must be a logical filter description array or a callable"
701
                    ." instead of "
702
                    .var_export($callback, true)
703
                );
704
            }
705
706
            $out = [];
707
            foreach ($this->data as $key => $value) {
708
                if ($callback($value, $key)) {
709
                    $out[$key] = $value;
710
                    unset( $this->data[$key] );
711
                }
712
            }
713
        }
714
715
        return new static($out);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $out does not seem to be defined for all execution paths leading up to this point.
Loading history...
Unused Code introduced by
The call to JClaveau\Arrays\Chainabl...ls_Trait::__construct() has too many arguments starting with $out. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

715
        return /** @scrutinizer ignore-call */ new static($out);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
716
    }
717
718
    /**/
719
}
720