Passed
Push — master ( 1a4698...0b2a91 )
by Jean
03:30 queued 52s
created

ChainableArray_Utils_Trait::flatten()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 28
rs 9.0777
c 0
b 0
f 0
cc 6
nc 6
nop 0
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(
183
                        "No conflict resolver for a merge provoking one: $key \n\n"
184
                        .var_export($row, true) . "\n\n"
185
                        .var_export($out[$key], true)
186
                    );
187
                }
188
189
                $arguments = [
190
                    &$key,
191
                    $out[$key],
192
                    $row
193
                ];
194
195
                $out[$key] = call_user_func_array(
196
                    $conflictResolver,
197
                    $arguments
198
                );
199
            }
200
        }
201
202
        return $this->returnConstant($out);
203
    }
204
205
    /**
206
     * Merge the table $otherTable into the current table.
207
     * (same as self::mergeWith with the other table as $this)
208
     * @return static
209
     */
210
    public function mergeIn( $otherTable, callable $conflictResolver=null )
211
    {
212
        $otherTable->mergeWith($this, $conflictResolver);
213
        return $this;
214
    }
215
216
    /**
217
     * The same as self::mergeWith with an array of tables.
218
     *
219
     * @param array $othersTable array of HelperTable
220
     * @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...
221
     */
222
    public function mergeSeveralWith(array $othersTable, callable $conflictResolver = null)
223
    {
224
        foreach ($othersTable as $otherTable) {
225
            $this->mergeWith($otherTable, $conflictResolver);
226
        }
227
228
        return $this;
229
    }
230
231
    /**
232
     *
233
     */
234
    public function each(callable $rowTransformer)
235
    {
236
        $out  = [];
237
        foreach ($this->data as $key => $row) {
238
            $out[$key] = call_user_func_array(
239
                $rowTransformer,
240
                [$row, &$key, $this->data]
241
            );
242
        }
243
244
        return $this->returnConstant($out);
245
    }
246
247
    /**
248
     * Rename a column on every row.
249
     *
250
     * @todo remove this method and force the usage of $this->renameColumns()?
251
     * @deprecated use $this->renameColumns(Array) instead]
252
     *
253
     */
254
    public function renameColumn($old_name, $new_name)
255
    {
256
        return $this->renameColumns([$old_name => $new_name]);
257
    }
258
259
    /**
260
     * Rename a column on every row.
261
     *
262
     * @return static
263
     */
264
    public function renameColumns(array $old_to_new_names)
265
    {
266
        $out  = [];
267
        foreach ($this->data as $key => $row) {
268
            try {
269
                foreach ($old_to_new_names as $old_name => $new_name) {
270
                    $row[$new_name] = $row[$old_name];
271
                    unset($row[$old_name]);
272
                }
273
            }
274
            catch (\Exception $e) {
275
                self::throwUsageException( $e->getMessage() );
276
            }
277
278
            $out[$key] = $row;
279
        }
280
281
        return $this->returnConstant($out);
282
    }
283
284
    /**
285
     * Limits the size of the array.
286
     *
287
     * @param  int         $max
288
     * @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...
289
     *
290
     * @todo implement other parameters for this function like in SQL
291
     */
292
    public function limit()
293
    {
294
        $arguments = func_get_args();
295
        if (count($arguments) == 1 && is_numeric($arguments[0]))
296
            $max = $arguments[0];
297
        else
298
            self::throwUsageException("Bad arguments type and count for limit()");
299
300
        $out   = [];
301
        $count = 0;
302
        foreach ($this->data as $key => $row) {
303
304
            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...
305
                break;
306
307
            $out[$key] = $row;
308
309
            $count++;
310
        }
311
312
        return $this->returnConstant($out);
313
    }
314
315
    /**
316
     * Appends an array to the current one.
317
     *
318
     * @param  array|static $new_rows to append
319
     * @param  callable           $conflict_resolver to use if a new row as the
320
     *                            same key as an existing row. By default, the new
321
     *                            key will be lost and the row appended as natively.
322
     *
323
     * @throws UsageException     If the $new_rows parameter is neither an array
324
     *                            nor a static.
325
     * @return static       $this
326
     */
327
    public function append($new_rows, callable $conflict_resolver=null)
