From 091b60337317a30f54d1b6ddd79aba8d0615880c Mon Sep 17 00:00:00 2001 From: John Watkins Date: Tue, 18 Feb 2020 10:06:33 -0600 Subject: [PATCH 1/4] Save autoshare meta from post form before publishing post --- includes/admin/post-meta.php | 20 ++++++++++++++------ includes/admin/post-transition.php | 4 ++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/includes/admin/post-meta.php b/includes/admin/post-meta.php index 72a3f041..468ed12d 100644 --- a/includes/admin/post-meta.php +++ b/includes/admin/post-meta.php @@ -46,19 +46,21 @@ function setup() { add_action( 'post_submitbox_misc_actions', __NAMESPACE__ . '\tweet_submitbox_callback', 15 ); add_action( 'autoshare_for_twitter_metabox', __NAMESPACE__ . '\render_tweet_submitbox', 10, 1 ); - add_action( 'save_post', __NAMESPACE__ . '\save_tweet_meta', 10, 1 ); + add_action( 'save_post', __NAMESPACE__ . '\save_tweet_meta', 10, 3 ); } /** * Handles the saving of post_meta to catch the times the ajax save might not run. * Like when clicking 'Save Draft' or 'Publish' straight from the tweet body field. * - * @param int $post_id The post id. + * @param int $post_id The post id. + * @param WP_Post $post Post object. + * @param boolean $update Whether the post already exists. * * @return void */ -function save_tweet_meta( $post_id ) { - if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_post', $post_id ) ) { +function save_tweet_meta( $post_id, $post = null, $update = true ) { + if ( ! $update || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_post', $post_id ) ) { return; } @@ -105,8 +107,14 @@ function sanitize_autoshare_for_twitter_meta_data( $data ) { * @param array $data Associative array of data to save. */ function save_autoshare_for_twitter_meta_data( $post_id, $data ) { - if ( empty( $data ) || ! is_array( $data ) ) { - return; + + if ( ! is_array( $data ) ) { + $data = []; + } + + // If the enable key is not set, it should be turned off. + if ( ! isset( $data[ ENABLE_AUTOSHARE_FOR_TWITTER_KEY ] ) ) { + $data[ ENABLE_AUTOSHARE_FOR_TWITTER_KEY ] = 0; } foreach ( $data as $key => $value ) { diff --git a/includes/admin/post-transition.php b/includes/admin/post-transition.php index 20b8301c..45af520e 100644 --- a/includes/admin/post-transition.php +++ b/includes/admin/post-transition.php @@ -12,6 +12,7 @@ use TenUp\AutoshareForTwitter\Utils as Utils; use function TenUp\AutoshareForTwitter\Utils\delete_autoshare_for_twitter_meta; use function TenUp\AutoshareForTwitter\Utils\update_autoshare_for_twitter_meta; +use function TenUp\AutoshareForTwitter\Core\Post_Meta\save_tweet_meta; /** * Setup function. @@ -46,6 +47,9 @@ function maybe_publish_tweet( $new_status, $old_status, $post ) { return; } + // Ensure Autoshare-related form data is saved before reaching the publish_tweet step. + save_tweet_meta( $post->ID ); + /** * Don't bother enqueuing assets if the post type hasn't opted into autosharing */ From 9d9a457384a818cc230ef24bab81f7adbb302cae Mon Sep 17 00:00:00 2001 From: John Watkins Date: Thu, 20 Feb 2020 09:39:19 -0600 Subject: [PATCH 2/4] Add tests --- includes/admin/post-meta.php | 22 ++- tests/phpunit/integration/TestPostMeta.php | 61 ++++++++- .../integration/TestPostTransition.php | 129 ++++++++++++++++++ 3 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 tests/phpunit/integration/TestPostTransition.php diff --git a/includes/admin/post-meta.php b/includes/admin/post-meta.php index 468ed12d..e7020149 100644 --- a/includes/admin/post-meta.php +++ b/includes/admin/post-meta.php @@ -64,14 +64,28 @@ function save_tweet_meta( $post_id, $post = null, $update = true ) { return; } - $form_data = sanitize_autoshare_for_twitter_meta_data( - // Using FILTER_DEFAULT here as data is being passed to sanitize function. - filter_input( INPUT_POST, META_PREFIX, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ) - ); + $form_data = sanitize_autoshare_for_twitter_meta_data( get_autoshare_post_form_data() ); save_autoshare_for_twitter_meta_data( $post_id, $form_data ); } +/** + * Provides data passed from the post editor form. + * + * @return array + */ +function get_autoshare_post_form_data() { + // Using FILTER_DEFAULT here as data is being passed to sanitize function. + $data = filter_input( INPUT_POST, META_PREFIX, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); + + /** + * Filters data received from the post form. + * + * @param array $data + */ + return apply_filters( 'autoshare_post_form_data', $data ); +} + /** * Sanitizes autoshare-related fields passed while saving a post. * diff --git a/tests/phpunit/integration/TestPostMeta.php b/tests/phpunit/integration/TestPostMeta.php index 185cea22..87dca3db 100644 --- a/tests/phpunit/integration/TestPostMeta.php +++ b/tests/phpunit/integration/TestPostMeta.php @@ -11,14 +11,20 @@ use WP_UnitTestCase; use const TenUp\AutoshareForTwitter\Core\Admin\AT_SETTINGS; +use const TenUp\AutoshareForTwitter\Core\Post_Meta\ENABLE_AUTOSHARE_FOR_TWITTER_KEY; +use const TenUp\AutoshareForTwitter\Core\Post_Meta\TWEET_BODY_KEY; use const TenUp\AutoshareForTwitter\Core\Post_Meta\TWITTER_STATUS_KEY; use function TenUp\AutoshareForTwitter\Core\Post_Meta\get_tweet_status_message; +use function TenUp\AutoshareForTwitter\Core\Post_Meta\save_autoshare_for_twitter_meta_data; +use function TenUp\AutoshareForTwitter\Utils\get_autoshare_for_twitter_meta; /** * TestUtils class. * * @sincd 1.0.0 + * + * @group post_meta */ class TestPostMeta extends WP_UnitTestCase { /** @@ -32,7 +38,7 @@ public function test_get_tweet_status_message() { get_tweet_status_message( -1 ) ); - $post = $this->factory->post->create( [ 'status' => 'publish' ] ); + $post = $this->factory->post->create( [ 'post_status' => 'publish' ] ); $published_filter = function( $data, $id, $key ) use ( $post ) { if ( intval( $post ) === intval( $id ) && TWITTER_STATUS_KEY === $key ) { @@ -112,4 +118,57 @@ public function test_get_tweet_status_message() { remove_filter( 'autoshare_for_twitter_meta', $other_filter ); } + /** + * Provides test data. + * + * @return array + */ + public function save_autoshare_for_twitter_meta_data_provider() { + return [ + [ + // Test autoshare is disabled when no data is passed. + [ 'post_status' => 'publish' ], + [], + false, + ], + [ + // Test autoshare is disabled when false is passed. + [ 'post_status' => 'publish' ], + [ ENABLE_AUTOSHARE_FOR_TWITTER_KEY => '0' ], + false, + ], + [ + // Test autoshare is disabled when only a tweet body is passed. + [ 'post_status' => 'publish' ], + [ TWEET_BODY_KEY => 'my cool tweet' ], + false, + ], + [ + // Test autoshare is enabled when true is passed. + [ 'post_status' => 'publish' ], + [ ENABLE_AUTOSHARE_FOR_TWITTER_KEY => '1' ], + true, + ], + ]; + } + + /** + * Tests the save_autoshare_for_twitter_meta_data function. + * + * @dataProvider save_autoshare_for_twitter_meta_data_provider + * + * @param array $args Create post args. + * @param array $data Meta data to save. + * @param boolean $expected Expecte result. + */ + public function test_save_autoshare_for_twitter_meta_data( $args, $data, $expected ) { + $id = $this->factory->post->create( $args ); + save_autoshare_for_twitter_meta_data( $id, $data ); + + if ( $expected ) { + $this->assertTrue( (bool) get_autoshare_for_twitter_meta( $id, ENABLE_AUTOSHARE_FOR_TWITTER_KEY ) ); + } else { + $this->assertFalse( (bool) get_autoshare_for_twitter_meta( $id, ENABLE_AUTOSHARE_FOR_TWITTER_KEY ) ); + } + } } diff --git a/tests/phpunit/integration/TestPostTransition.php b/tests/phpunit/integration/TestPostTransition.php new file mode 100644 index 00000000..181666f9 --- /dev/null +++ b/tests/phpunit/integration/TestPostTransition.php @@ -0,0 +1,129 @@ + 'publish' ], + '1', + 'draft', + 'publish', + false, + ], + [ + // Already-published post should not tweet. + [ 'post_status' => 'publish' ], + '1', + 'publish', + 'publish', + false, + ], + [ + // Post transitioning from draft to publish should tweet if autotweet_enabled is true. + [ + 'post_status' => 'draft', + 'post_title' => 'TEST', + 'post_author' => 1, + ], + '1', + 'publish', + 'draft', + true, + ], + [ + // Post transitioning from draft to publish should not tweet if autotweet is not true. + [ 'post_status' => 'draft' ], + '0', + 'publish', + 'draft', + false, + ], + ]; + } + + /** + * Tests the maybe_publish_tweet function. + * + * @dataProvider maybe_publish_tweet_provider + * + * @param array $post_args Args to pass to the create post function. + * @param boolean $autoshare_enabled_form_data Updated autoshare enabled meta value. + * @param string $new_status The new post status. + * @param string $old_status The old post status. + * @param boolean $expected_should_tweet Whether the post should be tweeted. + */ + public function test_maybe_publish_tweet( + $post_args, + $autoshare_enabled_form_data, + $new_status, + $old_status, + $expected_should_tweet + ) { + $the_post = $this->factory->post->create_and_get( $post_args ); + $post_was_tweeted = false; + $pre_status_update_callback = function() use ( &$post_was_tweeted ) { + $post_was_tweeted = true; + + // Minimum valid response. + return (object) [ + 'id' => 1, + 'created_at' => time(), + ]; + }; + add_filter( 'autoshare_for_twitter_pre_status_update', $pre_status_update_callback ); + + $post_form_data_callback = function() use ( $autoshare_enabled_form_data ) { + return [ ENABLE_AUTOSHARE_FOR_TWITTER_KEY => $autoshare_enabled_form_data ]; + }; + add_filter( 'autoshare_post_form_data', $post_form_data_callback ); + + maybe_publish_tweet( $new_status, $old_status, $the_post ); + + if ( $expected_should_tweet ) { + $this->assertTrue( $post_was_tweeted ); + } else { + $this->assertFalse( $post_was_tweeted ); + } + + remove_filter( 'autoshare_for_twitter_pre_status_update', $pre_status_update_callback ); + remove_filter( 'autoshare_post_form_data', $post_form_data_callback ); + } +} From 92b1a083e982547c34c01092907281147bed7fcb Mon Sep 17 00:00:00 2001 From: John Watkins Date: Thu, 20 Feb 2020 09:41:42 -0600 Subject: [PATCH 3/4] Remove unused imports --- tests/phpunit/integration/TestPostMeta.php | 1 - tests/phpunit/integration/TestPostTransition.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/phpunit/integration/TestPostMeta.php b/tests/phpunit/integration/TestPostMeta.php index 87dca3db..d6203560 100644 --- a/tests/phpunit/integration/TestPostMeta.php +++ b/tests/phpunit/integration/TestPostMeta.php @@ -10,7 +10,6 @@ use WP_UnitTestCase; -use const TenUp\AutoshareForTwitter\Core\Admin\AT_SETTINGS; use const TenUp\AutoshareForTwitter\Core\Post_Meta\ENABLE_AUTOSHARE_FOR_TWITTER_KEY; use const TenUp\AutoshareForTwitter\Core\Post_Meta\TWEET_BODY_KEY; use const TenUp\AutoshareForTwitter\Core\Post_Meta\TWITTER_STATUS_KEY; diff --git a/tests/phpunit/integration/TestPostTransition.php b/tests/phpunit/integration/TestPostTransition.php index 181666f9..44716b55 100644 --- a/tests/phpunit/integration/TestPostTransition.php +++ b/tests/phpunit/integration/TestPostTransition.php @@ -11,9 +11,7 @@ use WP_UnitTestCase; use const TenUp\AutoshareForTwitter\Core\Post_Meta\ENABLE_AUTOSHARE_FOR_TWITTER_KEY; -use const TenUp\AutoshareForTwitter\Core\Post_Meta\TWITTER_STATUS_KEY; -use function TenUp\AutoshareForTwitter\Core\Post_Meta\get_tweet_status_message; use function TenUp\AutoshareForTwitter\Core\Post_Transition\maybe_publish_tweet; /** From e7f7b6d120c1b0f6bdc6a250d33a474db99533d8 Mon Sep 17 00:00:00 2001 From: John Watkins Date: Thu, 20 Feb 2020 10:54:52 -0600 Subject: [PATCH 4/4] Small 5.0 refactor --- includes/admin/post-meta.php | 18 +++- includes/admin/post-transition.php | 13 ++- includes/rest.php | 10 +- languages/autoshare-for-twitter.pot | 130 +++++++++++++++++++++---- tests/phpunit/integration/TestRest.php | 2 +- 5 files changed, 143 insertions(+), 30 deletions(-) diff --git a/includes/admin/post-meta.php b/includes/admin/post-meta.php index e7020149..b90e4c32 100644 --- a/includes/admin/post-meta.php +++ b/includes/admin/post-meta.php @@ -60,7 +60,20 @@ function setup() { * @return void */ function save_tweet_meta( $post_id, $post = null, $update = true ) { - if ( ! $update || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_post', $post_id ) ) { + if ( ! $update ) { + return; + } + + // Meta is saved in a separate request in the block editor. + if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { + return; + } + + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { + return; + } + + if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } @@ -121,13 +134,12 @@ function sanitize_autoshare_for_twitter_meta_data( $data ) { * @param array $data Associative array of data to save. */ function save_autoshare_for_twitter_meta_data( $post_id, $data ) { - if ( ! is_array( $data ) ) { $data = []; } // If the enable key is not set, it should be turned off. - if ( ! isset( $data[ ENABLE_AUTOSHARE_FOR_TWITTER_KEY ] ) ) { + if ( ! array_key_exists( ENABLE_AUTOSHARE_FOR_TWITTER_KEY, $data ) ) { $data[ ENABLE_AUTOSHARE_FOR_TWITTER_KEY ] = 0; } diff --git a/includes/admin/post-transition.php b/includes/admin/post-transition.php index 45af520e..c458b958 100644 --- a/includes/admin/post-transition.php +++ b/includes/admin/post-transition.php @@ -47,9 +47,6 @@ function maybe_publish_tweet( $new_status, $old_status, $post ) { return; } - // Ensure Autoshare-related form data is saved before reaching the publish_tweet step. - save_tweet_meta( $post->ID ); - /** * Don't bother enqueuing assets if the post type hasn't opted into autosharing */ @@ -58,8 +55,16 @@ function maybe_publish_tweet( $new_status, $old_status, $post ) { } if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { - add_action( sprintf( 'rest_after_insert_%s', $post->post_type ), __NAMESPACE__ . '\publish_tweet' ); + add_action( + sprintf( 'rest_after_insert_%s', $post->post_type ), + function( $post ) { + publish_tweet( $post->ID ); + } + ); } else { + // Ensure Autoshare-related form data is saved before reaching the publish_tweet step. + // This will already have been done in REST because post data is updated before transition post status. + save_tweet_meta( $post->ID ); publish_tweet( $post->ID ); } } diff --git a/includes/rest.php b/includes/rest.php index e00b2518..fbef3881 100644 --- a/includes/rest.php +++ b/includes/rest.php @@ -16,7 +16,7 @@ use function TenUp\AutoshareForTwitter\Core\Post_Meta\get_tweet_status_message; use function TenUp\AutoshareForTwitter\Core\Post_Meta\save_autoshare_for_twitter_meta_data; - +use function TenUp\AutoshareForTwitter\Utils\get_autoshare_for_twitter_meta; /** * The namespace for plugin REST endpoints. @@ -122,15 +122,17 @@ function update_post_autoshare_for_twitter_meta( $request ) { $params = $request->get_params(); save_autoshare_for_twitter_meta_data( $request['id'], $params ); - $message = 1 === $params[ ENABLE_AUTOSHARE_FOR_TWITTER_KEY ] ? + + $enabled = (bool) get_autoshare_for_twitter_meta( $request['id'], ENABLE_AUTOSHARE_FOR_TWITTER_KEY, true ); + $message = $enabled ? __( 'Autoshare enabled.', 'autoshare-for-twitter' ) : __( 'Autoshare disabled.', 'autoshare-for-twitter' ); return rest_ensure_response( [ - 'enabled' => $params[ ENABLE_AUTOSHARE_FOR_TWITTER_KEY ], + 'enabled' => $enabled, 'message' => $message, - 'override' => ! empty( $params[ TWEET_BODY_KEY ] ), + 'override' => ! empty( get_autoshare_for_twitter_meta( $request['id'], TWEET_BODY_KEY, true ) ), ] ); } diff --git a/languages/autoshare-for-twitter.pot b/languages/autoshare-for-twitter.pot index c9c9e873..7b5adb99 100644 --- a/languages/autoshare-for-twitter.pot +++ b/languages/autoshare-for-twitter.pot @@ -1,40 +1,134 @@ +# Copyright (C) 2020 10up +# This file is distributed under the GPL-2.0-or-later. msgid "" msgstr "" +"Project-Id-Version: Autoshare for Twitter 1.0.1\n" +"Report-Msgid-Bugs-To: " +"https://wordpress.org/support/plugin/autoshare-for-twitter\n" +"POT-Creation-Date: 2020-02-20 16:54:31+00:00\n" +"MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" -"X-Generator: babel-plugin-makepot\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"X-Generator: node-wp-i18n 1.2.3\n" -#: src/js/AutoshareForTwitterPostStatusInfo.js:16 -msgid "View" +#: includes/admin/assets.php:168 +msgid "Error" +msgstr "" + +#: includes/admin/assets.php:173 +msgid "An unknown error occurred" msgstr "" -#: src/js/AutoshareForTwitterPrePublishPanel.js:106 -msgid "Tweet this post?" +#: includes/admin/post-meta.php:217 includes/admin/post-meta.php:270 +msgid "This post was not tweeted." msgstr "" -#: src/js/AutoshareForTwitterPrePublishPanel.js:126 -msgid "Custom message:" +#: includes/admin/post-meta.php:254 +#. Translators: Placeholder is a date. +msgid "Tweeted on %s" msgstr "" -#: src/js/AutoshareForTwitterPrePublishPanel.js:141 -msgid "Hide" +#: includes/admin/post-meta.php:260 +msgid "Failed to tweet: " msgstr "" -#: src/js/AutoshareForTwitterPrePublishPanel.js:141 +#: includes/admin/post-meta.php:294 +msgid "Tweeted on" +msgstr "" + +#: includes/admin/post-meta.php:297 +msgid "View" +msgstr "" + +#: includes/admin/post-meta.php:313 +msgid "Failed to tweet" +msgstr "" + +#: includes/admin/post-meta.php:348 +msgid "Tweet this post" +msgstr "" + +#: includes/admin/post-meta.php:349 msgid "Edit" msgstr "" -#: src/js/AutoshareForTwitterPrePublishPanel.js:63 -msgid "An error occurred." +#: includes/admin/post-meta.php:354 +msgid "Custom Message" +msgstr "" + +#: includes/admin/post-transition.php:144 +msgid "Something happened during Twitter update." +msgstr "" + +#: includes/admin/post-transition.php:180 +msgid "This post was not published to Twitter." +msgstr "" + +#. Plugin Name of the plugin/theme +msgid "Autoshare for Twitter" +msgstr "" + +#: includes/admin/settings.php:50 +msgid "Twitter Credentials" +msgstr "" + +#: includes/admin/settings.php:58 +msgid "API key" +msgstr "" + +#: includes/admin/settings.php:68 +msgid "API secret" +msgstr "" + +#: includes/admin/settings.php:78 +msgid "Access token" +msgstr "" + +#: includes/admin/settings.php:88 +msgid "Access secret" +msgstr "" + +#: includes/admin/settings.php:98 +msgid "Twitter handle" +msgstr "" + +#: includes/rest.php:67 +msgid "Unique identifier for the object." msgstr "" -#: src/js/index.js:32 -msgid "Enabled" +#: includes/rest.php:74 +msgid "Tweet text, if overriding the default" msgstr "" -#: src/js/index.js:32 -msgid "Disabled" +#: includes/rest.php:81 +msgid "Whether autoshare is enabled for the current post" msgstr "" -#: src/js/index.js:46 -msgid "Autoshare:" +#: includes/rest.php:128 +msgid "Autoshare enabled." msgstr "" + +#: includes/rest.php:129 +msgid "Autoshare disabled." +msgstr "" + +#: includes/rest.php:157 +msgid "Autoshare status message" +msgstr "" + +#. Description of the plugin/theme +msgid "" +"Automatically tweets the post title or custom message and a link to the " +"post." +msgstr "" + +#. Author of the plugin/theme +msgid "10up" +msgstr "" + +#. Author URI of the plugin/theme +msgid "https://10up.com" +msgstr "" \ No newline at end of file diff --git a/tests/phpunit/integration/TestRest.php b/tests/phpunit/integration/TestRest.php index 946633dc..1ae1d18a 100644 --- a/tests/phpunit/integration/TestRest.php +++ b/tests/phpunit/integration/TestRest.php @@ -96,7 +96,7 @@ public function test_update_post_autoshare_for_twitter_meta() { $this->assertEquals( [ 'enabled' => true, - 'message' => 'Autoshare disabled.', + 'message' => 'Autoshare enabled.', 'override' => true, ], $response->get_data()