Преглед изворни кода

alpha version of graphql api

bach пре 3 година
родитељ
комит
0ded8695ad

+ 2 - 0
src/composer.json

@@ -19,9 +19,11 @@
         "drupal/core-composer-scaffold": "^9.1",
         "drupal/core-project-message": "^9.1",
         "drupal/core-recommended": "^9.1",
+        "drupal/graphql": "^4.0",
         "drupal/insert": "2.x-dev@dev",
         "drupal/paragraphs": "^1.12",
         "drupal/redirect_after_login": "^2.7",
+        "drupal/typed_data": "1.x-dev@dev",
         "drupal/views_autocomplete_filters": "^1.3",
         "wikimedia/composer-merge-plugin": "^1.4"
     },

+ 182 - 1
src/composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "301af180ae3a0ebbc461ae46db51bf5a",
+    "content-hash": "803f9f2c0655a1fb79f86ec3ae05374e",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -5097,6 +5097,72 @@
             },
             "time": "2020-11-17T18:20:11+00:00"
         },
+        {
+            "name": "drupal/graphql",
+            "version": "4.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://git.drupalcode.org/project/graphql.git",
+                "reference": "8.x-4.0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://ftp.drupal.org/files/projects/graphql-8.x-4.0.zip",
+                "reference": "8.x-4.0",
+                "shasum": "639dd29fb6005ba2b15a389f03a6596308c9f14e"
+            },
+            "require": {
+                "drupal/core": "^8 || ^9",
+                "drupal/typed_data": "*",
+                "php": ">=7.2",
+                "webonyx/graphql-php": "^14.3.0"
+            },
+            "require-dev": {
+                "drupal/node-node": "*"
+            },
+            "type": "drupal-module",
+            "extra": {
+                "drupal": {
+                    "version": "8.x-4.0",
+                    "datestamp": "1607692423",
+                    "security-coverage": {
+                        "status": "covered",
+                        "message": "Covered by Drupal's security advisory policy"
+                    }
+                }
+            },
+            "notification-url": "https://packages.drupal.org/8/downloads",
+            "license": [
+                "GPL-2.0+"
+            ],
+            "authors": [
+                {
+                    "name": "fubhy",
+                    "homepage": "https://www.drupal.org/user/761344"
+                },
+                {
+                    "name": "hideaway",
+                    "homepage": "https://www.drupal.org/user/741876"
+                },
+                {
+                    "name": "joaogarin",
+                    "homepage": "https://www.drupal.org/user/612814"
+                },
+                {
+                    "name": "klausi",
+                    "homepage": "https://www.drupal.org/user/262198"
+                },
+                {
+                    "name": "pmelab",
+                    "homepage": "https://www.drupal.org/user/555322"
+                }
+            ],
+            "description": "Exposes your Drupal data model through a GraphQL schema.",
+            "homepage": "http://drupal.org/project/graphql",
+            "support": {
+                "source": "https://git.drupalcode.org/project/graphql"
+            }
+        },
         {
             "name": "drupal/honeypot",
             "version": "2.0.1",
@@ -7469,6 +7535,58 @@
                 "source": "https://git.drupalcode.org/project/translation_views"
             }
         },
+        {
+            "name": "drupal/typed_data",
+            "version": "dev-1.x",
+            "source": {
+                "type": "git",
+                "url": "https://git.drupalcode.org/project/typed_data.git",
+                "reference": "27555f47b522730d04f3b33c9a46c0acbcb3146e"
+            },
+            "require": {
+                "drupal/core": "^8.8.2 || ^9"
+            },
+            "type": "drupal-module",
+            "extra": {
+                "branch-alias": {
+                    "dev-1.x": "1.x-dev"
+                },
+                "drupal": {
+                    "version": "8.x-1.0-alpha5+21-dev",
+                    "datestamp": "1600719315",
+                    "security-coverage": {
+                        "status": "not-covered",
+                        "message": "Dev releases are not covered by Drupal security advisories."
+                    }
+                },
+                "drush": {
+                    "services": {
+                        "drush.services.yml": "^9 || ^10"
+                    }
+                }
+            },
+            "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"
+            },
+            "time": "2020-10-30T06:56:14+00:00"
+        },
         {
             "name": "drupal/ultimate_cron",
             "version": "2.0.0-alpha5",
@@ -12560,6 +12678,68 @@
             "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
             "time": "2015-12-17T08:42:14+00:00"
         },
