Passed
Pull Request — 1.x (#346)
by Akihito
03:15 queued 01:34
created

Requests::groupBy()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource\DataLoader;
6
7
use function parse_str;
8
use function parse_url;
9
10
use const PHP_URL_QUERY;
11
12
/**
13
 * Collection of URIs for DataLoader processing with helper methods
14
 *
15
 * @psalm-type UriString = string
16
 */
17
final class Requests
18
{
19
    /** @param list<string> $uris */
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\DataLoader\list 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...
20
    public function __construct(private readonly array $uris)
21
    {
22
    }
23
24
    /**
25
     * Get all URIs
26
     *
27
     * @return list<string>
28
     */
29
    public function uris(): array
30
    {
31
        return $this->uris;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->uris returns the type array which is incompatible with the documented return type BEAR\Resource\DataLoader\list.
Loading history...
32
    }
33
34
    /**
35
     * Get values of a specific query parameter from all URIs
36
     *
37
     * @return list<mixed>
38
     */
39
    public function getQueryParam(string $name): array
40
    {
41
        $values = [];
42
        foreach ($this->uris as $uri) {
43
            $query = $this->parseQuery($uri);
44
            if (! isset($query[$name])) {
45
                continue;
46
            }
47
48
            /** @psalm-suppress MixedAssignment -- $query values are mixed by design */
49
            $values[] = $query[$name];
50
        }
51
52
        return $values;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $values returns the type array which is incompatible with the documented return type BEAR\Resource\DataLoader\list.
Loading history...
53
    }
54
55
    /**
56
     * Group URIs by a query parameter value
57
     *
58
     * @return array<string, list<string>> parameter value => URIs
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, list<string>> at position 4 could not be parsed: Expected '>' at position 4, but found 'list'.
Loading history...
59
     */
60
    public function groupBy(string $paramName): array
61
    {
62
        $grouped = [];
63
        foreach ($this->uris as $uri) {
64
            $query = $this->parseQuery($uri);
65
            if (! isset($query[$paramName])) {
66
                continue;
67
            }
68
69
            $key = (string) $query[$paramName];
70
            $grouped[$key][] = $uri;
71
        }
72
73
        return $grouped;
74
    }
75
76
    /**
77
     * Map result rows to URIs based on a key column
78
     *
79
     * @param list<array<string, mixed>> $rows      Result rows from database
80
     * @param string                     $keyColumn Column name to use as key for mapping
81
     */
82
    public function mapResults(array $rows, string $keyColumn): Results
83
    {
84
        $grouped = $this->groupBy($keyColumn);
85
        $results = [];
86
87
        foreach ($this->uris as $uri) {
88
            $results[$uri] = [];
89
        }
90
91
        foreach ($rows as $row) {
92
            if (! isset($row[$keyColumn])) {
93
                continue;
94
            }
95
96
            $keyValue = (string) $row[$keyColumn];
97
            if (! isset($grouped[$keyValue])) {
98
                continue;
99
            }
100
101
            foreach ($grouped[$keyValue] as $uri) {
102
                $results[$uri][] = $row;
103
            }
104
        }
105
106
        return new Results($results);
107
    }
108
109
    /**
110
     * Parse query string from URI
111
     *
112
     * @return array<string, mixed>
113
     */
114
    private function parseQuery(string $uri): array
115
    {
116
        $queryString = parse_url($uri, PHP_URL_QUERY);
117
        if ($queryString === null || $queryString === false) {
118
            return [];
119
        }
120
121
        parse_str($queryString, $query);
122
123
        /** @var array<string, mixed> $query */
124
        return $query;
125
    }
126
}
127