Can existing field types be extended

Created on 13 June 2023, over 1 year ago
Updated 17 July 2023, over 1 year ago

It's not mentioned in the docs so not sure if its possible but I'm trying to extend the metatags module so that I can add support for https://www.drupal.org/project/schema_metatag

I've tried the following

<?php

declare(strict_types=1);

namespace Drupal\graphql_compose_extra_metatags_schema\Plugin\GraphQLCompose\SchemaType;

use Drupal\graphql_compose\Plugin\GraphQLCompose\GraphQLComposeSchemaTypeBase;
use GraphQL\Type\Definition\UnionType;

/**
 * {@inheritdoc}
 *
 * @GraphQLComposeSchemaType(
 *   id = "MetaTagUnion",
 * )
 */
class MetaTagUnionExtra extends GraphQLComposeSchemaTypeBase
{

  /**
   * {@inheritdoc}
   */
  public function getTypes(): array
  {
    $types = [];

    $types[] = new UnionType([
      'name' => $this->getPluginId(),
      'types' => fn () => [
        static::type('MetaTagLink'),
        static::type('MetaTagValue'),
        static::type('MetaTagProperty'),
        static::type('MetaTagSchema'),
      ],
    ]);

    return $types;
  }
}

along with adding

/**
 * {@inheritdoc}
 *
 * @GraphQLComposeFieldType(
 *   id = "metatag_computed",
 *   type_sdl = "MetaTagUnion",
 * )
 */
class MetatagSchemaComputedExtra extends GraphQLComposeFieldTypeBase implements FieldProducerItemsInterface
{
}

I've even tried a new type_sdl i.e MetaTagUnionExtra but nothing seems to allow me to extend an existing field, I'm probably doing something wrong but just thought I check it's actually possible.

💬 Support request
Status

Closed: outdated

Version

2.0

Component

Code

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @marcus.williams
  • 🇦🇺Australia almunnings Melbourne, 🇦🇺

    Thats the right idea, swap out the plugin with your own.

    We'd need to define what MetaTagSchema is with a new SchemaType, I'd go with a scalar based on 30seconds of looking at the module.
    We'd also need to take a look at the MetaTagUnion resolver in MetatagsSchemaExtension and see if there is a weird tag going on, or if we can just return generically to enable scalar stuff for things like this.

    Short answer: Not so simple
    Long answer: Its PHP 🌈 ~ anything is possible ~ 🌈

    I reckon we could do this fairly simply with a scalar dump of whatever is within the schema.

    I'll try take a look after next release in a week or so.

  • Ah ok I was trying to extend the existing graphql_compose_metatags so now just gone with a module that completely replaces it. For the schema one I just went with the easy option of returning the json for the schema as there's a lot of nesting going on in the schema

    I've got a few modules now that may be of interest so I'll put a link to them on here in the next few day they include

    Config pages
    A version of edges with filtering
    A version of Image Style that allowing selecting the styles rather that all variation of styles enabled, and also one for Responsive images
    Search api

  • 🇦🇺Australia almunnings Melbourne, 🇦🇺

    Re: Extending the schema... This could be done now by using a plugin:

    declare(strict_types=1);
    
    namespace Drupal\graphql_compose\Plugin\GraphQLCompose\SchemaType;
    
    use Drupal\graphql_compose\Plugin\GraphQLCompose\GraphQLComposeSchemaTypeBase;
    use GraphQL\Type\Definition\ObjectType;
    use GraphQL\Type\Definition\Type;
    use GraphQL\Type\Definition\UnionType;
    
    /**
     * {@inheritdoc}
     *
     * @GraphQLComposeSchemaType(
     *   id = "MetaTagSchema",
     * )
     */
    class MetaTagSchema extends GraphQLComposeSchemaTypeBase {
    
      /**
       * {@inheritdoc}
       */
      public function getTypes(): array {
        $types = [];
    
        $types[] = new ObjectType([
          'name' => $this->getPluginId(),
          'description' => (string) $this->t('Metatag Schema'),
          'interfaces' => fn() => [
            static::type('MetaTag'),
          ],
          'fields' => fn() => [
            'tag' => Type::nonNull(Type::string()),
            'value' => Type::string(),
          ],
        ]);
    
        return $types;
      }
    
      /**
       * {@inheritdoc}
       */
      public function getExtensions(): array {
        $extensions = [];
    
        $extensions[] = new UnionType([
          'name' => 'MetaTagUnion',
          'types' => [
            static::type('MetaTagSchema'),
          ],
        ]);
    
        return $extensions;
      }
    
    }
    

    This should work as of beta 8.
    How you resolve the data in these definitions is completely up to you.

  • 🇦🇺Australia almunnings Melbourne, 🇦🇺

    I could also add a hook, to fire within the schema printers.

    That would give you the ability to inject and extend before printing the schema without having to create a plugin. Its a "flexibility" hook. Maybe an anti-pattern. If you wanted to extend a Union for example...

    /**
     * Inject custom types to the schema just before printing.
     *
     * @param \Drupal\graphql_compose\Plugin\GraphQLComposeSchemaTypeManager $manager
     *   Schema type manager.
     */
    function hook_graphql_compose_schema_types_alter(\Drupal\graphql_compose\Plugin\GraphQLComposeSchemaTypeManager $manager): void {
    
      $meta_tag_schema = new \GraphQL\Type\Definition\ObjectType([
        'name' => 'MetaTagSchema',
        'interfaces' => fn() => [
          $manager->get('MetaTag'),
        ],
        'fields' => fn() => [
          'tag' => \GraphQL\Type\Definition\Type::nonNull(\GraphQL\Type\Definition\Type::string()),
          'value' => \GraphQL\Type\Definition\Type::string(),
        ],
      ]);
    
      $manager->add($meta_tag_schema);
    }
    
    /**
     * Extend types in the schema just before printing.
     *
     * @param \Drupal\graphql_compose\Plugin\GraphQLComposeSchemaTypeManager $manager
     *   Schema type manager.
     */
    function hook_graphql_compose_schema_extensions_alter(\Drupal\graphql_compose\Plugin\GraphQLComposeSchemaTypeManager $manager): void {
    
      $my_union = new \GraphQL\Type\Definition\UnionType([
        'name' => 'MetaTagUnion',
        'types' => [
          $manager->get('MetaTagSchema'),
        ],
      ]);
    
      $manager->extend($my_union);
    }
    
    

    That could be possible.
    Its also possible for you to mutilate the Schema Manager whenever and however you want.

    Whats still not resolved, is how you're getting that data across to the resolver in MetatagsSchemaExtension without having to butcher it up.

  • 🇦🇺Australia almunnings Melbourne, 🇦🇺

    The GraphQL addTypeResolver for the union just needs to be callable, maybe its worth adding a service in here that we can add plugins into. Make that process predictable and extendable.

    That way you could add a new condition for MetaTagUnion resolution.
    That works (in my head)

    So all thats left is the `resolveFieldItems` in the metatag_computed field.
    This can be altered already using `graphql_compose_field_results_alter` hook.

    I reckon if I can get a better way to do addTypeResolver, we have most cases covered.

  • Status changed to Closed: outdated over 1 year ago
  • 🇦🇺Australia almunnings Melbourne, 🇦🇺

    No action on this in almost a month,
    I've improved the online documentation with this post in mind.

    dev branch introduces the hook for the metatag union specifically mentioned, and a hook for modifying the schema at time of print.

    Closing without any further feedback.
    Thanks!

Production build 0.71.5 2024