+        {
+            "name": "webonyx/graphql-php",
+            "version": "v14.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/webonyx/graphql-php.git",
+                "reference": "3af8b92d07e0d7a9085c0b83daf86beaeb76f092"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/3af8b92d07e0d7a9085c0b83daf86beaeb76f092",
+                "reference": "3af8b92d07e0d7a9085c0b83daf86beaeb76f092",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "php": "^7.1||^8.0"
+            },
+            "require-dev": {
+                "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",
+                "react/promise": "2.*",
+                "simpod/php-coveralls-mirror": "^3.0",
+                "squizlabs/php_codesniffer": "3.5.4"
+            },
+            "suggest": {
+                "psr/http-message": "To use standard GraphQL server",
+                "react/promise": "To leverage async resolving on React PHP platform"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "GraphQL\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "A PHP port of GraphQL reference implementation",
+            "homepage": "https://github.com/webonyx/graphql-php",
+            "keywords": [
+                "api",
+                "graphql"
+            ],
+            "funding": [
+                {
+                    "url": "https://opencollective.com/webonyx-graphql-php",
+                    "type": "open_collective"
+                }
+            ],
+            "time": "2021-02-05T10:51:56+00:00"
+        },
         {
             "name": "wikimedia/composer-merge-plugin",
             "version": "v1.4.1",
@@ -12615,6 +12795,7 @@
     "minimum-stability": "stable",
     "stability-flags": {
         "drupal/insert": 20,
+        "drupal/typed_data": 20,
         "drupal/autocomplete_deluxe": 5,
         "drupal/better_exposed_filters": 10,
         "drupal/bulkdelete": 20,

+ 3 - 0
src/config/sync/core.extension.yml

@@ -43,6 +43,7 @@ module:
   editor: 0
   email_registration: 0
   embed: 0
+  enfrancais_graphql: 0
   entity_browser: 0
   entity_browser_enhanced: 0
   entity_reference_revisions: 0
@@ -52,6 +53,7 @@ module:
   file: 0
   filter: 0
   filter_perms: 0
+  graphql: 0
   help: 0
   honeypot: 0
   image: 0
@@ -101,6 +103,7 @@ module:
   token: 0
   toolbar: 0
   translation_views: 0
+  typed_data: 0
   update: 0
   url_to_video_filter: 0
   user: 0

+ 16 - 0
src/config/sync/graphql.graphql_servers.enfrancais.yml

@@ -0,0 +1,16 @@
+uuid: f3465d3d-f092-4afe-a50a-e9422fdab297
+langcode: fr
+status: true
+dependencies: {  }
+name: enfrancais
+label: enfrancais
+schema: enfr
+schema_configuration:
+  enfr:
+    extensions:
+      enfr_extension: enfr_extension
+persisted_queries_settings: {  }
+endpoint: /gql
+debug_flag: 3
+caching: true
+batching: true

+ 1 - 0
src/config/sync/language.types.yml

@@ -14,6 +14,7 @@ negotiation:
       language-url-fallback: 1
   language_interface:
     enabled:
+      language-graphql-operation: -999
       language-url: 0
 _core:
   default_config_hash: dqouFqVseNJNvEjsoYKxbinFOITuCxYhi4y2OTNQP_8

+ 1 - 1
src/config/sync/node.type.static.yml

@@ -10,7 +10,7 @@ third_party_settings:
     parent: ''
 _core:
   default_config_hash: Gbpk2gnakDOKmsOEikWuVfLDOZ8rtrlW-UoZFjqWCF0
-name: Static
+name: Statique
 type: static
 description: 'Static Page'
 help: ''

+ 9 - 0
src/web/modules/custom/enfrancais_graphql/enfrancais_graphql.info.yml

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

+ 97 - 0
src/web/modules/custom/enfrancais_graphql/graphql/enfr_extension.base.graphqls

@@ -0,0 +1,97 @@
+scalar Violation
+
+interface NodeInterface {
+  id: Int!
+  path: String!
+}
+
+type Textref implements NodeInterface {
+  id: Int!
+  uuid: String!
+  title: String!
+  path: String!
+  author: String
+  texte: String
+  text_en_rebond: [Textref]
+  text_produits: [Textprod]
+  images: [Image]
+  videos: [VideoLink]
+  tags: [Taxoterm]
+  familles: [Taxoterm]
+  # field_degres_detrangement
+  # notes: [Note]
+  # auteur: Auteur
+  # edition: Edition
+  # Date: String
+}
+
+type Textprod implements NodeInterface {
+  id: Int!
+  uuid: String!
+  title: String!
+  path: String!
+  author: String
+  texte: String
+  text_de_depart: [Textref]
+  images: [Image]
+  videos: [VideoLink]
+  tagsprod: [Taxoterm]
+  familles: [Taxoterm]
+  # notes: [Note]
+  # auteur: Auteur
+  # edition: Edition
+  # date: Date
+}
+
+type Filefield {
+  file: File!
+  description: String
+}
+
+type File {
+  fid: String!
+  uuid: String!
+  filename: String!
+  filemime: String!
+  filesize: String!
+  url: String!
+}
+
+type Taxoterm {
+  id: Int!
+  uuid: String!
+  name: String!
+}
+
+type Date {
+  start: String
+  end: String
+}
+
+type VideoLink {
+  url: String
+}
+
+type Image {
+  id: Int!
+  url: String!
+  alt: String
+  # style_minicard: ImageStyle
+  # style_minicard_url: String
+  # style_linkedmaterialcard: ImageStyle
+  # style_linkedmaterialcard_url: String
+  # style_cardmedium: ImageStyle
+  # style_cardmedium_url: String
+  # style_cardfull: ImageStyle
+  # style_cardfull_url: String
+  # style_articlecardmedium: ImageStyle
+  # style_articlecardmedium_url: String
+  # style_hd: ImageStyle
+  # style_hd_url: String
+}
+
+type ImageStyle {
+  width: Int
+  height: Int
+  url: String
+}

+ 31 - 0
src/web/modules/custom/enfrancais_graphql/graphql/enfr_extension.extension.graphqls

@@ -0,0 +1,31 @@
+# extend type Query {
+#   route(path: String!): NodeInterface
+# }
+
+extend type Query {
+  textref(id: Int!): Textref
+}
+
+extend type Query {
+  textsref(ids: [Int]): [Textref]
+}
+
+extend type Query {
+  textprod(id: Int!): Textprod
+}
+
+extend type Query {
+  textsprod(ids: [Int]): [Textprod]
+}
+
+extend type Query {
+  famille(id: Int!): Taxoterm
+}
+
+extend type Query {
+  tag(id: Int!): Taxoterm
+}
+
+extend type Query {
+  tagprod(id: Int!): Taxoterm
+}

+ 47 - 0
src/web/modules/custom/enfrancais_graphql/src/Plugin/GraphQL/Schema/EnFrSchema.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace Drupal\enfrancais_graphql\Plugin\GraphQL\Schema;
+
+use Drupal\graphql\Plugin\GraphQL\Schema\ComposableSchema;
+use Drupal\graphql\GraphQL\ResolverBuilder;
+use Drupal\graphql\GraphQL\ResolverRegistry;
+// use Drupal\graphql\Plugin\GraphQL\Schema\SdlSchemaPluginBase;
+use GraphQL\Error\Error;
+/**
+ * @Schema(
+ *   id = "enfr",
+ *   name = "En Francais schema",
+ *   extensions = "enfr",
+ * )
+ */
+class EnFrSchema extends ComposableSchema {
+
+  // /**
+  //  * {@inheritdoc}
+  //  */
+  // public function getResolverRegistry() {
+  //   $builder = new ResolverBuilder();
+  //   $registry = new ResolverRegistry();
+  //
+  //   // Tell GraphQL how to resolve types of a common interface.
+  //   $registry->addTypeResolver('NodeInterface', function ($value) {
+  //     if ($value instanceof NodeInterface) {
+  //       switch ($value->bundle()) {
+  //         case 'article': return 'Article';
+  //         case 'materiau': return 'Materiau';
+  //       }
+  //     }
+  //     throw new Error('Could not resolve content type.');
+  //   });
+  //
+  //   $registry->addFieldResolver('Query', 'route', $builder->compose(
+  //     $builder->produce('route_load')
+  //       ->map('path', $builder->fromArgument('path')),
+  //     $builder->produce('route_entity')
+  //       ->map('url', $builder->fromParent())
+  //   ));
+  //
+  //   return $registry;
+  // }
+
+}

+ 555 - 0
src/web/modules/custom/enfrancais_graphql/src/Plugin/GraphQL/SchemaExtension/EnFrSchemaExtension.php

@@ -0,0 +1,555 @@
+<?php
+
+namespace Drupal\enfrancais_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;
+use Drupal\Core\Url;
+
+use GraphQL\Error\Error;
+
+/**
+ * @SchemaExtension(
+ *   id = "enfr_extension",
+ *   name = "En Francais extension",
+ *   description = "En Francais extension.",
+ *   schema = "enfr"
+ * )
+ */
+class EnFrSchemaExtension extends SdlSchemaExtensionPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function registerResolvers(ResolverRegistryInterface $registry) {
+    $builder = new ResolverBuilder();
+
+    $this->addRouteResolver($registry, $builder);
+
+    $this->addTextref($registry, $builder);
+
+    $this->addTextprod($registry, $builder);
+    //
+    $this->addFilefield($registry, $builder);
+    //
+    $this->addFile($registry, $builder);
+    //
+    $this->addDate($registry, $builder);
+    //
+    $this->addVideolink($registry, $builder);
+    //
+    $this->addImage($registry, $builder);
+    //
+    $this->addTaxoterm($registry, $builder);
+    //
+    // $this->addNote($registry, $builder);
+    //
+    // $this->addSearchResult($registry, $builder);
+    //
+    // $this->addSample($registry, $builder);
+    //
+    // $this->addArticle($registry, $builder);
+    //
+    // $this->addThematique($registry, $builder);
+    //
+    // $this->addCompany($registry, $builder);
+    //
+    // $this->addProduct($registry, $builder);
+    //
+    // $this->addVariation($registry, $builder);
+    //
+    // $this->addPrice($registry, $builder);
+    //
+    // $this->addAddress($registry, $builder);
+    //
+    // $this->addLink($registry, $builder);
+    //
+    // $this->addShowroom($registry, $builder);
+    //
+    // $this->addThesaurus($registry, $builder);
+    //
+
+  }
+
+  //  ___          _
+  // | _ \___ _  _| |_ ___
+  // |   / _ \ || |  _/ -_)
+  // |_|_\___/\_,_|\__\___|
+  protected function addRouteResolver(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    // Tell GraphQL how to resolve types of a common interface.
+    $registry->addTypeResolver('NodeInterface', function ($value) {
+
+      $path = explode('\\', get_class($value));
+      $class = array_pop($path);
+
+      if ($class === 'Node') {
+        switch ($value->bundle()) {
+          case 'texte': return 'Textref';
+          case 'texte_prod': return 'TextProd';
+        }
+      }
+      throw new Error('Could not resolve content type.');
+    });
+
+    $registry->addFieldResolver('Query', 'route',
+      $builder->compose(
+        $builder->produce('route_load')
+          ->map('path', $builder->fromArgument('path')),
+        $builder->produce('route_entity')
+          ->map('url', $builder->fromParent())
+    ));
+  }
+
+
+  //  _____        _            __
+  // |_   _|____ _| |_ _ _ ___ / _|
+  //   | |/ -_) \ /  _| '_/ -_)  _|
+  //   |_|\___/_\_\\__|_| \___|_|
+  protected function addTextref(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+
+    // $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
+
+    $registry->addFieldResolver('Query', 'textref',
+      $builder->produce('entity_load')
+        ->map('type', $builder->fromValue('node'))
+        ->map('bundles', $builder->fromValue(['texte']))
+        ->map('id', $builder->fromArgument('id'))
+    );
+
+    $registry->addFieldResolver('Query', 'textsref',
+      $builder->produce('entity_load_multiple')
+        ->map('type', $builder->fromValue('node'))
+        ->map('ids', $builder->fromArgument('ids'))
+    );
+
+    $registry->addFieldResolver('Textref', 'id',
+      $builder->produce('entity_id')
+        ->map('entity', $builder->fromParent())
+      );
+
+    $registry->addFieldResolver('Textref', 'uuid',
+      $builder->produce('entity_uuid')
+        ->map('entity', $builder->fromParent())
+      );
+
+    $registry->addFieldResolver('Textref', 'path',
+      $builder->compose(
+        $builder->produce('entity_url')
+          ->map('entity', $builder->fromParent()),
+        $builder->produce('url_path')
+          ->map('url', $builder->fromParent())
+      )
+    );
+
+    $registry->addFieldResolver('Textref', 'title',
+      $builder->compose(
+        $builder->produce('entity_label')
+          ->map('entity', $builder->fromParent())
+      ));
+
+    $registry->addFieldResolver('Textref', 'texte',
+      $builder->produce('property_path')
+        ->map('type', $builder->fromValue('entity:node'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('body.value'))
+      );
+
+    $registry->addFieldResolver('Textref', 'author',
+      $builder->compose(
+        $builder->produce('entity_owner')
+          ->map('entity', $builder->fromParent()),
+        $builder->produce('entity_label')
+          ->map('entity', $builder->fromParent())
+      ));
+
+    $registry->addFieldResolver('Textref', 'text_en_rebond',
+      $builder->compose(
+        $builder->produce('entity_reference')
+          ->map('entity', $builder->fromParent())
+          ->map('field', $builder->fromValue('field_texte_en_rebond'))
+      ));
+
+    $registry->addFieldResolver('Textref', 'text_produits',
+      $builder->compose(
+        $builder->produce('entity_reference')
+          ->map('entity', $builder->fromParent())
+          ->map('field', $builder->fromValue('field_textes_produits'))
+      ));
+
+    $registry->addFieldResolver('Textref', 'images',
+      $builder->produce('entity_reference')
+        ->map('entity', $builder->fromParent())
+        ->map('field', $builder->fromValue('field_images'))
+      );
+
+    $registry->addFieldResolver('Textref', 'videos',
+      $builder->produce('property_path')
+        ->map('type', $builder->fromValue('entity:node'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('field_video'))
+      );
+
+    $registry->addFieldResolver('Textref', 'tags',
+      $builder->produce('entity_reference')
+        ->map('entity', $builder->fromParent())
+        ->map('field', $builder->fromValue('field_tag'))
+      );
+
+    $registry->addFieldResolver('Textref', 'familles',
+      $builder->produce('entity_reference')
+        ->map('entity', $builder->fromParent())
+        ->map('field', $builder->fromValue('field_famille'))
+      );
+  }
+
+
+  //  _____        _   ___             _
+  // |_   _|____ _| |_| _ \_ _ ___  __| |
+  //   | |/ -_) \ /  _|  _/ '_/ _ \/ _` |
+  //   |_|\___/_\_\\__|_| |_| \___/\__,_|
+  protected function addTextprod(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+
+    // $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
+
+    $registry->addFieldResolver('Query', 'textprod',
+      $builder->produce('entity_load')
+        ->map('type', $builder->fromValue('node'))
+        ->map('bundles', $builder->fromValue(['texte_prod']))
+        ->map('id', $builder->fromArgument('id'))
+    );
+
+    $registry->addFieldResolver('Query', 'textsprod',
+      $builder->produce('entity_load_multiple')
+        ->map('type', $builder->fromValue('node'))
+        ->map('ids', $builder->fromArgument('ids'))
+    );
+
+    $registry->addFieldResolver('Textprod', 'id',
+      $builder->produce('entity_id')
+        ->map('entity', $builder->fromParent())
+      );
+
+    $registry->addFieldResolver('Textprod', 'uuid',
+      $builder->produce('entity_uuid')
+        ->map('entity', $builder->fromParent())
+      );
+
+    $registry->addFieldResolver('Textprod', 'path',
+      $builder->compose(
+        $builder->produce('entity_url')
+          ->map('entity', $builder->fromParent()),
+        $builder->produce('url_path')
+          ->map('url', $builder->fromParent())
+      )
+    );
+
+    $registry->addFieldResolver('Textprod', 'title',
+      $builder->compose(
+        $builder->produce('entity_label')
+          ->map('entity', $builder->fromParent())
+      ));
+
+    $registry->addFieldResolver('Textprod', 'texte',
+      $builder->produce('property_path')
+        ->map('type', $builder->fromValue('entity:node'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('body.value'))
+      );
+
+    $registry->addFieldResolver('Textprod', 'author',
+      $builder->compose(
+        $builder->produce('entity_owner')
+          ->map('entity', $builder->fromParent()),
+        $builder->produce('entity_label')
+          ->map('entity', $builder->fromParent())
+      ));
+
+    $registry->addFieldResolver('Textprod', 'text_de_depart',
+      $builder->compose(
+        $builder->produce('entity_reference')
+          ->map('entity', $builder->fromParent())
+          ->map('field', $builder->fromValue('field_texte_de_depart'))
+      ));
+
+    $registry->addFieldResolver('Textprod', 'images',
+      $builder->produce('entity_reference')
+        ->map('entity', $builder->fromParent())
+        ->map('field', $builder->fromValue('field_images'))
+      );
+
+    $registry->addFieldResolver('Textprod', 'videos',
+      $builder->produce('property_path')
+        ->map('type', $builder->fromValue('entity:node'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('field_video'))
+      );
+
+    $registry->addFieldResolver('Textprod', 'tags',
+      $builder->produce('entity_reference')
+        ->map('entity', $builder->fromParent())
+        ->map('field', $builder->fromValue('field_tag_prod'))
+      );
+
+    $registry->addFieldResolver('Textprod', 'familles',
+      $builder->produce('entity_reference')
+        ->map('entity', $builder->fromParent())
+        ->map('field', $builder->fromValue('field_famille'))
+      );
+  }
+
+  //  ___       _
+  // |   \ __ _| |_ ___
+  // | |) / _` |  _/ -_)
+  // |___/\__,_|\__\___|
+  protected function addDate(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    $registry->addFieldResolver('Date', 'start',
+      $builder->callback(function ($parent, $args) {
+        return isset($parent[0]) ? $parent[0]['value'] : null;
+      })
+    );
+    $registry->addFieldResolver('Date', 'end',
+      $builder->callback(function ($parent, $args) {
+        return isset($parent[0]) ? $parent[0]['end_value'] : null;
+      })
+    );
+  }
+
+  //  ___ _ _      __ _     _    _
+  // | __(_) |___ / _(_)___| |__| |
+  // | _|| | / -_)  _| / -_) / _` |
+  // |_| |_|_\___|_| |_\___|_\__,_|
+  protected function addFilefield(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    $registry->addFieldResolver('Filefield', 'description',
+      $builder->callback(function ($parent, $args) {
+        return $parent['description'];
+      })
+    );
+    $registry->addFieldResolver('Filefield', 'file',
+      $builder->callback(function ($parent, $args) {
+        return \Drupal\file\Entity\File::load($parent['target_id']);
+      })
+    );
+  }
+
+  //  ___ _ _
+  // | __(_) |___
+  // | _|| | / -_)
+  // |_| |_|_\___|
+  protected function addFile(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    $registry->addFieldResolver('File', 'url',
+      $builder->callback(function ($parent, $args) {
+        return $parent->url();
+      })
+    );
+
+    $registry->addFieldResolver('File', 'filesize',
+      $builder->callback(function ($parent, $args) {
+        return $parent->getSize();
+      })
+    );
+
+    $registry->addFieldResolver('File', 'filemime',
+      $builder->callback(function ($parent, $args) {
+        return $parent->getMimeType();
+      })
+    );
+
+    $registry->addFieldResolver('File', 'filename',
+      $builder->callback(function ($parent, $args) {
+        return $parent->getFilename();
+      })
+    );
+
+    $registry->addFieldResolver('File', 'fid',
+      $builder->callback(function ($parent, $args) {
+        return $parent->id();
+      })
+    );
+
+    $registry->addFieldResolver('File', 'uuid',
+      $builder->callback(function ($parent, $args) {
+        return $parent->uuid();
+      })
+    );
+  }
+
+  //  ___
+  // |_ _|_ __  __ _ __ _ ___
+  //  | || '  \/ _` / _` / -_)
+  // |___|_|_|_\__,_\__, \___|
+  //                |___/
+  protected function addImage(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    $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'))
+      );
+
+    $registry->addFieldResolver('Image', 'style_minicard_url',
+      $builder->compose(
+        $builder->produce('image_derivative')
+          ->map('entity', $builder->fromParent())
+          ->map('style', $builder->fromValue('card_medium_half')),
+        $builder->callback(function($parent, $args){
+            return $parent['url'];
+          })
+      ));
+
+    $registry->addFieldResolver('Image', 'style_linkedmaterialcard',
+      $builder->produce('image_derivative')
+        ->map('entity', $builder->fromParent())
+        ->map('style', $builder->fromValue('linkedmaterial_card'))
+      );
+
+    $registry->addFieldResolver('Image', 'style_linkedmaterialcard_url',
+      $builder->compose(
+        $builder->produce('image_derivative')
+          ->map('entity', $builder->fromParent())
+          ->map('style', $builder->fromValue('linkedmaterial_card')),
+        $builder->callback(function($parent, $args){
+            return $parent['url'];
+          })
+      ));
+
+    $registry->addFieldResolver('Image', 'style_cardmedium',
+      $builder->produce('image_derivative')
+        ->map('entity', $builder->fromParent())
+        ->map('style', $builder->fromValue('card_medium'))
+      );
+
+    $registry->addFieldResolver('Image', 'style_cardmedium_url',
+      $builder->compose(
+        $builder->produce('image_derivative')
+          ->map('entity', $builder->fromParent())
+          ->map('style', $builder->fromValue('card_medium')),
+        $builder->callback(function($parent, $args){
+            return $parent['url'];
+          })
+      ));
+
+    $registry->addFieldResolver('Image', 'style_cardfull',
+      $builder->produce('image_derivative')
+        ->map('entity', $builder->fromParent())
+        ->map('style', $builder->fromValue('card_full'))
+      );
+
+    $registry->addFieldResolver('Image', 'style_cardfull_url',
+      $builder->compose(
+        $builder->produce('image_derivative')
+          ->map('entity', $builder->fromParent())
+          ->map('style', $builder->fromValue('card_full')),
+        $builder->callback(function($parent, $args){
+            return $parent['url'];
+          })
+      ));
+
+    $registry->addFieldResolver('Image', 'style_articlecardmedium',
+      $builder->produce('image_derivative')
+        ->map('entity', $builder->fromParent())
+        ->map('style', $builder->fromValue('article_card_medium'))
+      );
+
+    $registry->addFieldResolver('Image', 'style_articlecardmedium_url',
+      $builder->compose(
+        $builder->produce('image_derivative')
+          ->map('entity', $builder->fromParent())
+          ->map('style', $builder->fromValue('article_card_medium')),
+        $builder->callback(function($parent, $args){
+            return $parent['url'];
+          })
+      ));
+
+    $registry->addFieldResolver('Image', 'style_hd',
+      $builder->produce('image_derivative')
+        ->map('entity', $builder->fromParent())
+        ->map('style', $builder->fromValue('hd'))
+      );
+
+    $registry->addFieldResolver('Image', 'style_hd_url',
+      $builder->compose(
+        $builder->produce('image_derivative')
+          ->map('entity', $builder->fromParent())
+          ->map('style', $builder->fromValue('hd')),
+        $builder->callback(function($parent, $args){
+            return $parent['url'];
+          })
+      ));
+
+  }
+
+  // __   ___    _         _    _      _
+  // \ \ / (_)__| |___ ___| |  (_)_ _ | |__
+  //  \ V /| / _` / -_) _ \ |__| | ' \| / /
+  //   \_/ |_\__,_\___\___/____|_|_||_|_\_\
+  protected function addVideolink(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    $registry->addFieldResolver('VideoLink', 'url',
+      $builder->produce('property_path')
+        ->map('type', $builder->fromValue('field_item:video_embed_field'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('value'))
+      );
+  }
+
+  //  _____
+  // |_   _|_ _ __ _
+  //   | |/ _` / _` |
+  //   |_|\__,_\__, |
+  //           |___/
+  protected function addTaxoterm(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+    $registry->addFieldResolver('Query', 'tag',
+     $builder->produce('entity_load')
+       ->map('type', $builder->fromValue('taxonomy_term'))
+       ->map('bundles', $builder->fromValue(['tag']))
+       ->map('id', $builder->fromArgument('id'))
+     );
+    $registry->addFieldResolver('Query', 'famille',
+      $builder->produce('entity_load')
+        ->map('type', $builder->fromValue('taxonomy_term'))
+        ->map('bundles', $builder->fromValue(['famille']))
+        ->map('id', $builder->fromArgument('id'))
+    );
+    $registry->addFieldResolver('Query', 'tagprod',
+     $builder->produce('entity_load')
+       ->map('type', $builder->fromValue('taxonomy_term'))
+       ->map('bundles', $builder->fromValue(['tag_prod']))
+       ->map('id', $builder->fromArgument('id'))
+     );
+
+    $registry->addFieldResolver('Taxoterm', 'id',
+     $builder->produce('entity_id')
+       ->map('entity', $builder->fromParent())
+     );
+
+    $registry->addFieldResolver('Taxoterm', 'uuid',
+     $builder->produce('entity_uuid')
+       ->map('entity', $builder->fromParent())
+     );
+
+    $registry->addFieldResolver('Taxoterm', 'name',
+     $builder->produce('entity_label')
+       ->map('entity', $builder->fromParent())
+     );
+  }
+
+
+}