From 787494bfc8147dff3e0e0a4af38d87453e81ca68 Mon Sep 17 00:00:00 2001 From: bach Date: Wed, 21 Sep 2022 11:28:14 +0200 Subject: [PATCH] graphql enabled and configured with existing content architecture --- src/composer.json | 5 + src/composer.lock | 184 ++++- ...ntity_form_display.node.entite.default.yml | 43 +- ....paragraph.entite_concernement.default.yml | 16 + ...ntity_view_display.node.entite.default.yml | 14 + ...entity_view_display.node.entite.teaser.yml | 2 + ....paragraph.entite_concernement.default.yml | 24 + src/config/sync/core.extension.yml | 3 + ...d.field.node.concernement.field_entite.yml | 2 +- .../field.field.node.entite.field_liens.yml | 23 + ...agraph.entite_concernement.field_angle.yml | 23 + ...agraph.entite_concernement.field_rayon.yml | 23 + .../sync/field.storage.node.field_liens.yml | 19 + .../field.storage.paragraph.field_angle.yml | 20 + .../field.storage.paragraph.field_rayon.yml | 20 + .../graphql.graphql_servers.ouatterrir.yml | 19 + src/config/sync/language.types.yml | 1 + ...fix-invalid-translation-language-dev.patch | 98 +++ .../graphql/ouatt_extension.base.graphqls | 105 +++ .../ouatt_extension.extension.graphqls | 48 ++ .../ouatt_graphql/ouatt_graphql.info.yml | 9 + .../src/Plugin/GraphQL/Schema/OuattSchema.php | 47 ++ .../SchemaExtension/OuattSchemaExtension.php | 658 ++++++++++++++++++ 23 files changed, 1403 insertions(+), 3 deletions(-) create mode 100644 src/config/sync/field.field.node.entite.field_liens.yml create mode 100644 src/config/sync/field.field.paragraph.entite_concernement.field_angle.yml create mode 100644 src/config/sync/field.field.paragraph.entite_concernement.field_rayon.yml create mode 100644 src/config/sync/field.storage.node.field_liens.yml create mode 100644 src/config/sync/field.storage.paragraph.field_angle.yml create mode 100644 src/config/sync/field.storage.paragraph.field_rayon.yml create mode 100644 src/config/sync/graphql.graphql_servers.ouatterrir.yml create mode 100644 src/patches/graphql-fix-invalid-translation-language-dev.patch create mode 100644 src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.base.graphqls create mode 100644 src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.extension.graphqls create mode 100644 src/web/modules/custom/ouatt_graphql/ouatt_graphql.info.yml create mode 100644 src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/Schema/OuattSchema.php create mode 100644 src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/SchemaExtension/OuattSchemaExtension.php diff --git a/src/composer.json b/src/composer.json index 9824482..92bbfd5 100644 --- a/src/composer.json +++ b/src/composer.json @@ -20,8 +20,10 @@ "drupal/core-composer-scaffold": "^9.4", "drupal/core-project-message": "^9.4", "drupal/core-recommended": "^9.4", + "drupal/graphql": "4.x-dev@dev", "drupal/paragraphs": "^1.15", "drupal/structure_sync": "^2.0", + "drupal/typed_data": "1.x-dev@dev", "wikimedia/composer-merge-plugin": "^2.0" }, "conflict": { @@ -108,6 +110,9 @@ "patches": { "drupal/paragraphs": { "Skip saving empty paragraphs for certain types https://www.drupal.org/project/paragraphs/issues/2877695" : "https://www.drupal.org/files/issues/2021-03-31/2877695-35.patch" + }, + "drupal/graphql": { + "invalid translation language https://github.com/drupal-graphql/graphql/pull/1176": "./patches/graphql-fix-invalid-translation-language-dev.patch" } } } diff --git a/src/composer.lock b/src/composer.lock index ff2cafb..5e4a77b 100644 --- a/src/composer.lock +++ b/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": "9f22f2a18cec2f9fe341a284cef4d4bb", + "content-hash": "c28f37daf42fd941e5a8be2f3cb6e2a2", "packages": [ { "name": "alchemy/zippy", @@ -5297,6 +5297,69 @@ "issues": "http://drupal.org/project/issues/formatter_suite" } }, + { + "name": "drupal/graphql", + "version": "dev-4.x", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/graphql.git", + "reference": "dedd45ccdea0430b7820acbad4557dc443eff196" + }, + "require": { + "drupal/core": "^9.3 || ^10", + "drupal/typed_data": "*", + "php": ">=7.3", + "webonyx/graphql-php": "^14.8.0" + }, + "require-dev": { + "drupal/node-node": "*" + }, + "type": "drupal-module", + "extra": { + "branch-alias": { + "dev-4.x": "4.x-dev" + }, + "drupal": { + "version": "8.x-4.3+11-dev", + "datestamp": "1662992472", + "security-coverage": { + "status": "not-covered", + "message": "Dev releases are not covered by Drupal security advisories." + } + } + }, + "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.1.1", @@ -7592,6 +7655,57 @@ "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": "94141cf338e5a3a3ec8bdea276bce6a0a84c4bfa" + }, + "require": { + "drupal/core": "^9.1 || ^10" + }, + "type": "drupal-module", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + }, + "drupal": { + "version": "8.x-1.0-beta1+12-dev", + "datestamp": "1650833384", + "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" + } + }, { "name": "drupal/ultimate_cron", "version": "2.0.0-alpha5", @@ -13372,6 +13486,72 @@ "abandoned": "symfony/filesystem", "time": "2015-12-17T08:42:14+00:00" }, + { + "name": "webonyx/graphql-php", + "version": "v14.11.6", + "source": { + "type": "git", + "url": "https://github.com/webonyx/graphql-php.git", + "reference": "6070542725b61fc7d0654a8a9855303e5e157434" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/6070542725b61fc7d0654a8a9855303e5e157434", + "reference": "6070542725b61fc7d0654a8a9855303e5e157434", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^7.1 || ^8" + }, + "require-dev": { + "amphp/amp": "^2.3", + "doctrine/coding-standard": "^6.0", + "nyholm/psr7": "^1.2", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "0.12.82", + "phpstan/phpstan-phpunit": "0.12.18", + "phpstan/phpstan-strict-rules": "0.12.9", + "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" + ], + "support": { + "issues": "https://github.com/webonyx/graphql-php/issues", + "source": "https://github.com/webonyx/graphql-php/tree/v14.11.6" + }, + "funding": [ + { + "url": "https://opencollective.com/webonyx-graphql-php", + "type": "open_collective" + } + ], + "time": "2022-04-13T16:25:32+00:00" + }, { "name": "wikimedia/composer-merge-plugin", "version": "v2.0.1", @@ -13430,6 +13610,8 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "drupal/graphql": 20, + "drupal/typed_data": 20, "drupal/autocomplete_deluxe": 5, "drupal/better_exposed_filters": 10, "drupal/bulkdelete": 20, diff --git a/src/config/sync/core.entity_form_display.node.entite.default.yml b/src/config/sync/core.entity_form_display.node.entite.default.yml index c55fa46..b8af9af 100644 --- a/src/config/sync/core.entity_form_display.node.entite.default.yml +++ b/src/config/sync/core.entity_form_display.node.entite.default.yml @@ -6,6 +6,7 @@ dependencies: - field.field.node.entite.body - field.field.node.entite.field_documents - field.field.node.entite.field_images + - field.field.node.entite.field_liens - field.field.node.entite.field_videos - image.style.thumbnail - node.type.entite @@ -13,6 +14,7 @@ dependencies: - field_group - file - image + - link - text - video_embed_field third_party_settings: @@ -21,6 +23,8 @@ third_party_settings: children: - group_texte - group_media + - group_documents + - group_liens label: Tabs region: content parent_name: '' @@ -36,7 +40,6 @@ third_party_settings: children: - field_images - field_videos - - field_documents label: Media region: content parent_name: group_tabs @@ -83,6 +86,36 @@ third_party_settings: description: '' required_fields: true weight: -100 + group_documents: + children: + - field_documents + label: Documents + region: content + parent_name: group_tabs + weight: 17 + format_type: tab + format_settings: + classes: '' + show_empty_fields: false + id: '' + formatter: closed + description: '' + required_fields: true + group_liens: + children: + - field_liens + label: Liens + region: content + parent_name: group_tabs + weight: 18 + format_type: tab + format_settings: + classes: '' + show_empty_fields: false + id: '' + formatter: closed + description: '' + required_fields: true id: node.entite.default targetEntityType: node bundle: entite @@ -119,6 +152,14 @@ content: progress_indicator: throbber preview_image_style: thumbnail third_party_settings: { } + field_liens: + type: link_default + weight: 26 + region: content + settings: + placeholder_url: '' + placeholder_title: '' + third_party_settings: { } field_videos: type: video_embed_field_textfield weight: 12 diff --git a/src/config/sync/core.entity_form_display.paragraph.entite_concernement.default.yml b/src/config/sync/core.entity_form_display.paragraph.entite_concernement.default.yml index 31f5ac7..28a2f7c 100644 --- a/src/config/sync/core.entity_form_display.paragraph.entite_concernement.default.yml +++ b/src/config/sync/core.entity_form_display.paragraph.entite_concernement.default.yml @@ -3,13 +3,22 @@ langcode: fr status: true dependencies: config: + - field.field.paragraph.entite_concernement.field_angle - field.field.paragraph.entite_concernement.field_entite + - field.field.paragraph.entite_concernement.field_rayon - paragraphs.paragraphs_type.entite_concernement id: paragraph.entite_concernement.default targetEntityType: paragraph bundle: entite_concernement mode: default content: + field_angle: + type: number + weight: 2 + region: content + settings: + placeholder: '' + third_party_settings: { } field_entite: type: entity_reference_autocomplete weight: 0 @@ -20,6 +29,13 @@ content: size: 60 placeholder: '' third_party_settings: { } + field_rayon: + type: number + weight: 1 + region: content + settings: + placeholder: '' + third_party_settings: { } hidden: created: true status: true diff --git a/src/config/sync/core.entity_view_display.node.entite.default.yml b/src/config/sync/core.entity_view_display.node.entite.default.yml index 6d704fa..eda8418 100644 --- a/src/config/sync/core.entity_view_display.node.entite.default.yml +++ b/src/config/sync/core.entity_view_display.node.entite.default.yml @@ -6,11 +6,13 @@ dependencies: - field.field.node.entite.body - field.field.node.entite.field_documents - field.field.node.entite.field_images + - field.field.node.entite.field_liens - field.field.node.entite.field_videos - node.type.entite module: - file - image + - link - text - user - video_embed_field @@ -45,6 +47,18 @@ content: third_party_settings: { } weight: 102 region: content + field_liens: + type: link + label: above + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + weight: 105 + region: content field_videos: type: video_embed_field_video label: above diff --git a/src/config/sync/core.entity_view_display.node.entite.teaser.yml b/src/config/sync/core.entity_view_display.node.entite.teaser.yml index 63c56b4..0ac8b54 100644 --- a/src/config/sync/core.entity_view_display.node.entite.teaser.yml +++ b/src/config/sync/core.entity_view_display.node.entite.teaser.yml @@ -7,6 +7,7 @@ dependencies: - field.field.node.entite.body - field.field.node.entite.field_documents - field.field.node.entite.field_images + - field.field.node.entite.field_liens - field.field.node.entite.field_videos - node.type.entite module: @@ -33,6 +34,7 @@ content: hidden: field_documents: true field_images: true + field_liens: true field_videos: true langcode: true search_api_excerpt: true diff --git a/src/config/sync/core.entity_view_display.paragraph.entite_concernement.default.yml b/src/config/sync/core.entity_view_display.paragraph.entite_concernement.default.yml index b7c5d25..228dddc 100644 --- a/src/config/sync/core.entity_view_display.paragraph.entite_concernement.default.yml +++ b/src/config/sync/core.entity_view_display.paragraph.entite_concernement.default.yml @@ -3,13 +3,26 @@ langcode: fr status: true dependencies: config: + - field.field.paragraph.entite_concernement.field_angle - field.field.paragraph.entite_concernement.field_entite + - field.field.paragraph.entite_concernement.field_rayon - paragraphs.paragraphs_type.entite_concernement id: paragraph.entite_concernement.default targetEntityType: paragraph bundle: entite_concernement mode: default content: + field_angle: + type: number_decimal + label: above + settings: + thousand_separator: '' + decimal_separator: . + scale: 2 + prefix_suffix: true + third_party_settings: { } + weight: 2 + region: content field_entite: type: entity_reference_label label: above @@ -18,5 +31,16 @@ content: third_party_settings: { } weight: 0 region: content + field_rayon: + type: number_decimal + label: above + settings: + thousand_separator: '' + decimal_separator: . + scale: 2 + prefix_suffix: true + third_party_settings: { } + weight: 1 + region: content hidden: search_api_excerpt: true diff --git a/src/config/sync/core.extension.yml b/src/config/sync/core.extension.yml index 7e3bf6b..098d67c 100644 --- a/src/config/sync/core.extension.yml +++ b/src/config/sync/core.extension.yml @@ -53,6 +53,7 @@ module: filter: 0 filter_perms: 0 formatter_suite: 0 + graphql: 0 help: 0 honeypot: 0 image: 0 @@ -77,6 +78,7 @@ module: mysql: 0 node: 0 options: 0 + ouatt_graphql: 0 page_cache: 0 pagerer: 0 path: 0 @@ -99,6 +101,7 @@ module: token: 0 toolbar: 0 translation_views: 0 + typed_data: 0 update: 0 url_to_video_filter: 0 user: 0 diff --git a/src/config/sync/field.field.node.concernement.field_entite.yml b/src/config/sync/field.field.node.concernement.field_entite.yml index 0470d8d..749237b 100644 --- a/src/config/sync/field.field.node.concernement.field_entite.yml +++ b/src/config/sync/field.field.node.concernement.field_entite.yml @@ -12,7 +12,7 @@ id: node.concernement.field_entite field_name: field_entite entity_type: node bundle: concernement -label: Entité +label: Entités description: '' required: false translatable: false diff --git a/src/config/sync/field.field.node.entite.field_liens.yml b/src/config/sync/field.field.node.entite.field_liens.yml new file mode 100644 index 0000000..80a4112 --- /dev/null +++ b/src/config/sync/field.field.node.entite.field_liens.yml @@ -0,0 +1,23 @@ +uuid: bfb6a38e-4497-490d-8bb0-ce895c2e95b5 +langcode: fr +status: true +dependencies: + config: + - field.storage.node.field_liens + - node.type.entite + module: + - link +id: node.entite.field_liens +field_name: field_liens +entity_type: node +bundle: entite +label: Liens +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + title: 1 + link_type: 16 +field_type: link diff --git a/src/config/sync/field.field.paragraph.entite_concernement.field_angle.yml b/src/config/sync/field.field.paragraph.entite_concernement.field_angle.yml new file mode 100644 index 0000000..912eabd --- /dev/null +++ b/src/config/sync/field.field.paragraph.entite_concernement.field_angle.yml @@ -0,0 +1,23 @@ +uuid: 3d803a88-cde3-43d3-a266-712210d37188 +langcode: fr +status: true +dependencies: + config: + - field.storage.paragraph.field_angle + - paragraphs.paragraphs_type.entite_concernement +id: paragraph.entite_concernement.field_angle +field_name: field_angle +entity_type: paragraph +bundle: entite_concernement +label: Angle +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + min: !!float 0 + max: !!float 360 + prefix: '' + suffix: '' +field_type: decimal diff --git a/src/config/sync/field.field.paragraph.entite_concernement.field_rayon.yml b/src/config/sync/field.field.paragraph.entite_concernement.field_rayon.yml new file mode 100644 index 0000000..0e78c8f --- /dev/null +++ b/src/config/sync/field.field.paragraph.entite_concernement.field_rayon.yml @@ -0,0 +1,23 @@ +uuid: 108ef2b1-7685-4ffc-a9b3-a6b0d7c88101 +langcode: fr +status: true +dependencies: + config: + - field.storage.paragraph.field_rayon + - paragraphs.paragraphs_type.entite_concernement +id: paragraph.entite_concernement.field_rayon +field_name: field_rayon +entity_type: paragraph +bundle: entite_concernement +label: rayon +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + min: !!float 0 + max: !!float 100 + prefix: '' + suffix: '' +field_type: decimal diff --git a/src/config/sync/field.storage.node.field_liens.yml b/src/config/sync/field.storage.node.field_liens.yml new file mode 100644 index 0000000..126d3d4 --- /dev/null +++ b/src/config/sync/field.storage.node.field_liens.yml @@ -0,0 +1,19 @@ +uuid: 9c3df3fe-a34f-41a6-a9d3-d12c116ca711 +langcode: fr +status: true +dependencies: + module: + - link + - node +id: node.field_liens +field_name: field_liens +entity_type: node +type: link +settings: { } +module: link +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/src/config/sync/field.storage.paragraph.field_angle.yml b/src/config/sync/field.storage.paragraph.field_angle.yml new file mode 100644 index 0000000..f3fc9da --- /dev/null +++ b/src/config/sync/field.storage.paragraph.field_angle.yml @@ -0,0 +1,20 @@ +uuid: 745fa859-a99d-4ebf-94d5-eaad168db650 +langcode: fr +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_angle +field_name: field_angle +entity_type: paragraph +type: decimal +settings: + precision: 10 + scale: 2 +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/src/config/sync/field.storage.paragraph.field_rayon.yml b/src/config/sync/field.storage.paragraph.field_rayon.yml new file mode 100644 index 0000000..f465c71 --- /dev/null +++ b/src/config/sync/field.storage.paragraph.field_rayon.yml @@ -0,0 +1,20 @@ +uuid: 0dcd010f-36ff-4d18-b29e-7a3615d1fd4f +langcode: fr +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_rayon +field_name: field_rayon +entity_type: paragraph +type: decimal +settings: + precision: 10 + scale: 2 +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/src/config/sync/graphql.graphql_servers.ouatterrir.yml b/src/config/sync/graphql.graphql_servers.ouatterrir.yml new file mode 100644 index 0000000..ac968f4 --- /dev/null +++ b/src/config/sync/graphql.graphql_servers.ouatterrir.yml @@ -0,0 +1,19 @@ +uuid: b3116921-3275-4e06-ba9d-e2d186fda048 +langcode: fr +status: true +dependencies: { } +name: ouatterrir +label: ouatterrir +endpoint: /gql +debug_flag: 1 +schema: composable +caching: true +batching: true +disable_introspection: false +query_depth: null +query_complexity: null +schema_configuration: + composable: + extensions: + ouatt_extension: ouatt_extension +persisted_queries_settings: { } diff --git a/src/config/sync/language.types.yml b/src/config/sync/language.types.yml index 5c1b320..3a1022a 100644 --- a/src/config/sync/language.types.yml +++ b/src/config/sync/language.types.yml @@ -17,4 +17,5 @@ negotiation: language-url-fallback: 1 language_interface: enabled: + language-graphql-operation: -999 language-url: 0 diff --git a/src/patches/graphql-fix-invalid-translation-language-dev.patch b/src/patches/graphql-fix-invalid-translation-language-dev.patch new file mode 100644 index 0000000..e05d897 --- /dev/null +++ b/src/patches/graphql-fix-invalid-translation-language-dev.patch @@ -0,0 +1,98 @@ +diff --git a/src/Plugin/GraphQL/DataProducer/Entity/EntityLoad.php b/src/Plugin/GraphQL/DataProducer/Entity/EntityLoad.php +index 867a28c..386b2b3 100644 +--- a/src/Plugin/GraphQL/DataProducer/Entity/EntityLoad.php ++++ b/src/Plugin/GraphQL/DataProducer/Entity/EntityLoad.php +@@ -172,8 +172,10 @@ class EntityLoad extends DataProducerPluginBase implements ContainerFactoryPlugi + + // Get the correct translation. + if (isset($language) && $language !== $entity->language()->getId() && $entity instanceof TranslatableInterface) { +- $entity = $entity->getTranslation($language); +- $entity->addCacheContexts(["static:language:{$language}"]); ++ if ($entity->hasTranslation($language)) { ++ $entity = $entity->getTranslation($language); ++ $entity->addCacheContexts(["static:language:{$language}"]); ++ } + } + + // Check if the passed user (or current user if none is passed) has access +diff --git a/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadByUuid.php b/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadByUuid.php +index 10e2d40..e4e6ed0 100644 +--- a/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadByUuid.php ++++ b/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadByUuid.php +@@ -165,8 +165,10 @@ class EntityLoadByUuid extends DataProducerPluginBase implements ContainerFactor + + // Get the correct translation. + if (isset($language) && $language != $entity->language()->getId() && $entity instanceof TranslatableInterface) { +- $entity = $entity->getTranslation($language); +- $entity->addCacheContexts(["static:language:{$language}"]); ++ if ($entity->hasTranslation($language)) { ++ $entity = $entity->getTranslation($language); ++ $entity->addCacheContexts(["static:language:{$language}"]); ++ } + } + + // Check if the passed user (or current user if none is passed) has access +diff --git a/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadMultiple.php b/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadMultiple.php +index 2a0259c..27a19e5 100644 +--- a/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadMultiple.php ++++ b/src/Plugin/GraphQL/DataProducer/Entity/EntityLoadMultiple.php +@@ -172,8 +172,10 @@ class EntityLoadMultiple extends DataProducerPluginBase implements ContainerFact + } + + if (isset($language) && $language !== $entities[$id]->language()->getId() && $entities[$id] instanceof TranslatableInterface) { +- $entities[$id] = $entities[$id]->getTranslation($language); +- $entities[$id]->addCacheContexts(["static:language:{$language}"]); ++ if ($entities[$id]->hasTranslation($language)) { ++ $entities[$id] = $entities[$id]->getTranslation($language); ++ $entities[$id]->addCacheContexts(["static:language:{$language}"]); ++ } + } + + if ($access) { +diff --git a/src/Plugin/GraphQL/DataProducer/Entity/EntityTranslation.php b/src/Plugin/GraphQL/DataProducer/Entity/EntityTranslation.php +index 633bdc2..3773a9b 100644 +--- a/src/Plugin/GraphQL/DataProducer/Entity/EntityTranslation.php ++++ b/src/Plugin/GraphQL/DataProducer/Entity/EntityTranslation.php +@@ -101,7 +101,7 @@ class EntityTranslation extends DataProducerPluginBase implements ContainerFacto + * @return \Drupal\Core\Entity\EntityInterface|null + */ + public function resolve(EntityInterface $entity, $language, ?bool $access, ?AccountInterface $accessUser, ?string $accessOperation) { +- if ($entity instanceof TranslatableInterface && $entity->isTranslatable()) { ++ if ($entity instanceof TranslatableInterface && $entity->isTranslatable() && $entity->hasTranslation($language)) { + $entity = $entity->getTranslation($language); + $entity->addCacheContexts(["static:language:{$language}"]); + // Check if the passed user (or current user if none is passed) has access +diff --git a/src/Plugin/GraphQL/DataProducer/Routing/RouteEntity.php b/src/Plugin/GraphQL/DataProducer/Routing/RouteEntity.php +index 10ea4e6..1eef22a 100644 +--- a/src/Plugin/GraphQL/DataProducer/Routing/RouteEntity.php ++++ b/src/Plugin/GraphQL/DataProducer/Routing/RouteEntity.php +@@ -126,8 +126,10 @@ class RouteEntity extends DataProducerPluginBase implements ContainerFactoryPlug + + // Get the correct translation. + if (isset($language) && $language != $entity->language()->getId() && $entity instanceof TranslatableInterface) { +- $entity = $entity->getTranslation($language); +- $entity->addCacheContexts(["static:language:{$language}"]); ++ if ($entity->hasTranslation($language)) { ++ $entity = $entity->getTranslation($language); ++ $entity->addCacheContexts(["static:language:{$language}"]); ++ } + } + + $access = $entity->access('view', NULL, TRUE); +diff --git a/src/Plugin/GraphQL/DataProducer/Taxonomy/TaxonomyLoadTree.php b/src/Plugin/GraphQL/DataProducer/Taxonomy/TaxonomyLoadTree.php +index 1bcd624..8b2caf2 100644 +--- a/src/Plugin/GraphQL/DataProducer/Taxonomy/TaxonomyLoadTree.php ++++ b/src/Plugin/GraphQL/DataProducer/Taxonomy/TaxonomyLoadTree.php +@@ -175,8 +175,10 @@ class TaxonomyLoadTree extends DataProducerPluginBase implements ContainerFactor + $context->addCacheableDependency($entities[$id]); + + if (isset($language) && $language !== $entities[$id]->language()->getId() && $entities[$id] instanceof TranslatableInterface) { +- $entities[$id] = $entities[$id]->getTranslation($language); +- $entities[$id]->addCacheContexts(["static:language:{$language}"]); ++ if ($entities[$id]->hasTranslation($language)) { ++ $entities[$id] = $entities[$id]->getTranslation($language); ++ $entities[$id]->addCacheContexts(["static:language:{$language}"]); ++ } + } + + if ($access) { diff --git a/src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.base.graphqls b/src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.base.graphqls new file mode 100644 index 0000000..aa0ad25 --- /dev/null +++ b/src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.base.graphqls @@ -0,0 +1,105 @@ +scalar Violation + +interface NodeInterface { + id: Int! + path: String! +} + +type Concernement implements NodeInterface { + id: Int! + uuid: String! + bundle: String! + title: String! + path: String! + author: String + texte: String + entites: [Entiteintegre] +} + +type Entiteintegre { + entite: Entite + rayon: Float + angle: Float +} + +type Entite implements NodeInterface { + id: Int! + uuid: String! + bundle: String! + title: String! + path: String! + author: String + texte: String + images: [Image] + fichiers: [File] + liens: [Link] +} + +type Static implements NodeInterface { + id: Int! + uuid: String! + bundle: String! + title: String! + path: String! + author: String + texte: String +} + +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! + vocabulary: 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 +} + +type Link { + url: String + title: String +} + +type Date { + start: String + end: String +} diff --git a/src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.extension.graphqls b/src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.extension.graphqls new file mode 100644 index 0000000..2df9c2a --- /dev/null +++ b/src/web/modules/custom/ouatt_graphql/graphql/ouatt_extension.extension.graphqls @@ -0,0 +1,48 @@ +# extend type Query { +# route(path: String!): NodeInterface +# } + + +extend type Query { + allconcernements: [Concernement] +} + +extend type Query { + concernements(ids: [Int]): [Concernement] +} + +extend type Query { + concernement(id: Int!): Concernement +} + +extend type Query { + allentites: [Entite] +} + +extend type Query { + entites(ids: [Int]): [Entite] +} + +extend type Query { + entite(id: Int!): Entite +} + +extend type Query { + allstatics: [Static] +} + +extend type Query { + statics(ids: [Int]): [Static] +} + +extend type Query { + static(id: Int!): Static +} + +# extend type Query { +# alltags: [Taxoterm] +# } + +# extend type Query { +# tag(id: Int!): Taxoterm +# } diff --git a/src/web/modules/custom/ouatt_graphql/ouatt_graphql.info.yml b/src/web/modules/custom/ouatt_graphql/ouatt_graphql.info.yml new file mode 100644 index 0000000..05bdabf --- /dev/null +++ b/src/web/modules/custom/ouatt_graphql/ouatt_graphql.info.yml @@ -0,0 +1,9 @@ +name: Où Atterrir Graphql +type: module +description: 'Où Atterrir GraphQL schema.' +package: Ouatterrir +core: 8.x +dependencies: + - graphql:graphql + - node:node +core_version_requirement: ^8 || ^9 diff --git a/src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/Schema/OuattSchema.php b/src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/Schema/OuattSchema.php new file mode 100644 index 0000000..6614982 --- /dev/null +++ b/src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/Schema/OuattSchema.php @@ -0,0 +1,47 @@ +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; + // } + +} diff --git a/src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/SchemaExtension/OuattSchemaExtension.php b/src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/SchemaExtension/OuattSchemaExtension.php new file mode 100644 index 0000000..dc1a0fb --- /dev/null +++ b/src/web/modules/custom/ouatt_graphql/src/Plugin/GraphQL/SchemaExtension/OuattSchemaExtension.php @@ -0,0 +1,658 @@ +addRouteResolver($registry, $builder); + // + $this->addConcernements($registry, $builder); + // + $this->addEntitesIntegres($registry, $builder); + // + $this->addEntites($registry, $builder); + // + $this->addStatic($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->addLink($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 'concernement': return 'Concernement'; + case 'entite': return 'Entite'; + } + } + 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 addConcernements(ResolverRegistryInterface $registry, ResolverBuilder $builder){ + $registry->addFieldResolver('Query', 'allconcernements', + $builder->compose( + $builder->callback(function($parent, $arg){ + $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); + $query = $entity_storage->getQuery() + ->condition('type', ['concernement'], 'IN') + ->accessCheck(TRUE); + $results = $query->execute(); + return $results; + }), + $builder->produce('entity_load_multiple') + ->map('type', $builder->fromValue('node')) + ->map('ids', $builder->fromParent()) + ) + ); + + $registry->addFieldResolver('Query', 'concernements', + $builder->compose( + $builder->callback(function($parent, $arg){ + $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); + $query = $entity_storage->getQuery() + ->condition('type', ['concernement'], 'IN') + ->accessCheck(TRUE); + $results = $query->execute(); + return $results; + }), + $builder->produce('entity_load_multiple') + ->map('type', $builder->fromValue('node')) + ->map('ids', $builder->fromArgument('ids')) + ) + ); + + $registry->addFieldResolver('Query', 'concernement', + $builder->produce('entity_load') + ->map('type', $builder->fromValue('node')) + ->map('id', $builder->fromArgument('id')) + ); + + $registry->addFieldResolver('Concernement', 'id', + $builder->produce('entity_id') + ->map('entity', $builder->fromParent()) + ); + + $registry->addFieldResolver('Concernement', 'uuid', + $builder->produce('entity_uuid') + ->map('entity', $builder->fromParent()) + ); + + $registry->addFieldResolver('Concernement', 'path', + $builder->compose( + $builder->produce('entity_url') + ->map('entity', $builder->fromParent()), + $builder->produce('url_path') + ->map('url', $builder->fromParent()) + ) + ); + + $registry->addFieldResolver('Concernement', 'title', + $builder->compose( + $builder->produce('entity_label') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Concernement', 'bundle', + $builder->compose( + $builder->produce('entity_bundle') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Concernement', 'texte', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:node')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('body.value')) + ); + + $registry->addFieldResolver('Concernement', 'author', + $builder->compose( + $builder->produce('entity_owner') + ->map('entity', $builder->fromParent()), + $builder->produce('entity_label') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Concernement', 'entites', + $builder->produce('entity_reference_revisions') + ->map('entity', $builder->fromParent()) + ->map('field', $builder->fromValue('field_entite')) + ); + } + + // _____ _ _ _ __ ___ _ __ __ + // | ____|_ __ | |_(_) |_ /_/ ___ |_ _|_ __ | |_ /_/ __ _ _ __ /_/ ___ ___ + // | _| | '_ \| __| | __/ _ \/ __| | || '_ \| __/ _ \/ _` | '__/ _ \/ _ \/ __| + // | |___| | | | |_| | || __/\__ \ | || | | | || __/ (_| | | | __/ __/\__ \ + // |_____|_| |_|\__|_|\__\___||___/ |___|_| |_|\__\___|\__, |_| \___|\___||___/ + // |___/ + protected function addEntitesIntegres(ResolverRegistryInterface $registry, ResolverBuilder $builder) { + + $registry->addFieldResolver('Entiteintegre', 'entite', + $builder->compose( + $builder->produce('entity_reference') + ->map('entity', $builder->fromParent()) + ->map('field', $builder->fromValue('field_entite')), + $builder->callback(function ($items) { + return $items[0]; + }) + )); + + $registry->addFieldResolver('Entiteintegre', 'rayon', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:paragraph')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('field_rayon.value')) + ); + + $registry->addFieldResolver('Entiteintegre', 'angle', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:paragraph')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('field_angle.value')) + ); + } + + // _____ _ _ _ + // | ____|_ __ | |_(_) |_ ___ ___ + // | _| | '_ \| __| | __/ _ \/ __| + // | |___| | | | |_| | || __/\__ \ + // |_____|_| |_|\__|_|\__\___||___/ + + protected function addEntites(ResolverRegistryInterface $registry, ResolverBuilder $builder){ + $registry->addFieldResolver('Query', 'allentites', + $builder->compose( + $builder->callback(function($parent, $arg){ + $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); + $query = $entity_storage->getQuery() + ->condition('type', ['entite'], 'IN') + ->accessCheck(TRUE); + $results = $query->execute(); + return $results; + }), + $builder->produce('entity_load_multiple') + ->map('type', $builder->fromValue('node')) + ->map('ids', $builder->fromParent()) + ) + ); + + $registry->addFieldResolver('Query', 'entites', + $builder->compose( + $builder->callback(function($parent, $arg){ + $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); + $query = $entity_storage->getQuery() + ->condition('type', ['entite'], 'IN') + ->accessCheck(TRUE); + $results = $query->execute(); + return $results; + }), + $builder->produce('entity_load_multiple') + ->map('type', $builder->fromValue('node')) + ->map('ids', $builder->fromArgument('ids')) + ) + ); + + $registry->addFieldResolver('Query', 'entite', + $builder->produce('entity_load') + ->map('type', $builder->fromValue('node')) + ->map('id', $builder->fromArgument('id')) + ); + + $registry->addFieldResolver('Entite', 'id', + $builder->produce('entity_id') + ->map('entity', $builder->fromParent()) + ); + + $registry->addFieldResolver('Entite', 'uuid', + $builder->produce('entity_uuid') + ->map('entity', $builder->fromParent()) + ); + + $registry->addFieldResolver('Entite', 'path', + $builder->compose( + $builder->produce('entity_url') + ->map('entity', $builder->fromParent()), + $builder->produce('url_path') + ->map('url', $builder->fromParent()) + ) + ); + + $registry->addFieldResolver('Entite', 'title', + $builder->compose( + $builder->produce('entity_label') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Entite', 'bundle', + $builder->compose( + $builder->produce('entity_bundle') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Entite', 'texte', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:node')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('body.value')) + ); + + $registry->addFieldResolver('Entite', 'author', + $builder->compose( + $builder->produce('entity_owner') + ->map('entity', $builder->fromParent()), + $builder->produce('entity_label') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Entite', 'images', + $builder->produce('entity_reference') + ->map('entity', $builder->fromParent()) + ->map('field', $builder->fromValue('field_images')) + ); + + $registry->addFieldResolver('Entite', 'videos', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:node')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('field_videos')) + ); + + $registry->addFieldResolver('Entite', 'fichiers', + $builder->produce('entity_reference') + ->map('entity', $builder->fromParent()) + ->map('field', $builder->fromValue('field_fichiers')) + ); + + $registry->addFieldResolver('Entite', 'liens', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:node')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('field_liens')) + ); + + } + + // ___ _ _ _ + // / __| |_ __ _| |_(_)__ ___ + // \__ \ _/ _` | _| / _(_-< + // |___/\__\__,_|\__|_\__/__/ + protected function addStatic(ResolverRegistryInterface $registry, ResolverBuilder $builder) { + + $registry->addFieldResolver('Query', 'allstatics', + $builder->compose( + $builder->callback(function($parent, $arg){ + $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); + $query = $entity_storage->getQuery() + ->condition('type', ['static'], 'IN') + ->accessCheck(TRUE); + $results = $query->execute(); + return $results; + }), + $builder->produce('entity_load_multiple') + ->map('type', $builder->fromValue('node')) + ->map('ids', $builder->fromParent()) + ) + ); + + $registry->addFieldResolver('Query', 'statics', + $builder->produce('entity_load_multiple') + ->map('type', $builder->fromValue('node')) + ->map('ids', $builder->fromArgument('ids')) + ); + + $registry->addFieldResolver('Query', 'static', + $builder->produce('entity_load') + ->map('type', $builder->fromValue('node')) + ->map('bundles', $builder->fromValue(['static'])) + ->map('id', $builder->fromArgument('id')) + ); + + $registry->addFieldResolver('Static', 'id', + $builder->produce('entity_id') + ->map('entity', $builder->fromParent()) + ); + + $registry->addFieldResolver('Static', 'uuid', + $builder->produce('entity_uuid') + ->map('entity', $builder->fromParent()) + ); + + $registry->addFieldResolver('Static', 'path', + $builder->compose( + $builder->produce('entity_url') + ->map('entity', $builder->fromParent()), + $builder->produce('url_path') + ->map('url', $builder->fromParent()) + ) + ); + + $registry->addFieldResolver('Static', 'title', + $builder->compose( + $builder->produce('entity_label') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Static', 'bundle', + $builder->compose( + $builder->produce('entity_bundle') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Static', 'texte', + $builder->produce('property_path') + ->map('type', $builder->fromValue('entity:node')) + ->map('value', $builder->fromParent()) + ->map('path', $builder->fromValue('body.value')) + ); + + $registry->addFieldResolver('Static', 'author', + $builder->compose( + $builder->produce('entity_owner') + ->map('entity', $builder->fromParent()), + $builder->produce('entity_label') + ->map('entity', $builder->fromParent()) + )); + + $registry->addFieldResolver('Static', 'fichiers', + $builder->produce('entity_reference') + ->map('entity', $builder->fromParent()) + ->map('field', $builder->fromValue('field_fichier')) + ); + + } + + // ___ _ + // | \ __ _| |_ ___ + // | |) / _` | _/ -_) + // |___/\__,_|\__\___| + 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->createFileUrl(); + }) + ); + + $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']; + }) + )); + + } + + // __ ___ _ _ _ _ + // \ \ / (_)__| |___ ___| | (_)_ _ | |__ + // \ 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', 'alltags', + // $builder->compose( + // $builder->callback(function($parent, $arg){ + // $entity_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term'); + // $query = $entity_storage->getQuery() + // ->condition('vid', ['tag','tag_prod'], 'IN') + // ->accessCheck(TRUE); + // $results = $query->execute(); + // return $results; + // }), + // $builder->produce('entity_load_multiple') + // ->map('type', $builder->fromValue('taxonomy_term')) + // ->map('ids', $builder->fromParent()) + // ) + // ); + + // $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')) + // ); + + // // get all tags for a given familly + // // $registry->addFieldResolver('Query', 'famillytags', + // // $builder->compose( + // // $builder->callback(function($parent, $arg){ + // // $entity_storage = \Drupal::entityTypeManager()->getStorage('node'); + // // $query = $entity_storage->getQuery() + // // ->condition('type', ['texte', 'texte_prod'], 'IN') + // // ->condition('field_famille', $arg->famillyid) + // // ->accessCheck(TRUE); + // // $results = $query->execute(); + // // return $results; + // // }), + // // $builder->produce('entity_load_multiple') + // // ->map('type', $builder->fromValue('node')) + // // ->map('ids', $builder->fromParent()) + // // // $builder->produce('entity_load_multiple') + // // // ->map('type', $builder->fromValue('taxonomy_term')) + // // // ->map('ids', $builder->fromParent()) + // // ) + // // ); + + + // $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()) + // ); + + // $registry->addFieldResolver('Taxoterm', 'vocabulary', + // $builder->produce('entity_bundle') + // ->map('entity', $builder->fromParent()) + // ); + // } + + + // _ _ _ + // | | (_)_ _ | |__ + // | |__| | ' \| / / + // |____|_|_||_|_\_\ + protected function addLink(ResolverRegistryInterface $registry, ResolverBuilder $builder) { + $registry->addFieldResolver('Link', 'url', + $builder->callback(function ($parent, $args) { + return isset($parent[0]) ? $parent[0]['uri'] : null; + }) + ); + $registry->addFieldResolver('Link', 'title', + $builder->callback(function ($parent, $args) { + return isset($parent[0]) ? $parent[0]['title'] : null; + }) + ); + } +}