Last active
February 4, 2026 03:51
-
-
Save therealgilles/1c31817ccc231a8771e094b1d84fbf88 to your computer and use it in GitHub Desktop.
Events GraphQL functions
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 | |
| /** | |
| * Events GraphQL functions | |
| */ | |
| namespace Events; | |
| use WPGraphQL\Data\Connection\TermObjectConnectionResolver; | |
| use WPGraphQL\AppContext; | |
| use WPGraphQL\Model\Post; | |
| defined( 'ABSPATH' ) || die( 'Direct script access disallowed.' ); | |
| /** | |
| * GraphQL class | |
| */ | |
| class GQL { | |
| /** | |
| * Constructor | |
| */ | |
| public function __construct() { | |
| $class = get_called_class(); | |
| // Exclude default Event→taxonomy connections so we can register custom ones. | |
| add_filter( 'register_post_type_args', array( $class, 'exclude_event_taxonomy_connections' ), 10, 2 ); | |
| // register additional query fields with GraphQL | |
| add_action( 'graphql_register_types', array( $class, 'gql_register_types' ) ); | |
| // register custom Event→taxonomy connections with provisional ID normalization | |
| add_action( 'graphql_register_types', array( $class, 'gql_register_connections' ) ); | |
| add_filter( | |
| 'graphql_post_object_connection_query_args', | |
| array( $class, 'gql_post_object_connection_query_args' ), | |
| 10, | |
| 5 | |
| ); | |
| } | |
| /** | |
| * Exclude default Event→taxonomy connections via graphql_exclude_connections. | |
| * | |
| * This allows us to register custom versions that normalize TEC provisional IDs. | |
| * | |
| * @param array $args The post type args. | |
| * @param string $post_type The post type name. | |
| * @return array Modified args. | |
| */ | |
| public static function exclude_event_taxonomy_connections( $args, $post_type ) { | |
| if ( 'tribe_events' !== $post_type ) { | |
| return $args; | |
| } | |
| // Exclude these connections so we can register custom ones with provisional ID support. | |
| $exclude = array( 'eventsCategories', 'categories' ); | |
| if ( empty( $args['graphql_exclude_connections'] ) ) { | |
| $args['graphql_exclude_connections'] = $exclude; | |
| } else { | |
| $args['graphql_exclude_connections'] = array_merge( | |
| $args['graphql_exclude_connections'], | |
| $exclude | |
| ); | |
| } | |
| return $args; | |
| } | |
| /** | |
| * Register additional query fields with GraphQL | |
| */ | |
| public static function gql_register_types() { | |
| register_graphql_fields( | |
| 'RootQueryToEventConnectionWhereArgs', | |
| array( | |
| 'CategorySlugIn' => array( | |
| 'type' => array( 'list_of' => 'String' ), | |
| 'description' => __( 'Include only event in these category slugs', 'theme' ), | |
| ), | |
| 'CategorySlugNotIn' => array( | |
| 'type' => array( 'list_of' => 'String' ), | |
| 'description' => __( 'Exclude event in these category slugs', 'theme' ), | |
| ), | |
| 'EventsCategorySlugIn' => array( | |
| 'type' => array( 'list_of' => 'String' ), | |
| 'description' => __( 'Include only event in these events category slugs', 'theme' ), | |
| ), | |
| 'EventsCategorySlugNotIn' => array( | |
| 'type' => array( 'list_of' => 'String' ), | |
| 'description' => __( 'Exclude event in these events category slugs', 'theme' ), | |
| ), | |
| ) | |
| ); | |
| } | |
| /** | |
| * Register GraphQL connections for Event→taxonomy with provisional ID normalization. | |
| * | |
| * TEC Pro uses provisional IDs for recurring event occurrences. Taxonomy terms | |
| * are attached to the event post, not the occurrence, so we normalize the ID. | |
| */ | |
| public static function gql_register_connections() { | |
| $taxonomies = array( | |
| 'tribe_events_cat' => array( | |
| 'graphql_plural_name' => 'eventsCategories', | |
| 'graphql_single_name' => 'eventsCategory', | |
| ), | |
| 'category' => array( | |
| 'graphql_plural_name' => 'categories', | |
| 'graphql_single_name' => 'Category', | |
| ), | |
| ); | |
| foreach ( $taxonomies as $taxonomy => $names ) { | |
| register_graphql_connection( | |
| array( | |
| 'fromType' => 'Event', | |
| 'toType' => $names['graphql_single_name'], | |
| 'fromFieldName' => $names['graphql_plural_name'], | |
| 'resolve' => function ( | |
| Post $post, | |
| array $args, | |
| AppContext $context, | |
| $info | |
| ) use ( $taxonomy ) { | |
| // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase | |
| $object_id = true === $post->isPreview | |
| // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase | |
| && ! empty( $post->parentDatabaseId ) ? $post->parentDatabaseId : $post->databaseId; | |
| if ( empty( $object_id ) || ! absint( $object_id ) ) { | |
| return null; | |
| } | |
| // Normalize provisional IDs from TEC custom tables. | |
| if ( $object_id >= 10000000 ) { | |
| $object_id = \TEC\Events\Custom_Tables\V1\Models\Occurrence::normalize_id( $object_id ); | |
| } | |
| $resolver = new TermObjectConnectionResolver( $post, $args, $context, $info, $taxonomy ); | |
| $resolver->set_query_arg( 'object_ids', absint( $object_id ) ); | |
| return $resolver->get_connection(); | |
| }, | |
| ) | |
| ); | |
| } | |
| } | |
| /** | |
| * Implement where filter for categorySlugIn/categorySlugNotIn | |
| * and eventsCategorySlugIn/eventsCategorySlugNotIn for event post type | |
| * | |
| * @param array $query_args The WP_Query arguments. | |
| * @param mixed $source The source object for the connection. | |
| * @param array $input_args The `where` input arguments. | |
| * @param \WPGraphQL\AppContext $context The GraphQL AppContext. | |
| * @param \GraphQL\Type\Definition\ResolveInfo $info ResolveInfo object with field-specific execution state | |
| * (AST info, return type, path, etc). | |
| * @return array Modified $query_args to be passed into WP_Query. | |
| */ | |
| public static function gql_post_object_connection_query_args( $query_args, $source, $input_args, $context, $info ) { | |
| $post_types = (array) ( $query_args['post_type'] ?? array() ); | |
| if ( in_array( \Tribe__Events__Main::POSTTYPE, $post_types, true ) ) { | |
| if ( ! empty( $input_args['where']['categorySlugIn'] ) ) { | |
| $query_args['tax_query'][] = array( | |
| 'taxonomy' => 'category', | |
| 'field' => 'slug', | |
| 'terms' => array_map( 'sanitize_title', $input_args['where']['categorySlugIn'] ), | |
| 'operator' => 'IN', | |
| ); | |
| } | |
| if ( ! empty( $input_args['where']['categorySlugNotIn'] ) ) { | |
| $query_args['tax_query'][] = array( | |
| 'taxonomy' => 'category', | |
| 'field' => 'slug', | |
| 'terms' => array_map( 'sanitize_title', $input_args['where']['categorySlugNotIn'] ), | |
| 'operator' => 'NOT IN', | |
| ); | |
| } | |
| if ( ! empty( $input_args['where']['eventsCategorySlugIn'] ) ) { | |
| $query_args['tax_query'][] = array( | |
| 'taxonomy' => \Tribe__Events__Main::TAXONOMY, | |
| 'field' => 'slug', | |
| 'terms' => array_map( 'sanitize_title', $input_args['where']['eventsCategorySlugIn'] ), | |
| 'operator' => 'IN', | |
| ); | |
| } | |
| if ( ! empty( $input_args['where']['eventsCategorySlugNotIn'] ) ) { | |
| $query_args['tax_query'][] = array( | |
| 'taxonomy' => \Tribe__Events__Main::TAXONOMY, | |
| 'field' => 'slug', | |
| 'terms' => array_map( 'sanitize_title', $input_args['where']['eventsCategorySlugNotIn'] ), | |
| 'operator' => 'NOT IN', | |
| ); | |
| } | |
| } | |
| return $query_args; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment