GroupingBy   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 16
c 1
b 0
f 0
dl 0
loc 105
ccs 19
cts 19
cp 1
rs 10
wmc 8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A scalar() 0 3 2
A finalize() 0 3 1
A __construct() 0 5 1
A hash() 0 3 1
A aggregate() 0 12 3
1
<?php
2
3
namespace Bdf\Collection\Stream\Collector;
4
5
use Bdf\Collection\HashTable;
6
use Bdf\Collection\TableInterface;
7
use Bdf\Collection\Util\Functor\Transformer\Getter;
8
use Bdf\Collection\Util\Hash;
9
use function is_callable;
10
11
/**
12
 * Grouping elements by an extracted key
13
 *
14
 * Elements with same key will be append to an array
15
 *
16
 * <code>
17
 * $stream = new ArrayStream([
18
 *     new Person('John', 'Doe'),
19
 *     new Person('John', 'Smith'),
20
 *     new Person('Mickey', 'Mouse'),
21
 *     new Person('Donald', 'Duck'),
22
 * ]);
23
 *
24
 * $stream->collect(new GroupingBy(new Getter('firstName')));
25
 * // Result : Array [
26
 * //     'John'   => [ Person('John', 'Doe'), Person('John', 'Smith') ],
27
 * //     'Mickey' => [ Person('Mickey', 'Mouse') ],
28
 * //     'Donald' => [ Person('Donald', 'Duck') ], ]
29
 * </code>
30
 *
31
 * @template V
32
 * @template K
33
 * @template RK
34
 * @template R of array|TableInterface
35
 *
36
 * @implements CollectorInterface<V, K, R>
37
 */
38
final class GroupingBy implements CollectorInterface
39
{
40
    /**
41
     * @var callable
42
     */
43
    private $getter;
44
45
    /**
46
     * @var bool
47
     */
48
    private $preserveKeys;
49
50
    /**
51
     * @var R
0 ignored issues
show
Bug introduced by
The type Bdf\Collection\Stream\Collector\R 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...
52
     */
53
    private $table;
54
55
56
    /**
57
     * GroupingBy constructor.
58
     *
59
     * @param callable(V):RK $getter Extract the group key from element
60
     * @param bool $preserveKeys Preserve the keys on group array
61
     * @param array<RK, V[]>|TableInterface<RK, V[]> $table The result table or array
62
     */
63 4
    public function __construct(callable $getter, bool $preserveKeys = false, iterable $table = [])
64
    {
65 4
        $this->getter = $getter;
66 4
        $this->preserveKeys = $preserveKeys;
67 4
        $this->table = $table;
0 ignored issues
show
Documentation Bug introduced by
It seems like $table of type iterable or array is incompatible with the declared type Bdf\Collection\Stream\Collector\R of property $table.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
68 4
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73 4
    public function aggregate($element, $key = null): void
74
    {
75 4
        $groupKey = ($this->getter)($element);
76
77 4
        if (!isset($this->table[$groupKey])) {
78 4
            $this->table[$groupKey] = [];
79
        }
80
81 4
        if ($this->preserveKeys) {
82 1
            $this->table[$groupKey][$key] = $element;
83
        } else {
84 3
            $this->table[$groupKey][] = $element;
85
        }
86 4
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 4
    public function finalize()
92
    {
93 4
        return $this->table;
94
    }
95
96
    /**
97
     * Grouping elements by a scalar key (integer or string)
98
     *
99
     * <code>
100
     * // Perform the same operation
101
     * $stream->collection(GroupingBy::scalar(function ($entity) { return $entity->firstName(); });
102
     * $stream->collection(GroupingBy::scalar(new Getter('firstName'));
103
     * $stream->collection(GroupingBy::scalar('firstName'));
104
     * </code>
105
     *
106
     * @template sV
107
     * @template sRK of array-key
108
     *
109
     * @param string|callable(sV):sRK $getter The key getter function or name
110
     *
111
     * @return GroupingBy<sV, mixed, sRK, array<sRK, sV[]>>
112
     */
113 1
    public static function scalar($getter): self
114
    {
115 1
        return new GroupingBy(is_callable($getter) ? $getter : new Getter($getter));
0 ignored issues
show
Bug introduced by
It seems like $getter can also be of type callable; however, parameter $name of Bdf\Collection\Util\Func...r\Getter::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

115
        return new GroupingBy(is_callable($getter) ? $getter : new Getter(/** @scrutinizer ignore-type */ $getter));
Loading history...
116
    }
117
118
    /**
119
     * Indexing elements by a complex type key like array or object
120
     *
121
     * <code>
122
     * // Grouping by multiple key values
123
     * $stream->collection(GroupingBy::hash(function ($e) { return [$e->pk1(), $e->pk2()]; }));
124
     *
125
     * // Grouping by object
126
     * $stream->collection(GroupingBy::hash(new Getter('embeddedEntity'));
127
     * </code>
128
     *
129
     * @template hV
130
     * @template hRK
131
     *
132
     * @param callable(hV):hRK $getter The key getter
133
     * @param bool $preserveKeys Preserve the key on the group array
134
     * @param callable(hRK):array-key|null $hashFunction The hash function, which will be applied to the key value. By default use Hash::compute
135
     *
136
     * @return GroupingBy<hV, mixed, hRK, TableInterface<hRK, hV[]>>
137
     *
138
     * @see Hash::compute()
139
     */
140 1
    public static function hash(callable $getter, bool $preserveKeys = false, callable $hashFunction = null): self
141
    {
142 1
        return new GroupingBy($getter, $preserveKeys, new HashTable($hashFunction));
143
    }
144
}
145