Test Setup Failed
Push — master ( a8db57...31905c )
by Kirill
30:43
created

ObjectTypeBuilder::callAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
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 GraphQL\Type\Definition\ObjectType;
13
use GraphQL\Type\Definition\ResolveInfo;
14
use Railt\Adapters\InputInterface;
15
use Railt\Adapters\Webonyx\Input;
16
use Railt\Adapters\Webonyx\Output;
17
use Railt\Reflection\Abstraction\ObjectTypeInterface;
18
19
/**
20
 * Class ObjectTypeBuilder
21
 *
22
 * @package Railt\Adapters\Webonyx\Builder
23
 * @property-read ObjectTypeInterface $type
24
 */
25
class ObjectTypeBuilder extends Builder
26
{
27
    /**
28
     * @return ObjectType
29
     * @throws \LogicException
30
     * @throws \ReflectionException
31
     * @throws \Psr\Container\NotFoundExceptionInterface
32
     * @throws \Psr\Container\ContainerExceptionInterface
33
     * @throws \InvalidArgumentException
34
     */
35
    public function build(): ObjectType
36
    {
37
        return new ObjectType([
38
            'name'         => $this->type->getName(),
39
            'description'  => $this->type->getDescription(),
40
            'fields'       => function (): array {
41
                return iterator_to_array($this->getObjectFields());
42
            },
43
            'resolveField' => function ($value, array $args = [], $context, ResolveInfo $info) {
44
                $input = new Input($args, $info);
45
46
                $input = $this->events->dispatch('request:' . $input->getPath(), $input);
47
48
                $value = $this->fetchData($input, $value);
0 ignored issues
show
Documentation introduced by
$input is of type array, but the function expects a object<Railt\Adapters\InputInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
49
50
                $value = $this->events->dispatch('response:' . $input->getPath(), $value);
0 ignored issues
show
Bug introduced by
The method getPath cannot be called on $input (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
51
52
                return $value;
53
            },
54
        ]);
55
    }
56
57
    /**
58
     * @return \Traversable
59
     * @throws \LogicException
60
     */
61
    private function getObjectFields(): \Traversable
62
    {
63
        $prefix = 'field:' . $this->type->getName();
64
65
        foreach ($this->type->getFields() as $field) {
66
            if ($this->events->dispatch($prefix . '.' . $field->getName(), $field)) {
67
                yield $field->getName() => $this->make($field, FieldBuilder::class);
68
            }
69
        }
70
    }
71
72
    /**
73
     * @param InputInterface $input
74
     * @param mixed $value
75
     * @return mixed|null
76
     * @throws \InvalidArgumentException
77
     * @throws \Psr\Container\ContainerExceptionInterface
78
     * @throws \Psr\Container\NotFoundExceptionInterface
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 mixed $value
98
     * @return mixed
99
     * @throws \InvalidArgumentException
100
     * @throws \Psr\Container\ContainerExceptionInterface
101
     * @throws \Psr\Container\NotFoundExceptionInterface
102
     * @throws \ReflectionException
103
     */
104
    private function resolveResponder(InputInterface $input, $value)
105
    {
106
        $parent = $value;
107
108
        $value = $this->getFieldValue($input, $value, $value);
109
110
        $container = $this->router->getContainer();
111
112
        foreach ($this->router->get($input->getPath()) as $route) {
113
            $data = [
114
                'input'  => $input,
115
                'value'  => $value,
116
                'parent' => $parent,
117
                'field'  => $this->type,
118
                'output' => new Output($value, $parent),
119
            ];
120
121
            $value = $route->call($container, $data);
122
        }
123
124
        return $value;
125
    }
126
127
    /**
128
     * @param InputInterface $input
129
     * @param mixed $value
130
     * @param null $default
131
     * @return mixed|null
132
     */
133
    private function getFieldValue(InputInterface $input, $value, $default = null)
134
    {
135
        if (is_array($value) || $value instanceof \ArrayAccess) {
136
            return $value[$input->getFieldName()] ?? $default;
137
        }
138
139
        return $default;
140
    }
141
}
142