Issues (281)

src/Resolver/ObjectFieldResolver.php (1 issue)

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 GraphQL\Type\Definition\ResolveInfo;
15
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
16
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
19
use Symfony\Component\PropertyAccess\PropertyAccessor;
20
use Ynlo\GraphQLBundle\Definition\FieldDefinition;
21
use Ynlo\GraphQLBundle\Definition\QueryDefinition;
22
use Ynlo\GraphQLBundle\Events\GraphQLEvents;
23
use Ynlo\GraphQLBundle\Events\GraphQLFieldEvent;
24
use Ynlo\GraphQLBundle\Model\NodeInterface;
25
use Ynlo\GraphQLBundle\Type\Types;
26
use Ynlo\GraphQLBundle\Util\IDEncoder;
27
28
/**
29
 * Default resolver for all object fields
30
 */
31
class ObjectFieldResolver implements ContainerAwareInterface
32
{
33
    use ContainerAwareTrait;
34
35
    /**
36
     * ObjectFieldResolver constructor.
37
     *
38
     * @param ContainerInterface $container
39
     */
40
    public function __construct(ContainerInterface $container)
41
    {
42
        $this->container = $container;
43
    }
44
45
    /**
46
     * @param mixed           $root
47
     * @param array           $args
48
     * @param ResolverContext $context
49
     * @param ResolveInfo     $info
50
     *
51
     * @return mixed|null|string
52
     *
53
     * @throws \Exception
54
     */
55
    public function __invoke($root, array $args, ResolverContext $context, ResolveInfo $info)
56
    {
57
        $value = null;
58
        $eventDispatcher = $this->container->get(EventDispatcherInterface::class);
59
        $fieldDefinition = $context->getDefinition();
60
61
        if (!$fieldDefinition instanceof FieldDefinition) {
62
            throw new \RuntimeException('This resolver can only resolve fields');
63
        }
64
65
        $event = new GraphQLFieldEvent($context);
66
        $eventDispatcher->dispatch(GraphQLEvents::PRE_READ_FIELD, $event);
67
68
        if ($event->isPropagationStopped() || $event->getValue()) {
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\EventD...:isPropagationStopped() has been deprecated: since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

68
        if (/** @scrutinizer ignore-deprecated */ $event->isPropagationStopped() || $event->getValue()) {

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
69
            $eventDispatcher->dispatch(GraphQLEvents::POST_READ_FIELD, $event);
70
71
            return $event->getValue();
72
        }
73
74
        //when use external resolver or use a object method with arguments
75
        if (($resolver = $fieldDefinition->getResolver()) || $fieldDefinition->getArguments()) {
76
            $queryDefinition = new QueryDefinition();
77
            $queryDefinition->setName($fieldDefinition->getName());
78
            $queryDefinition->setType($fieldDefinition->getType());
79
            $queryDefinition->setNode($fieldDefinition->getNode());
80
            $queryDefinition->setArguments($fieldDefinition->getArguments());
81
            $queryDefinition->setList($fieldDefinition->isList());
82
            $queryDefinition->setMetas($fieldDefinition->getMetas());
83
84
            if ($resolver) {
85
                $queryDefinition->setResolver($resolver);
86
            } elseif ($fieldDefinition->getOriginType() === \ReflectionMethod::class) {
87
                $queryDefinition->setResolver($fieldDefinition->getOriginName());
88
            }
89
90
            $context = ContextBuilder::create($context->getEndpoint())
91
                                     ->setArgs($args)
92
                                     ->setRoot($root)
93
                                     ->setDefinition($queryDefinition)
94
                                     ->setResolveInfo($info)
95
                                     ->setMetas($context->getMetas())
96
                                     ->build();
97
98
            $resolver = new ResolverExecutor($this->container, $queryDefinition);
99
            $value = $resolver($root, $args, $context, $info);
100
        } else {
101
            $accessor = new PropertyAccessor(true);
102
            $originName = $fieldDefinition->getOriginName() ?: $fieldDefinition->getName();
103
            $value = $accessor->getValue($root, $originName);
104
        }
105
106
        if (null !== $value && Types::ID === $fieldDefinition->getType() && $root instanceof NodeInterface) {
107
            //ID are formed with base64 representation of the Types and real database ID
108
            //in order to create a unique and global identifier for each resource
109
            //@see https://facebook.github.io/relay/docs/graphql-object-identification.html
110
            $value = IDEncoder::encode($root);
111
        }
112
113
        if ($value instanceof Collection) {
114
            $value = $value->toArray();
115
        }
116
117
        $event->setValue($value);
118
        $eventDispatcher->dispatch(GraphQLEvents::POST_READ_FIELD, $event);
119
120
        return $event->getValue();
121
    }
122
}
123