graphql_compose-1.0.0-beta20/src/Plugin/GraphQL/Schema/GraphQLComposeSchema.php
src/Plugin/GraphQL/Schema/GraphQLComposeSchema.php
<?php
declare(strict_types=1);
namespace Drupal\graphql_compose\Plugin\GraphQL\Schema;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Routing\CurrentRouteMatch;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\graphql\Attribute\Schema as SchemaAttribute;
use Drupal\graphql\GraphQL\ResolverRegistryInterface;
use Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema;
use Drupal\graphql_compose\Utility\ComposeContext;
use Drupal\graphql_compose\Utility\ComposeProviders;
use Drupal\graphql_compose\Plugin\GraphQLComposeEntityTypeManager;
use Drupal\graphql_compose\Plugin\GraphQLComposeSchemaTypeManager;
use GraphQL\Type\Schema;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The provider of the schema base for the GraphQL Compose GraphQL API.
*
* Provides a target schema for GraphQL Schema extensions.
*
* Schema Extensions should implement `SchemaExtensionPluginInterface`
* and should not subclass this class.
*
* @internal
*/
#[SchemaAttribute(
id: "graphql_compose",
name: new TranslatableMarkup("GraphQL Compose schema"),
)]
class GraphQLComposeSchema extends ComposableSchema {
use StringTranslationTrait;
use MessengerTrait;
/**
* The GraphQL Compose Entity Type Manager.
*
* @var \Drupal\graphql_compose\Plugin\GraphQLComposeEntityTypeManager
*/
protected GraphQLComposeEntityTypeManager $gqlEntityTypeManager;
/**
* The GraphQL Compose Field Type Manager.
*
* @var \Drupal\graphql_compose\Plugin\GraphQLComposeSchemaTypeManager
*/
protected GraphQLComposeSchemaTypeManager $gqlSchemaTypeManager;
/**
* The current route match service.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected CurrentRouteMatch $currentRoute;
/**
* The extension list service.
*
* @var \Drupal\Core\Extension\ModuleExtensionList
*/
protected ModuleExtensionList $extensionList;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->gqlEntityTypeManager = $container->get('graphql_compose.entity_type_manager');
$instance->gqlSchemaTypeManager = $container->get('graphql_compose.schema_type_manager');
$instance->currentRoute = $container->get('current_route_match');
$instance->extensionList = $container->get('extension.list.module');
return $instance;
}
/**
* {@inheritdoc}
*
* - Prepare the schema type and entity type extensions.
* - This pre-loads the plugins so that they are available for the schema.
*/
public function getSchema(ResolverRegistryInterface $registry): Schema {
// Let plugins know what server they are being used on.
$server_id = $this->configuration['server_id'] ?? $this->currentRoute->getParameter('graphql_server')?->id();
ComposeContext::setServerId($server_id);
$cid = $this->getCacheId('full');
if ($this->inDevelopment || !$this->astCache->get($cid)) {
// Add GraphQL Compose EntityType plugins to the registry.
$this->gqlEntityTypeManager->getPluginInstances();
// Add GraphQL Compose SchemaType plugins to the registry.
$this->gqlSchemaTypeManager->getPluginInstances();
}
return parent::getSchema($registry);
}
/**
* {@inheritdoc}
*/
protected function getSchemaDefinition(): string {
return <<<GQL
# GraphQL Compose
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
"""
The schema's entry-point for queries.
"""
type Query
"""
The schema's entry-point for mutations.
"""
type Mutation {
"""
Placeholder for mutation extension.
"""
_: Boolean!
}
"""
The schema's entry-point for subscriptions.
"""
type Subscription {
"""
Placeholder for subscription extension.
"""
_: Boolean!
}
GQL;
}
/**
* {@inheritDoc}
*/
public function defaultConfiguration() {
return [
'providers' => [],
];
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
$providers = ComposeProviders::enabled();
// Enable all extensions that are provided by the enabled providers.
$extensions = $this->extensionManager->getDefinitions();
$extensions = array_filter($extensions, function ($definition) use ($providers) {
return $definition['schema'] === 'graphql_compose' && in_array($definition['provider'], $providers, TRUE);
});
$this->configuration['extensions'] = array_keys($extensions);
return $this->configuration;
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// A way to exclude modules and all their plugins.
$form['providers'] = [
'#type' => 'checkboxes',
'#required' => FALSE,
'#title' => $this->t('Enabled GraphQL Compose modules'),
'#options' => [],
'#default_value' => $this->configuration['providers'] ?? [],
];
$providers = ComposeProviders::all();
// Load up each module's info.
$providers = array_map(
fn ($module) => $this->extensionList->get($module),
$providers
);
foreach ($providers as $key => $module) {
$form['providers']['#options'][$key] = $module->info['name'] ?? $key;
if (!empty($module->info['hidden'])) {
$form['providers'][$key]['#disabled'] = TRUE;
$form['providers'][$key]['#wrapper_attributes'] = [
'class' => ['hidden'],
];
$form['providers']['#default_value'][$key] = $key;
}
}
return $form;
}
}
