-
-
Save jasonbahl/da87dbccb58f1323a324a9b3e8952d6c to your computer and use it in GitHub Desktop.
add_filter( 'graphql_PostObjectsConnectionOrderbyEnum_values', function( $values ) { | |
$values['LIKE_COUNT'] = [ | |
'value' => 'like_count', | |
'description' => __( 'The number of likes on the post', 'wp-graphql' ), | |
]; | |
return $values; | |
} ); | |
add_filter( 'graphql_post_object_connection_query_args', function( $query_args, $source, $input ) { | |
if ( isset( $input['where']['orderby'] ) && is_array( $input['where']['orderby'] ) ) { | |
foreach( $input['where']['orderby'] as $orderby ) { | |
if ( ! isset( $orderby['field'] ) || 'like_count' !== $orderby['field'] ) { | |
continue; | |
} | |
$query_args['meta_type'] = 'NUMERIC'; | |
$query_args['meta_key'] = 'like_count'; | |
$query_args['orderby']['meta_value_num'] = $orderby['order']; | |
} | |
} | |
return $query_args; | |
}, 10, 3); |
Hi @jasonbahl,
I have used the above code to sort posts based on view count but it's not working, please let me know if I am missing someting.
order by view count
add_filter( 'graphql_PostObjectsConnectionOrderbyEnum_values', function( $values ) {
$values['VIEW_COUNT'] = [
'value' => 'view_count',
'description' => __( 'The number of views on the post', 'wp-graphql' ),
];
return $values;
} );
add_filter( 'graphql_post_object_connection_query_args', function( $query_args, $source, $input ) {
if ( isset( $input['where']['orderby'] ) && is_array( $input['where']['orderby'] ) ) {
foreach( $input['where']['orderby'] as $orderby ) {
if ( ! isset( $orderby['field'] ) || 'view_count' !== $orderby['field'] ) {
continue;
}
$query_args['meta_key'] = 'wp_post_view_count';
$query_args['orderby'] = 'meta_value_num';
$query_args['order'] = $orderby['order'];
}
}
return $query_args;
}, 10, 3);
mutate view count
add_action( 'graphql_register_types', function() {
register_graphql_field( 'Post', 'viewCount', [
'type' => 'Int',
'description' => __( 'The number of views for the post', 'your-textdomain' ),
'resolve' => function( $post ) {
$views = get_post_meta( $post->ID, 'views', true );
return isset( $views ) ? (int) $views : 0;
}
] );
register_graphql_mutation( 'viewPost', [
'inputFields' => [
'id' => [
'type' => [
'non_null' => 'ID'
],
'description' => __( 'ID of the post to increase view count', 'your-textdomain' ),
],
],
'outputFields' => [
'post' => [
'type' => 'Post',
'description' => __( 'The post that was viewed', 'your-textdomain' ),
],
],
'mutateAndGetPayload' => function( $input ) {
$id = null;
if ( absint( $input['id'] ) ) {
$id = absint( $input['id'] );
} else {
$id_parts = \GraphQLRelay\Relay::fromGlobalId( $input['id'] );
if ( ! empty( $id_parts['id'] ) && absint( $id_parts['id'] ) ) {
$id = absint( $id_parts['id'] );
}
}
/**
* If the ID is invalid or the post object doesn't exist, throw an error
*/
if ( empty( $id ) || false == $post = get_post( absint( $id ) ) ) {
throw new \GraphQL\Error\UserError( __( 'The ID entered is invalid' ) );
}
/**
* If you wanted to only allow certain users to "like" a post, you could do
* some capability checks here too, or whatever validation you want to apply. . .
*/
$current_views = (int) get_post_meta( $post->ID, 'views', true );
update_post_meta( $post->ID, 'views', absint( $current_views + 1 ) );
return [
'post' => $post
];
}
] );
} );
mutation works fine, but order by returning an empty array.
Hi @hereisfahad, looks like your first comment has been removed.
Anyway didn't work for me either. For a workaround, I have added another field to specify ordering and handled the sorting myself in the front end.
If you're after the code in a "plugin" format that also allows you to specify in the request the "meta field" you'd like to order by, try the following:
<?php
/*
Plugin Name: WP GraphQL Meta Field Ordering
Description: Adds functionality to order by a meta field as specified by the user.
Version: 1.0.0
*/
defined('ABSPATH') or die('Nope, not accessing this');
class WPGraphQLOrderByMetaField
{
public function __construct()
{
add_filter('graphql_PostObjectsConnectionOrderbyEnum_values', [$this, 'register_meta_key_option']);
add_filter('graphql_TermObjectsConnectionOrderbyEnum_values', [$this, 'register_meta_key_option']);
add_filter('graphql_PostObjectsConnectionOrderbyInput_fields', [$this, 'register_meta_key_field']);
add_filter('graphql_TermObjectsConnectionOrderbyInput_fields', [$this, 'register_meta_key_field']);
add_filter('graphql_post_object_connection_query_args', [$this, 'graphql_orderby_meta'], 10, 3);
add_filter('graphql_term_object_connection_query_args', [$this, 'graphql_orderby_meta'], 10, 3);
}
public function register_meta_key_option($values)
{
$values['META_KEY'] = ['value' => 'META_KEY', 'description' => __('Order posts by the meta value "order"', 'wp-graphql') , ];
return $values;
}
public function register_meta_key_field($fields)
{
$fields['metaKeyField'] = ['type' => 'String', 'description' => __('Array of names to return term(s) for. Default empty.', 'wp-graphql') , ];
return $fields;
}
public function graphql_orderby_meta($query_args, $source, $input)
{
if (isset($input['where']['orderby']) && is_array($input['where']['orderby']))
{
foreach ($input['where']['orderby'] as $orderby)
{
if (!isset($orderby['field']) || 'META_KEY' !== $orderby['field'] || !isset($orderby['metaKeyField']))
{
continue;
}
$query_args['meta_key'] = $orderby['metaKeyField'];
// ////////////////////////////////////////////////////////
// Explanation for the below order values:
// ////////////////////////////////////////////////////////
//
// Order is attached to the "META_KEY" value as defined on line 25 of this file.
// This needs to be corrected to the value that has been already been processed by WP-Graphql
// otherwise pagination will not work correctly as the value for the direction of pagination
// is calculated here: wp-graphql/src/Data/Connection/PostObjectConnectionResolver.php | Lines 323-333
//
// See docs on order and orderby here for more info on how this is handled in wp queries:
// https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters
$query_args['order'] = isset($query_args['orderby']['META_KEY']) ? $query_args['orderby']['META_KEY'] : 'DESC';
// We run this last which overwrites the processed value for 'orderby' with
// the required value for meta ordering as per the above Wordpress docs.
$query_args['orderby'] = 'meta_value';
}
}
return $query_args;
}
}
new WPGraphQLOrderByMetaField();
~ Updated (02 Aug 2022)
And the query would look something like this:
query GetAllEvents {
events(
where: {
orderby: {
order: DESC,
field: META_KEY,
metaKeyField: "event_date" // Or your custom field to order by
}
}
) {
nodes {
title
slug
event_date
}
}
}
Hope this helps.
@jeremyProwseYS I am trying to make this work but I am getting the following errors:
{
"errors": [
{
"message": "Field \"posts\" argument \"where\" requires type PostObjectsConnectionOrderbyEnum, found META_KEY.",
"extensions": {
"category": "graphql"
},
"locations": [
{
"line": 3,
"column": 30
}
]
},
{
"message": "Field \"metaKeyField\" is not defined by type PostObjectsConnectionOrderbyInput.",
"extensions": {
"category": "graphql"
},
"locations": [
{
"line": 3,
"column": 52
}
]
},
Oh never mind, I was doing an unauthenticated request when my changes were only for an authenticated user.
All good, glad you got it sorted. I was running a couple of tests trying to replicate the issue with no success, so was scratching my head for a bit there!
Sorry for the false alarm :/ And thank you for posting your solution :) I'm trying to get the Events Calendar events properly sorted by event start dates, which is stored into a _EventStartDate meta field and after much research, I believe this is exactly what I needed!
If you're after the code in a "plugin" format that also allows you to specify in the request the "meta field" you'd like to order by, try the following:
<?php /* Plugin Name: WP GraphQL Meta Field Ordering Description: Adds functionality to order by a meta field as specified by the user. Version: 1.0.0 */ defined('ABSPATH') or die('Nope, not accessing this'); class WPGraphQLOrderByMetaField { public function __construct() { add_filter('graphql_PostObjectsConnectionOrderbyEnum_values', [$this, 'register_meta_key_option']); add_filter('graphql_TermObjectsConnectionOrderbyEnum_values', [$this, 'register_meta_key_option']); add_filter('graphql_PostObjectsConnectionOrderbyInput_fields', [$this, 'register_meta_key_field']); add_filter('graphql_TermObjectsConnectionOrderbyInput_fields', [$this, 'register_meta_key_field']); add_filter('graphql_post_object_connection_query_args', [$this, 'graphql_orderby_meta'], 10, 3); add_filter('graphql_term_object_connection_query_args', [$this, 'graphql_orderby_meta'], 10, 3); } public function register_meta_key_option($values) { $values['META_KEY'] = ['value' => 'META_KEY', 'description' => __('Order posts by the meta value "order"', 'wp-graphql') , ]; return $values; } public function register_meta_key_field($fields) { $fields['metaKeyField'] = ['type' => 'String', 'description' => __('Array of names to return term(s) for. Default empty.', 'wp-graphql') , ]; return $fields; } public function graphql_orderby_meta($query_args, $source, $input) { if (isset($input['where']['orderby']) && is_array($input['where']['orderby'])) { foreach ($input['where']['orderby'] as $orderby) { if (!isset($orderby['field']) || 'META_KEY' !== $orderby['field'] || !isset($orderby['metaKeyField'])) { continue; } $query_args['meta_key'] = $orderby['metaKeyField']; // //////////////////////////////////////////////////////// // Explanation for the below order values: // //////////////////////////////////////////////////////// // // Order is attached to the "META_KEY" value as defined on line 25 of this file. // This needs to be corrected to the value that has been already been processed by WP-Graphql // otherwise pagination will not work correctly as the value for the direction of pagination // is calculated here: wp-graphql/src/Data/Connection/PostObjectConnectionResolver.php | Lines 323-333 // // See docs on order and orderby here for more info on how this is handled in wp queries: // https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters $query_args['order'] = isset($query_args['orderby']['META_KEY']) ? $query_args['orderby']['META_KEY'] : 'DESC'; // We run this last which overwrites the processed value for 'orderby' with // the required value for meta ordering as per the above Wordpress docs. $query_args['orderby'] = 'meta_value'; } } return $query_args; } } new WPGraphQLOrderByMetaField();
~ Updated (02 Aug 2022)
And the query would look something like this:
query GetAllEvents { events( where: { orderby: { order: DESC, field: META_KEY, metaKeyField: "event_date" // Or your custom field to order by } } ) { nodes { title slug event_date } } }
Hope this helps.
Hi, this answer is amazing, but it only works for the first element when it comes to numbers and sorts only the first numeric value, the rest of the digits are ignored.
I used it and I ordered the prices in this way
"listings": {
"nodes": [
{
"title": "Propiedad 9",
"listing": {
"price": 1
}
},
{
"title": "Propiedad 4",
"listing": {
"price": 10
}
},
{
"title": "Propiedad 6",
"listing": {
"price": 100
}
},
{
"title": "Propiedad 5",
"listing": {
"price": 10000
}
},
{
"title": "Propiedad 8",
"listing": {
"price": 3223
}
},
{
"title": "propiedad 2",
"listing": {
"price": 38888
}
},
{
"title": "Propiedad 10",
"listing": {
"price": 4123
}
},
{
"title": "Propiedad 3",
"listing": {
"price": 87
}
},
{
"title": "escazu",
"listing": {
"price": 9000
}
},
{
"title": "Propiedad 7",
"listing": {
"price": 999999
}
}
]
}
},```
@juanu96 I believe if the field is storing numbers, you need:
$query_args['orderby'] = 'meta_value_num';
instead of:
$query_args['orderby'] = 'meta_value';
@juanu96 I believe if the field is storing numbers, you need:
$query_args['orderby'] = 'meta_value_num';
instead of:
$query_args['orderby'] = 'meta_value';
yes, this worked for me, thank you very much for your help
Hi all,
I've used this solution in my own code.
add_filter( 'graphql_PostObjectsConnectionOrderbyEnum_values', function( $values ) {
$values['PARTNER_TIER'] = [
'value' => 'partner_tier',
'description' => __( 'Tier Level of the partner'),
];
return $values;}
);
add_filter( 'graphql_post_object_connection_query_args', function( $query_args, $source, $input ) {
if ( isset( $input['where']['orderby'] ) && is_array( $input['where']['orderby'] ) ) {
foreach( $input['where']['orderby'] as $orderby ) {
if ( ! isset( $orderby['field'] ) || 'partner_tier' !== $orderby['field'] ) {
continue;
}
$query_args['meta_type'] = 'NUMERIC';
$query_args['meta_key'] = 'partner_tier';
$query_args['orderby']['meta_value_num'] = $orderby['order'];
}
}
return $query_args;
}, 10, 3);
And while the initial call works, the cursor pagination is not working, and returning and empty set of partners when calling the next page.
Here's the working initial query.
And here's the query calling the next page
Was wondering if anyone else here had a similar issue or if there's something I am doing incorrectly
Was wondering if anyone else here had a similar issue or if there's something I am doing incorrectly
@ndigenpcc Did you ever find a solution to your problem? I'm facing something similar, and can't seem to find the bug.
@mickras I never ended up finding a solution, so I had moved back to the Wordpress REST API and created my own search filters
Thanks for posting this example, @jasonbahl ! It worked flawlessly for my use case (ordering posts by a Number ACF field VIEW_COUNT
).
Hi @jasonbahl,
Thanks for sharing the gist. Beginner here... I wonder how I can add this to my WordPress site. I have tried to add the snippet above to my
functions.php
(wp-content/themes/twentytwenty/functions.php) but theorderBy
seems not working...Here's how I do the graphql request
Btw, the
category_order
field was created from ACF and I'm trying to sort the product categories based on that custom fieldThanks in advance for your help. 🙏