Completed
Branch EDTR/refactor-fast-api-fetch (cef37c)
by
unknown
09:44 queued 46s
created

RequestHandler::populateResolverCollection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 25
rs 9.52
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\graphql;
4
5
use EventEspresso\core\services\collections\CollectionDetailsException;
6
use EventEspresso\core\services\collections\CollectionInterface;
7
use EventEspresso\core\services\collections\CollectionLoaderException;
8
use EventEspresso\core\services\loaders\LoaderInterface;
9
use EventEspresso\core\services\request\RequestInterface;
10
11
/**
12
 * Class RequestHandler
13
 * Description
14
 *
15
 * @package EventEspresso\core\services\graphql
16
 * @author  Brent Christensen
17
 * @since   $VID:$
18
 */
19
class RequestHandler
20
{
21
22
    /**
23
     * @var LoaderInterface $loader
24
     */
25
    protected $loader;
26
27
    /**
28
     * @var RequestInterface $request
29
     */
30
    protected $request;
31
32
    /**
33
     * @var CollectionInterface|ResolverInterface[] $resolvers
34
     */
35
    private $resolvers;
36
37
38
    /**
39
     * RequestHandler constructor.
40
     *
41
     * @param ResolverCollection $resolvers
42
     * @param RequestInterface $request
43
     * @param LoaderInterface $loader
44
     */
45
    public function __construct(ResolverCollection $resolvers, RequestInterface $request, LoaderInterface $loader)
46
    {
47
        $this->resolvers = $resolvers;
48
        $this->request = $request;
49
        $this->loader = $loader;
50
    }
51
52
53
    /**
54
     * @throws CollectionDetailsException
55
     * @throws CollectionLoaderException
56
     * @since $VID:$
57
     */
58
    public function init()
59
    {
60
        // Register GQL resolvers by first loading all ResolverInterface objects
61
        // in EventEspresso\core\domain\services\graphql\resolvers.
62
        // Other folders can be added to that list by addons
63
        // simply by using the collection FQCNs filter in that method.
64
        // Alternately, an addon could load a shared instance of the collection
65
        // and manually add/remove/replace resolvers as needed
66
        $this->resolvers->loadResolvers();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface EventEspresso\core\servi...ons\CollectionInterface as the method loadResolvers() does only exist in the following implementations of said interface: EventEspresso\core\servi...phql\ResolverCollection.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
67
        add_action('graphql_register_types', [$this, 'registerResolvers']);
68
    }
69
70
71
    public function registerResolvers()
72
    {
73
        // loop through the collection of resolvers and register them.
74
        // We're taking care of calling register_graphql_field() from here,
75
        // which centralizes where everything happens, allowing for more control
76
        // and making the resolver classes easier to unit test because
77
        // they are decoupled from the third party api
78
        foreach ($this->resolvers as $resolver) {
79
            /** @var ResolverInterface $resolver */
80
             register_graphql_field(
81
                $resolver->query(),
82
                $resolver->field(),
83
                [
84
                    'type'    => $resolver->type(),
85
                    'resolve' => [$resolver, 'resolve']
86
                ]
87
            );
88
89
        }
90
    }
91
92
}