IndexingBy::hash()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
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
10
/**
11
 * Indexing elements by an extracted key
12
 *
13
 * Only one occurrence can be set for one key. If two elements have the same key, the last one will override the first one
14
 * It's advisable to perform a StreamInterface::distinct() using the same getter before indexing the elements if there is possible duplicate keys
15
 *
16
 * <code>
17
 * $stream = new ArrayStream([
18
 *     new Person('John', 'Doe'),
19
 *     new Person('Mickey', 'Mouse'),
20
 *     new Person('Donald', 'Duck'),
21
 * ]);
22
 *
23
 * $stream->collect(new IndexingBy(new Getter('firstName')));
24
 * // Result : Array [
25
 * //     'John'   => Person('John', 'Doe'),
26
 * //     'Mickey' => Person('Mickey', 'Mouse'),
27
 * //     'Donald' => Person('Donald', 'Duck'), ]
28
 * </code>
29
 *
30
 * @template V
31
 * @template RK
32
 * @template R of array|TableInterface
33
 *
34
 * @implements CollectorInterface<V, mixed, R>
35
 */
36
final class IndexingBy implements CollectorInterface
37
{
38
    /**
39
     * @var callable(V):RK
40
     */
41
    private $getter;
42
43
    /**
44
     * @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...
45
     */
46
    private $table;
47
48
49
    /**
50
     * GroupingBy constructor.
51
     *
52
     * @param callable(V):RK $getter Extract the group key from element
53
     * @param array<RK,V>|TableInterface<RK,V> $table The result table or array
54
     */
55 4
    public function __construct(callable $getter, iterable $table = [])
56
    {
57 4
        $this->getter = $getter;
58 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...
59 4
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 4
    public function aggregate($element, $key = null): void
65
    {
66 4
        $this->table[($this->getter)($element)] = $element;
67 4
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72 4
    public function finalize()
73
    {
74 4
        return $this->table;
75
    }
76
77
    /**
78
     * Indexing elements by a scalar key (integer or string)
79
     *
80
     * <code>
81
     * // Perform the same operation
82
     * $stream->collection(IndexingBy::scalar(function ($entity) { return $entity->firstName(); });
83
     * $stream->collection(IndexingBy::scalar(new Getter('firstName'));
84
     * $stream->collection(IndexingBy::scalar('firstName'));
85
     * </code>
86
     *
87
     * @template sV
88
     * @template sRK as array-key
89
     *
90
     * @param string|callable(sV):sRK $getter The key getter function or name
91
     *
92
     * @return IndexingBy<sV, sRK, array<sRK, sV>>
93
     */
94 1
    public static function scalar($getter): self
95
    {
96 1
        return new IndexingBy(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

96
        return new IndexingBy(is_callable($getter) ? $getter : new Getter(/** @scrutinizer ignore-type */ $getter));
Loading history...
97
    }
98
99
    /**
100
     * Indexing elements by a complex type key like array or object
101
     *
102
     * <code>
103
     * // Indexing by multiple key values
104
     * $stream->collection(IndexingBy::hash(function ($e) { return [$e->pk1(), $e->pk2()]; }));
105
     *
106
     * // Indexing by object
107
     * $stream->collection(IndexingBy::hash(new Getter('embeddedEntity'));
108
     * </code>
109
     *
110
     * @template hV
111
     * @template hRK
112
     *
113
     * @param callable(hV):hRK $getter The key getter
114
     * @param callable(hRK):array-key|null $hashFunction The hash function, which will be applied to the key value. By default use Hash::compute
115
     *
116
     * @return IndexingBy<hV, hRK, TableInterface<hRK, hV>>
117
     *
118
     * @see Hash::compute()
119
     */
120 1
    public static function hash(callable $getter, ?callable $hashFunction = null): self
121
    {
122 1
        return new IndexingBy($getter, new HashTable($hashFunction));
123
    }
124
}
125