diff --git a/external-permalinks-redux.php b/external-permalinks-redux.php index 70571546a2f81848d44b2f30849b32b43c168397..fd4eb1d3733c8837f3f6ff81a3abf9e39552e963 100644 --- a/external-permalinks-redux.php +++ b/external-permalinks-redux.php @@ -230,21 +230,43 @@ class external_permalinks_redux { return; } - $link = get_post_meta( $post->ID, $this->meta_key_target, true ); + $redirect = $this->get_redirect_data( $post->ID ); - if ( ! empty( $link ) ) { - $type = (int) get_post_meta( $post->ID, $this->meta_key_type, true ); - $type = apply_filters( 'epr_status_code', $type, $link, $post ); + if ( false === $redirect ) { + return; + } - if ( ! $type ) { - $type = 302; - } + // Unreasonable to validate redirect destination. + // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect + wp_redirect( $redirect['link'], $redirect['type'] ); + exit; + } - // Unreasonable to validate redirect destination. - // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect - wp_redirect( $link, $type ); - exit; + /** + * Retrieve redirect data for a given post ID. + * + * @param int $post_id Post ID. + * @return array|bool + */ + public function get_redirect_data( $post_id ) { + if ( ! is_numeric( $post_id ) ) { + return false; } + + $link = get_post_meta( $post_id, $this->meta_key_target, true ); + + if ( empty( $link ) ) { + return false; + } + + $type = (int) get_post_meta( $post_id, $this->meta_key_type, true ); + $type = apply_filters( 'epr_status_code', $type, $link, get_post( $post_id ) ); + + if ( ! $type ) { + $type = 302; + } + + return compact( 'link', 'type' ); } } diff --git a/tests/test-redirect-callbacks.php b/tests/test-redirect-callbacks.php new file mode 100755 index 0000000000000000000000000000000000000000..e0b914bf0698d887cba9e82c69aa383b3c3699ee --- /dev/null +++ b/tests/test-redirect-callbacks.php @@ -0,0 +1,94 @@ +<?php +/** + * Class RedirectCallbacks + * + * @package External_Permalinks_Redux + */ + +/** + * Test redirect callbacks + */ +class RedirectCallbacks extends WP_UnitTestCase { + /** + * Redirect destination. + */ + const DESTINATION = 'https://w.org/'; + + /** + * Plugin instance. + * + * @var external_permalinks_redux + */ + protected $plugin; + + /** + * Create some objects with redirects. + */ + public function setUp() { + parent::setUp(); + + $this->plugin = external_permalinks_redux::get_instance(); + } + + /** + * Helper to retrieve a clean post. + * + * @return int + */ + protected function get_new_post() { + return $this->factory->post->create( + [ + 'post_type' => 'post', + ] + ); + } + + /** + * Test post with default redirect code. + */ + public function test_post_redirect_default_status() { + $post_id = $this->get_new_post(); + update_post_meta( $post_id, $this->plugin->meta_key_target, static::DESTINATION ); + + $redirect = $this->plugin->get_redirect_data( $post_id ); + + $this->assertEquals( static::DESTINATION, $redirect['link'] ); + $this->assertEquals( 302, $redirect['type'] ); + } + + /** + * test post with custom redirect code. + */ + public function test_post_redirect_custom_status() { + $post_id = $this->get_new_post(); + update_post_meta( $post_id, $this->plugin->meta_key_target, static::DESTINATION ); + update_post_meta( $post_id, $this->plugin->meta_key_type, 307 ); + + $redirect = $this->plugin->get_redirect_data( $post_id ); + + $this->assertEquals( static::DESTINATION, $redirect['link'] ); + $this->assertEquals( 307, $redirect['type'] ); + } + + /** + * Test post with redirect type but no destination. + */ + public function test_post_redirect_missing_destination() { + $post_id = $this->get_new_post(); + update_post_meta( $post_id, $this->plugin->meta_key_type, 307 ); + + $redirect = $this->plugin->get_redirect_data( $post_id ); + + $this->assertFalse( $redirect ); + } + + /** + * Test post without redirect. + */ + public function test_post_no_redirect() { + $post_id = $this->get_new_post(); + $redirect = $this->plugin->get_redirect_data( $post_id ); + + $this->assertFalse( $redirect ); + } +}