328
    {
329
        if ($new_rows instanceof static)
330
            $new_rows = $new_rows->getArray();
331
332
        if (!is_array($new_rows)) {
333
            $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

333
            $this->/** @scrutinizer ignore-call */ 
334
                   throwUsageException(
Loading history...
334
                "\$new_rows parameter must be an array or an instance of " . __CLASS__
335
            );
336
        }
337
338
        if (!$conflict_resolver) {
339
            // default conflict resolver: append with numeric key
340
            $conflict_resolver = function (&$data, $existing_row, $confliuct_row, $key) {
341
                $data[] = $confliuct_row;
342
            };
343
        }
344
345
        foreach ($new_rows as $key => $new_row) {
346
            if (isset($this->data[$key])) {
347
                $arguments = [
348
                    &$this->data,
349
                    $existing_row,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $existing_row seems to be never defined.
Loading history...
350
                    $confliuct_row,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $confliuct_row seems to be never defined.
Loading history...
351
                    $key
352
                ];
353
354
                call_user_func_array($conflict_resolver, $arguments);
355
            }
356
            else {
357
                $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...
358
            }
359
        }
360
361
        return $this;
362
    }
363
364
    /**
365
     * @param $columnNames scalar[] The names of the newly created columns.
366
     * @param $options     array    Unsed presently
367
     *
368
     * @see self::dimensionsAsColumns_recurser()
369
     *
370
     * @return static
371
     */
372
    public function dimensionsAsColumns(array $columnNames, array $options=null)
373
    {
374
        $out = $this->dimensionsAsColumns_recurser($this->data, $columnNames);
375
        return $this->returnConstant($out);
376
    }
377
378
    /**
379
     *
380
     * @todo Fix case of other columns
381
     *
382
     * Example:
383
     *  dimensionsAsColumns_recurser([
384
     *      [
385
     *          0,
386
     *          'me',
387
     *      ],
388
     *      [
389
     *          1,
390
     *          'me_too',
391
     *      ],
392
     *  ],
393
     *  [
394
     *      'id',
395
     *      'name',
396
     *  ]
397
     *
398
     * => [
399
     *      'id:0-name:me'     => [
400
     *          'id'   => 0,
401
     *          'name' => 'me',
402
     *      ],
403
     *      'id:1-name:me_too' => [
404
     *          'id'   => 1,
405
     *          'name' => 'me_too',
406
     *      ],
407
     * ]
408
     */
409
    protected function dimensionsAsColumns_recurser(array $data, $columnNames, $rowIdParts=[])
410
    {
411
        $out = [];
412
        // if (!$columnNames)
413
            // return $data;
414
        $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...
415
416
        // If all the names have been given to the dimensions
417
        // we compile the index key of the row at the current level
418
        if (empty($columnNames)) {
419
            // echo json_encode([
420
                // 'columnNames' => $columnNames,
421
                // 'rowIdParts'  => $rowIdParts,
422
                // 'data'        => $data,
423
            // ]);
424
            // exit;
425
426
            $indexParts = [];
427
            foreach ($rowIdParts as $name => $value) {
428
                $indexParts[] = $name.':'.$value;
429
            }
430
            $row_id = implode('-', $indexParts);
431
432
            // If we are at a "leaf" of the tree
433
            foreach ($rowIdParts as $name => $value) {
434
                if (isset($data[$name]) && $data[$name] !== $value) {
435
                    self::throwUsageException(
436
                         "Trying to populate a column '$name' that "
437
                        ."already exists with a different value "
438
                        .var_export($data[$name], true). " => '$value'"
439
                    );
440
                }
441
                $data[$name] = $value;
442
            }
443
444
            $out = [
445
                $row_id => $data,
446
            ];
447
448
            return $out;
449
        }
450
451
        $currentDimensionName = array_shift($columnNames);
452
453
        foreach ($data as $key => $row) {
454
455
            // if (!$no_more_column)
456
                $rowIdParts[$currentDimensionName] = $key;
457
            // else
458
                // $rowIdParts[] = $key;
459
460
461
            if (is_array($row)) {
462
                $rows = $this->dimensionsAsColumns_recurser($row, $columnNames, $rowIdParts);
463
                foreach ($rows as $row_id => $joined_row) {
464
                    $out[$row_id] = $joined_row;
465
                }
466
            }
467
            else {
468
469
                if (!isset($rows)) {
470
                    echo json_encode([
471
                        '$rowIdParts' => $rowIdParts,
472
                        '$row' => $row,
473
                    ]);
474
                    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...
475
                }
476
477
                foreach ($rowIdParts as $rowIdPartName => $rowIdPartValue)
478
                    $row[$rowIdPartName] = $rowIdPartValue;
479
480
                $indexParts = [];
481
                foreach ($rowIdParts as $name => $value) {
482
                    $indexParts[] = $name.':'.$value;
483
                }
484
                $row_id = implode('-', $indexParts);
485
486
                $out[$row_id] = $row;
487
            }
488
489
        }
490
491
        return $out;
492
    }
