Skip to content

Added entity reference layout revisions plugin. #968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

dasjo
Copy link
Contributor

@dasjo dasjo commented Jan 25, 2020

Based on #909, I added a similar plugin for entity reference layout revisions.
https://www.drupal.org/project/entity_reference_layout

This works for me to access the data from paragraph fields, what is still missing is exposing any layout information.

Because it took a me a while to figure out how to draft the schema, also sharing the code I am currently using for it. Maybe for later reference:

schema file

schema {
  query: Query
}

type Query {
  article(id: Int!): Article
  articles(
    offset: Int = 0
    limit: Int = 10
  ): ArticleConnection!
}

type Article {
  id: Int!
  title: String!
  author: String
  body: String
  contents: [ListItem]!
}

interface ListItem {
  id: Int!
}

type SectionItem implements ListItem {
  id: Int!
}

type ProductItem implements ListItem {
  id: Int!
  title: String!
  body: String
  product_reference_id: String
}

type TextItem implements ListItem {
  id: Int!
  text: String!
}

type ArticleConnection {
  total: Int!
  items: [Article!]
}

Schema class

  /**
   * {@inheritdoc}
   */
  public function getResolverRegistry() {
    $builder = new ResolverBuilder();
    $registry = new ResolverRegistry();

    $this->addQueryFields($registry, $builder);
    $this->addArticleFields($registry, $builder);

    // Re-usable connection type fields.
    $this->addConnectionFields('ArticleConnection', $registry, $builder);

    return $registry;
  }

  /**
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addArticleFields(ResolverRegistry $registry, ResolverBuilder $builder) {
    $registry->addFieldResolver('Article', 'id',
      $builder->produce('entity_id')
        ->map('entity', $builder->fromParent())
    );

    $registry->addFieldResolver('Article', 'title',
      $builder->produce('entity_label')
        ->map('entity', $builder->fromParent())
    );

    $registry->addFieldResolver('Article', 'author',
      $builder->compose(
        $builder->produce('entity_owner')
          ->map('entity', $builder->fromParent()),
        $builder->produce('entity_label')
          ->map('entity', $builder->fromParent())
      )
    );

    $registry->addFieldResolver('Article', 'body',
      $builder->produce('property_path')
        ->map('type', $builder->fromValue('entity:node'))
        ->map('value', $builder->fromParent())
        ->map('path', $builder->fromValue('body.value'))
    );

    $registry->addFieldResolver('Article', 'contents',
      $builder->produce('entity_reference_layout_revisions')
        ->map('entity', $builder->fromParent())
        ->map('field', $builder->fromValue('field_contents'))
    );

    $registry->addTypeResolver('ListItem', function ($value) {
      if ($value instanceof Paragraph) {
        switch ($value->bundle()) {
          case 'section': return 'SectionItem';
          case 'product_item': return 'ProductItem';
          case 'text': return 'TextItem';
        }
      }
      throw new Error('Could not resolve ListItem type.');
    });
    
    // Helps traverse from paragraph over entity reference to the field values.
    $productItemBuilder = $builder->compose(
      $builder->produce('entity_reference')
        ->map('entity', $builder->fromParent())
        ->map('field', $builder->fromValue('field_product')),
      $builder->produce('seek')
        ->map('input', $builder->fromParent())
        ->map('position', $builder->fromValue(0))
    );

    $registry->addFieldResolver('ProductItem', 'id',
      $builder->compose(
        $productItemBuilder,
        $builder->produce('entity_id')
          ->map('entity', $builder->fromParent())
      )
    );

    $registry->addFieldResolver('ProductItem', 'title',
      $builder->compose(
        $productItemBuilder,
        $builder->produce('entity_label')
          ->map('entity', $builder->fromParent())
      )
    );

    $registry->addFieldResolver('ProductItem', 'body',
      $builder->compose(
        $productItemBuilder,
        $builder->produce('property_path')
          ->map('type', $builder->fromValue('entity:node'))
          ->map('value', $builder->fromParent())
          ->map('path', $builder->fromValue('body.value'))
      )
    );

    $registry->addFieldResolver('ProductItem', 'product_reference_id',
      $builder->compose(
        $productItemBuilder,
        $builder->produce('property_path')
          ->map('type', $builder->fromValue('entity:node'))
          ->map('value', $builder->fromParent())
          ->map('path', $builder->fromValue('field_product_reference_id.value'))
      )
    );

    $registry->addFieldResolver('TextItem', 'id',
      $builder->produce('entity_id')
        ->map('entity', $builder->fromParent())
    );

    $registry->addFieldResolver('TextItem', 'text',
      $builder->produce('property_path')
        ->map('type', $builder->fromValue('entity:paragraph'))
        ->map('value', $builder->fromParent())
        ->map('path', $builder->fromValue('field_text.value'))
    );
  }

  /**
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addQueryFields(ResolverRegistry $registry, ResolverBuilder $builder) {
    $registry->addFieldResolver('Query', 'article',
      $builder->produce('entity_load')
        ->map('type', $builder->fromValue('node'))
        ->map('bundles', $builder->fromValue(['article']))
        ->map('id', $builder->fromArgument('id'))
    );

    $registry->addFieldResolver('Query', 'articles',
      $builder->produce('query_articles')
        ->map('offset', $builder->fromArgument('offset'))
        ->map('limit', $builder->fromArgument('limit'))
    );
  }

  /**
   * @param string $type
   * @param \Drupal\graphql\GraphQL\ResolverRegistry $registry
   * @param \Drupal\graphql\GraphQL\ResolverBuilder $builder
   */
  protected function addConnectionFields($type, ResolverRegistry $registry, ResolverBuilder $builder) {
    $registry->addFieldResolver($type, 'total',
      $builder->callback(function (HeadlessConnection $connection) {
        return $connection->total();
      })
    );

    $registry->addFieldResolver($type, 'items',
      $builder->callback(function (HeadlessConnection $connection) {
        return $connection->items();
      })
    );
  }

@codecov
Copy link

codecov bot commented Jan 25, 2020

Codecov Report

Merging #968 into 8.x-4.x will decrease coverage by 1.46%.
The diff coverage is 0%.

Impacted file tree graph

@@              Coverage Diff              @@
##             8.x-4.x     #968      +/-   ##
=============================================
- Coverage      62.03%   60.57%   -1.47%     
- Complexity       537      558      +21     
=============================================
  Files             95       96       +1     
  Lines           1367     1400      +33     
=============================================
  Hits             848      848              
- Misses           519      552      +33
Impacted Files Coverage Δ Complexity Δ
...aProducer/Field/EntityReferenceLayoutRevisions.php 0% <0%> (ø) 21 <21> (?)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c8bc59d...393b8e1. Read the comment docs.

@dasjo dasjo marked this pull request as ready for review January 25, 2020 13:41
@fubhy fubhy merged commit 4141327 into drupal-graphql:8.x-4.x Feb 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants