diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d0cbf..3411c0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [Unreleased] +- feat!: Narrow `seo` field types to their implementations. - chore!: Bump minimum supported WPGraphQL version to v1.26.0. - dev: Update `RedirectionConnectionResolver` for v1.26.0 compatibility. - fix: Correctly resolve `rankMathSettings.homepage.description` field. Props @offminded 🙌 diff --git a/docs/reference/queries.md b/docs/reference/queries.md index de025f6..23e24fe 100644 --- a/docs/reference/queries.md +++ b/docs/reference/queries.md @@ -62,14 +62,12 @@ query MyPosts { } robots title - ... on RankMathContentNodeSeo { # Only available on `contentNode` types. - isPillarContent - seoScore { - badgeHtml - hasFrontendScore - rating - score - } + isPillarContent + seoScore { + badgeHtml + hasFrontendScore + rating + score } } author { @@ -192,14 +190,12 @@ query MyPosts { } robots title - ... on RankMathContentNodeSeo { # Only available on `contentNode` types. - isPillarContent - seoScore { - badgeHtml - hasFrontendScore - rating - score - } + isPillarContent + seoScore { + badgeHtml + hasFrontendScore + rating + score } } } @@ -282,14 +278,12 @@ query MyCategories { } robots title - ... on RankMathContentNodeSeo { # Only available on `contentNode` types. - isPillarContent - seoScore { - badgeHtml - hasFrontendScore - rating - score - } + isPillarContent + seoScore { + badgeHtml + hasFrontendScore + rating + score } } } @@ -330,7 +324,10 @@ query MyCategories { ### Querying with `nodeByUri` -> **Note**: Currently, `nodeByUri` does not detect links associated with a Rank Math Redirection. This will be addressed [in a future release](https://github.com/AxeWP/wp-graphql-rank-math/issues/53). +> [!IMPORTANT] +> Currently, `nodeByUri` does not detect links associated with a Rank Math Redirection. This will be addressed [in a future release](https://github.com/AxeWP/wp-graphql-rank-math/issues/53). +> +> See [Querying Redirections](#querying-redirections) for more information. ```graphql query MyNodeByUriQuery( $uri: String ) { @@ -422,7 +419,8 @@ The Sitemap Module must be enabled in the [Rank Math settings](https://rankmath. The Redirections Module [must be enabled] in the [Rank Math settings](https://rankmath.com/kb/setting-up-redirections/) for the sitemap data to be available. -> **Note**: Currently, `nodeByUri` does not detect links associated with a Rank Math Redirection. This will be addressed [in a future release](https://github.com/AxeWP/wp-graphql-rank-math/issues/53). +> [!NOTE] +> Currently, `nodeByUri` does not detect links associated with a Rank Math Redirection. This will be addressed [in a future release](https://github.com/AxeWP/wp-graphql-rank-math/issues/53). > > In the interim, we recommend handling redirects in your frontend app, such as with the [NextJS `redirects` config key](https://nextjs.org/docs/pages/api-reference/next-config-js/redirects). diff --git a/src/Type/WPInterface/NodeWithSeo.php b/src/Type/WPInterface/NodeWithSeo.php index f34cd06..6a04b10 100644 --- a/src/Type/WPInterface/NodeWithSeo.php +++ b/src/Type/WPInterface/NodeWithSeo.php @@ -16,6 +16,8 @@ use WPGraphQL\RankMath\Model\ContentTypeSeo; use WPGraphQL\RankMath\Model\TermNodeSeo; use WPGraphQL\RankMath\Model\UserSeo; +use WPGraphQL\RankMath\Type\WPInterface\ContentNodeSeo as WPInterfaceContentNodeSeo; +use WPGraphQL\RankMath\Utils\Utils; use WPGraphQL\RankMath\Vendor\AxeWP\GraphQL\Abstracts\InterfaceType; use WPGraphQL\RankMath\Vendor\AxeWP\GraphQL\Interfaces\TypeWithInterfaces; @@ -50,6 +52,11 @@ public static function register(): void { // @todo only apply to ContentTypes that have SEO data. register_graphql_interfaces_to_types( self::type_name(), $types_with_seo ); + + // Narrow down ContentNode types. + Utils::overload_graphql_field_type( 'ContentNode', 'seo', WPInterfaceContentNodeSeo::get_type_name() ); + // This is necessary because the filter doesn't work for inheritance. + Utils::overload_graphql_field_type( 'HierarchicalContentNode', 'seo', WPInterfaceContentNodeSeo::get_type_name() ); } /** diff --git a/src/Type/WPObject/SeoObjects.php b/src/Type/WPObject/SeoObjects.php index 89ec954..cf83301 100644 --- a/src/Type/WPObject/SeoObjects.php +++ b/src/Type/WPObject/SeoObjects.php @@ -13,6 +13,7 @@ use WPGraphQL; use WPGraphQL\RankMath\Type\WPInterface\ContentNodeSeo; use WPGraphQL\RankMath\Type\WPInterface\Seo; +use WPGraphQL\RankMath\Utils\Utils; use WPGraphQL\RankMath\Vendor\AxeWP\GraphQL\Interfaces\Registrable; use WPGraphQL\RankMath\Vendor\AxeWP\GraphQL\Traits\TypeNameTrait; @@ -37,9 +38,10 @@ public static function register(): void { foreach ( $post_types as $post_type ) { /** @var \WP_Post_Type $post_type */ - // Register Post Objects seo. + $type_name_for_post_object = 'RankMath' . graphql_format_type_name( $post_type->graphql_single_name . 'ObjectSeo' ); + // Register Post Object seo. register_graphql_object_type( - 'RankMath' . graphql_format_type_name( $post_type->graphql_single_name . 'ObjectSeo' ), + $type_name_for_post_object, [ // translators: %s is the post type name. 'description' => sprintf( __( 'The %s post object SEO data', 'wp-graphql-rank-math' ), $post_type->name ), @@ -49,9 +51,13 @@ public static function register(): void { ] ); + // Register Post Object's SEO field. + Utils::overload_graphql_field_type( $post_type->graphql_single_name, 'seo', $type_name_for_post_object ); + // Register Post Type seo. + $type_name_for_post_type = 'RankMath' . graphql_format_type_name( $post_type->graphql_single_name . 'TypeSeo' ); register_graphql_object_type( - 'RankMath' . graphql_format_type_name( $post_type->graphql_single_name . 'TypeSeo' ), + $type_name_for_post_type, [ // translators: %s is the post type name. 'description' => sprintf( __( 'The %s post type object SEO data', 'wp-graphql-rank-math' ), $post_type->name ), @@ -67,9 +73,9 @@ public static function register(): void { foreach ( $taxonomies as $taxonomy ) { /** @var \WP_Taxonomy $taxonomy */ - $name = 'RankMath' . graphql_format_type_name( $taxonomy->graphql_single_name . 'TermSeo' ); + $type_name_for_term = 'RankMath' . graphql_format_type_name( $taxonomy->graphql_single_name . 'TermSeo' ); register_graphql_object_type( - $name, + $type_name_for_term, [ // translators: %s is the tax term name. 'description' => sprintf( __( 'The %s term object SEO data', 'wp-graphql-rank-math' ), $taxonomy->name ), @@ -78,11 +84,15 @@ public static function register(): void { 'eagerlyLoadType' => true, ] ); + + // Register Term Object's SEO field. + Utils::overload_graphql_field_type( $taxonomy->graphql_single_name, 'seo', $type_name_for_term ); } // Register user object seo. + $type_name_for_user = 'RankMathUserSeo'; register_graphql_object_type( - graphql_format_type_name( 'RankMathUserSeo' ), + $type_name_for_user, [ 'description' => __( 'The user object SEO data', 'wp-graphql-rank-math' ), 'interfaces' => [ Seo::get_type_name() ], @@ -103,5 +113,8 @@ public static function register(): void { 'eagerlyLoadType' => true, ] ); + + // Register User Object's SEO field. + Utils::overload_graphql_field_type( 'User', 'seo', $type_name_for_user ); } } diff --git a/src/Utils/Utils.php b/src/Utils/Utils.php index 2b04779..420f67e 100644 --- a/src/Utils/Utils.php +++ b/src/Utils/Utils.php @@ -59,4 +59,30 @@ public static function base_url( string $path = '' ): string { return user_trailingslashit( $base_url ); } + + /** + * Overloads the field type of an existing GraphQL field. + * + * This is necessary because register_graphql_field() doesn't have a way to check inheritance. + * + * @see https://github.com/wp-graphql/wp-graphql/issues/3096 + * + * @param string $object_type The WPGraphQL object type name where the field is located. + * @param string $field_name The field name to overload. + * @param string $new_type_name The new GraphQL type name to use. + */ + public static function overload_graphql_field_type( string $object_type, string $field_name, string $new_type_name ): void { + add_filter( + 'graphql_' . $object_type . '_fields', + static function ( array $fields ) use ( $field_name, $new_type_name ) { + if ( isset( $fields[ $field_name ] ) ) { + $fields[ $field_name ]['type'] = $new_type_name; + } + + return $fields; + }, + 10, + 1 + ); + } } diff --git a/tests/functional/UserSeoQueryCept.php b/tests/functional/UserSeoQueryCept.php index 45dfa81..5879e6d 100644 --- a/tests/functional/UserSeoQueryCept.php +++ b/tests/functional/UserSeoQueryCept.php @@ -56,17 +56,15 @@ title } } - ... on RankMathUserSeo { - additionalProfiles - facebookProfileUrl - twitterUserName - } + additionalProfiles + facebookProfileUrl + twitterUserName } } } ', 'variables' => [ - 'id' => $user_id, + 'id' => $user_id, ], ] ) diff --git a/tests/wpunit/ContentNodeSeoQueryTest.php b/tests/wpunit/ContentNodeSeoQueryTest.php index 193c2c6..263e2ca 100644 --- a/tests/wpunit/ContentNodeSeoQueryTest.php +++ b/tests/wpunit/ContentNodeSeoQueryTest.php @@ -70,14 +70,12 @@ protected function get_query() : string { jsonLd { raw } - ... on RankMathContentNodeSeo { - isPillarContent - seoScore { - badgeHtml - hasFrontendScore - rating - score - } + isPillarContent + seoScore { + badgeHtml + hasFrontendScore + rating + score } } } diff --git a/tests/wpunit/UserSeoQueryTest.php b/tests/wpunit/UserSeoQueryTest.php index 428d413..e5a53e2 100644 --- a/tests/wpunit/UserSeoQueryTest.php +++ b/tests/wpunit/UserSeoQueryTest.php @@ -65,11 +65,9 @@ public function testUserSeo() { } robots title - ... on RankMathUserSeo { - additionalProfiles - facebookProfileUrl - twitterUserName - } + additionalProfiles + facebookProfileUrl + twitterUserName } } } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 60073d3..ed65099 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'axepress/wp-graphql-rank-math', - 'pretty_version' => 'dev-main', - 'version' => 'dev-main', - 'reference' => 'c9b62d7260ed1cb9ad215e36675e6f1581395548', + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '26c12338bf979a09d681555c5d8ee84419e94e6d', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -20,9 +20,9 @@ 'dev_requirement' => false, ), 'axepress/wp-graphql-rank-math' => array( - 'pretty_version' => 'dev-main', - 'version' => 'dev-main', - 'reference' => 'c9b62d7260ed1cb9ad215e36675e6f1581395548', + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '26c12338bf979a09d681555c5d8ee84419e94e6d', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(),