Test Setup Failed
Push — master ( 31905c...c65f95 )
by Kirill
02:41
created

ObjectTypeBuilder::getFieldResolver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
crap 2
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 Railt\Adapters\AdapterInterface;
13
use Railt\Adapters\Webonyx\Input;
14
use Railt\Adapters\InputInterface;
15
use GraphQL\Type\Definition\ObjectType;
16
use GraphQL\Type\Definition\ResolveInfo;
17
use Railt\Adapters\Webonyx\Repository;
18
use Railt\Reflection\Abstraction\DefinitionInterface;
19
use Railt\Reflection\Abstraction\FieldInterface;
20
use Railt\Reflection\Abstraction\ObjectTypeInterface;
21
use Railt\Reflection\Abstraction\Type\TypeInterface;
22
23
/**
24
 * Class ObjectTypeBuilder
25
 *
26
 * @package Railt\Adapters\Webonyx\Builder
27
 * @property-read ObjectTypeInterface $type
28
 */
29
class ObjectTypeBuilder extends Builder
30
{
31
    /**
32
     * @var Repository
33
     */
34
    private $repository;
35
36
    /**
37
     * ObjectTypeBuilder constructor.
38
     * @param AdapterInterface $adapter
39
     * @param DefinitionInterface|TypeInterface $target
40
     */
41
    public function __construct(AdapterInterface $adapter, $target)
42
    {
43
        parent::__construct($adapter, $target);
44
45
        $this->repository = new Repository($this->router, $this->type);
46
    }
47
48
    /**
49
     * @return ObjectType
50
     * @throws \RuntimeException
51
     * @throws \LogicException
52
     * @throws \ReflectionException
53
     * @throws \Psr\Container\NotFoundExceptionInterface
54
     * @throws \Psr\Container\ContainerExceptionInterface
55
     * @throws \InvalidArgumentException
56
     */
57
    public function build(): ObjectType
58
    {
59
        return new ObjectType([
60
            'name'         => $this->type->getName(),
61
            'description'  => $this->type->getDescription(),
62
            'fields'       => function (): array {
63
                return iterator_to_array($this->getObjectFields());
64
            },
65
            'resolveField' => $this->getFieldResolver(),
66
        ]);
67
    }
68
69
    /**
70
     * @return \Traversable
71
     * @throws \LogicException
72
     */
73
    private function getObjectFields(): \Traversable
74
    {
75
        foreach ($this->type->getFields() as $field) {
76
            if ((bool)$this->dispatchFieldEvent($field)) {
77
                yield $field->getName() => $this->make($field, FieldBuilder::class);
78
            }
79
        }
80
    }
81
82
    /**
83
     * @param FieldInterface $field
84
     * @return FieldInterface|bool|mixed
85
     */
86
    private function dispatchFieldEvent(FieldInterface $field)
87
    {
88
        $event = sprintf('field:%s.%s', $field->getParent()->getName(), $field->getName());
89
90
        return $this->events->dispatch($event, $field);
91
    }
92
93
    /**
94
     * @return \Closure
95
     */
96
    private function getFieldResolver(): \Closure
97
    {
98
        return function ($value, array $args = [], $context, ResolveInfo $info) {
99
            $input = $this->createInput($info, $args);
100
101
            $input = $this->dispatchRequestEvent($input);
102
103
            $result = $this->repository->fetch($input, $value);
104
105
            $result = $this->dispatchResponseEvent($input, $result);
106
107
            return $result;
108
        };
109
    }
110
111
    /**
112
     * @param array $arguments
113
     * @param ResolveInfo $info
114
     * @return Input|InputInterface
115
     */
116
    private function createInput(ResolveInfo $info, array $arguments = []): InputInterface
117
    {
118
        return new Input($arguments, $info);
119
    }
120
121
    /**
122
     * @param InputInterface $input
123
     * @return InputInterface
124
     */
125
    private function dispatchRequestEvent(InputInterface $input): InputInterface
126
    {
127
        $name = 'request:' . $input->getPath();
128
129
        return $this->events->dispatch($name, $input);
130
    }
131
132
    /**
133
     * @param InputInterface $input
134
     * @param $output
135
     * @return mixed
136
     */
137
    private function dispatchResponseEvent(InputInterface $input, $output)
138
    {
139
        $name = 'request:' . $input->getPath();
140
141
        return $this->events->dispatch($name, $output);
142
    }
143
}
144