added working graphql 4 module and started materio_graphql

This commit is contained in:
Bachir Soussi Chiadmi 2020-12-09 22:55:16 +01:00
parent 2fbba0fe7f
commit 2071a99ca2
16 changed files with 525 additions and 27 deletions

View File

@ -41,7 +41,7 @@
"drupal/field_permissions": "^1.0", "drupal/field_permissions": "^1.0",
"drupal/flag_lists": "^4.0@beta", "drupal/flag_lists": "^4.0@beta",
"drupal/genpass": "^1.x-dev", "drupal/genpass": "^1.x-dev",
"drupal/graphql": "^3.1", "drupal/graphql": "4.x-dev@dev",
"drupal/image_delta_formatter": "^1.x-dev", "drupal/image_delta_formatter": "^1.x-dev",
"drupal/image_effects": "3.x-dev@dev", "drupal/image_effects": "3.x-dev@dev",
"drupal/jsonapi_extras": "^3.7", "drupal/jsonapi_extras": "^3.7",

118
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "4de458a514e6c8847c1a5d2ca4c0187d", "content-hash": "d537c65dd030c043b106fe27f25a754a",
"packages": [ "packages": [
{ {
"name": "alchemy/zippy", "name": "alchemy/zippy",
@ -7211,30 +7211,32 @@
}, },
{ {
"name": "drupal/graphql", "name": "drupal/graphql",
"version": "3.1.0", "version": "dev-4.x",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://git.drupalcode.org/project/graphql.git", "url": "https://git.drupalcode.org/project/graphql.git",
"reference": "8.x-3.1" "reference": "47bd0ddafc2bc6f0177ff0b3e75d64890610f086"
},
"dist": {
"type": "zip",
"url": "https://ftp.drupal.org/files/projects/graphql-8.x-3.1.zip",
"reference": "8.x-3.1",
"shasum": "088430befbf13f2c8dadf1d9d14d01487e6f52bc"
}, },
"require": { "require": {
"drupal/core": "^8.8 || ^9", "drupal/core": "^8 || ^9",
"webonyx/graphql-php": "^0.12.5" "drupal/typed_data": "*",
"php": ">=7.2",
"webonyx/graphql-php": "^14.3.0"
},
"require-dev": {
"drupal/node-node": "*"
}, },
"type": "drupal-module", "type": "drupal-module",
"extra": { "extra": {
"branch-alias": {
"dev-4.x": "4.x-dev"
},
"drupal": { "drupal": {
"version": "8.x-3.1", "version": "8.x-4.0-beta3+12-dev",
"datestamp": "1603962169", "datestamp": "1606548247",
"security-coverage": { "security-coverage": {
"status": "covered", "status": "not-covered",
"message": "Covered by Drupal's security advisory policy" "message": "Dev releases are not covered by Drupal security advisories."
} }
} }
}, },
@ -7264,7 +7266,8 @@
"homepage": "http://drupal.org/project/graphql", "homepage": "http://drupal.org/project/graphql",
"support": { "support": {
"source": "https://git.drupalcode.org/project/graphql" "source": "https://git.drupalcode.org/project/graphql"
} },
"time": "2020-12-05T14:12:52+00:00"
}, },
{ {
"name": "drupal/honeypot", "name": "drupal/honeypot",
@ -11244,6 +11247,55 @@
}, },
"time": "2020-09-06T12:45:51+00:00" "time": "2020-09-06T12:45:51+00:00"
}, },
{
"name": "drupal/typed_data",
"version": "1.0.0-alpha5",
"source": {
"type": "git",
"url": "https://git.drupalcode.org/project/typed_data.git",
"reference": "8.x-1.0-alpha5"
},
"dist": {
"type": "zip",
"url": "https://ftp.drupal.org/files/projects/typed_data-8.x-1.0-alpha5.zip",
"reference": "8.x-1.0-alpha5",
"shasum": "44cfaf8f6d6bc0b876e88a8b9d473799818d395f"
},
"require": {
"drupal/core": "^8.7.7 || ^9"
},
"type": "drupal-module",
"extra": {
"drupal": {
"version": "8.x-1.0-alpha5",
"datestamp": "1591397037",
"security-coverage": {
"status": "not-covered",
"message": "Alpha releases are not covered by Drupal security advisories."
}
}
},
"notification-url": "https://packages.drupal.org/8/downloads",
"license": [
"GPL-2.0-or-later"
],
"authors": [
{
"name": "TR",
"homepage": "https://www.drupal.org/user/202830"
},
{
"name": "fago",
"homepage": "https://www.drupal.org/user/16747"
}
],
"description": "Extends the core Typed Data API with new APIs and features.",
"homepage": "https://www.drupal.org/project/typed_data",
"support": {
"source": "https://git.drupalcode.org/project/typed_data",
"issues": "https://www.drupal.org/project/issues/typed_data"
}
},
{ {
"name": "drupal/ultimate_cron", "name": "drupal/ultimate_cron",
"version": "dev-2.x", "version": "dev-2.x",
@ -17636,26 +17688,37 @@
}, },
{ {
"name": "webonyx/graphql-php", "name": "webonyx/graphql-php",
"version": "v0.12.6", "version": "v14.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webonyx/graphql-php.git", "url": "https://github.com/webonyx/graphql-php.git",
"reference": "4c545e5ec4fc37f6eb36c19f5a0e7feaf5979c95" "reference": "aab3d49181467db064b41429cde117a7589625fc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webonyx/graphql-php/zipball/4c545e5ec4fc37f6eb36c19f5a0e7feaf5979c95", "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/aab3d49181467db064b41429cde117a7589625fc",
"reference": "4c545e5ec4fc37f6eb36c19f5a0e7feaf5979c95", "reference": "aab3d49181467db064b41429cde117a7589625fc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"php": ">=5.6" "php": "^7.1||^8.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8", "amphp/amp": "^2.3",
"doctrine/coding-standard": "^6.0",
"nyholm/psr7": "^1.2",
"phpbench/phpbench": "^0.16.10",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "0.12.32",
"phpstan/phpstan-phpunit": "0.12.11",
"phpstan/phpstan-strict-rules": "0.12.2",
"phpunit/phpunit": "^7.2|^8.5",
"psr/http-message": "^1.0", "psr/http-message": "^1.0",
"react/promise": "2.*" "react/promise": "2.*",
"simpod/php-coveralls-mirror": "^3.0",
"squizlabs/php_codesniffer": "3.5.4"
}, },
"suggest": { "suggest": {
"psr/http-message": "To use standard GraphQL server", "psr/http-message": "To use standard GraphQL server",
@ -17677,7 +17740,13 @@
"api", "api",
"graphql" "graphql"
], ],
"time": "2018-09-02T14:59:54+00:00" "funding": [
{
"url": "https://opencollective.com/webonyx-graphql-php",
"type": "open_collective"
}
],
"time": "2020-12-03T16:05:21+00:00"
}, },
{ {
"name": "wikimedia/composer-merge-plugin", "name": "wikimedia/composer-merge-plugin",
@ -17792,6 +17861,7 @@
"drupal/content_sync": 20, "drupal/content_sync": 20,
"drupal/flag_lists": 10, "drupal/flag_lists": 10,
"drupal/genpass": 20, "drupal/genpass": 20,
"drupal/graphql": 20,
"drupal/image_delta_formatter": 20, "drupal/image_delta_formatter": 20,
"drupal/image_effects": 20, "drupal/image_effects": 20,
"drupal/jsonrpc": 20, "drupal/jsonrpc": 20,

View File

@ -83,7 +83,6 @@ module:
flag_lists: 0 flag_lists: 0
genpass: 0 genpass: 0
graphql: 0 graphql: 0
graphql_core: 0
help: 0 help: 0
honeypot: 0 honeypot: 0
image: 0 image: 0
@ -110,6 +109,7 @@ module:
mailsystem: 0 mailsystem: 0
materio_decoupled: 0 materio_decoupled: 0
materio_flag: 0 materio_flag: 0
materio_graphql: 0
materio_home: 0 materio_home: 0
materio_jsonapi: 0 materio_jsonapi: 0
materio_migrate: 0 materio_migrate: 0
@ -172,6 +172,7 @@ module:
toolbar: 0 toolbar: 0
toolbar_themes: 0 toolbar_themes: 0
translation_views: 0 translation_views: 0
typed_data: 0
ultimate_cron: 0 ultimate_cron: 0
update: 0 update: 0
url_to_video_filter: 0 url_to_video_filter: 0

View File

@ -0,0 +1,16 @@
uuid: 459392ea-9948-4df3-bf5d-64905bafea0d
langcode: en
status: true
dependencies: { }
name: materio
label: materio
schema: materio
schema_configuration:
materio:
extensions:
materio_extension: materio_extension
persisted_queries_settings: { }
endpoint: /mgq
debug_flag: 0
caching: false
batching: false

View File

@ -0,0 +1 @@
contexts_used: '["materio","stringTranslationUi"]'

View File

@ -21,6 +21,8 @@ permissions:
- 'create generique workflow_transition' - 'create generique workflow_transition'
- 'create migration workflow_transition' - 'create migration workflow_transition'
- 'create workflow workflow_transition' - 'create workflow workflow_transition'
- 'execute materio arbitrary graphql requests'
- 'execute materio persisted graphql requests'
- 'issue subrequests' - 'issue subrequests'
- 'restful get config_rest_resource' - 'restful get config_rest_resource'
- 'restful post user_registration' - 'restful post user_registration'

View File

@ -27,6 +27,8 @@ permissions:
- 'edit own chutier entities' - 'edit own chutier entities'
- 'edit own composition entities' - 'edit own composition entities'
- 'edit own fil entities' - 'edit own fil entities'
- 'execute materio arbitrary graphql requests'
- 'execute materio persisted graphql requests'
- 'issue subrequests' - 'issue subrequests'
- 'manage own commerce_payment_method' - 'manage own commerce_payment_method'
- 'materio_jsonapi ownroles' - 'materio_jsonapi ownroles'

View File

@ -6,4 +6,5 @@ id: unverified
label: Unverified label: Unverified
weight: -10 weight: -10
is_admin: null is_admin: null
permissions: { } permissions:
- 'execute materio persisted graphql requests'

View File

@ -0,0 +1,40 @@
type Mutation
scalar Violation
type Materiau {
id: Int!
uuid: String!
title: String!
author: String
memo: String
linked_materials: [Materiau]
images: [Image]
}
type MateriauResponse implements Response {
errors: [Violation]
materiau: Materiau
}
interface Response {
errors: [Violation]
}
input MateriauInput {
title: String!
description: String
}
type Image {
id: Int!
url: String!
alt: String
style_minicard: ImageStyle
}
type ImageStyle {
width: Int
height: Int
url: String
}

View File

@ -0,0 +1,7 @@
extend type Query {
materiau(id: Int!): Materiau
}
extend type Mutation {
createMateriau(data: MateriauInput): MateriauResponse
}

View File

@ -0,0 +1,9 @@
name: Materio GraphQL
type: module
description: 'Materio GraphQL schema.'
package: Materio
core: 8.x
dependencies:
- graphql:graphql
- node:node
core_version_requirement: ^8 || ^9

View File

@ -0,0 +1,40 @@
<?php
namespace Drupal\materio_graphql\GraphQL\Response;
use Drupal\Core\Entity\EntityInterface;
use Drupal\graphql\GraphQL\Response\Response;
/**
* Type of response used when an materiau is returned.
*/
class MateriauResponse extends Response {
/**
* The materiau to be served.
*
* @var \Drupal\Core\Entity\EntityInterface|null
*/
protected $materiau;
/**
* Sets the content.
*
* @param \Drupal\Core\Entity\EntityInterface|null $materiau
* The materiau to be served.
*/
public function setMateriau(?EntityInterface $materiau): void {
$this->materiau = $materiau;
}
/**
* Gets the materiau to be served.
*
* @return \Drupal\Core\Entity\EntityInterface|null
* The materiau to be served.
*/
public function materiau(): ?EntityInterface {
return $this->materiau;
}
}

View File

@ -0,0 +1,98 @@
<?php
namespace Drupal\materio_graphql\Plugin\GraphQL\DataProducer;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;
use Drupal\materio_graphql\GraphQL\Response\MateriauResponse;
use Drupal\node\Entity\Node;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Creates a new materiau entity.
*
* @DataProducer(
* id = "create_materiau",
* name = @Translation("Create Materiau"),
* description = @Translation("Creates a new materiau."),
* produces = @ContextDefinition("any",
* label = @Translation("Materiau")
* ),
* consumes = {
* "data" = @ContextDefinition("any",
* label = @Translation("Materiau data")
* )
* }
* )
*/
class CreateMateriau extends DataProducerPluginBase implements ContainerFactoryPluginInterface {
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_user')
);
}
/**
* CreateMateriau constructor.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param array $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(array $configuration, string $plugin_id, array $plugin_definition, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->currentUser = $current_user;
}
/**
* Creates an materiau.
*
* @param array $data
* The submitted values for the materiau.
*
* @return \Drupal\graphql_composable\GraphQL\Response\MateriauResponse
* The newly created materiau.
*
* @throws \Exception
*/
public function resolve(array $data) {
$response = new MateriauResponse();
if ($this->currentUser->hasPermission("create materiau content")) {
$values = [
'type' => 'materiau',
'title' => $data['title'],
'body' => $data['description'],
];
$node = Node::create($values);
$node->save();
$response->setMateriau($node);
}
else {
$response->addViolation(
$this->t('You do not have permissions to create materiaus.')
);
}
return $response;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Drupal\materio_graphql\Plugin\GraphQL\Schema;
use Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema;
/**
* @Schema(
* id = "materio",
* name = "Materio schema",
* extensions = "materio",
* )
*/
class MaterioSchema extends ComposableSchema {
}

View File

@ -0,0 +1,153 @@
<?php
namespace Drupal\materio_graphql\Plugin\GraphQL\SchemaExtension;
use Drupal\graphql\GraphQL\ResolverBuilder;
use Drupal\graphql\GraphQL\ResolverRegistryInterface;
use Drupal\graphql\GraphQL\Response\ResponseInterface;
use Drupal\graphql\Plugin\GraphQL\SchemaExtension\SdlSchemaExtensionPluginBase;
use Drupal\materio_graphql\GraphQL\Response\MaterioResponse;
/**
* @SchemaExtension(
* id = "materio_extension",
* name = "Materio extension",
* description = "Materio extension.",
* schema = "materio"
* )
*/
class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
/**
* {@inheritdoc}
*/
public function registerResolvers(ResolverRegistryInterface $registry) {
$builder = new ResolverBuilder();
$registry->addFieldResolver('Query', 'materiau',
$builder->produce('entity_load')
->map('type', $builder->fromValue('node'))
->map('bundles', $builder->fromValue(['materiau']))
->map('id', $builder->fromArgument('id'))
);
// Create materiau mutation.
$registry->addFieldResolver('Mutation', 'createMateriau',
$builder->produce('create_materiau')
->map('data', $builder->fromArgument('data'))
);
$registry->addFieldResolver('MateriauResponse', 'materiau',
$builder->callback(function (MateriauResponse $response) {
return $response->materiau();
})
);
$registry->addFieldResolver('MateriauResponse', 'errors',
$builder->callback(function (MateriauResponse $response) {
return $response->getViolations();
})
);
$registry->addFieldResolver('Materiau', 'id',
$builder->produce('entity_id')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Materiau', 'uuid',
$builder->produce('entity_uuid')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Materiau', 'title',
$builder->compose(
$builder->produce('entity_label')
->map('entity', $builder->fromParent())
)
);
$registry->addFieldResolver('Materiau', 'author',
$builder->compose(
$builder->produce('entity_owner')
->map('entity', $builder->fromParent()),
$builder->produce('entity_label')
->map('entity', $builder->fromParent())
)
);
// https://github.com/drupal-graphql/graphql/blob/8.x-4.x/doc/SUMMARY.md
// https://blog.chrismitchellonline.com/posts/custom_graphql_data/
$registry->addFieldResolver('Materiau', 'linked_materials',
$builder->compose(
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_linked_materials'))
)
);
$registry->addFieldResolver('Materiau', 'memo',
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_memo.value'))
);
$registry->addFieldResolver('Materiau', 'images',
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_materiau_images'))
);
$registry->addFieldResolver('Image', 'id',
$builder->produce('entity_id')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Image', 'url',
$builder->produce('image_url')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Image', 'alt',
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_image.alt'))
);
$registry->addFieldResolver('Image', 'style_minicard',
$builder->produce('image_derivative')
->map('entity', $builder->fromParent())
->map('style', $builder->fromValue('card_medium_half'))
);
// Response type resolver.
$registry->addTypeResolver('Response', [
__CLASS__,
'resolveResponse',
]);
}
/**
* Resolves the response type.
*
* @param \Drupal\graphql\GraphQL\Response\ResponseInterface $response
* Response object.
*
* @return string
* Response type.
*
* @throws \Exception
* Invalid response type.
*/
public static function resolveResponse(ResponseInterface $response): string {
// Resolve content response.
if ($response instanceof MateriauResponse) {
return 'MateriauResponse';
}
throw new \Exception('Invalid response type.');
}
}

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types = 1);
namespace Drupal\materio_graphql\Wrappers\Response;
use Drupal\Core\Entity\EntityInterface;
use Drupal\graphql\GraphQL\Response\Response;
/**
* Type of response used when an materiau is returned.
*/
class MateriauResponse extends Response {
/**
* The materiau to be served.
*
* @var \Drupal\Core\Entity\EntityInterface|null
*/
protected $materiau;
/**
* Sets the content.
*
* @param \Drupal\Core\Entity\EntityInterface|null $materiau
* The materiau to be served.
*/
public function setMateriau(?EntityInterface $materiau): void {
$this->materiau = $materiau;
}
/**
* Gets the materiau to be served.
*
* @return \Drupal\Core\Entity\EntityInterface|null
* The materiau to be served.
*/
public function materiau(): ?EntityInterface {
return $this->materiau;
}
}