493
494
    /**
495
     * Returns the first element of the array
496
     */
497
    public function first($strict=false)
498
    {
499
        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

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

613
        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...
614
    }
615
616
    /**
617
     * Checks if the array is empty or not.
618
     * @return bool
619
     */
620
    public function isEmpty()
621
    {
622
        return empty($this->getArray());
623
    }
624
625
    /**
626
     * Computes the weighted mean of the values of a column weighted
627
     * by the values of a second one.
628
     *
629
     * @param  string $valueColumnName
630
     * @param  string $weightColumnName
631
     *
632
     * @return float The calculated weighted mean.
633
     */
634
    public function weightedMean($valueColumnName, $weightColumnName)
635
    {
636
        $values  = array_column($this->data, $valueColumnName);
637
        $weights = array_column($this->data, $weightColumnName);
638
639
        return Arrays::weightedMean($values, $weights);
640
    }
641
642
    /**
643
     * Equivalent of var_dump().
644
     *
645
     * @see http://php.net/manual/fr/function.var-dump.php
646
     * @todo Handle xdebug dump formatting
647
     */
648
    public function dump($exit=false)
649
    {
650
        $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
651
        $caller = $bt[0];
652
653
        var_export([
654
            'location' => $caller['file'] . ':' . $caller['line'],
655
            'data'     => $this->data,
656
        ]);
657
658
        if ($exit)
659
            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...
660
661
        return $this;
662
    }
663
664
    /**
665
     * Scans the array recursivelly (until the max depthis reached) and replaces
666
     * the entries with the callback;
667
     *
668
     * @todo move it to an Arrays class storing static methods
669
     */
670
    public static function replaceEntries(
671
        array $array, callable $replacer, $max_depth=null
672
    ) {
673
        foreach ($array as $key => &$row) {
674
            $arguments = [&$row, $key];
675
            call_user_func_array($replacer, $arguments);
676
677
            if (is_array($row) && $max_depth !== 0) { // allowing null to have no depth limit
678
                $row = self::replaceEntries(
679
                    $row, $replacer, $max_depth ? $max_depth-1 : $max_depth
680
                );
681
            }
682
        }
683
684
        return $array;
685
    }
686
687
    /**
688
     * Equivalent of ->filter() but removes the matching values
689
     *
690
     * @param  callable|array $callback The filter logic with $value and $key
691
     *                            as parameters.
692
     *
693
     * @return static $this or a new static.
694
     */
695
    public function extract($callback=null)
696
    {
697
        if ($callback) {
698
699
            if (is_array($callback)) {
700
                $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...
701
            }
702
703
            if (!is_callable($callback)) {
704
                $this->throwUsageException(
705
                    "\$callback must be a logical filter description array or a callable"
706
                    ." instead of "
707
                    .var_export($callback, true)
708
                );
709
            }
710
711
            $out = [];
712
            foreach ($this->data as $key => $value) {
713
                if ($callback($value, $key)) {
714
                    $out[$key] = $value;
715
                    unset( $this->data[$key] );
716
                }
717
            }
718
        }
719
720
        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

720
        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...
721
    }
722
723
    /**
724
     * 
725
     */
726
    public function flatten()
727
    {
728
        $result = [];
729
        foreach ($this->data as $key => $value) {
730
            if ( ! Arrays::isTraversable($value)) {
731
                $result[ $key ] = $value;
732
            }
733
            else {
734
                foreach ($value as $sub_key => $sub_value) {
735
                    if (is_int($sub_key)) {
736
                        $result[] = $sub_value;
737
                    }
738
                    elseif (isset($result[ $sub_key ])) {
739
                        throw new \LogicException(
740
                            "Conflict during flatten merge for key $sub_key between: \n"
741
                            ."Existing: " . var_export($result[ $sub_key ], true)
742
                            ."\n and \n"
743
                            ."Conflict: " . var_export($sub_value, true)
744
                        );
745
                    }
746
                    else {
747
                        $result[ $sub_key ] = $sub_value;
748
                    }
749
                }
750
            }
751
        }
752
753
        return $this->returnConstant($result);
754
    }
755
756
    public function flattenMergeBuckets()
757
    {
758
        $result = Arrays::flattenMergeBuckets($this->data);
759
        return $this->returnConstant($result);
760
    }
761
    
762
    /**/
763
}
764