Skip to content

Commit 8a790e0

Browse files
authored
Merge pull request #3073 from justlevine/feat/expose-post-passwords
feat: expose `hasPassword` and `password` fields on Post objects
2 parents c95087c + 6f4e2d0 commit 8a790e0

File tree

3 files changed

+161
-8
lines changed

3 files changed

+161
-8
lines changed

src/Model/Post.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,15 @@
5151
* @property array $editLock
5252
* @property string $enclosure
5353
* @property string $guid
54+
* @property bool $hasPassword
5455
* @property int $menuOrder
5556
* @property string $link
5657
* @property string $uri
5758
* @property int $commentCount
5859
* @property string $featuredImageId
5960
* @property int $featuredImageDatabaseId
6061
* @property string $pageTemplate
62+
* @property string $password
6163
* @property int $previewRevisionDatabaseId
6264
*
6365
* @property string $captionRaw
@@ -152,6 +154,7 @@ public function __construct( WP_Post $post ) {
152154
'isPostsPage',
153155
'isFrontPage',
154156
'isPrivacyPage',
157+
'hasPassword',
155158
];
156159

157160
if ( isset( $this->post_type_object->graphql_single_name ) ) {
@@ -595,6 +598,12 @@ protected function init() {
595598

596599
return false;
597600
},
601+
'hasPassword' => function () {
602+
return ! empty( $this->data->post_password );
603+
},
604+
'password' => function () {
605+
return ! empty( $this->data->post_password ) ? $this->data->post_password : null;
606+
},
598607
'toPing' => function () {
599608
$to_ping = get_to_ping( $this->databaseId );
600609

@@ -690,12 +699,6 @@ protected function init() {
690699

691700
return ! empty( $thumbnail_id ) ? absint( $thumbnail_id ) : null;
692701
},
693-
'password' => [
694-
'callback' => function () {
695-
return ! empty( $this->data->post_password ) ? $this->data->post_password : null;
696-
},
697-
'capability' => isset( $this->post_type_object->cap->edit_others_posts ) ?: 'edit_others_posts',
698-
],
699702
'enqueuedScriptsQueue' => static function () {
700703
global $wp_scripts;
701704
do_action( 'wp_enqueue_scripts' );

src/Registry/Utils/PostObject.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,22 @@ public static function get_fields( WP_Post_Type $post_type_object ) {
360360
return absint( $post->ID );
361361
},
362362
],
363+
'hasPassword' => [
364+
'type' => 'Boolean',
365+
'description' => sprintf(
366+
// translators: %s: custom post-type name.
367+
__( 'Whether the %s object is password protected.', 'wp-graphql' ),
368+
$post_type_object->name
369+
),
370+
],
371+
'password' => [
372+
'type' => 'String',
373+
'description' => sprintf(
374+
// translators: %s: custom post-type name.
375+
__( 'The password for the %s object.', 'wp-graphql' ),
376+
$post_type_object->name
377+
),
378+
],
363379
];
364380

365381
if ( 'page' === $post_type_object->name ) {

tests/wpunit/PostObjectQueriesTest.php

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ public function set_permalink_structure( $structure = '' ) {
101101
}
102102

103103
public function createPostObject( $args ) {
104-
105104
/**
106105
* Set up the $defaults
107106
*/
@@ -212,6 +211,8 @@ static function ( $param ) {
212211
}
213212
enclosure
214213
excerpt
214+
hasPassword
215+
password
215216
status
216217
link
217218
postId
@@ -270,6 +271,8 @@ static function ( $param ) {
270271
'slug' => 'test-title-for-postobjectqueriestest',
271272
'toPing' => null,
272273
'pinged' => null,
274+
'hasPassword' => false,
275+
'password' => null,
273276
'modified' => \WPGraphQL\Utils\Utils::prepare_date_response( get_post( $post_id )->post_modified ),
274277
'modifiedGmt' => \WPGraphQL\Utils\Utils::prepare_date_response( get_post( $post_id )->post_modified_gmt ),
275278
'title' => apply_filters( 'the_title', 'Test Title for PostObjectQueriesTest' ),
@@ -2396,7 +2399,7 @@ public function testQueryPostBySlugWithNonAsciiSlug() {
23962399
);
23972400

23982401
// assert that the response is what we expect
2399-
self::assertQuerySuccessful(
2402+
$this->assertQuerySuccessful(
24002403
$actual,
24012404
[
24022405
$this->expectedField( 'post.__typename', 'Post' ),
@@ -2406,4 +2409,135 @@ public function testQueryPostBySlugWithNonAsciiSlug() {
24062409
]
24072410
);
24082411
}
2412+
2413+
public function testPasswordProtectedPost() {
2414+
$subscriber = $this->factory()->user->create(
2415+
[
2416+
'role' => 'subscriber',
2417+
]
2418+
);
2419+
2420+
$post_author_one = $this->factory()->user->create(
2421+
[
2422+
'role' => 'author',
2423+
]
2424+
);
2425+
2426+
$post_author_two = $this->factory()->user->create(
2427+
[
2428+
'role' => 'author',
2429+
]
2430+
);
2431+
2432+
$post = $this->factory()->post->create_and_get(
2433+
[
2434+
'post_type' => 'post',
2435+
'post_status' => 'publish',
2436+
'post_password' => 'mypassword',
2437+
'title' => 'Password Protected post',
2438+
'content' => 'Some content',
2439+
'post_author' => $post_author_one,
2440+
]
2441+
);
2442+
2443+
$query = '
2444+
query GetPasswordProtectedPost( $id: ID! ) {
2445+
post( id: $id, idType: DATABASE_ID ) {
2446+
title
2447+
content
2448+
status
2449+
password
2450+
hasPassword
2451+
}
2452+
}
2453+
';
2454+
2455+
// Test password protected post as unauthenticated user.
2456+
$actual = $this->graphql( [
2457+
'query' => $query,
2458+
'variables' => [
2459+
'id' => $post->ID,
2460+
],
2461+
] );
2462+
2463+
$this->assertArrayNotHasKey( 'errors', $actual );
2464+
$this->assertEquals( $post->post_title, $actual['data']['post']['title'], 'Title should be returned when unauthenticated' );
2465+
$this->assertEquals( 'publish', $actual['data']['post']['status'], 'Status should be "publish" when unauthenticated' );
2466+
$this->assertNull( $actual['data']['post']['content'], 'Content should be null when unauthenticated' );
2467+
$this->assertNull( $actual['data']['post']['password'], 'Password should be null when unauthenticated' );
2468+
$this->assertTrue( $actual['data']['post']['hasPassword'], 'hasPassword should be true when unauthenticated' );
2469+
2470+
// Test password protected post as a subscriber.
2471+
wp_set_current_user( $subscriber );
2472+
$actual = $this->graphql( [
2473+
'query' => $query,
2474+
'variables' => [
2475+
'id' => $post->ID,
2476+
],
2477+
] );
2478+
2479+
$this->assertArrayNotHasKey( 'errors', $actual );
2480+
$this->assertEquals( $post->post_title, $actual['data']['post']['title'], 'Title should be returned when lacking permissions' );
2481+
$this->assertEquals( 'publish', $actual['data']['post']['status'], 'Status should be "publish" when lacking permissions' );
2482+
$this->assertNull( $actual['data']['post']['content'], 'Content should be null when lacking permissions' );
2483+
$this->assertNull( $actual['data']['post']['password'], 'Password should be null when lacking permissions' );
2484+
$this->assertTrue( $actual['data']['post']['hasPassword'], 'hasPassword should be true when lacking permissions' );
2485+
2486+
// Test password protected post as different author.
2487+
wp_set_current_user( $post_author_two );
2488+
$actual = $this->graphql( [
2489+
'query' => $query,
2490+
'variables' => [
2491+
'id' => $post->ID,
2492+
],
2493+
] );
2494+
2495+
$this->assertArrayNotHasKey( 'errors', $actual );
2496+
$this->assertEquals( $post->post_title, $actual['data']['post']['title'], 'Title should be returned when lacking permissions' );
2497+
$this->assertEquals( 'publish', $actual['data']['post']['status'], 'Status should be "publish" when lacking permissions' );
2498+
$this->assertNull( $actual['data']['post']['content'], 'Content should be null when lacking permissions' );
2499+
$this->assertNull( $actual['data']['post']['password'], 'Password should be null when lacking permissions' );
2500+
$this->assertTrue( $actual['data']['post']['hasPassword'], 'hasPassword should be true when lacking permissions' );
2501+
2502+
// Test password protected post as current author.
2503+
wp_set_current_user( $post_author_one );
2504+
2505+
$actual = $this->graphql( [
2506+
'query' => $query,
2507+
'variables' => [
2508+
'id' => $post->ID,
2509+
],
2510+
] );
2511+
2512+
$this->assertArrayNotHasKey( 'errors', $actual );
2513+
$this->assertEquals( $post->post_title, $actual['data']['post']['title'], 'Title should be returned when authenticated' );
2514+
$this->assertEquals( 'publish', $actual['data']['post']['status'], 'Status should be "publish" when authenticated' );
2515+
$this->assertNotEmpty( $actual['data']['post']['content'], 'Content should be returned when authenticated' );
2516+
$this->assertEquals( $post->post_password, $actual['data']['post']['password'], 'Password should be returned when authenticated' );
2517+
$this->assertTrue( $actual['data']['post']['hasPassword'], 'hasPassword should be true when authenticated' );
2518+
2519+
// Test password protected post as admin.
2520+
wp_set_current_user( $this->admin );
2521+
2522+
$actual = $this->graphql( [
2523+
'query' => $query,
2524+
'variables' => [
2525+
'id' => $post->ID,
2526+
],
2527+
] );
2528+
2529+
$this->assertArrayNotHasKey( 'errors', $actual );
2530+
$this->assertEquals( $post->post_title, $actual['data']['post']['title'], 'Title should be returned when authenticated' );
2531+
$this->assertEquals( 'publish', $actual['data']['post']['status'], 'Status should be "publish" when authenticated' );
2532+
$this->assertNotEmpty( $actual['data']['post']['content'], 'Content should be returned when authenticated' );
2533+
$this->assertEquals( $post->post_password, $actual['data']['post']['password'], 'Password should be returned when authenticated' );
2534+
$this->assertTrue( $actual['data']['post']['hasPassword'], 'hasPassword should be true when authenticated' );
2535+
2536+
// @todo add case with password supplied once supported.
2537+
// @see https://github.com/wp-graphql/wp-graphql/issues/930
2538+
2539+
// cleanup
2540+
wp_delete_post( $post->ID, true );
2541+
wp_delete_user( $subscriber );
2542+
}
24092543
}

0 commit comments

Comments
 (0)