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\Definition\Plugin; |
||||||
12 | |||||||
13 | use GraphQL\Type\Definition\ObjectType; |
||||||
14 | use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
||||||
15 | use Symfony\Component\Config\Definition\Builder\NodeBuilder; |
||||||
16 | use Ynlo\GraphQLBundle\Definition\ArgumentDefinition; |
||||||
17 | use Ynlo\GraphQLBundle\Definition\DefinitionInterface; |
||||||
18 | use Ynlo\GraphQLBundle\Definition\EnumDefinition; |
||||||
19 | use Ynlo\GraphQLBundle\Definition\EnumValueDefinition; |
||||||
20 | use Ynlo\GraphQLBundle\Definition\ExecutableDefinitionInterface; |
||||||
21 | use Ynlo\GraphQLBundle\Definition\FieldDefinition; |
||||||
22 | use Ynlo\GraphQLBundle\Definition\FieldsAwareDefinitionInterface; |
||||||
23 | use Ynlo\GraphQLBundle\Definition\InputObjectDefinition; |
||||||
24 | use Ynlo\GraphQLBundle\Definition\InterfaceDefinition; |
||||||
25 | use Ynlo\GraphQLBundle\Definition\ObjectDefinition; |
||||||
26 | use Ynlo\GraphQLBundle\Definition\QueryDefinition; |
||||||
27 | use Ynlo\GraphQLBundle\Definition\Registry\Endpoint; |
||||||
28 | use Ynlo\GraphQLBundle\DependencyInjection\BackwardCompatibilityAwareInterface; |
||||||
29 | use Ynlo\GraphQLBundle\DependencyInjection\BackwardCompatibilityAwareTrait; |
||||||
30 | use Ynlo\GraphQLBundle\Filter\FilterFactory; |
||||||
31 | use Ynlo\GraphQLBundle\Model\OrderBy; |
||||||
32 | use Ynlo\GraphQLBundle\OrderBy\Common\OrderByRelatedField; |
||||||
33 | use Ynlo\GraphQLBundle\OrderBy\Common\OrderBySimpleField; |
||||||
34 | use Ynlo\GraphQLBundle\OrderBy\OrderByInterface; |
||||||
35 | use Ynlo\GraphQLBundle\Query\Node\AllNodesWithPagination; |
||||||
36 | use Ynlo\GraphQLBundle\Type\Registry\TypeRegistry; |
||||||
37 | use Ynlo\GraphQLBundle\Util\FieldOptionsHelper; |
||||||
38 | |||||||
39 | /** |
||||||
40 | * Convert a simple return of nodes into a paginated collection with edges |
||||||
41 | */ |
||||||
42 | class PaginationDefinitionPlugin extends AbstractDefinitionPlugin implements BackwardCompatibilityAwareInterface |
||||||
43 | { |
||||||
44 | use BackwardCompatibilityAwareTrait; |
||||||
45 | |||||||
46 | public const ONE_TO_MANY = 'ONE_TO_MANY'; |
||||||
47 | public const MANY_TO_MANY = 'MANY_TO_MANY'; |
||||||
48 | |||||||
49 | /** |
||||||
50 | * @var FilterFactory |
||||||
51 | */ |
||||||
52 | protected $filterFactory; |
||||||
53 | |||||||
54 | /** |
||||||
55 | * @var int |
||||||
56 | */ |
||||||
57 | protected $limit; |
||||||
58 | |||||||
59 | /** |
||||||
60 | * PaginationDefinitionPlugin constructor. |
||||||
61 | * |
||||||
62 | * @param FilterFactory $filterFactory |
||||||
63 | * @param array $config |
||||||
64 | */ |
||||||
65 | public function __construct(FilterFactory $filterFactory, array $config = []) |
||||||
66 | { |
||||||
67 | $this->filterFactory = $filterFactory; |
||||||
68 | $this->limit = $config['limit'] ?? 100; |
||||||
69 | } |
||||||
70 | |||||||
71 | /** |
||||||
72 | * {@inheritDoc} |
||||||
73 | */ |
||||||
74 | public function buildConfig(ArrayNodeDefinition $root): void |
||||||
75 | { |
||||||
76 | $config = $root |
||||||
77 | ->info('Enable pagination in queries or sub-fields') |
||||||
78 | ->canBeEnabled() |
||||||
79 | ->children(); |
||||||
80 | |||||||
81 | /** @var NodeBuilder $rootNode */ |
||||||
82 | $config->scalarNode('target') |
||||||
83 | ->info('Target node to properly paginate. If is possible will be auto-resolved using naming conventions') |
||||||
84 | ->isRequired(); |
||||||
85 | $config->variableNode('filters') |
||||||
86 | ->info('Filters configuration'); |
||||||
87 | $config->variableNode('order_by'); |
||||||
88 | $config->variableNode('search_fields'); |
||||||
89 | $config->integerNode('limit')->info('Max number of records allowed for first & last')->defaultValue($this->limit); |
||||||
90 | $config->scalarNode('parent_field') |
||||||
91 | ->info('When is used in sub-fields should be the field to filter by parent instance'); |
||||||
92 | $config->enumNode('parent_relation') |
||||||
93 | ->info('When is used in sub-fields should be the type of relation with the parent field') |
||||||
94 | ->defaultValue(self::ONE_TO_MANY) |
||||||
95 | ->values([self::ONE_TO_MANY, self::MANY_TO_MANY]); |
||||||
96 | } |
||||||
97 | |||||||
98 | /** |
||||||
99 | * {@inheritDoc} |
||||||
100 | */ |
||||||
101 | public function normalizeConfig(DefinitionInterface $definition, $config): array |
||||||
102 | { |
||||||
103 | if (true === $config && $definition instanceof ExecutableDefinitionInterface) { |
||||||
104 | $config = []; |
||||||
105 | } |
||||||
106 | |||||||
107 | if (\is_array($config) && !isset($config['target'])) { |
||||||
108 | $config['target'] = $definition->getType(); |
||||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
109 | } |
||||||
110 | |||||||
111 | if (false === $config) { |
||||||
112 | $config = []; |
||||||
113 | } |
||||||
114 | |||||||
115 | return $config; |
||||||
116 | } |
||||||
117 | |||||||
118 | /** |
||||||
119 | * {@inheritdoc} |
||||||
120 | */ |
||||||
121 | public function configure(DefinitionInterface $definition, Endpoint $endpoint, array $config): void |
||||||
122 | { |
||||||
123 | if (!$config) { |
||||||
0 ignored issues
–
show
The expression
$config of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||||||
124 | return; |
||||||
125 | } |
||||||
126 | |||||||
127 | if (!$definition instanceof QueryDefinition && !$definition instanceof FieldDefinition) { |
||||||
128 | return; |
||||||
129 | } |
||||||
130 | |||||||
131 | $target = null; |
||||||
132 | if ($definition instanceof FieldDefinition) { |
||||||
133 | $target = $definition->getType(); |
||||||
134 | // only apply pagination to inherited fields |
||||||
135 | // if all interfaces has pagination enabled |
||||||
136 | if ($definition->getInheritedFrom()) { |
||||||
137 | foreach ($definition->getInheritedFrom() as $inheritedType) { |
||||||
138 | /** @var InterfaceDefinition $inheritedDefinition */ |
||||||
139 | $inheritedDefinition = $endpoint->getType($inheritedType); |
||||||
140 | if (!$inheritedDefinition->getField($definition->getName())->hasMeta('pagination')) { |
||||||
141 | return; |
||||||
142 | } |
||||||
143 | } |
||||||
144 | } |
||||||
145 | } |
||||||
146 | |||||||
147 | $search = new ArgumentDefinition(); |
||||||
148 | $search->setName('search'); |
||||||
149 | $search->setType('string'); |
||||||
150 | $search->setNonNull(false); |
||||||
151 | $search->setDescription('Search in current list by given string'); |
||||||
152 | $definition->addArgument($search); |
||||||
153 | |||||||
154 | $target = $config['target'] ?? $target; |
||||||
155 | if ($endpoint->hasTypeForClass($target)) { |
||||||
0 ignored issues
–
show
It seems like
$target can also be of type null ; however, parameter $class of Ynlo\GraphQLBundle\Defin...oint::hasTypeForClass() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
156 | $target = $endpoint->getTypeForClass($target); |
||||||
0 ignored issues
–
show
It seems like
$target can also be of type null ; however, parameter $class of Ynlo\GraphQLBundle\Defin...oint::getTypeForClass() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
157 | } |
||||||
158 | $targetNode = $endpoint->getType($target); |
||||||
159 | |||||||
160 | $this->addPaginationArguments($definition); |
||||||
161 | $this->createOrderBy($endpoint, $definition, $targetNode); |
||||||
162 | |||||||
163 | $connection = $this->createConnection($endpoint, $targetNode); |
||||||
164 | $definition->setType($connection->getName()); |
||||||
165 | $definition->setList(false); |
||||||
166 | $definition->setNode($target); |
||||||
167 | $definition->setMeta('pagination', $config); |
||||||
168 | |||||||
169 | if (!$definition->getResolver()) { |
||||||
170 | $definition->setResolver(AllNodesWithPagination::class); |
||||||
171 | } |
||||||
172 | |||||||
173 | $this->filterFactory->build($definition, $targetNode, $endpoint); |
||||||
174 | |||||||
175 | //deprecated, keep for BC with v1 |
||||||
176 | if ($this->bcConfig['filters'] ?? false) { |
||||||
177 | $this->addFilters($definition, $target, $endpoint); |
||||||
0 ignored issues
–
show
It seems like
$target can also be of type null ; however, parameter $targetType of Ynlo\GraphQLBundle\Defin...ionPlugin::addFilters() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() The function
Ynlo\GraphQLBundle\Defin...ionPlugin::addFilters() has been deprecated: since v1.2, should use `where` instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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. ![]() |
|||||||
178 | } |
||||||
179 | } |
||||||
180 | |||||||
181 | /** |
||||||
182 | * @param Endpoint $endpoint |
||||||
183 | * @param DefinitionInterface $node |
||||||
184 | * |
||||||
185 | * @return ObjectDefinition |
||||||
186 | */ |
||||||
187 | private function createConnection(Endpoint $endpoint, DefinitionInterface $node): ObjectDefinition |
||||||
188 | { |
||||||
189 | $connection = new ObjectDefinition(); |
||||||
190 | $connection->setName("{$node->getName()}Connection"); |
||||||
191 | |||||||
192 | if (!$endpoint->hasType($connection->getName())) { |
||||||
193 | $endpoint->addType($connection); |
||||||
194 | |||||||
195 | $totalCount = new FieldDefinition(); |
||||||
196 | $totalCount->setName('totalCount'); |
||||||
197 | $totalCount->setType('Int'); |
||||||
198 | $totalCount->setNonNull(true); |
||||||
199 | $connection->addField($totalCount); |
||||||
200 | |||||||
201 | $pages = new FieldDefinition(); |
||||||
202 | $pages->setName('pages'); |
||||||
203 | $pages->setType('Int'); |
||||||
204 | $pages->setNonNull(true); |
||||||
205 | $connection->addField($pages); |
||||||
206 | |||||||
207 | $pageInfo = new FieldDefinition(); |
||||||
208 | $pageInfo->setName('pageInfo'); |
||||||
209 | $pageInfo->setType('PageInfo'); |
||||||
210 | $pageInfo->setNonNull(true); |
||||||
211 | $connection->addField($pageInfo); |
||||||
212 | |||||||
213 | $edgeObject = new ObjectDefinition(); |
||||||
214 | $edgeObject->setName("{$node->getName()}Edge"); |
||||||
215 | if (!$endpoint->hasType($edgeObject->getName())) { |
||||||
216 | $endpoint->addType($edgeObject); |
||||||
217 | |||||||
218 | $nodeField = new FieldDefinition(); |
||||||
219 | $nodeField->setName('node'); |
||||||
220 | $nodeField->setType($node->getName()); |
||||||
221 | $nodeField->setNonNull(true); |
||||||
222 | $edgeObject->addField($nodeField); |
||||||
223 | |||||||
224 | $cursor = new FieldDefinition(); |
||||||
225 | $cursor->setName('cursor'); |
||||||
226 | $cursor->setType('string'); |
||||||
227 | $cursor->setNonNull(true); |
||||||
228 | $edgeObject->addField($cursor); |
||||||
229 | } |
||||||
230 | |||||||
231 | $edges = new FieldDefinition(); |
||||||
232 | $edges->setName('edges'); |
||||||
233 | $edges->setType($edgeObject->getName()); |
||||||
234 | $edges->setList(true); |
||||||
235 | $connection->addField($edges); |
||||||
236 | } else { |
||||||
237 | $connection = $endpoint->getType($connection->getName()); |
||||||
238 | } |
||||||
239 | |||||||
240 | return $connection; |
||||||
0 ignored issues
–
show
|
|||||||
241 | } |
||||||
242 | |||||||
243 | /** |
||||||
244 | * @param Endpoint $endpoint |
||||||
245 | * @param ExecutableDefinitionInterface $query |
||||||
246 | * @param FieldsAwareDefinitionInterface $node |
||||||
247 | */ |
||||||
248 | private function createOrderBy(Endpoint $endpoint, ExecutableDefinitionInterface $query, FieldsAwareDefinitionInterface $node) |
||||||
249 | { |
||||||
250 | /** @var InputObjectDefinition $orderBy */ |
||||||
251 | $orderBy = unserialize(serialize($endpoint->getType(OrderBy::class)), ['allowed_classes' => true]); //clone recursively |
||||||
252 | $orderBy->setName("{$node->getName()}OrderBy"); |
||||||
253 | |||||||
254 | if (!$endpoint->hasType($orderBy->getName())) { |
||||||
255 | $orderByFields = new EnumDefinition(); |
||||||
256 | $orderByFields->setName("{$node->getName()}OrderByField"); |
||||||
257 | $options = $query->getMeta('pagination')['order_by'] ?? ['*']; |
||||||
258 | $options = FieldOptionsHelper::normalize($options); |
||||||
259 | |||||||
260 | foreach ($node->getFields() as $field) { |
||||||
261 | if (!FieldOptionsHelper::isEnabled($options, $field->getName())) { |
||||||
262 | continue; |
||||||
263 | } |
||||||
264 | |||||||
265 | //ignore if non related to entity property |
||||||
266 | if ($field->getOriginType() !== \ReflectionProperty::class) { |
||||||
267 | continue; |
||||||
268 | } |
||||||
269 | |||||||
270 | //ignore if is a list |
||||||
271 | if ($field->isList()) { |
||||||
272 | continue; |
||||||
273 | } |
||||||
274 | |||||||
275 | //ignore if is related to other object |
||||||
276 | if ($endpoint->hasType($field->getType()) && $endpoint->getType($field->getType()) instanceof FieldsAwareDefinitionInterface) { |
||||||
277 | continue; |
||||||
278 | } |
||||||
279 | |||||||
280 | $definition = new EnumValueDefinition($field->getName()); |
||||||
281 | $definition->setMeta('resolver', OrderBySimpleField::class); |
||||||
282 | $definition->setMeta('field', $field->getName()); |
||||||
283 | |||||||
284 | $orderByFields->addValue($definition); |
||||||
285 | } |
||||||
286 | |||||||
287 | //configure custom orderBy and support for children, like "parentName" => parent.name |
||||||
288 | foreach ($options as $fieldName => $config) { |
||||||
289 | if ('*' === $fieldName || '*' === $config || !FieldOptionsHelper::isEnabled($options, $fieldName)) { |
||||||
290 | continue; |
||||||
291 | } |
||||||
292 | |||||||
293 | if (array_key_exists($fieldName, $orderByFields->getValues())) { |
||||||
294 | continue; |
||||||
295 | } |
||||||
296 | |||||||
297 | $field = $fieldName; |
||||||
298 | $resolver = OrderBySimpleField::class; |
||||||
299 | if (strpos($config, '.') !== false) { |
||||||
300 | $resolver = OrderByRelatedField::class; |
||||||
301 | $field = $config; |
||||||
302 | } elseif (is_string($config)) { |
||||||
303 | $field = $config; |
||||||
304 | } |
||||||
305 | |||||||
306 | if (class_exists($config) && is_a($config, OrderByInterface::class, true)) { |
||||||
307 | $resolver = $config; |
||||||
308 | $field = $fieldName; |
||||||
309 | } |
||||||
310 | |||||||
311 | $definition = new EnumValueDefinition($fieldName); |
||||||
312 | $definition->setMeta('resolver', $resolver); |
||||||
313 | $definition->setMeta('field', $field); |
||||||
314 | |||||||
315 | $orderByFields->addValue($definition); |
||||||
316 | } |
||||||
317 | |||||||
318 | if ($orderByFields->getValues()) { |
||||||
319 | $orderBy->getField('field')->setType($orderByFields->getName()); |
||||||
320 | $endpoint->addType($orderByFields); |
||||||
321 | $endpoint->addType($orderBy); |
||||||
322 | } else { |
||||||
323 | return; |
||||||
324 | } |
||||||
325 | } else { |
||||||
326 | $orderBy = $endpoint->getType($orderBy->getName()); |
||||||
327 | } |
||||||
328 | |||||||
329 | $arg = new ArgumentDefinition(); |
||||||
330 | $arg->setName('order'); |
||||||
331 | $arg->setType($orderBy->getName()); |
||||||
332 | $arg->setNonNull(false); |
||||||
333 | $arg->setList(true); |
||||||
334 | $arg->setDescription('Ordering options for this list.'); |
||||||
335 | $query->addArgument($arg); |
||||||
336 | |||||||
337 | //to keep BC |
||||||
338 | if ($this->bcConfig['orderBy'] ?? false) { |
||||||
339 | $arg = new ArgumentDefinition(); |
||||||
340 | $arg->setName('orderBy'); |
||||||
341 | $arg->setType(OrderBy::class); |
||||||
342 | $arg->setNonNull(false); |
||||||
343 | $arg->setList(true); |
||||||
344 | $deprecateMessage = \is_string($this->bcConfig['orderBy']) ? $this->bcConfig['orderBy'] : '**DEPRECATED** use `order` instead.'; |
||||||
345 | $arg->setDescription($deprecateMessage); |
||||||
346 | $query->addArgument($arg); |
||||||
347 | } |
||||||
348 | } |
||||||
349 | |||||||
350 | /** |
||||||
351 | * @param ExecutableDefinitionInterface $definition |
||||||
352 | */ |
||||||
353 | private function addPaginationArguments(ExecutableDefinitionInterface $definition): void |
||||||
354 | { |
||||||
355 | $first = new ArgumentDefinition(); |
||||||
356 | $first->setName('first'); |
||||||
357 | $first->setType('int'); |
||||||
358 | $first->setNonNull(false); |
||||||
359 | $first->setDescription('Returns the first *n* elements from the list.'); |
||||||
360 | $definition->addArgument($first); |
||||||
361 | |||||||
362 | $last = new ArgumentDefinition(); |
||||||
363 | $last->setName('last'); |
||||||
364 | $last->setType('int'); |
||||||
365 | $last->setNonNull(false); |
||||||
366 | $last->setDescription('Returns the last *n* elements from the list.'); |
||||||
367 | $definition->addArgument($last); |
||||||
368 | |||||||
369 | $after = new ArgumentDefinition(); |
||||||
370 | $after->setName('after'); |
||||||
371 | $after->setType('string'); |
||||||
372 | $after->setNonNull(false); |
||||||
373 | $after->setDescription('Returns the last *n* elements from the list.'); |
||||||
374 | $definition->addArgument($after); |
||||||
375 | |||||||
376 | $before = new ArgumentDefinition(); |
||||||
377 | $before->setName('before'); |
||||||
378 | $before->setType('string'); |
||||||
379 | $before->setNonNull(false); |
||||||
380 | $before->setDescription('Returns the last *n* elements from the list.'); |
||||||
381 | $definition->addArgument($before); |
||||||
382 | |||||||
383 | $page = new ArgumentDefinition(); |
||||||
384 | $page->setName('page'); |
||||||
385 | $page->setType('integer'); |
||||||
386 | $page->setNonNull(false); |
||||||
387 | $page->setDescription('Page to fetch in order to use page pagination instead of cursor based'); |
||||||
388 | $definition->addArgument($page); |
||||||
389 | } |
||||||
390 | |||||||
391 | /** |
||||||
392 | * @param ExecutableDefinitionInterface $definition |
||||||
393 | * @param string $targetType |
||||||
394 | * @param Endpoint $endpoint |
||||||
395 | * |
||||||
396 | * @throws \ReflectionException |
||||||
397 | * |
||||||
398 | * @deprecated since v1.2, should use `where` instead |
||||||
399 | */ |
||||||
400 | private function addFilters(ExecutableDefinitionInterface $definition, string $targetType, Endpoint $endpoint): void |
||||||
401 | { |
||||||
402 | $filterName = ucfirst($definition->getName()).'Filter'; |
||||||
403 | if ($endpoint->hasType($filterName)) { |
||||||
404 | $filters = $endpoint->getType($filterName); |
||||||
405 | } else { |
||||||
406 | $filters = new InputObjectDefinition(); |
||||||
407 | $filters->setName($filterName); |
||||||
408 | $endpoint->add($filters); |
||||||
409 | |||||||
410 | $object = $endpoint->getType($targetType); |
||||||
411 | if ($object instanceof FieldsAwareDefinitionInterface) { |
||||||
412 | foreach ($object->getFields() as $field) { |
||||||
413 | if ('id' === $field->getName() |
||||||
414 | || !$field->getOriginName() |
||||||
415 | || \ReflectionProperty::class !== $field->getOriginType()) { |
||||||
416 | continue; |
||||||
417 | } |
||||||
418 | |||||||
419 | $filter = new FieldDefinition(); |
||||||
420 | $filter->setName($field->getName()); |
||||||
421 | $type = $field->getType(); |
||||||
422 | if ($endpoint->hasType($type)) { |
||||||
423 | $typeDefinition = $endpoint->getType($type); |
||||||
424 | if (!$typeDefinition instanceof EnumDefinition) { |
||||||
425 | $type = 'ID'; |
||||||
426 | } |
||||||
427 | $filter->setList(true); |
||||||
428 | } |
||||||
429 | |||||||
430 | // fields using custom object as type |
||||||
431 | // are not available for filters |
||||||
432 | if (TypeRegistry::getTypeMapp()) { |
||||||
433 | if (isset(TypeRegistry::getTypeMapp()[$type])) { |
||||||
434 | $class = TypeRegistry::getTypeMapp()[$type]; |
||||||
435 | $ref = new \ReflectionClass($class); |
||||||
436 | if ($ref->isSubclassOf(ObjectType::class)) { |
||||||
437 | continue; |
||||||
438 | } |
||||||
439 | } |
||||||
440 | } |
||||||
441 | |||||||
442 | $filter->setType($type); |
||||||
443 | $filters->addField($filter); |
||||||
444 | } |
||||||
445 | } |
||||||
446 | } |
||||||
447 | |||||||
448 | if (!$filters->getFields()) { |
||||||
0 ignored issues
–
show
The method
getFields() does not exist on Ynlo\GraphQLBundle\Definition\DefinitionInterface . It seems like you code against a sub-type of Ynlo\GraphQLBundle\Definition\DefinitionInterface such as Ynlo\GraphQLBundle\Definition\ImplementorInterface or Ynlo\GraphQLBundle\Defin...wareDefinitionInterface or Ynlo\GraphQLBundle\Defin...jectDefinitionInterface .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
449 | return; |
||||||
450 | } |
||||||
451 | |||||||
452 | $search = new ArgumentDefinition(); |
||||||
453 | $search->setName('filters'); |
||||||
454 | $search->setType($filters->getName()); |
||||||
455 | $deprecateMessage = \is_string($this->bcConfig['filters']) ? $this->bcConfig['filters'] : '**DEPRECATED** use `where` instead to filter the list.'; |
||||||
456 | $search->setDescription($deprecateMessage); |
||||||
457 | $search->setNonNull(false); |
||||||
458 | $definition->addArgument($search); |
||||||
459 | } |
||||||
460 | } |
||||||
461 |