diff --git a/src/Event/AlterSchemaDataEvent.php b/src/Event/AlterSchemaDataEvent.php index a772652636d3ebadaaab1dc63fdf0d2c685a51c7..dce6179d5bee5f58faca469407961a97694cdce7 100644 --- a/src/Event/AlterSchemaDataEvent.php +++ b/src/Event/AlterSchemaDataEvent.php @@ -27,7 +27,7 @@ class AlterSchemaDataEvent extends Event { * @param array $schemaData * The schema data reference. */ - public function __construct(array &$schemaData) { + public function __construct(array $schemaData) { $this->schemaData = $schemaData; } diff --git a/src/Plugin/GraphQL/Schema/AlterableComposableSchema.php b/src/Plugin/GraphQL/Schema/AlterableComposableSchema.php index 2a7252869f1b548b5f008764ddcb6a71305e3824..5245ac224fb3c4f9ce7fd82d5dc3fe7f2ba2f68d 100644 --- a/src/Plugin/GraphQL/Schema/AlterableComposableSchema.php +++ b/src/Plugin/GraphQL/Schema/AlterableComposableSchema.php @@ -4,22 +4,12 @@ declare(strict_types=1); namespace Drupal\graphql\Plugin\GraphQL\Schema; -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\graphql\Event\AlterSchemaDataEvent; -use Drupal\graphql\Event\AlterSchemaExtensionDataEvent; -use Drupal\graphql\Plugin\SchemaExtensionPluginInterface; -use Drupal\graphql\Plugin\SchemaExtensionPluginManager; -use GraphQL\Language\AST\DocumentNode; -use GraphQL\Language\Parser; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; - /** - * Allows to alter the graphql files data before parsing. + * The same as ComposableSchema. * - * @see \Drupal\graphql\Event\AlterSchemaDataEvent - * @see \Drupal\graphql\Event\AlterSchemaExtensionDataEvent + * @deprecated in graphql:5.0.0 and is removed from graphql:6.0.0 Use + * ComposableSchema instead, it now dispatches the schema alter events. + * @see https://www.drupal.org/project/graphql/issues/3520035 * * @Schema( * id = "alterable_composable", @@ -28,153 +18,4 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; */ class AlterableComposableSchema extends ComposableSchema { - /** - * The event dispatcher service. - */ - protected EventDispatcherInterface $dispatcher; - - /** - * {@inheritdoc} - * - * @codeCoverageIgnore - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('cache.graphql.ast'), - $container->get('module_handler'), - $container->get('plugin.manager.graphql.schema_extension'), - $container->getParameter('graphql.config'), - $container->get('event_dispatcher') - ); - } - - /** - * AlterableComposableSchema constructor. - * - * @param array $configuration - * The plugin configuration array. - * @param string $pluginId - * The plugin id. - * @param array $pluginDefinition - * The plugin definition array. - * @param \Drupal\Core\Cache\CacheBackendInterface $astCache - * The cache bin for caching the parsed SDL. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler - * The module handler service. - * @param \Drupal\graphql\Plugin\SchemaExtensionPluginManager $extensionManager - * The schema extension plugin manager. - * @param array $config - * The service configuration. - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher - * The event dispatcher. - * - * @codeCoverageIgnore - */ - public function __construct( - array $configuration, - string $pluginId, - array $pluginDefinition, - CacheBackendInterface $astCache, - ModuleHandlerInterface $moduleHandler, - SchemaExtensionPluginManager $extensionManager, - array $config, - EventDispatcherInterface $dispatcher, - ) { - parent::__construct( - $configuration, - $pluginId, - $pluginDefinition, - $astCache, - $moduleHandler, - $extensionManager, - $config - ); - $this->dispatcher = $dispatcher; - } - - /** - * Retrieves the parsed AST of the schema definition. - * - * Almost copy of the original method except it - * provides alter schema event in order to manipulate data. - * - * @param array $extensions - * The Drupal GraphQl schema plugins data. - * - * @return \GraphQL\Language\AST\DocumentNode - * The parsed schema document. - * - * @throws \GraphQL\Error\SyntaxError - * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException - * - * @see \Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema::getSchemaDocument() - */ - protected function getSchemaDocument(array $extensions = []): DocumentNode { - // Only use caching of the parsed document if we aren't in development mode. - $cid = "schema:{$this->getPluginId()}"; - if (empty($this->inDevelopment) && $cache = $this->astCache->get($cid)) { - return $cache->data; - } - - $extensions = array_filter(array_map(function (SchemaExtensionPluginInterface $extension) { - return $extension->getBaseDefinition(); - }, $extensions), function ($definition) { - return !empty($definition); - }); - $schema = array_merge([$this->getSchemaDefinition()], $extensions); - // Event in order to alter the schema data. - $event = new AlterSchemaDataEvent($schema); - $this->dispatcher->dispatch( - $event, - AlterSchemaDataEvent::EVENT_NAME - ); - // For caching and parsing big schemas we need to disable the creation of - // location nodes in the AST object to prevent serialization and memory - // errors. See https://github.com/webonyx/graphql-php/issues/1164 - $ast = Parser::parse(implode("\n\n", $event->getSchemaData()), ['noLocation' => TRUE]); - if (empty($this->inDevelopment)) { - $this->astCache->set($cid, $ast, CacheBackendInterface::CACHE_PERMANENT, ['graphql']); - } - return $ast; - } - - /** - * Retrieves the parsed AST of the schema extension definitions. - * - * Almost copy of the original method except it - * provides alter schema extension event in order to manipulate data. - * - * @param array $extensions - * The Drupal GraphQl extensions data. - * - * @return \GraphQL\Language\AST\DocumentNode|null - * The parsed schema document. - * - * @throws \GraphQL\Error\SyntaxError - * - * @see \Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema::getSchemaDocument() - */ - protected function getExtensionDocument(array $extensions = []): ?DocumentNode { - $extensions = array_filter(array_map(function (SchemaExtensionPluginInterface $extension) { - return $extension->getExtensionDefinition(); - }, $extensions), function ($definition) { - return !empty($definition); - }); - - // Event in order to alter the schema extension data. - $event = new AlterSchemaExtensionDataEvent($extensions); - $this->dispatcher->dispatch( - $event, - AlterSchemaExtensionDataEvent::EVENT_NAME - ); - $extensions = array_filter($event->getSchemaExtensionData()); - $ast = !empty($extensions) ? Parser::parse(implode("\n\n", $extensions), ['noLocation' => TRUE]) : NULL; - - // No AST caching here as that will be done in getFullSchemaDocument(). - return $ast; - } - } diff --git a/src/Plugin/GraphQL/Schema/SdlSchemaPluginBase.php b/src/Plugin/GraphQL/Schema/SdlSchemaPluginBase.php index 3469d22de4e5f82adb2df24ca53eec90de0a59da..3c2b53707d578537add9a41b9de61c44e9047d1b 100644 --- a/src/Plugin/GraphQL/Schema/SdlSchemaPluginBase.php +++ b/src/Plugin/GraphQL/Schema/SdlSchemaPluginBase.php @@ -12,6 +12,8 @@ use Drupal\Core\Cache\CacheableDependencyInterface; use Drupal\Core\Cache\RefinableCacheableDependencyTrait; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\graphql\Event\AlterSchemaDataEvent; +use Drupal\graphql\Event\AlterSchemaExtensionDataEvent; use Drupal\graphql\GraphQL\ResolverRegistryInterface; use Drupal\graphql\Plugin\SchemaExtensionPluginInterface; use Drupal\graphql\Plugin\SchemaExtensionPluginManager; @@ -26,6 +28,7 @@ use GraphQL\Utils\BuildSchema; use GraphQL\Utils\SchemaExtender; use GraphQL\Utils\SchemaPrinter; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Base class that can be used by schema plugins. @@ -53,6 +56,11 @@ abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInt */ protected ModuleHandlerInterface $moduleHandler; + /** + * The event dispatcher service. + */ + protected EventDispatcherInterface $dispatcher; + /** * {@inheritdoc} * @@ -66,7 +74,8 @@ abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInt $container->get('cache.graphql.ast'), $container->get('module_handler'), $container->get('plugin.manager.graphql.schema_extension'), - $container->getParameter('graphql.config') + $container->getParameter('graphql.config'), + $container->get('event_dispatcher') ); } @@ -87,6 +96,8 @@ abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInt * The schema extension plugin manager. * @param array $config * The service configuration. + * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher + * The event dispatcher. * * @codeCoverageIgnore */ @@ -98,12 +109,14 @@ abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInt ModuleHandlerInterface $moduleHandler, SchemaExtensionPluginManager $extensionManager, array $config, + EventDispatcherInterface $dispatcher, ) { parent::__construct($configuration, $pluginId, $pluginDefinition); $this->inDevelopment = !empty($config['development']); $this->astCache = $astCache; $this->extensionManager = $extensionManager; $this->moduleHandler = $moduleHandler; + $this->dispatcher = $dispatcher; } /** @@ -186,10 +199,16 @@ abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInt }); $schema = array_merge([$this->getSchemaDefinition()], $extensions); + // Event in order to alter the schema data. + $event = new AlterSchemaDataEvent($schema); + $this->dispatcher->dispatch( + $event, + AlterSchemaDataEvent::EVENT_NAME + ); // For caching and parsing big schemas we need to disable the creation of // location nodes in the AST object to prevent serialization and memory // errors. See https://github.com/webonyx/graphql-php/issues/1164 - $ast = Parser::parse(implode("\n\n", $schema), ['noLocation' => TRUE]); + $ast = Parser::parse(implode("\n\n", $event->getSchemaData()), ['noLocation' => TRUE]); if (empty($this->inDevelopment)) { $this->astCache->set($cid, $ast, CacheBackendInterface::CACHE_PERMANENT, ['graphql']); } @@ -239,6 +258,13 @@ abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInt return !empty($definition); }); + // Event in order to alter the schema extension data. + $event = new AlterSchemaExtensionDataEvent($extensions); + $this->dispatcher->dispatch( + $event, + AlterSchemaExtensionDataEvent::EVENT_NAME + ); + $extensions = array_filter($event->getSchemaExtensionData()); $ast = !empty($extensions) ? Parser::parse(implode("\n\n", $extensions), ['noLocation' => TRUE]) : NULL; // No AST caching here as that will be done in getFullSchemaDocument(). return $ast; diff --git a/tests/src/Kernel/AlterableSchemaTest.php b/tests/src/Kernel/AlterableSchemaTest.php index 9402f474d846b53664c45793d0e0de999af38eef..bd293931f94e918cbda5f2a4d490345efb202618 100644 --- a/tests/src/Kernel/AlterableSchemaTest.php +++ b/tests/src/Kernel/AlterableSchemaTest.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace Drupal\Tests\graphql\Kernel; use Drupal\graphql\GraphQL\ResolverRegistry; -use Drupal\graphql\Plugin\GraphQL\Schema\AlterableComposableSchema; +use Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema; use Drupal\graphql\Plugin\SchemaExtensionPluginInterface; use Drupal\graphql\Plugin\SchemaExtensionPluginManager; @@ -174,7 +174,7 @@ class AlterableSchemaTest extends GraphQLTestBase { ->willReturn($extensions['graphql_alterable_schema_test']); // Replace mock schema with our own implementation. - $this->schema = $this->getMockBuilder(AlterableComposableSchema::class) + $this->schema = $this->getMockBuilder(ComposableSchema::class) ->setConstructorArgs([ [ 'extensions' => ['graphql_alterable_schema_test' => 'graphql_alterable_schema_test'], diff --git a/tests/src/Kernel/SchemaExtensionPluginPriorityTest.php b/tests/src/Kernel/SchemaExtensionPluginPriorityTest.php index e68565e866fe66613f4c46656b2e963d7c1e68ff..b4cc2318d9cfa50d508544cf16d54a4a53749a25 100644 --- a/tests/src/Kernel/SchemaExtensionPluginPriorityTest.php +++ b/tests/src/Kernel/SchemaExtensionPluginPriorityTest.php @@ -114,6 +114,7 @@ class SchemaExtensionPluginPriorityTest extends GraphQLTestBase { $this->container->get('module_handler'), $this->container->get('plugin.manager.graphql.schema_extension'), ['development' => FALSE], + $this->container->get('event_dispatcher'), ]) ->onlyMethods(['getConfiguration', 'getResolverRegistry']) ->getMock(); diff --git a/tests/src/Kernel/ServerConfigurationTest.php b/tests/src/Kernel/ServerConfigurationTest.php index 465a621425b9afa447fe126d842f2fa5d9715ec8..9f49aa749e5e777ac0e03045d1f3f2e2fc6d211d 100644 --- a/tests/src/Kernel/ServerConfigurationTest.php +++ b/tests/src/Kernel/ServerConfigurationTest.php @@ -138,6 +138,7 @@ class ServerConfigurationTest extends GraphQLTestBase { $this->container->get('module_handler'), $extensionManager, ['development' => FALSE], + $this->container->get('event_dispatcher'), ]) ->onlyMethods(['getSchemaDefinition', 'getResolverRegistry']) ->getMock(); diff --git a/tests/src/Traits/MockingTrait.php b/tests/src/Traits/MockingTrait.php index c97ac53a16d7417bd85480e347daed75a2bdffff..3cd355fcac3d5e876e18bcc88139132b5347c7a6 100644 --- a/tests/src/Traits/MockingTrait.php +++ b/tests/src/Traits/MockingTrait.php @@ -148,6 +148,7 @@ trait MockingTrait { $this->container->get('module_handler'), $extensionManager, ['development' => FALSE], + $this->container->get('event_dispatcher'), ]) ->onlyMethods(['getSchemaDefinition', 'getResolverRegistry']) ->getMock();