-
Notifications
You must be signed in to change notification settings - Fork 19
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
Add REST API endpoint to replace AJAX callback #33
Conversation
@@ -3,93 +3,87 @@ | |||
* | |||
* @todo soooo much dependency :facepalm: |
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.
Most of this file's changeset is ESLint.
@@ -3,93 +3,87 @@ | |||
* | |||
* @todo soooo much dependency :facepalm: | |||
*/ | |||
(function ($) { | |||
( function( $ ) { |
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.
Intentionally not removing the jQuery dependency for this PR.
includes/admin/post-meta.php
Outdated
|
||
/** | ||
* The meta prefix that all meta related keys should have | ||
*/ | ||
const META_PREFIX = 'tenup-auto-tweet'; | ||
const META_PREFIX = 'tenup-autotweet'; |
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.
OK that this would break backward-compatibility?
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.
probably not, leave as is
This might be an issue, this is already in active use on 9to5. |
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.
Thanks for your work here @johnwatkins0! I left some feedback, let me know if you have any questions. Will also test locally.
includes/admin/assets.php
Outdated
$post_id = intval( get_the_ID() ); | ||
|
||
if ( empty( $post_id ) ) { | ||
$post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0; // phpcs:disable WordPress.Security.NonceVerification.Recommended |
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.
Can you document the reason for ignoring the nonce check here? See adamsilverstein/wp-post-meta-revisions#58 (comment) for format
assets/js/admin-auto_tweet.js
Outdated
'post_id': adminTUAT.postId, | ||
'text': $tweetText.val(), | ||
'type': event.type | ||
$.ajax( adminAutotweet.restUrl, { |
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.
should we consider changing this to wp.apiFetch
?
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.
That would be nice, but I believe for WP 4.9 we'd have to install it as an NPM dependency and bundle it with this file. Which is not a big lift at all.
Or is there another best practice for using WP5 JS packages in WP4?
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.
it is tiny so we could bundle, however wp externalizes already so we can bundle a standalone wp.apiFetch file for 4.9 (either a copy from core or we can build on the fly from the npm package which is what core/gb and site kit do).
once we include the script in the plugin, we register the script if its not already registered, then add api-fetch
as a dependency for our script. (we do this with a slew of scripts for Site Kit - https://github.com/google/site-kit-wp/blob/7d4aac9711a1174dc76acfad601c3fcd50a0baca/includes/Core/Assets/Assets.php#L627)... already registerd check: https://github.com/google/site-kit-wp/blob/develop/includes/Core/Assets/Script.php#L59
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.
Nice, thanks for the links. I'll give that a shot.
includes/admin/post-meta.php
Outdated
@@ -134,25 +60,32 @@ function save_tweet_meta( $post_id ) { | |||
// Check check. | |||
if ( | |||
! isset( $_POST['tenup_auto_tweet_meta_nonce'] ) || | |||
! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tenup_auto_tweet_meta_nonce'] ) ), 'tenup_auto_tweet_meta_fields' ) || | |||
! wp_verify_nonce( |
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.
can we drop this nonce check since the rest api is already performing a nonce check?
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 nonce check can now be removed.
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.
I have one more commit in progress -- got delayed by client work in the middle of these updates 😄
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.
👍 I will patiently await your updates!
assets/js/admin-auto_tweet.js
Outdated
$.ajax( adminAutotweet.restUrl, { | ||
beforeSend: function( xhr ) { | ||
pendingStatus(); | ||
xhr.setRequestHeader( 'X-WP-Nonce', adminAutotweet.nonce ); |
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.
if we do use wp.apiFetch
I think it handles the nonce already?
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.
Yup!
includes/rest.php
Outdated
$id = isset( $request->get_attributes()['id'] ) ? $request->get_attributes()['id'] : null; | ||
} | ||
|
||
if ( ! is_int( $id ) || 1 > $id ) { |
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.
same
includes/rest.php
Outdated
return false; | ||
} | ||
|
||
return current_user_can( 'edit_post', $id ); |
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.
sanitization is missing? in sanitize_callback cast this as an int
includes/rest.php
Outdated
function update_post_autotweet_meta( $request ) { | ||
$post_id = $request['id'] ? $request['id'] : null; | ||
|
||
if ( empty( $post_id ) ) { |
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.
move to validate_callback
includes/rest.php
Outdated
|
||
$params = $request->get_params(); | ||
|
||
$sanitized_tweet_body = trim( sanitize_text_field( wp_unslash( $params[ TWEET_BODY_KEY ] ) ) ); |
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.
sanitize the parameter in sanitize_callback
* | ||
* @sincd 1.0.0 | ||
*/ | ||
class TestRest extends WP_UnitTestCase { |
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.
Nice!
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.
Requested changes :)
Thanks, @adamsilverstein -- great feedback! I'll follow up within the next few days. |
data[adminAutotweet.enableAutotweetKey] = status; | ||
data[adminAutotweet.tweetBodyKey] = $tweetText.val(); | ||
|
||
wp.apiFetch( |
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.
excellent!
|
||
}); | ||
}; | ||
).catch( onRequestFail ); |
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.
We may want to look for errors in the then
handler as well, we should do some testing around different errors: eg network error, blocked request (rest disabled) etc. See https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
|
||
if ( empty( $post_id ) ) { | ||
$post_id = intval( | ||
filter_input( INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT ) // Filter removes all characters except digits. |
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.
nice
@adamsilverstein . I've pushed a few commits, and this is ready for another round of review. Let me know if you see anything else. Summary of recent commits:
Thank you for all your feedback! I'm looking forward to getting into Gutenberg metabox next. |
assets/js/admin-auto_tweet.js
Outdated
function onRequestFail( error ) { | ||
var errorText = ''; | ||
if ( 'statusText' in error && 'status' in error ) { | ||
errorText = adminAutotweet.errorText + ' ' + error.status + ': ' + error.statusText; |
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 can use a template literal:
errorText = adminAutotweet.errorText + ' ' + error.status + ': ' + error.statusText; | |
errorText = `${ adminAutotweet.errorText } ${ error.status }: ${ error.statusText }`; |
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.
@adamsilverstein This JS isn't transpiled -- is browser support an issue if we use a template literal? https://caniuse.com/#feat=template-literals
includes/utils.php
Outdated
/** | ||
* Updates autotweet-related post metadata by prefixing the passed key. | ||
* | ||
* @param int $id Post ID. |
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.
parameter descriptions should be aligned
includes/utils.php
Outdated
* @param int $id Post ID. | ||
* @param string $key Autotweet meta key. | ||
* @param mixed $value The meta value to save. | ||
* @return mixed meta_id if the meta doesn't exist, otherwise returns true on success and false on failure. |
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.
Capitalize "If"
This looks great @johnwatkins0 ! I left a little bit of final feedback. One thing I noticed when testing is that images are not sent with tweets - possibly because of the image I am testing with. I know this worked at some point in the past because I see images in my test tweets (https://twitter.com/adamtest110/). This was pulling from the featured image. We can address this in a follow up PR |
Thanks, @adamsilverstein . Addressed those last bits of feedback in those last two commits, and re-requesting review now. |
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.
Fantastic work @johnwatkins0 - thank you!
This is intended to resolve #14 .
It depends on #29(Merged)Description of the Change
REST endpoint
The current version of the plugin uses an AJAX handler to save the metadata that determines whether a post will be tweeted and whether the default autotweet content will be overridden.
This update removes the AJAX handler in favor of a custom REST endpoint. The endpoint is simple, accepting a POST request with three required fields (post ID, whether autotweet is enabled, and override content). Permission on the REST endpoint is set to check that the current user can edit the post. After the data is successfully saved, the REST endpoint sends back details about the data that was saved.
I also updated the JS file that handles the autotweet feature in the classic editor. It's now hooked up the REST endpoint instead of the AJAX endpoint.
Post meta updates
While setting up the REST endpoint, I did a minor refactor of some details around how post meta is handled. There was already a
get_autotweet_meta
function that wrapsget_post_meta
with a prefix on the meta key, and I created equivalents for updating and deleting meta. I also renamed some of the meta-related constants and used them in several places where the values were hardcoded. And I used the meta keys as the required parameters in the REST endpoint for clarity and consistency.**Note: ** I changed the meta prefix to use
autotweet
instead ofauto-tweet
, and changed one of the meta keys to make it more descriptive. This will break backward-compatibility if the current version of this plugin is being used anywhere. Could that be an issue? If so, I will switch it back to what it was.What this does not do
Although I modified the existing JS file to use the REST endpoint instead of AJAX -- and some ESLinting was applied to the file -- I stopped there. That JS file could easily be refactored to remove the jQuery dependency and use ES6 (via the Webpack config), but I considered that out of scope.
Alternative designs
I considered adding autotweet-related metadata as REST fields, eliminating the need for the REST endpoint. But with that approach, the autotweet data would be included in all REST responses for the supported posts, which probably isn't useful anywhere outside this plugin's narrow set of features.
Verification Process
Confirm that the integration with the classic editor still works as expected. It now runs through the REST API rather than AJAX.
Checklist: