Completed
Push — master ( f0c7c5...1bf4f0 )
by Rafael
08:34
created

ObjectFieldResolver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 3
crap 1
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Resolver;
12
13
use Doctrine\Common\Collections\Collection;
14
use Doctrine\Common\Persistence\Proxy;
15
use GraphQL\Deferred;
16
use GraphQL\Type\Definition\ResolveInfo;
17
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
18
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
19
use Symfony\Component\DependencyInjection\ContainerInterface;
20
use Symfony\Component\PropertyAccess\PropertyAccessor;
21
use Ynlo\GraphQLBundle\Definition\FieldsAwareDefinitionInterface;
22
use Ynlo\GraphQLBundle\Definition\QueryDefinition;
23
use Ynlo\GraphQLBundle\Definition\Registry\Endpoint;
24
use Ynlo\GraphQLBundle\Model\ID;
25
use Ynlo\GraphQLBundle\Model\NodeInterface;
26
use Ynlo\GraphQLBundle\Type\Definition\EndpointAwareInterface;
27
use Ynlo\GraphQLBundle\Type\Definition\EndpointAwareTrait;
28
use Ynlo\GraphQLBundle\Type\Types;
29
30
/**
31
 * Default resolver for all object fields
32
 */
33
class ObjectFieldResolver implements ContainerAwareInterface, EndpointAwareInterface
34
{
35
    use ContainerAwareTrait;
36
    use EndpointAwareTrait;
37
38
    /**
39
     * @var FieldsAwareDefinitionInterface
40
     */
41
    protected $definition;
42
43
    /**
44
     * @var DeferredBuffer
45
     */
46
    protected $deferredBuffer;
47
48
    /**
49
     * ObjectFieldResolver constructor.
50
     *
51
     * @param ContainerInterface             $container
52
     * @param Endpoint                       $endpoint
53
     * @param FieldsAwareDefinitionInterface $definition
54
     */
55 21
    public function __construct(ContainerInterface $container, Endpoint $endpoint, FieldsAwareDefinitionInterface $definition)
56
    {
57 21
        $this->definition = $definition;
58 21
        $this->container = $container;
59 21
        $this->endpoint = $endpoint;
60 21
        $this->deferredBuffer = $container->get(DeferredBuffer::class);
61 21
    }
62
63
    /**
64
     * @param mixed       $root
65
     * @param array       $args
66
     * @param mixed       $context
67
     * @param ResolveInfo $info
68
     *
69
     * @return mixed|null|string
70
     */
71 21
    public function __invoke($root, array $args, $context, ResolveInfo $info)
72
    {
73 21
        $value = null;
74 21
        $fieldDefinition = $this->definition->getField($info->fieldName);
75
76
        //when use external resolver or use a object method with arguments
77 21
        if ($fieldDefinition->getResolver() || $fieldDefinition->getArguments()) {
78 19
            $queryDefinition = new QueryDefinition();
79 19
            $queryDefinition->setName($fieldDefinition->getName());
80 19
            $queryDefinition->setType($fieldDefinition->getType());
81 19
            $queryDefinition->setNode($fieldDefinition->getNode());
82 19
            $queryDefinition->setArguments($fieldDefinition->getArguments());
83 19
            $queryDefinition->setList($fieldDefinition->isList());
84 19
            $queryDefinition->setMetas($fieldDefinition->getMetas());
85
86 19
            if (!$fieldDefinition->getResolver()) {
87
                if ($fieldDefinition->getOriginType() === \ReflectionMethod::class) {
88
                    $queryDefinition->setResolver($fieldDefinition->getOriginName());
89
                }
90
            } else {
91 19
                $queryDefinition->setResolver($fieldDefinition->getResolver());
92
            }
93
94 19
            $resolver = new ResolverExecutor($this->container, $this->endpoint, $queryDefinition);
95 19
            $value = $resolver($root, $args, $context, $info);
96
        } else {
97 21
            $accessor = new PropertyAccessor(true);
98 21
            $originName = $fieldDefinition->getOriginName() ?? $fieldDefinition->getName();
99 21
            $value = $accessor->getValue($root, $originName);
100
        }
101
102 21
        if (null !== $value && Types::ID === $fieldDefinition->getType()) {
103
            //ID are formed with base64 representation of the Types and real database ID
104
            //in order to create a unique and global identifier for each resource
105
            //@see https://facebook.github.io/relay/docs/graphql-object-identification.html
106 16
            if ($value instanceof ID) {
107 2
                $value = (string) $value;
108
            } else {
109 15
                $value = (string) new ID($this->definition->getName(), $value);
110
            }
111
        }
112
113 21
        if ($value instanceof Collection) {
114 3
            $value = $value->toArray();
115
        }
116
117 21
        if ($value instanceof Proxy && $value instanceof NodeInterface && !$value->__isInitialized()) {
118 4
            $this->deferredBuffer->add($value);
119
120 4
            return new Deferred(
121 4
                function () use ($value) {
122 4
                    $this->deferredBuffer->loadBuffer();
123
124 4
                    return $this->deferredBuffer->getLoadedEntity($value);
125 4
                }
126
            );
127
        }
128
129 21
        return $value;
130
    }
131
}
132