From a4961cff60ae4a38771592b8357ae2adb017f21f Mon Sep 17 00:00:00 2001 From: Dovid Levine Date: Sat, 10 Aug 2024 14:40:09 +0300 Subject: [PATCH] fix: improve openGraph type handling (#104) --- CHANGELOG.md | 3 ++- src/Type/WPObject/OpenGraph/Article.php | 17 ++++++++++++----- src/Type/WPObject/OpenGraph/Facebook.php | 13 ++++++++++--- src/Type/WPObject/OpenGraph/Image.php | 2 +- src/Type/WPObject/OpenGraph/Product.php | 4 ++-- src/Type/WPObject/OpenGraph/Twitter.php | 10 +++++----- 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a3fdbc..1b6ccdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,9 @@ ## [Unreleased] -- chore: Update Composer dev-deps. +- fix: Improve `seo.openGraph` type handling to prevent fatal errors when resolving custom schemas. H/t @juniorzenb - fix: expose `RankMathSeo.canonicalUrl` to unauthenticated users. H/t @marziolek +- chore: Update Composer dev-deps. - ci: test plugin compatibility with WordPress 6.6.1. - ci: replace uses of deprecated `docker-compose` with `docker compose`. - ci: Remove WP < 6.3 from GitHub Actions tests for RankMath 1.0.218+ compatibility. diff --git a/src/Type/WPObject/OpenGraph/Article.php b/src/Type/WPObject/OpenGraph/Article.php index 5497565..17839e5 100644 --- a/src/Type/WPObject/OpenGraph/Article.php +++ b/src/Type/WPObject/OpenGraph/Article.php @@ -37,12 +37,12 @@ public static function get_fields(): array { 'modifiedTime' => [ 'type' => 'String', 'description' => __( 'The date modified.', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?string => ! empty( $source['modified_time'] ) ? $source['modified_time'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['modified_time'] ) ? (string) $source['modified_time'] : null, ], 'publishedTime' => [ 'type' => 'String', 'description' => __( 'The date published.', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?string => ! empty( $source['published_time'] ) ? $source['published_time'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['published_time'] ) ? (string) $source['published_time'] : null, ], 'publisher' => [ 'type' => 'String', @@ -58,17 +58,24 @@ public static function get_fields(): array { 'resolve' => static function ( $source ): ?array { $value = ! empty( $source['tag'] ) ? $source['tag'] : null; - if ( is_string( $value ) ) { - $value = [ $value ]; + if ( empty( $value ) ) { + return null; } + if ( ! is_array( $value ) ) { + $value = [ (string) $value ]; + } + + // Ensure all tags are strings. + $value = array_map( 'strval', $value ); + return $value; }, ], 'section' => [ 'type' => 'String', 'description' => __( 'The article category.', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?string => ! empty( $source['section'] ) ? $source['section'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['section'] ) ? (string) $source['section'] : null, ], ]; } diff --git a/src/Type/WPObject/OpenGraph/Facebook.php b/src/Type/WPObject/OpenGraph/Facebook.php index 0a22fe4..badf7b1 100644 --- a/src/Type/WPObject/OpenGraph/Facebook.php +++ b/src/Type/WPObject/OpenGraph/Facebook.php @@ -37,7 +37,7 @@ public static function get_fields(): array { 'appId' => [ 'type' => 'ID', 'description' => __( 'The Facebook app ID associated with this resource', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?string => ! empty( $source['app_id'] ) ? $source['app_id'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['app_id'] ) ? (string) $source['app_id'] : null, ], 'admins' => [ 'type' => [ 'list_of' => 'String' ], @@ -45,10 +45,17 @@ public static function get_fields(): array { 'resolve' => static function ( $source ): ?array { $value = ! empty( $source['admins'] ) ? $source['admins'] : null; - if ( is_string( $value ) ) { - $value = [ $value ]; + if ( empty( $value ) ) { + return null; } + if ( ! is_array( $value ) ) { + $value = [ (string) $value ]; + } + + // Ensure all tags are strings. + $value = array_map( 'strval', $value ); + return $value; }, ], diff --git a/src/Type/WPObject/OpenGraph/Image.php b/src/Type/WPObject/OpenGraph/Image.php index d5715b4..fd21353 100644 --- a/src/Type/WPObject/OpenGraph/Image.php +++ b/src/Type/WPObject/OpenGraph/Image.php @@ -41,7 +41,7 @@ public static function get_fields(): array { 'secureUrl' => [ 'type' => 'String', 'description' => __( 'The https:// URL for the image.', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?string => ! empty( $source['secure_url'] ) ? $source['secure_url'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['secure_url'] ) ? (string) $source['secure_url'] : null, ], 'type' => [ 'type' => 'String', // @todo diff --git a/src/Type/WPObject/OpenGraph/Product.php b/src/Type/WPObject/OpenGraph/Product.php index e7863dd..bb0e794 100644 --- a/src/Type/WPObject/OpenGraph/Product.php +++ b/src/Type/WPObject/OpenGraph/Product.php @@ -43,14 +43,14 @@ public static function get_fields(): array { 'type' => 'Float', 'description' => __( 'The price of the object', 'wp-graphql-rank-math' ), 'resolve' => static function ( $source ): ?float { - return ! empty( $source['price']['amount'] ) ? $source['price']['amount'] : null; + return ! empty( $source['price']['amount'] ) ? (float) $source['price']['amount'] : null; }, ], 'currency' => [ 'type' => 'String', 'description' => __( 'The currency of the object price.', 'wp-graphql-rank-math' ), 'resolve' => static function ( $source ): ?string { - return ! empty( $source['price']['currency'] ) ? $source['price']['currency'] : null; + return ! empty( $source['price']['currency'] ) ? (string) $source['price']['currency'] : null; }, ], 'availability' => [ diff --git a/src/Type/WPObject/OpenGraph/Twitter.php b/src/Type/WPObject/OpenGraph/Twitter.php index 87150ba..2892739 100644 --- a/src/Type/WPObject/OpenGraph/Twitter.php +++ b/src/Type/WPObject/OpenGraph/Twitter.php @@ -50,7 +50,7 @@ public static function get_fields(): array { 'appCountry' => [ 'type' => 'String', 'description' => __( 'The app country.', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?string => ! empty( $source['app:country'] ) ? $source['app:country'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['app:country'] ) ? (string) $source['app:country'] : null, ], 'ipadApp' => [ 'type' => TwitterApp::get_type_name(), @@ -68,14 +68,14 @@ public static function get_fields(): array { 'resolve' => static fn ( $source ): ?array => self::get_app_meta( $source, 'googleplay' ), ], 'playerUrl' => [ - 'type' => 'Integer', + 'type' => 'Int', 'description' => __( 'URL of the twitter player.', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?int => ! empty( $source['player'] ) ? $source['player'] : null, + 'resolve' => static fn ( $source ): ?int => ! empty( $source['player'] ) ? (int) $source['player'] : null, ], 'playerStream' => [ 'type' => 'String', 'description' => __( 'URL to raw video or audio stream', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?int => ! empty( $source['player:stream'] ) ? $source['player:stream'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['player:stream'] ) ? (string) $source['player:stream'] : null, ], 'site' => [ 'type' => 'String', @@ -84,7 +84,7 @@ public static function get_fields(): array { 'playerStreamContentType' => [ 'type' => 'String', 'description' => __( 'The content type of the stream', 'wp-graphql-rank-math' ), - 'resolve' => static fn ( $source ): ?int => ! empty( $source['player:stream:content_type'] ) ? $source['player:stream:content_type'] : null, + 'resolve' => static fn ( $source ): ?string => ! empty( $source['player:stream:content_type'] ) ? (string) $source['player:stream:content_type'] : null, ], 'image' => [ 'type' => 'String',