Skip to content
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

Get queried/resolved language for a given post #44

Closed
simplenotezy opened this issue Apr 22, 2021 · 9 comments
Closed

Get queried/resolved language for a given post #44

simplenotezy opened this issue Apr 22, 2021 · 9 comments

Comments

@simplenotezy
Copy link

I am trying to register a GraphQL field (https://www.wpgraphql.com/2020/03/11/registering-graphql-fields-with-arguments/), and inside the resolve callback, I need to do a WP query, and for that I’d like to query posts in specific language. How can I get the current language? Unfortunately pll_current_language() returns false.

You specifically say that you have deactivated the "native" way Polylang fetches posts when using WP_Query, but actually, in my case I'd prefer if it only queried in the language that was resolved.

I query by URI like this:

query Posts {
  post(id: "/en/unlimited", idType: URI) {

Although not very pretty, I came up with this workaround that gives me the language of the queried object:

/**
 * For lack of a better way to get the currently queried language inside GraphQL
 * @return mixed
 */
function get_queried_language() {
    $lang = pll_get_post_language($GLOBALS['wp_the_query']->queried_object->ID);
    return ($lang) ? $lang : pll_default_language();
}

A better solution would be if pll_current_language could be used inside resolve of register_graphql_field

@esamattis
Copy link
Member

esamattis commented Apr 22, 2021

It's not clear what you are trying to achieve from what you have posted. Are you adding a field to post or new root level field? Why do you need pll_current_language()? If you have a post id or an URI you can get the language using that.

There's really no concept of "current language" in the graphql since in single graphql query you can query posts, terms etc. in multiple languages at once so pll_current_language() can't really return a single value for it. You need to figure out the language in some other way.

Linking #40 as it might be related.

@simplenotezy
Copy link
Author

Hey @esamattis thanks for a fast reply 😊

In code, this is what I am trying to do:

register_graphql_field('Post_Sections_Sections_Faq', 'questions', [
		'type' => 'Json',
		'description' => __('Fetches the questions defined in the section'),
		'resolve' => function ($fields) {
				$args = [
						'post_type' => 'question',
						'lang' => get_queried_language() // I need some way to ensure that the "question" post type only includes current language
				];

				$query = new WP_Query($args);
				// [...] and so on
				return $posts;
		}
]);

This way I can query like this:

    ... on Post_Sections_Sections_Faq {
      backgroundColor
      fieldGroupName
      text
      header
      questions <!---
      features
    }

@esamattis
Copy link
Member

And what Post_Sections_Sections_Faq is? That's not part of wp-graphql or this plugin 🙂

@simplenotezy
Copy link
Author

Well @esamattis technically it's just Advanced Custom Fields with a Flexible Content section. But in theory, my registering of graph field didn't have to be Post_Sections_Sections_Faq, it could be any other element.

@esamattis
Copy link
Member

esamattis commented Apr 23, 2021

But in theory, my registering of graph field didn't have to be Post_Sections_Sections_Faq, it could be any other element.

It matters how you get the language.

Still guessing what you are doing but maybe something like this?

{
  post(id: "/en/unlimited", idType: URI) {
    something {
      ... on Post_Sections_Sections_Faq {
        questions
      }
    }
  }
}

What if query like this is made?

{

  post(id: "/en/unlimited", idType: URI) {
    something {
      ... on Post_Sections_Sections_Faq {
        questions
      }
    }
  }
  other: post(id: "/fi/suomeksi", idType: URI) {
    something {
      ... on Post_Sections_Sections_Faq {
        questions
      }
    }
  }
}

Now your resolver is called twice for posts of different languages. Since pll_current_language() is basically a global that gets set at the start of the request but with graphql requests the language "can change in flight".

In theory it could be possible to patch the global language every time a new post field starts resolving but that can be brittle since it can happen in so many situations. For example posts can be resolved inside posts like with the childNodes or translations fields.

The "graphql way" to solve this would be to walk up the field tree and check the language of the post your questions field is nested under.

I'm not that familiar how to do it with ACF fields (and you did not even tell what kind of situation you have) but maybe you can ask from the wpgraphql slack.

But if your are not using the $fields argument in your resolver then there's really no reason to define the questions field on the ACF field type. You could just put it on Post where it would be really easy to the language correctly:

register_graphql_field('Post', 'questions', [
	'type' => 'Json',
	'description' => __('Fetches the questions defined in the section'),
	'resolve' => function ($post, $args, $context, $info) {
	   $lang = pll_get_post_language($post->ID);
	}
]);

@esamattis
Copy link
Member

Even if you need the access to the ACF fields you could use the pll_ methods to get them manually using the $post model.

@simplenotezy
Copy link
Author

Thanks for your reply.

  1. Luckily I am only doing a single query, but I understand how this can be an issue if you do multiple queries
  2. The workaround I've implemented, which works when you only query ONE language at a time, works using the pll_ methods

I am still, very interested how this would be done "the right way", e.g. walking up the tree (from a resolver) and figuring out what language the given post found has.

@esamattis
Copy link
Member

Luckily I am only doing a single query, but I understand how this can be an issue if you do multiple queries

Just remembered that WPGraphQL actually calls setup_postdata() every time it starts resolving a post and sets it back to the previous post if any. Which means this should work 99% of the time:

global $post;
if ($post) {
  $lang = pll_get_post_language($post->ID);
} else {
  $lang = pll_default_language();
}

I am still, very interested how this would be done "the right way", e.g. walking up the tree (from a resolver) and figuring out what language the given post found has.

I can't remember how it can be done from the ACF group type but do ask from the #acf channel on the WPGraphQL slack.

@esamattis
Copy link
Member

Closing as there's nothing actionable. Feel free to comment still.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants