Completed
Branch EDTR/refactor-fast-api-fetch (b5d795)
by
unknown
09:04 queued 41s
created

FieldResolver::resolveEvent()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 8
nop 3
dl 0
loc 18
rs 9.3554
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\domain\services\graphql\resolvers;
4
5
use EEM_Base;
6
use EE_Base_Class;
7
use EE_Event;
8
use EE_Venue;
9
use EE_Datetime;
10
use EE_Ticket;
11
use EE_State;
12
use EEM_State;
13
use EE_Country;
14
use EEM_Country;
15
use EE_Error;
16
17
use EventEspresso\core\exceptions\InvalidDataTypeException;
18
use EventEspresso\core\exceptions\InvalidInterfaceException;
19
use EventEspresso\core\services\graphql\TypeBase;
20
use EventEspresso\core\services\graphql\ResolverBase;
21
use EventEspresso\core\domain\services\graphql\fields\GraphQLField;
22
use InvalidArgumentException;
23
use ReflectionException;
24
25
use WPGraphQL\Data\DataSource;
26
use GraphQL\Deferred;
27
use GraphQL\Error\UserError;
28
use WPGraphQL\Model\Post;
29
use GraphQL\Type\Definition\ResolveInfo;
30
use WPGraphQL\AppContext;
31
32
33
/**
34
 * Class FieldResolver
35
 * Field resolver for a GraphQL type
36
 *
37
 * @package EventEspresso\core\domain\services\graphql\resolvers
38
 * @author  Manzoor Wani
39
 * @since   $VID:$
40
 */
41
class FieldResolver extends ResolverBase
42
{
43
44
    /**
45
     * @var mixed $model
46
     */
47
    protected $model;
48
49
    /**
50
     * @var array $fields.
51
     */
52
    protected $fields;
53
54
55
    /**
56
     * FieldResolver constructor.
57
     *
58
	 * @param mixed   $model  The model instance.
59
     * @param array   $fields The fields registered for the type.
60
     */
61
    public function __construct($model, array $fields )
62
    {
63
		$this->model  = $model;
64
		$this->fields = $fields;
65
    }
66
67
    /**
68
     * @param mixed       $source     The source that's passed down the GraphQL queries
69
     * @param array       $args       The inputArgs on the field
70
     * @param AppContext  $context    The AppContext passed down the GraphQL tree
71
     * @param ResolveInfo $info       The ResolveInfo passed down the GraphQL tree
72
     * @return string
73
     * @since $VID:$
74
     */
75
    public function resolve($source, $args, AppContext $context, ResolveInfo $info)
76
    {
77
        $fieldName = $info->fieldName;
78
        
79
        // Field should exist in teh registered fields
80
		if (isset($this->fields[$fieldName]) && $this->fields[$fieldName] instanceof GraphQLField) {
81
            $field = $this->fields[$fieldName];
82
83
            // check if the field should be resolved.
84
            if (!$field->shouldResolve()) {
85
                return null;
86
            }
87
88
            // Give priority to the internal resolver.
89
            if ($field->hasInternalResolver()) {
90
                return call_user_func($field->resolve, $source, $args, $context, $info);
91
            }
92
93
            // Check if the field has a key mapped to model.
94
            if (!empty($field->key())) {
95
                $value = $source->{$field->key()}();
96
                return $field->mayBeFormatValue($value);
97
            }
98
99
            switch ($fieldName) {
100
                case 'parent':
101
                    return $this->resolveParent($source);
102
                case 'event':
103
                    return $this->resolveEvent($source, $args, $context);
104
                case 'wpUser':
105
                    return $this->resolveWpUser($source, $args, $context);
106
                case 'state': // Venue
107
                    return $this->resolveState($source);
108
                case 'country': // State, Venue
109
                    return $this->resolveCountry($source);
110
            }
111
        }
112
        return null;
113
    }
114
115
116
    /**
117
     * @param mixed     $source
118
     * @param           $args
119
     * @param           $context
120
     * @return Deferred|null
121
     * @throws EE_Error
122
     * @throws InvalidArgumentException
123
     * @throws InvalidDataTypeException
124
     * @throws InvalidInterfaceException
125
     * @throws ReflectionException
126
     * @throws UserError
127
     * @since $VID:$
128
     */
129
    public function resolveWpUser($source, $args, $context)
130
    {
131
        $user_id = $source->wp_user();
132
        return $user_id
133
            ? DataSource::resolve_user($user_id, $context)
134
            : null;
135
    }
136
137
138
    /**
139
     * @param mixed $source
140
     * @return EE_Base_Class|null
141
     * @throws EE_Error
142
     * @throws InvalidArgumentException
143
     * @throws InvalidDataTypeException
144
     * @throws InvalidInterfaceException
145
     * @throws ReflectionException
146
     * @since $VID:$
147
     */
148
    public function resolveParent($source)
149
    {
150
        return $this->model->get_one_by_ID($source->parent());
151
    }
152
153
154
    /**
155
     * @param mixed       $source
156
     * @param             $args
157
     * @param             $context
158
     * @return Deferred|null
159
     * @throws EE_Error
160
     * @throws InvalidDataTypeException
161
     * @throws InvalidInterfaceException
162
     * @throws UserError
163
     * @throws InvalidArgumentException
164
     * @throws ReflectionException
165
     * @since $VID:$
166
     */
167
    public function resolveEvent($source, $args, $context)
168
    {
169
        switch (true) {
170
            case $source instanceof EE_Datetime:
171
                $event = $source->event();
172
                break;
173
            case $source instanceof EE_Venue:
174
            case $source instanceof EE_Ticket:
175
                $event = $source->get_related_event();
0 ignored issues
show
Bug introduced by
The method get_related_event does only exist in EE_Ticket, but not in EE_Venue.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
176
                break;
177
            default:
178
                $event = null;
179
                break;
180
        }
181
        return $event instanceof EE_Event
182
            ? DataSource::resolve_post_object($event->ID(), $context)
183
            : null;
184
    }
185
186
187
    /**
188
     * @param mixed $source The source instance.
189
     * @return int
190
     * @since $VID:$
191
     */
192
    public function resolveState($source)
193
    {
194
        switch (true) {
195
            case $source instanceof EE_Venue:
196
                $state_id = $source->state_ID();
197
                break;
198
            default:
199
                $state_id = null;
200
                break;
201
        }
202
203
        if ($state_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $state_id of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
204
            return EEM_State::instance()->get_one_by_ID($state_id);
205
        }
206
        return null;
207
    }
208
209
210
    /**
211
     * @param mixed $source The source instance.
212
     * @return int
213
     * @since $VID:$
214
     */
215
    public function resolveCountry($source)
216
    {
217
        switch (true) {
218
            case $source instanceof EE_State:
219
                $country_iso = $source->country_iso();
220
                break;
221
            case $source instanceof EE_Venue:
222
                $country_iso = $source->country_ID();
223
                break;
224
            default:
225
                $country_iso = null;
226
                break;
227
        }
228
229
        if ($country_iso) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $country_iso of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
230
            return EEM_Country::instance()->get_one_by_ID($country_iso);
231
        }
232
        return null;
233
    }
234
}