-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle general form posts #923
Changes from 16 commits
c229cfc
e68a752
96c0bac
024d4e0
967a8c6
4b259df
ac86bf2
eca4789
1cbfff7
9c965ad
83a0799
09de420
40934c1
6dd4e9d
a9d9bfd
17ab3fd
92f3a76
1593f88
3791cd8
7a4b398
d38f03e
3b3b545
4090e4e
ee75de2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -406,17 +406,54 @@ function amp_print_schemaorg_metadata() { | |
* | ||
* @since 0.7.0 | ||
*/ | ||
function amp_prepare_comment_post() { | ||
if ( ! isset( $_GET['__amp_source_origin'] ) ) { // WPCS: CSRF ok. Beware of AMP_Theme_Support::purge_amp_query_vars(). | ||
function amp_handle_xhr_request() { | ||
global $pagenow; | ||
if ( isset( $_GET['__amp_redirect'] ) ) { // WPCS: CSRF ok. | ||
add_action( 'template_redirect', function() { | ||
// grab post data. | ||
$transint_name = wp_unslash( $_GET['__amp_redirect'] ); // WPCS: CSRF ok, input var ok. | ||
$_POST = get_transient( $transint_name ); | ||
delete_transient( $transint_name ); | ||
}, 0 ); | ||
} | ||
if ( ! isset( $_GET['__amp_source_origin'] ) || ! isset( $pagenow ) ) { // WPCS: CSRF ok. Beware of AMP_Theme_Support::purge_amp_query_vars(). | ||
return; | ||
} | ||
|
||
// Add amp comment hooks. | ||
add_filter( 'comment_post_redirect', function() { | ||
// We don't need any data, so just send a success. | ||
wp_send_json_success(); | ||
}, PHP_INT_MAX, 2 ); | ||
if ( 'wp-comments-post.php' === $pagenow ) { | ||
// This only runs on wp-comments-post.php. | ||
add_filter( 'comment_post_redirect', function() { | ||
// We don't need any data, so just send a success. | ||
wp_send_json_success(); | ||
}, PHP_INT_MAX, 2 ); | ||
amp_handle_xhr_headers_output(); | ||
} elseif ( isset( $_GET['_wp_amp_action_xhr_converted'] ) ) { // WPCS: CSRF ok. | ||
// Add amp redirect hooks. | ||
add_filter( 'wp_redirect', 'amp_intercept_post_request_redirect', PHP_INT_MAX, 2 ); | ||
add_action( 'template_redirect', function() { | ||
// grab post data. | ||
$transient_name = uniqid(); | ||
set_transient( $transient_name, wp_unslash( $_POST ), 60 ); // WPCS: CSRF ok, input var ok. | ||
|
||
/* | ||
* Buffering starts here, so unlikely the form has a redirect, | ||
* so force a redirect to the same page. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is clever, but I'm worried it could have unintended results. In particular, when a form submission does not do a redirect after a <form method="post">
<?php if ( ! empty( $_POST ) ) : ?>
Submission successful!
<pre><?php echo esc_html( wp_json_encode( wp_unslash( $_POST ) ) ); ?></pre>
<?php else : ?>
<input name="data"><button>Submit</button>
<?php endif; ?>
</form> Something like this will break if we do the redirect here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @westonruter this is somewhat a hack and will probably have side effects see a9d9bfd |
||
*/ | ||
$location = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); // WPCS: CSRF ok, input var ok. | ||
$location = add_query_arg( '__amp_redirect', $transient_name, $location ); | ||
amp_intercept_post_request_redirect( $location ); | ||
}, 0 ); | ||
amp_handle_xhr_headers_output(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Handle the AMP XHR headers and output errors. | ||
* | ||
* @since 0.7.0 | ||
*/ | ||
function amp_handle_xhr_headers_output() { | ||
// Add die handler for AMP error display. | ||
add_filter( 'wp_die_handler', function() { | ||
/** | ||
|
@@ -438,3 +475,20 @@ function amp_prepare_comment_post() { | |
$origin = esc_url_raw( wp_unslash( $_GET['__amp_source_origin'] ) ); // WPCS: CSRF ok. | ||
header( 'AMP-Access-Control-Allow-Source-Origin: ' . $origin, true ); | ||
} | ||
|
||
/** | ||
* Handle a general, non comment AMP XHR post. | ||
* | ||
* @since 0.7.0 | ||
* @param string $location The location to redirect to. | ||
*/ | ||
function amp_intercept_post_request_redirect( $location ) { | ||
$host = wp_parse_url( $location, PHP_URL_HOST ); | ||
if ( is_null( $host ) ) { | ||
$location = home_url( $location ); | ||
} | ||
header( 'AMP-Redirect-To: ' . $location ); | ||
header( 'Access-Control-Expose-Headers: AMP-Redirect-To;' ); | ||
// Send json success as no data is required. | ||
wp_send_json_success(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,11 @@ public function sanitize() { | |
} elseif ( 'post' === $method ) { | ||
$node->removeAttribute( 'action' ); | ||
if ( ! $xhr_action ) { | ||
// record that action was converted tp action-xhr. | ||
$action_url = add_query_arg( '_wp_amp_action_xhr_converted', 1, $action_url ); | ||
$node->setAttribute( 'action-xhr', $action_url ); | ||
// Append error handler if not found. | ||
$this->error_handler( $node ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very nice. |
||
} elseif ( 'http://' === substr( $xhr_action, 0, 7 ) ) { | ||
$node->setAttribute( 'action-xhr', substr( $xhr_action, 5 ) ); | ||
} | ||
|
@@ -108,4 +112,43 @@ public function sanitize() { | |
} | ||
} | ||
} | ||
|
||
/** | ||
* Checks if the form has an error handler else create one if not. | ||
* | ||
* @link https://www.ampproject.org/docs/reference/components/amp-form#success/error-response-rendering | ||
* @since 0.7 | ||
* @param DOMElement $node The form node to check. | ||
*/ | ||
public function error_handler( $node ) { | ||
$templates = $node->getElementsByTagName( 'template' ); | ||
if ( $templates->length ) { | ||
for ( $i = $templates->length - 1; $i >= 0; $i-- ) { | ||
if ( $templates->item( $i )->parentNode->hasAttribute( 'submit-error' ) ) { | ||
return; // Found error template, do nothing. | ||
} | ||
} | ||
} | ||
$node->appendChild( $this->create_error_template() ); | ||
} | ||
|
||
/** | ||
* Creates a error handler element node. | ||
* | ||
* @link https://www.ampproject.org/docs/reference/components/amp-form#success/error-response-rendering | ||
* @since 0.7 | ||
* | ||
* @return DOMElement The div[submit-error] element. | ||
*/ | ||
public function create_error_template() { | ||
$node = $this->dom->createElement( 'div' ); | ||
$template = $this->dom->createElement( 'template' ); | ||
$mustache = $this->dom->createTextNode( '{{{error}}}' ); | ||
$node->setAttribute( 'submit-error', '' ); | ||
$template->setAttribute( 'type', 'amp-mustache' ); | ||
$template->appendChild( $mustache ); | ||
$node->appendChild( $template ); | ||
|
||
return $node; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is clever, but I do fear it could lead to unexpected results like you said. So I think for now we should omit it and instead revisit it later if we find that it is a common problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@westonruter Ye I thought so to. I was going to just remove it, but wanted to see if I could at least make your example work. It's better not being there for now.