Fields.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\Framework\GraphQl\Query;
  8. use GraphQL\Language\AST\Node;
  9. use GraphQL\Language\AST\NodeKind;
  10. /**
  11. * This class holds a list of all queried fields and is used to enable performance optimization for schema loading.
  12. */
  13. class Fields
  14. {
  15. /**
  16. * @var string[]
  17. */
  18. private $fieldsUsedInQuery = [];
  19. /**
  20. * Set Query for extracting list of fields.
  21. *
  22. * @param string $query
  23. * @param array|null $variables
  24. *
  25. * @return void
  26. */
  27. public function setQuery($query, array $variables = null)
  28. {
  29. $queryFields = [];
  30. try {
  31. $queryAst = \GraphQL\Language\Parser::parse(new \GraphQL\Language\Source($query ?: '', 'GraphQL'));
  32. \GraphQL\Language\Visitor::visit(
  33. $queryAst,
  34. [
  35. 'leave' => [
  36. NodeKind::NAME => function (Node $node) use (&$queryFields) {
  37. $queryFields[$node->value] = $node->value;
  38. }
  39. ]
  40. ]
  41. );
  42. if (isset($variables)) {
  43. $queryFields = array_merge($queryFields, $this->extractVariables($variables));
  44. }
  45. } catch (\Exception $e) {
  46. // If a syntax error is encountered do not collect fields
  47. }
  48. if (isset($queryFields['IntrospectionQuery'])) {
  49. // It must be possible to query any fields during introspection query
  50. $queryFields = [];
  51. }
  52. $this->fieldsUsedInQuery = $queryFields;
  53. }
  54. /**
  55. * Get list of fields used in GraphQL query.
  56. *
  57. * This method is stateful and relies on the query being set with setQuery.
  58. *
  59. * @return string[]
  60. */
  61. public function getFieldsUsedInQuery()
  62. {
  63. return $this->fieldsUsedInQuery;
  64. }
  65. /**
  66. * Extract and return list of all used fields in GraphQL query's variables
  67. *
  68. * @param array $variables
  69. *
  70. * @return string[]
  71. */
  72. private function extractVariables(array $variables): array
  73. {
  74. $fields = [];
  75. foreach ($variables as $key => $value) {
  76. if (is_array($value)) {
  77. $fields = array_merge($fields, $this->extractVariables($value));
  78. }
  79. $fields[$key] = $key;
  80. }
  81. return $fields;
  82. }
  83. }