Completed
Push — master ( c2785f...c09443 )
by Kirill
07:19
created

ObjectTypeBuilder::getFieldValue()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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