Last active
February 4, 2026 04:13
-
-
Save therealgilles/106ddfdfa2dd508cf542807595a3c079 to your computer and use it in GitHub Desktop.
WP GraphQL Meta Field Ordering
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Plugin Name: WP GraphQL Meta Field Ordering | |
| * Description: Adds functionality to order by a meta field as specified by the user. | |
| * See: https://gist.github.com/jasonbahl/da87dbccb58f1323a324a9b3e8952d6c | |
| * and also: | |
| * https://github.com/wp-graphql/wp-graphql/issues/287 | |
| * https://github.com/wp-graphql/wp-graphql/pull/721 | |
| * https://github.com/wp-graphql/wp-graphql-meta-query/blob/develop/wp-graphql-meta-query.php | |
| */ | |
| namespace GQL; | |
| defined( 'ABSPATH' ) || die( 'Direct script access disallowed.' ); | |
| /** | |
| * WPGraphQLOrderByMetaField class | |
| */ | |
| class WPGraphQLOrderByMetaField { | |
| /** | |
| * Constructor | |
| */ | |
| public function __construct() { | |
| $class = get_called_class(); | |
| add_action( | |
| 'graphql_register_types', | |
| array( $class, 'register_types' ) | |
| ); | |
| add_filter( | |
| 'graphql_PostObjectsConnectionOrderbyEnum_values', | |
| array( | |
| $class, | |
| 'gql_add_orderby_enum_values', | |
| ) | |
| ); | |
| add_filter( | |
| 'graphql_TermObjectsConnectionOrderbyEnum_values', | |
| array( | |
| $class, | |
| 'gql_add_orderby_enum_values', | |
| ) | |
| ); | |
| add_filter( | |
| 'graphql_PostObjectsConnectionOrderbyInput_fields', | |
| array( | |
| $class, | |
| 'gql_add_orderby_input_fields', | |
| ) | |
| ); | |
| add_filter( | |
| 'graphql_TermObjectsConnectionOrderbyInput_fields', | |
| array( | |
| $class, | |
| 'gql_add_orderby_input_fields', | |
| ) | |
| ); | |
| add_filter( | |
| 'graphql_post_object_connection_query_args', | |
| array( $class, 'gql_object_connection_query_args' ), | |
| 10, | |
| 5 | |
| ); | |
| add_filter( | |
| 'graphql_term_object_connection_query_args', | |
| array( $class, 'gql_object_connection_query_args' ), | |
| 10, | |
| 5 | |
| ); | |
| } | |
| /** | |
| * Register custom GraphQL types. | |
| */ | |
| public static function register_types() { | |
| register_graphql_enum_type( | |
| 'MetaKeyTypeEnum', | |
| array( | |
| 'description' => __( 'Cast type for META_KEY ordering. Maps to WP_Query meta_type.', 'wp-graphql' ), | |
| 'values' => array( | |
| 'CHAR' => array( 'value' => 'CHAR' ), | |
| 'NUMERIC' => array( 'value' => 'NUMERIC' ), | |
| 'DECIMAL' => array( 'value' => 'DECIMAL' ), | |
| 'SIGNED' => array( 'value' => 'SIGNED' ), | |
| 'UNSIGNED' => array( 'value' => 'UNSIGNED' ), | |
| 'DATE' => array( 'value' => 'DATE' ), | |
| 'DATETIME' => array( 'value' => 'DATETIME' ), | |
| 'TIME' => array( 'value' => 'TIME' ), | |
| 'BINARY' => array( 'value' => 'BINARY' ), | |
| ), | |
| ) | |
| ); | |
| } | |
| /** | |
| * Add meta key to orderby field values | |
| * | |
| * @param array $values Existing values | |
| * @return array Returns update values | |
| */ | |
| public static function gql_add_orderby_enum_values( $values ) { | |
| $values['META_KEY'] = array( | |
| 'value' => 'META_KEY', | |
| 'description' => __( 'META_KEY option to orderby field.', 'wp-graphql' ), | |
| ); | |
| return $values; | |
| } | |
| /** | |
| * Add meta key field to orderby fields | |
| * | |
| * @param array $fields Existing fields | |
| * @return array Returns updated fields | |
| */ | |
| public static function gql_add_orderby_input_fields( $fields ) { | |
| $fields['metaKeyField'] = array( | |
| 'type' => 'String', | |
| 'description' => __( 'META_KEY value for orderby field.', 'wp-graphql' ), | |
| ); | |
| $fields['metaKeyType'] = array( | |
| 'type' => 'MetaKeyTypeEnum', | |
| 'description' => __( 'Cast type for META_KEY ordering. Defaults to CHAR (string comparison).', 'wp-graphql' ), | |
| ); | |
| return $fields; | |
| } | |
| /** | |
| * Update WP_Query args for orderby by META_KEY | |
| * | |
| * @param array $query_args Query arguments | |
| * @param mixed $source Source passed down from the resolve tree | |
| * @param array $args The inputArgs on the field | |
| * @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree | |
| * @param \WPGraphQL\ResolveInfo $info The ResolveInfo passed down the GraphQL tree | |
| * @return array Returns updated query arguments | |
| */ | |
| public static function gql_object_connection_query_args( | |
| $query_args, | |
| $source, | |
| $args, | |
| $context, | |
| $info | |
| ) { | |
| if ( isset( $args['where']['orderby'] ) && is_array( $args['where']['orderby'] ) ) { | |
| foreach ( $args['where']['orderby'] as $orderby ) { | |
| if ( | |
| ! isset( $orderby['field'] ) || | |
| 'META_KEY' !== $orderby['field'] || | |
| ! isset( $orderby['metaKeyField'] ) | |
| ) { | |
| continue; | |
| } | |
| // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key | |
| $query_args['meta_key'] = $orderby['metaKeyField']; | |
| // Extract the order direction from WPGraphQL's processed orderby | |
| // array (e.g. ['META_KEY' => 'DESC']) before we overwrite it below. | |
| // See: 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'; | |
| // Use meta_value_num for numeric types, meta_value for everything else. | |
| $meta_type = ! empty( $orderby['metaKeyType'] ) ? strtoupper( $orderby['metaKeyType'] ) : ''; | |
| $numeric_types = array( 'NUMERIC', 'DECIMAL', 'SIGNED', 'UNSIGNED' ); | |
| $query_args['orderby'] = in_array( $meta_type, $numeric_types, true ) | |
| ? 'meta_value_num' | |
| : 'meta_value'; | |
| if ( $meta_type ) { | |
| // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_type | |
| $query_args['meta_type'] = $meta_type; | |
| } | |
| } | |
| } | |
| return $query_args; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment