Passed
Push — master ( e85071...1e4f77 )
by Kirill
03:29
created

ObjectTypeBuilder::collect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Adapters\Webonyx\Builder;
11
12
use GraphQL\Type\Definition\ObjectType;
13
use GraphQL\Type\Definition\ResolveInfo;
14
use Railt\Adapters\RequestInterface;
15
use Railt\Adapters\Webonyx\Builder\Common\HasDescription;
16
use Railt\Adapters\Webonyx\Request;
17
use Railt\Reflection\Abstraction\ObjectTypeInterface;
18
19
/**
20
 * Class ObjectTypeBuilder
21
 * @package Railt\Adapters\Webonyx\Builder
22
 * @property-read ObjectTypeInterface $type
23
 */
24
class ObjectTypeBuilder extends Builder
25
{
26
    use HasDescription;
27
28
    /**
29
     * @return ObjectType
30
     * @throws \LogicException
31
     * @throws \ReflectionException
32
     * @throws \Railt\Routing\Exceptions\RouteCompilationException
33
     * @throws \Psr\Container\NotFoundExceptionInterface
34
     * @throws \Psr\Container\ContainerExceptionInterface
35
     * @throws \InvalidArgumentException
36
     */
37
    public function build(): ObjectType
38
    {
39
        return new ObjectType([
40
            'name'         => $this->type->getName(),
41
            'description'  => $this->getDescription(),
42
            'fields'       => function (): array {
43
                return iterator_to_array($this->getObjectFields());
44
            },
45
            'resolveField' => function ($value, array $args = [], $context, ResolveInfo $info) {
46
                $request = new Request($args, $info);
47
48
                $this->events->dispatch('request:' . $request->getPath(), $request);
49
50
                $value = $this->fetchData($request, $value);
51
52
                $this->events->dispatch('response:' . $request->getPath(), $value, $request);
53
54
                return $value;
55
            },
56
        ]);
57
    }
58
59
    /**
60
     * @return \Traversable
61
     * @throws \LogicException
62
     */
63
    private function getObjectFields(): \Traversable
64
    {
65
        foreach ($this->type->getFields() as $field) {
66
            yield $field->getName() => $this->make($field, FieldBuilder::class);
67
        }
68
    }
69
70
    /**
71
     * @param RequestInterface $request
72
     * @param mixed $value
73
     * @return mixed
74
     * @throws \InvalidArgumentException
75
     * @throws \Railt\Routing\Exceptions\RouteCompilationException
76
     * @throws \Psr\Container\ContainerExceptionInterface
77
     * @throws \Psr\Container\NotFoundExceptionInterface
78
     * @throws \ReflectionException
79
     */
80
    private function fetchData(RequestInterface $request, $value)
81
    {
82
        if (is_iterable($value)) {
83
            $value = $this->collect($value);
84
        }
85
86
        // When route allowed
87
        if ($this->router->has($request->getPath())) {
88
            return $this->resolveResponder($request, $value);
89
        }
90
91
        // If defined in parent
92
        if (is_array($value) && array_key_exists($request->getFieldName(), $value)) {
93
            return $value[$request->getFieldName()];
94
        }
95
96
        return null;
97
    }
98
99
    /**
100
     * @param iterable $iterable
101
     * @return array
102
     */
103
    private function collect(iterable $iterable): array
104
    {
105
        return $iterable instanceof \Traversable ? iterator_to_array($iterable) : $iterable;
106
    }
107
108
    /**
109
     * @param RequestInterface $request
110
     * @param mixed $value
111
     * @return mixed
112
     * @throws \ReflectionException
113
     * @throws \Psr\Container\NotFoundExceptionInterface
114
     * @throws \Psr\Container\ContainerExceptionInterface
115
     * @throws \Railt\Routing\Exceptions\RouteCompilationException
116
     * @throws \InvalidArgumentException
117
     */
118
    private function resolveResponder(RequestInterface $request, $value)
119
    {
120
        if (is_array($value) && array_key_exists($request->getFieldName(), $value)) {
121
            $value = $value[$request->getFieldName()];
122
        }
123
124
        foreach ($this->router->resolve($request->getPath()) as $responder) {
125
            $value = $responder->invoke([
126
                'request' => $request,
127
                'value' => $value,
128
            ]);
129
        }
130
131
        return $value;
132
    }
133
}
134