Skip to content

Instantly share code, notes, and snippets.

@atlowl
Created July 26, 2023 20:33
Show Gist options
  • Save atlowl/1072ad0acd7623ff09d739c66a42361b to your computer and use it in GitHub Desktop.
Save atlowl/1072ad0acd7623ff09d739c66a42361b to your computer and use it in GitHub Desktop.
ati_min_example graphql reproduction
name: Min test example
type: module
description: 'Min example to show schema.graphqls not working'
package: GraphQL
dependencies:
- graphql:graphql
- node:node
core_version_requirement: ^9.3 || ^10
# Information added by Drupal.org packaging script on 2023-04-17
version: '8.x-4.5'
project: 'graphql'
datestamp: 1681744541
type TaxTerm {
id: Int!
name: String!
}
type Image {
url: String
custom_style: String
}
type Url {
path: String
}
type Text {
summary: String
}
enum Language {
EN
IT
FR
DE
ES
}
type Date {
date: String!
}
input Condition {
field: String!
value: String!
}
type State {
value: StateType
}
enum StateType {
published
unpublished
}
<?php
namespace Drupal\ati_min_test\Plugin\GraphQL\Schema;
use Drupal\graphql\GraphQL\ResolverBuilder;
use Drupal\graphql\GraphQL\ResolverRegistry;
use Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema;
/**
* @Schema (
* id = "atimintestschema",
* name = "Min test example schema",
* )
*/
class AtiSchema extends ComposableSchema {
/**
* (@inheritdoc)
*/
public function getResolverRegistry() {
$registry = new ResolverRegistry();
$builder = new ResolverBuilder();
/* Resolve Any TaxTerms */
$registry->addFieldResolver('TaxTerm', 'id',
$builder->produce('entity_id')
->map('entity', $builder->fromParent()),
);
$registry->addFieldResolver('TaxTerm', 'name',
$builder->produce('entity_label')
->map('entity', $builder->fromParent()),
);
$registry->addFieldResolver('Image', 'url',
$builder->compose(
$builder->produce('property_path')
->map('type', $builder->fromValue('entity'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue(
'field_media_image.entity')),
$builder->produce('image_url')
->map('entity', $builder->fromParent()),
)
);
$registry->addFieldResolver('Text', 'summary',
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('body.summary')),
);
$registry->addFieldResolver('Url', 'path',
$builder->compose(
$builder->produce('entity_url')
->map('entity', $builder->fromParent()),
$builder->produce('url_path')
->map('url', $builder->fromParent()),
)
);
$registry->addFieldResolver('Date', 'date',
$builder->produce('entity_created')
->map('entity', $builder->fromParent()),
);
$registry->addFieldResolver('State', 'value',
$builder->compose(
$builder->produce('entity_published')
->map('entity', $builder->fromParent()),
$builder->callback(function ($published) {
return $published->value;
})
)
);
return $registry;
}
}
extend type Query {
event(id: Int!): Event
events(
offset: Int = 0
limit: Int = 10
conditions: [Condition]
language: Language
availability: [Condition]
exclude: [Condition]
sort: Sort
): EventConnection!
}
input Sort {
field: String
direction: Direction
}
enum Direction {
ASC
DESC
}
type Event {
id: Int!
type: String!
text_fields(language: Language = EN): EventTextFields
url: Url
}
type EventTextFields {
title: String
teaser_text: Text
}
<?php
namespace Drupal\ati_min_test\Plugin\GraphQL\SchemaExtension;
use Drupal\graphql\GraphQL\ResolverBuilder;
use Drupal\graphql\GraphQL\ResolverRegistry;
use Drupal\graphql\GraphQL\ResolverRegistryInterface;
use Drupal\graphql\Plugin\GraphQL\SchemaExtension\SdlSchemaExtensionPluginBase;
use Drupal\ati_schema\Wrappers\QueryEventConnection;
use Drupal\node\Entity\Node;
/**
* @SchemaExtension(
* id = "test_event_extension",
* name = "Test Event extension",
* description = "An extension testing the events using the common_types.graphqls",
* schema = "atimintestschema"
* )
*/
class TestEventSchemaExtension extends SdlSchemaExtensionPluginBase {
/**
* {@inheritdoc}
*/
public function registerResolvers(ResolverRegistryInterface $registry): void {
$builder = new ResolverBuilder();
// Re-usable connection type fields.
$this->addConnectionFields('EventConnection', $registry, $builder);
/* Queries ALL events */
$registry->addFieldResolver('Query', 'events',
$builder->produce('query_events')
->map('offset', $builder->fromArgument('offset'))
->map('limit', $builder->fromArgument('limit'))
->map('conditions', $builder->fromArgument('conditions'))
->map('langcode', $builder->fromArgument('language'))
->map('availability', $builder->fromArgument('availability'))
->map('exclude', $builder->fromArgument('exclude'))
->map('sort', $builder->fromArgument('sort'))
);
$registry->addFieldResolver('Query', 'event',
$builder->produce('entity_load')
->map('type', $builder->fromValue('node'))
->map('bundles', $builder->fromValue(['event']))
->map('id', $builder->fromArgument('id'))
);
$registry->addFieldResolver('Event', 'id',
$builder->produce('entity_id')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Event', 'type',
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_event_type.value')),
);
$registry->addFieldResolver('Event', 'title', $builder->fromParent());
$registry->addFieldResolver('Event', 'availability',
$builder->compose(
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_availability.entity.name.0')),
$builder->produce('seek')
->map('input', $builder->fromParent())
->map('position', $builder->fromValue(0)),
)
);
$registry->addFieldResolver('Event', 'url', $builder->fromParent());
$registry->addFieldResolver('Event', 'text_fields',
$builder->context('language', $builder->fromArgument('language'))
);
$registry->addFieldResolver('EventTextFields', 'title',
$builder->produce('entity_label')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('EventTextFields', 'teaser_text', $builder->fromParent());
$registry->addFieldResolver('Event', 'targeted_regions',
$builder->compose(
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_location')),
$builder->callback(function ($entity) {
$regions = [];
foreach ($entity as $ent) {
$regions[] = $ent->get('name')->value;
}
return $regions;
})
)
);
/* Resolve the video fields */
$registry->addFieldResolver('Event', 'video',
$builder->compose(
/* Stash the parent entity away just incase lower fields need it */
$builder->context('parent_entity', $builder->fromParent()),
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_youtube_video')),
$builder->produce('seek')
->map('input', $builder->fromParent())
->map('position', $builder->fromValue(0))
),
);
/* Resolve the market field */
$registry->addFieldResolver('Event', 'markets',
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_markets')),
);
/* Resolve the technology field */
$registry->addFieldResolver('Event', 'technology',
$builder->compose(
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_technology')),
$builder->produce('seek')
->map('input', $builder->fromParent())
->map('position', $builder->fromValue(0)),
)
);
/* Resolve the solution field */
$registry->addFieldResolver('Event', 'solutions',
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_solutions')),
);
$registry->addFieldResolver('Event', 'webinar_date',
$builder->compose(
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_date_time.date')),
$builder->callback(function ($date) {
/* Because we're returning this as a Date type, return an entity with
* the created field set to current date, the Date type knows how to
* deal with it then. */
return Node::create(['type' => 'node', 'created' => strtotime($date)]);
})
)
);
$registry->addFieldResolver('Event', 'default_image',
$builder->compose(
/* Stash the style argument to retrieve in the custom_style resolver */
$builder->context('style', $builder->fromArgument('style')),
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_default_image')),
$builder->produce('seek')
->map('input', $builder->fromParent())
->map('position', $builder->fromValue(0))
)
);
$registry->addFieldResolver('Event', 'state', $builder->fromParent());
}
/**
* @param string $type
* @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
* @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
*/
protected function addConnectionFields($type, ResolverRegistry $registry, ResolverBuilder $builder): void {
$registry->addFieldResolver($type, 'total',
$builder->callback(function (QueryEventConnection $connection) {
return $connection->total();
})
);
$registry->addFieldResolver($type, 'events',
$builder->callback(function (QueryEventConnection $connection) {
return $connection->events();
}),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment