diff --git a/CHANGELOG.md b/CHANGELOG.md index 333b535..21783bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- fix: Prevent fatal error when resolving seo from private `Post` models. H/t @MonPetitUd + ## [0.3.1] This _minor_ release fixes several bugs and improves compatibility with WPGraphQL for WooCommerce. diff --git a/src/Type/WPInterface/NodeWithSeo.php b/src/Type/WPInterface/NodeWithSeo.php index 6a04b10..d2b6f44 100644 --- a/src/Type/WPInterface/NodeWithSeo.php +++ b/src/Type/WPInterface/NodeWithSeo.php @@ -124,7 +124,7 @@ private static function get_model_for_node( Model $node_model ): ?Model { // A map of the node models to their corresponding SEO model classes. switch ( true ) { case $node_model instanceof \WPGraphQL\Model\Post: - $seo_model = new ContentNodeSeo( $node_model->ID ); + $seo_model = new ContentNodeSeo( $node_model->databaseId ); break; case $node_model instanceof \WPGraphQL\Model\PostType: $seo_model = new ContentTypeSeo( $node_model->name ); diff --git a/tests/wpunit/ContentNodeSeoQueryTest.php b/tests/wpunit/ContentNodeSeoQueryTest.php index 8058d78..0574b4c 100644 --- a/tests/wpunit/ContentNodeSeoQueryTest.php +++ b/tests/wpunit/ContentNodeSeoQueryTest.php @@ -20,7 +20,6 @@ public function setUp(): void { rank_math()->settings->set( 'general', 'breadcrumbs', true ); rank_math()->settings->set( 'general', 'headless_support', true ); - $this->admin = $this->factory()->user->create( [ @@ -53,7 +52,7 @@ public function tearDown(): void { $this->clearSchema(); } - protected function get_query() : string { + protected function get_query(): string { return ' query contentNode( $id: ID!, $idType: ContentNodeIdTypeEnum, $asPreview: Boolean ) { contentNode( id: $id, idType: $idType, asPreview: $asPreview ){ @@ -106,9 +105,9 @@ protected function assertValidSeo( array $actual ): void { 2 ), $this->expectedField( 'breadcrumbTitle', 'Post Title' ), - $this->expectedField( 'canonicalUrl', static::NOT_FALSY ), + $this->expectedField( 'canonicalUrl', self::NOT_FALSY ), $this->expectedField( 'description', get_the_excerpt( $this->database_id ) ), - $this->expectedField( 'focusKeywords', static::IS_NULL ), + $this->expectedField( 'focusKeywords', self::IS_NULL ), $this->expectedField( 'isPillarContent', false ), $this->expectedField( 'robots', @@ -124,7 +123,7 @@ protected function assertValidSeo( array $actual ): void { $this->expectedObject( 'seoScore', [ - $this->expectedField( 'badgeHtml', static::IS_NULL ), + $this->expectedField( 'badgeHtml', self::IS_NULL ), $this->expectedField( 'hasFrontendScore', false ), $this->expectedField( 'rating', 'UNKNOWN' ), $this->expectedField( 'score', 0 ), @@ -242,7 +241,7 @@ public function testContentNodeSeoAsPreview() { ), $this->expectedField( 'breadcrumbTitle', 'Draft Title' ), $this->expectedField( 'description', get_the_excerpt( $draft_id ) ), - $this->expectedField( 'focusKeywords', static::IS_NULL ), + $this->expectedField( 'focusKeywords', self::IS_NULL ), $this->expectedField( 'isPillarContent', false ), $this->expectedField( 'robots', @@ -258,7 +257,7 @@ public function testContentNodeSeoAsPreview() { $this->expectedObject( 'seoScore', [ - $this->expectedField( 'badgeHtml', static::IS_NULL ), + $this->expectedField( 'badgeHtml', self::IS_NULL ), $this->expectedField( 'hasFrontendScore', false ), $this->expectedField( 'rating', 'UNKNOWN' ), $this->expectedField( 'score', 0 ), @@ -275,4 +274,72 @@ public function testContentNodeSeoAsPreview() { wp_delete_post( $draft_id, true ); wp_delete_post( $revision_id, true ); } + + public function testPasswordProtectedContentNodeSeo() { + $protected_id = $this->factory()->post->create( + [ + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_title' => 'Protected Post Title', + 'post_content' => 'Protected Post Content', + 'post_password' => 'password', + ] + ); + + $query = $this->get_query(); + + $variables = [ + 'id' => $protected_id, + 'idType' => 'DATABASE_ID', + 'asPreview' => false, + ]; + + $actual = $this->graphql( compact( 'query', 'variables' ) ); + $this->assertArrayNotHasKey( 'errors', $actual ); + + $this->assertEquals( $protected_id, $actual['data']['contentNode']['databaseId'] ); + + $this->assertQuerySuccessful( + $actual, + [ + $this->expectedObject( + 'contentNode', + [ + $this->expectedObject( + 'seo', + [ + $this->expectedNode( + 'breadcrumbs', + [ + $this->expectedField( 'text', 'Protected: Protected Post Title' ), + $this->expectedField( 'url', get_permalink( $protected_id ) ), + $this->expectedField( 'isHidden', false ), + ], + 2 + ), + $this->expectedField( 'breadcrumbTitle', 'Protected: Protected Post Title' ), + $this->expectedField( 'canonicalUrl', self::NOT_FALSY ), + $this->expectedField( 'focusKeywords', self::IS_NULL ), + $this->expectedField( 'isPillarContent', false ), + $this->expectedField( + 'robots', + [ + 'index', + 'follow', + 'max-snippet:-1', + 'max-video-preview:-1', + 'max-image-preview:large', + ] + ), + $this->expectedField( 'title', 'Protected Post Title - Test' ), + ] + ), + ] + ), + ] + ); + + // cleanup. + wp_delete_post( $protected_id, true ); + } }