drupal-graphql / graphql

GraphQL integration for Drupal 9/10
286 stars 202 forks source link

[4.x] entity_reference parent's language #1149

Open bachy opened 3 years ago

bachy commented 3 years ago

nested Entity loaded via entity reference field come in the default language, not in the current language, meaning the language of the parent. I can't find a way to get the right language from entity_reference.

type Article implements NodeInterface {
  ... 
  linked_materials: [Materiau]
  ...
}
type Materiau implements NodeInterface {
  id: Int!
  uuid: String!
  title: String!
  ...
}
$registry->addFieldResolver('Article', 'linked_materials',
   $builder->produce('entity_reference')
   ->map('entity', $builder->fromParent())
   ->map('field', $builder->fromValue('field_linked_materials'))
);

where i am now with my try

$registry->addFieldResolver('Article', 'linked_materials',
      $builder->compose(
        $builder->callback(function($parent, $args){
          $linkedmaterials = $parent->get('field_linked_materials')->getValue();
          $nids = [];
          foreach ($linkedmaterials as $key => $value) {
            $nids[] = $value['target_id'];
          }
          $lang = $parent->language()->getId();
          // return [
          //   "ids" => $nids,
          //   "language" => $lang
          // ];
          return $nids;
        }),
        $builder->produce('entity_load_multiple')
          ->map('type', $builder->fromValue('node'))
          ->map('bundles', $builder->fromValue(['materiau']))
          ->map('ids', $builder->fromParent())
          ->map('language', $builder->fromValue('fr')) // hard coded language working, how can i transmit the language from the parent ?
   )
);
bachy commented 3 years ago

ok, i came up with this solution

$builder->compose(
        $builder->callback(function($parent, $args){
          $linkedmaterials = $parent->get('field_linked_materials')->getValue();
          $nids = [];
          foreach ($linkedmaterials as $key => $value) {
            $nids[] = $value['target_id'];
          }
          $lang = $parent->language()->getId();
          $test="test";
          return [
            "ids" => $nids,
            "language" => $lang
          ];
        }),
        $builder->produce('entity_load_multiple')
          ->map('type', $builder->fromValue('node'))
          ->map('bundles', $builder->fromValue(['materiau']))
          ->map('ids', $builder->callback(function($parent, $args){
            return $parent['ids'];
          }))
          ->map('language', $builder->callback(function($parent, $args){
            return $parent['language'];
          }))
      )

i also tried that, but entity_reference does not seems to understand the "language" parametre

$builder->produce('entity_reference')
        ->map('entity', $builder->fromParent())
        ->map('field', $builder->fromValue('field_linked_materials'))
        ->map('language', $builder->fromValue('fr')) // this is not working
        // ->map('language', $builder->produce('entity_language')
          // ->map('entity', $builder->fromParent())) // neither that
kevineinarsson commented 3 years ago

I noticed the same issue. Pull request #974 should sort out the issue but it has been open for almost a year now.

What is the status of this PR? Is it possible to pick up and work on remaining issues? I'd be happy to do so if it's possible.

justclint commented 3 years ago

Also running into this with entity reference on translated taxonomy. Also using version 4. @bachy example works but if a term is not translated it will error so this is what I got working for now to reference translated taxonomy terms or return the source term if not translated.

      $builder->compose(
        $builder->callback(function($parent, $args){
          $memberRatings = $parent->get('field_member_rating')->getValue();
          $tids = [];
          foreach ($memberRatings as $key => $value) {
            $tids[] = $value['target_id'];
          }

          $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($tids);
          $language = $parent->language()->getId();
          $termList = [];
          foreach($terms as $term) {
            if($term->hasTranslation($language)){
              $translated_term = \Drupal::service('entity.repository')->getTranslationFromContext($term, $language);
              $termList[] = $translated_term;
            } else {
              $termList[] = $term;
            }
          }

          return $termList;
        }),
      )

Not sure if this is how chaining the data producers is intended to work but was trying something like this without success.

      $builder->compose(
        $builder->produce('entity_reference')
          ->map('entity', $builder->fromParent())
          ->map('field', $builder->fromValue('field_member_rating')), 
        $builder->produce('entity_translations')
          ->map('entity', $builder->fromParent())
          ->map('language', $builder->fromParent()),
      ),