Skip to content

Commit 81b9df7

Browse files
authored
Merge pull request #5296 from ampproject/fix/validating-amp-unavailable-urls
Show error when attempting to validate an AMP-unavailable URL instead of forcing AMP to be available
2 parents e21a628 + 24583ad commit 81b9df7

File tree

6 files changed

+112
-30
lines changed

6 files changed

+112
-30
lines changed

includes/amp-helper-functions.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -480,16 +480,6 @@ function amp_is_available() {
480480
return false;
481481
}
482482

483-
/*
484-
* If this is a URL for validation, and validation is forced for all URLs, return true.
485-
* Normally, this would be false if the user has deselected a template,
486-
* like by unchecking 'Categories' in 'AMP Settings' > 'Supported Templates'.
487-
* But there's a flag for the WP-CLI command that sets this query var to validate all URLs.
488-
*/
489-
if ( AMP_Validation_Manager::is_theme_support_forced() ) {
490-
return true;
491-
}
492-
493483
$queried_object = get_queried_object();
494484
if ( ! $is_legacy ) {
495485
// Abort if in Transitional mode and AMP is not available for the URL.

includes/class-amp-theme-support.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,6 +1791,9 @@ public static function prepare_response( $response, $args = [] ) {
17911791
if ( is_bool( $status_code ) ) {
17921792
$status_code = 200; // Not a web server environment.
17931793
}
1794+
if ( ! headers_sent() ) {
1795+
header( 'Content-Type: application/json; charset=utf-8' );
1796+
}
17941797
return wp_json_encode(
17951798
[
17961799
'status_code' => $status_code,
@@ -1824,6 +1827,19 @@ public static function prepare_response( $response, $args = [] ) {
18241827
$response
18251828
)
18261829
) ) {
1830+
if ( AMP_Validation_Manager::$is_validate_request ) {
1831+
if ( ! headers_sent() ) {
1832+
status_header( 400 );
1833+
header( 'Content-Type: application/json; charset=utf-8' );
1834+
}
1835+
return wp_json_encode(
1836+
[
1837+
'code' => 'RENDERED_PAGE_NOT_AMP',
1838+
'message' => __( 'The requested URL did not result in an AMP page being rendered.', 'amp' ),
1839+
]
1840+
);
1841+
}
1842+
18271843
return $response;
18281844
}
18291845

includes/validation/class-amp-validation-manager.php

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
* @package AMP
66
*/
77

8-
use AmpProject\AmpWP\DevTools\BlockSources;
98
use AmpProject\AmpWP\DevTools\UserAccess;
109
use AmpProject\AmpWP\Icon;
11-
use AmpProject\AmpWP\Option;
1210
use AmpProject\AmpWP\QueryVar;
1311
use AmpProject\AmpWP\Services;
1412
use AmpProject\Attribute;
@@ -211,6 +209,7 @@ static function() {
211209

212210
add_action( 'all_admin_notices', [ __CLASS__, 'print_plugin_notice' ] );
213211
add_action( 'admin_bar_menu', [ __CLASS__, 'add_admin_bar_menu_items' ], 101 );
212+
add_action( 'wp', [ __CLASS__, 'maybe_fail_validate_request' ] );
214213
add_action( 'wp', [ __CLASS__, 'override_validation_error_statuses' ] );
215214
}
216215

@@ -244,17 +243,6 @@ public static function post_supports_validation( $post ) {
244243
);
245244
}
246245

247-
/**
248-
* Determine whether AMP theme support is forced via the amp_validate query param.
249-
*
250-
* @since 1.0
251-
*
252-
* @return bool Whether theme support forced.
253-
*/
254-
public static function is_theme_support_forced() {
255-
return self::$is_validate_request;
256-
}
257-
258246
/**
259247
* Return whether sanitization is initially accepted (by default) for newly encountered validation errors.
260248
*
@@ -428,7 +416,7 @@ public static function add_admin_bar_menu_items( $wp_admin_bar ) {
428416
/**
429417
* Override validation error statuses (when requested).
430418
*
431-
* When a query var is present along with the required nonce, override the status of the status of the invalid markup
419+
* When a query var is present along with the required nonce, override the status of the invalid markup
432420
* as requested.
433421
*
434422
* @since 1.5.0
@@ -468,6 +456,26 @@ public static function override_validation_error_statuses() {
468456
}
469457
}
470458

459+
/**
460+
* Short-circuit validation requests which are for URLs that are not AMP pages.
461+
*
462+
* @since 2.1
463+
*/
464+
public static function maybe_fail_validate_request() {
465+
if ( ! self::$is_validate_request || amp_is_request() ) {
466+
return;
467+
}
468+
469+
if ( ! amp_is_available() ) {
470+
$code = 'AMP_NOT_AVAILABLE';
471+
$message = __( 'The requested URL is not an AMP page. AMP may have been disabled for the URL. If so, you can forget the Validated URL.', 'amp' );
472+
} else {
473+
$code = 'AMP_NOT_REQUESTED';
474+
$message = __( 'The requested URL is not an AMP page.', 'amp' );
475+
}
476+
wp_send_json( compact( 'code', 'message' ), 400 );
477+
}
478+
471479
/**
472480
* Initialize a validate request.
473481
*

tests/php/test-amp-helper-functions.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -906,11 +906,6 @@ public function test_amp_is_request_and_amp_is_available() {
906906
$this->go_to( home_url( '/' ) );
907907
$this->assertFalse( amp_is_available() );
908908
$this->assertFalse( amp_is_request() );
909-
910-
// When the user passes a flag to the WP-CLI command, it forces AMP validation no matter whether the user disabled AMP on any template.
911-
AMP_Validation_Manager::$is_validate_request = true;
912-
$this->assertTrue( amp_is_available() );
913-
$this->assertTrue( amp_is_request() );
914909
}
915910

916911
/**

tests/php/test-class-amp-theme-support.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public function tearDown() {
7878

7979
parent::tearDown();
8080
unset( $GLOBALS['show_admin_bar'] );
81+
AMP_Validation_Manager::$is_validate_request = false;
8182
AMP_Validation_Manager::reset_validation_results();
8283
$this->set_template_mode( AMP_Theme_Support::READER_MODE_SLUG );
8384
remove_theme_support( 'custom-header' );
@@ -1758,6 +1759,19 @@ public function test_prepare_response_for_submitted_form() {
17581759
unset( $_SERVER['REQUEST_METHOD'] );
17591760
}
17601761

1762+
/**
1763+
* Test prepare_response when validating an invalid AMP page.
1764+
*
1765+
* @covers AMP_Theme_Support::prepare_response()
1766+
*/
1767+
public function test_prepare_response_for_validating_invalid_amp_page() {
1768+
AMP_Validation_Manager::$is_validate_request = true;
1769+
1770+
$response = AMP_Theme_Support::prepare_response( '' );
1771+
$this->assertJson( $response );
1772+
$this->assertStringContains( 'RENDERED_PAGE_NOT_AMP', $response );
1773+
}
1774+
17611775
/**
17621776
* Initializes and returns the original HTML.
17631777
*/

tests/php/validation/test-class-amp-validation-manager.php

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,66 @@ public function test_init() {
157157

158158
$this->assertEquals( 101, has_action( 'admin_bar_menu', [ self::TESTED_CLASS, 'add_admin_bar_menu_items' ] ) );
159159

160-
$this->assertFalse( has_action( 'wp', [ self::TESTED_CLASS, 'wrap_widget_callbacks' ] ) );
160+
$this->assertEquals( 10, has_action( 'wp', [ self::TESTED_CLASS, 'maybe_fail_validate_request' ] ) );
161+
$this->assertEquals( 10, has_action( 'wp', [ self::TESTED_CLASS, 'override_validation_error_statuses' ] ) );
162+
}
163+
164+
/**
165+
* Test ::maybe_fail_validate_request().
166+
*
167+
* @covers AMP_Validation_Manager::maybe_fail_validate_request()
168+
*/
169+
public function test_maybe_fail_validate_request() {
170+
$post_id = self::factory()->post->create();
171+
172+
remove_filter( 'wp', [ 'AMP_Validation_Manager', 'maybe_fail_validate_request' ] );
173+
add_filter( 'wp_doing_ajax', '__return_true' );
174+
add_filter(
175+
'wp_die_ajax_handler',
176+
static function () {
177+
return static function () {};
178+
}
179+
);
180+
181+
$get_output = static function () {
182+
ob_start();
183+
AMP_Validation_Manager::maybe_fail_validate_request();
184+
return ob_get_clean();
185+
};
186+
187+
// Verify there is no output if it is not a validation request.
188+
AMP_Validation_Manager::$is_validate_request = false;
189+
$this->assertEmpty( $get_output() );
190+
191+
// Verify there is no output if it is an AMP request.
192+
AMP_Validation_Manager::$is_validate_request = true;
193+
AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::STANDARD_MODE_SLUG );
194+
$this->go_to( get_permalink( $post_id ) );
195+
$this->assertEmpty( $get_output() );
196+
197+
// Verify correct response if not an AMP page.
198+
AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::READER_MODE_SLUG );
199+
$output = $get_output();
200+
$this->assertJson( $output );
201+
$this->assertStringContains( 'AMP_NOT_REQUESTED', $output );
202+
203+
// Verify correct response if AMP not available.
204+
AMP_Validation_Manager::$is_validate_request = true;
205+
AMP_Options_Manager::update_option( Option::THEME_SUPPORT, AMP_Theme_Support::READER_MODE_SLUG );
206+
207+
add_filter(
208+
'amp_skip_post',
209+
static function ( $skipped, $_post_id ) use ( $post_id ) {
210+
return $_post_id === $post_id;
211+
},
212+
10,
213+
2
214+
);
215+
216+
$this->go_to( amp_get_permalink( $post_id ) );
217+
$output = $get_output();
218+
$this->assertJson( $output );
219+
$this->assertStringContains( 'AMP_NOT_AVAILABLE', $output );
161220
}
162221

163222
/**

0 commit comments

Comments
 (0)