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

DataLoaderProcessor   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
c 1
b 0
f 0
dl 0
loc 71
rs 10
wmc 11

3 Methods

Rating   Name   Duplication   Size   Complexity  
B process() 0 33 8
A __construct() 0 3 1
A getDataLoader() 0 9 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource\DataLoader;
6
7
use BEAR\Resource\Annotation\Link;
8
use BEAR\Resource\LinkType;
9
use BEAR\Resource\Types;
10
use Ray\Di\InjectorInterface;
11
12
use function array_values;
13
use function assert;
14
use function uri_template;
15
16
/**
17
 * Processes DataLoader-enabled links in batch
18
 *
19
 * @psalm-import-type Query from Types
20
 * @psalm-import-type QueryList from Types
21
 * @psalm-import-type ObjectList from Types
22
 */
23
final class DataLoaderProcessor
24
{
25
    /** @var array<class-string<DataLoaderInterface>, DataLoaderInterface> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<DataL...>, DataLoaderInterface> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<DataLoaderInterface>, DataLoaderInterface>.
Loading history...
26
    private array $cache = [];
27
28
    public function __construct(
29
        private readonly InjectorInterface $injector,
30
    ) {
31
    }
32
33
    /**
34
     * Process DataLoader-enabled links
35
     *
36
     * @param ObjectList $annotations
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\DataLoader\ObjectList 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...
37
     * @param QueryList  $bodyList
0 ignored issues
show
Bug introduced by
The type BEAR\Resource\DataLoader\QueryList 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...
38
     *
39
     * @param-out QueryList $bodyList
40
     *
41
     * @psalm-suppress ReferenceConstraintViolation
42
     */
43
    public function process(array $annotations, LinkType $link, array &$bodyList): void
44
    {
45
        // Group URIs by DataLoader class
46
        /** @var array<class-string<DataLoaderInterface>, array{annotation: Link, uris: array<int, string>}> $loaderGroups */
47
        $loaderGroups = [];
48
49
        foreach ($annotations as $annotation) {
50
            if (! $annotation instanceof Link || $annotation->crawl !== $link->key) {
51
                continue;
52
            }
53
54
            if ($annotation->dataLoader === null) {
55
                continue;
56
            }
57
58
            $loaderClass = $annotation->dataLoader;
59
            $loaderGroups[$loaderClass] = ['annotation' => $annotation, 'uris' => []];
60
61
            foreach ($bodyList as $index => $body) {
62
                $uri = uri_template($annotation->href, $body);
63
                $loaderGroups[$loaderClass]['uris'][$index] = $uri;
64
            }
65
        }
66
67
        // Execute DataLoaders and distribute results
68
        foreach ($loaderGroups as $loaderClass => $group) {
69
            $loader = $this->getDataLoader($loaderClass);
70
            $requests = new Requests(array_values($group['uris']));
71
            $results = $loader($requests);
72
73
            foreach ($group['uris'] as $index => $uri) {
74
                /** @psalm-suppress MixedAssignment -- Results::get() returns mixed by design */
75
                $bodyList[$index][$group['annotation']->rel] = $results->get($uri);
76
            }
77
        }
78
    }
79
80
    /**
81
     * Get or create a DataLoader instance
82
     *
83
     * @param class-string<DataLoaderInterface> $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<DataLoaderInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<DataLoaderInterface>.
Loading history...
84
     */
85
    private function getDataLoader(string $class): DataLoaderInterface
86
    {
87
        if (! isset($this->cache[$class])) {
88
            $instance = $this->injector->getInstance($class);
89
            assert($instance instanceof DataLoaderInterface);
90
            $this->cache[$class] = $instance;
91
        }
92
93
        return $this->cache[$class];
94
    }
95
}
96