Skip to content

Commit

Permalink
refactor: change approach
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasio committed Mar 9, 2024
1 parent de5c030 commit ac7fd33
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 72 deletions.
11 changes: 10 additions & 1 deletion packages/next/src/handlers/previewHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,16 @@ export async function previewHandler(
*/
const getDefaultRedirectPath = () => {
if (preview?.usePostLinkForRedirect) {
return removeSourceUrl({ link: result.link, backendUrl: sourceUrl ?? '' });
if (
result.status === 'draft' &&
typeof result._tenup_preview_link === 'undefined'
) {
throw new Error(
'You are using usePostLinkForRedirect setting but your rest response does not have _tenup_preview_link, ensure you are running the latest version of the plugin',
);
}
const link = result._tenup_preview_link ?? result.link;
return removeSourceUrl({ link: link as string, backendUrl: sourceUrl ?? '' });
}

const singleRoute = postTypeDef.single || '/';
Expand Down
93 changes: 31 additions & 62 deletions wp/headless-wp/includes/classes/Preview/PreviewLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,46 @@ class PreviewLink {
public function register() {
add_filter( 'template_include', [ $this, 'handle_preview' ], 20 );

add_filter( 'post_link', [ $this, 'force_posts_drafts_to_have_permalinks' ], 10, 2 );
add_filter( 'post_type_link', [ $this, 'force_cpts_drafts_to_have_permalinks' ], 10, 2 );
add_action( 'page_link', [ $this, 'force_page_drafts_to_have_permalinks' ], 10, 2 );
add_action( 'rest_api_init', [ $this, 'add_preview_link_field' ] );
}

/**
* Force drafts to have permalinks
* Adds preview link field
*
* @param string $permalink The post's permalink.
* @param \WP_Post $post The post in question.
*
* @return string
* @return void
*/
protected function force_drafts_to_have_permalinks( string $permalink, \WP_Post $post ): string {
if ( 'draft' !== $post->post_status ) {
return $permalink;
public function add_preview_link_field() {
$post_types = get_post_types( [ 'show_in_rest' => true ], 'names' );

foreach ( $post_types as $post_type ) {
register_rest_field(
$post_type,
'_tenup_preview_link',
[
'get_callback' => function ( $object ) {
return $this->get_draft_permalink( get_post( $object['id'] ) );
},
'schema' => [
'type' => 'string',
],
]
);
}
}

/**
* Get drafts permalinks
*
* @param \WP_Post $post The post in question.
*
* @return string
*/
public function get_draft_permalink( \WP_Post $post ): string {
try {
$payload = PreviewToken::get_payload_from_token();

if ( ! $payload ) {
return $permalink;
return '';
}

if ( 'preview' === $payload->type && $post->ID === $payload->post_id ) {
Expand All @@ -55,60 +72,12 @@ protected function force_drafts_to_have_permalinks( string $permalink, \WP_Post
return $link;
}

return $permalink;
return '';
} catch ( \Exception $e ) {
return $permalink;
return '';
}
}

/**
* Force posts drafts to have permalinks
*
* @param string $permalink The post's permalink.
* @param \WP_Post $post The post in question.
*
* @return string
*/
public function force_posts_drafts_to_have_permalinks( string $permalink, \WP_Post $post ): string {
remove_filter( 'post_link', [ $this, 'force_posts_drafts_to_have_permalinks' ], 10, 2 );
$link = $this->force_drafts_to_have_permalinks( $permalink, $post );
add_filter( 'post_link', [ $this, 'force_posts_drafts_to_have_permalinks' ], 10, 2 );

return $link;
}

/**
* Force cpts drafts to have permalinks
*
* @param string $permalink The post's permalink.
* @param \WP_Post $post The post in question.
*
* @return string
*/
public function force_cpts_drafts_to_have_permalinks( string $permalink, \WP_Post $post ): string {
remove_filter( 'post_type_link', [ $this, 'force_cpts_drafts_to_have_permalinks' ], 10, 2 );
$link = $this->force_drafts_to_have_permalinks( $permalink, $post );
add_filter( 'post_type_link', [ $this, 'force_cpts_drafts_to_have_permalinks' ], 10, 2 );

return $link;
}

/**
* Force page drafts to have permalinks
*
* @param string $permalink The post's permalink.
* @param int $page_id The page_id
*
* @return string
*/
public function force_page_drafts_to_have_permalinks( string $permalink, int $page_id ): string {
remove_filter( 'page_link', [ $this, 'force_page_drafts_to_have_permalinks' ], 10, 2 );
$link = $this->force_drafts_to_have_permalinks( $permalink, get_post( $page_id ) );
add_filter( 'page_link', [ $this, 'force_page_drafts_to_have_permalinks' ], 10, 2 );

return $link;
}

/**
* Method to check if previews are to be handled
*
Expand Down
125 changes: 116 additions & 9 deletions wp/headless-wp/tests/php/tests/TestPreview.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use DateTime;
use HeadlessWP\Preview\PreviewLink;
use HeadlessWP\Preview\PreviewToken;
use WP_REST_Request;
use WP_UnitTestCase;

/**
Expand All @@ -31,6 +32,24 @@ class TestPreview extends WP_UnitTestCase {
*/
protected $wp_rewrite;

/**
* The rest server
*
* @var WP_REST_Server
*/
protected static \WP_REST_Server $rest_server;

/**
* Setup any pre-test data.
*
* @return void
*/
public static function setUpBeforeClass(): void {
parent::setUpBeforeClass();

self::$rest_server = rest_get_server();
}

/**
* Sets up the Test class
*
Expand All @@ -55,6 +74,18 @@ public function set_up() {
*/
$this->wp_rewrite->init();
$this->wp_rewrite->set_permalink_structure( '/%postname%/' );

add_filter( 'tenup_headless_wp_should_force_drafts_to_have_permalinks', '__return_true' );
}

/**
* Tears the tests down
*
* @return void
*/
public function tear_down() {
parent::tear_down();
remove_filter( 'tenup_headless_wp_should_force_drafts_to_have_permalinks', '__return_true' );
}

/**
Expand Down Expand Up @@ -165,15 +196,15 @@ public function test_draft_posts_permalink() {

$_SERVER['HTTP_AUTHORIZATION'] = "Bearer $token";

$this->assertEquals( 'http://localhost:8889/draft-post/', get_permalink( $draft ) );
$this->assertEquals( 'http://localhost:8889/draft-post/', $this->preview->get_draft_permalink( $draft ) );

unset( $_SERVER['HTTP_AUTHORIZATION'] );

// without authorization it shouldn't modify permalink
$this->assertEquals(
"http://localhost:8889/?p=$draft->ID",
get_permalink( $draft ),
"without authorization it shouldn't modify permalink"
'',
$this->preview->get_draft_permalink( $draft ),
'without authorization it should return an empty string'
);
}

Expand Down Expand Up @@ -206,7 +237,7 @@ public function test_draft_posts_permalink_with_date() {

$_SERVER['HTTP_AUTHORIZATION'] = "Bearer $token";

$this->assertEquals( "http://localhost:8889/{$date->format('Y/m/d')}/draft-post/", get_permalink( $draft ) );
$this->assertEquals( "http://localhost:8889/{$date->format('Y/m/d')}/draft-post/", $this->preview->get_draft_permalink( $draft ) );

unset( $_SERVER['HTTP_AUTHORIZATION'] );

Expand Down Expand Up @@ -238,11 +269,15 @@ public function test_draft_pages_permalink() {

$_SERVER['HTTP_AUTHORIZATION'] = "Bearer $token";

$this->assertEquals( 'http://localhost:8889/draft-page/', get_permalink( $draft ) );
$this->assertEquals( 'http://localhost:8889/draft-page/', $this->preview->get_draft_permalink( $draft ) );

unset( $_SERVER['HTTP_AUTHORIZATION'] );

$this->assertEquals( "http://localhost:8889/?page_id=$draft->ID", get_permalink( $draft ) );
$this->assertEquals(
'',
$this->preview->get_draft_permalink( $draft ),
'without authorization it should return an empty string'
);
}

/**
Expand Down Expand Up @@ -272,10 +307,82 @@ public function test_draft_cpt_permalink() {

$_SERVER['HTTP_AUTHORIZATION'] = "Bearer $token";

$this->assertEquals( 'http://localhost:8889/book/draft-book/', get_permalink( $draft ) );
$this->assertEquals( 'http://localhost:8889/book/draft-book/', $this->preview->get_draft_permalink( $draft ) );

unset( $_SERVER['HTTP_AUTHORIZATION'] );

$this->assertEquals( "http://localhost:8889/?post_type=book&p=$draft->ID", get_permalink( $draft ) );
$this->assertEquals(
'',
$this->preview->get_draft_permalink( $draft ),
'without authorization it should return an empty string'
);
}

/**
* Tests draft cpts with custom rewrite rules are not plain permalinks
*
* @return void
*/
public function test_draft_cpt_custom_permalink() {
register_post_type( 'news', [] );
register_taxonomy_for_object_type( 'category', 'news' );

$category = $this->factory()->term->create_and_get(
[
'taxonomy' => 'category',
]
);

$draft = $this->factory()->post->create_and_get(
[
'post_title' => 'Draft new',
'post_status' => 'draft',
'post_content' => 'draf new',
'post_type' => 'news',
'post_category' => [ $category->term_id ],
]
);

add_filter(
'post_type_link',
function ( $post_link, $post ) {
if ( 'news' !== $post->post_type ) {
return $post_link;
}

$post_name = empty( $post->post_name ) ? sanitize_title( $post->post_title ) : $post->post_name;
$post_name = empty( $post_name ) ? $post->ID : $post_name;

$fallback = esc_url( home_url( sprintf( 'newsroom/%s', $post_name ) ) );

$news_types = wp_get_post_terms( $post->ID, 'category', [ 'fields' => 'slugs' ] );

if (
is_wp_error( $news_types ) ||
! is_array( $news_types ) ||
! count( $news_types ) > 0
) {
return $fallback;
}

return esc_url( home_url( sprintf( 'newsroom/%s/%s', $news_types[0], $post_name ) ) );
},
10,
2
);

// simulate a REST request
$token = PreviewToken::generate(
[
'type' => 'preview',
'post_id' => $draft->ID,
]
);

$_SERVER['HTTP_AUTHORIZATION'] = "Bearer $token";

$this->assertEquals( "http://localhost:8889/newsroom/$category->slug/draft-new", $this->preview->get_draft_permalink( $draft ) );

unset( $_SERVER['HTTP_AUTHORIZATION'] );
}
}

0 comments on commit ac7fd33

Please sign in to comment.