View source
<?php
namespace Drupal\graphql\Plugin\GraphQL\Schema;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\RefinableCacheableDependencyTrait;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\graphql\GraphQL\ResolverRegistryInterface;
use Drupal\graphql\Plugin\SchemaExtensionPluginInterface;
use Drupal\graphql\Plugin\SchemaExtensionPluginManager;
use Drupal\graphql\Plugin\SchemaPluginInterface;
use GraphQL\Language\AST\InterfaceTypeDefinitionNode;
use GraphQL\Language\AST\TypeDefinitionNode;
use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\Parser;
use GraphQL\Utils\BuildSchema;
use GraphQL\Utils\SchemaExtender;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class SdlSchemaPluginBase extends PluginBase implements SchemaPluginInterface, ContainerFactoryPluginInterface, CacheableDependencyInterface {
use RefinableCacheableDependencyTrait;
protected $astCache;
protected $inDevelopment;
protected $extensionManager;
protected $moduleHandler;
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'));
}
public function __construct(array $configuration, $pluginId, array $pluginDefinition, CacheBackendInterface $astCache, ModuleHandlerInterface $moduleHandler, SchemaExtensionPluginManager $extensionManager, array $config) {
parent::__construct($configuration, $pluginId, $pluginDefinition);
$this->inDevelopment = !empty($config['development']);
$this->astCache = $astCache;
$this->extensionManager = $extensionManager;
$this->moduleHandler = $moduleHandler;
}
public function getSchema(ResolverRegistryInterface $registry) {
$extensions = $this
->getExtensions();
$resolver = [
$registry,
'resolveType',
];
$document = $this
->getSchemaDocument($extensions);
$schema = BuildSchema::build($document, function ($config, TypeDefinitionNode $type) use ($resolver) {
if ($type instanceof InterfaceTypeDefinitionNode || $type instanceof UnionTypeDefinitionNode) {
$config['resolveType'] = $resolver;
}
return $config;
});
if (empty($extensions)) {
return $schema;
}
foreach ($extensions as $extension) {
$extension
->registerResolvers($registry);
}
if ($extendSchema = $this
->getExtensionDocument($extensions)) {
return SchemaExtender::extend($schema, $extendSchema);
}
return $schema;
}
protected function getExtensions() {
return $this->extensionManager
->getExtensions($this
->getPluginId());
}
protected function getSchemaDocument(array $extensions = []) {
$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);
$ast = Parser::parse(implode("\n\n", $schema));
if (empty($this->inDevelopment)) {
$this->astCache
->set($cid, $ast, CacheBackendInterface::CACHE_PERMANENT, [
'graphql',
]);
}
return $ast;
}
protected function getExtensionDocument(array $extensions = []) {
$cid = "extension:{$this->getPluginId()}";
if (empty($this->inDevelopment) && ($cache = $this->astCache
->get($cid))) {
return $cache->data;
}
$extensions = array_filter(array_map(function (SchemaExtensionPluginInterface $extension) {
return $extension
->getExtensionDefinition();
}, $extensions), function ($definition) {
return !empty($definition);
});
$ast = !empty($extensions) ? Parser::parse(implode("\n\n", $extensions)) : NULL;
if (empty($this->inDevelopment)) {
$this->astCache
->set($cid, $ast, CacheBackendInterface::CACHE_PERMANENT, [
'graphql',
]);
}
return $ast;
}
protected function getSchemaDefinition() {
$id = $this
->getPluginId();
$definition = $this
->getPluginDefinition();
$module = $this->moduleHandler
->getModule($definition['provider']);
$path = 'graphql/' . $id . '.graphqls';
$file = $module
->getPath() . '/' . $path;
if (!file_exists($file)) {
throw new InvalidPluginDefinitionException($id, sprintf('The module "%s" needs to have a schema definition "%s" in its folder for "%s" to be valid.', $module
->getName(), $path, $definition['class']));
}
return file_get_contents($file) ?: NULL;
}
}