diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 09ee3b5a..ec6043bc 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -66,10 +66,10 @@ jobs: - name: Test run: npm run cypress:run env: - CYPRESS_TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }} - CYPRESS_TWITTER_API_SECRET: ${{ secrets.TWITTER_API_SECRET }} - CYPRESS_TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} - CYPRESS_TWITTER_ACCESS_SECRET: ${{ secrets.TWITTER_ACCESS_SECRET }} + CYPRESS_TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY_V2 }} + CYPRESS_TWITTER_API_SECRET: ${{ secrets.TWITTER_API_SECRET_V2 }} + CYPRESS_TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN_V2 }} + CYPRESS_TWITTER_ACCESS_SECRET: ${{ secrets.TWITTER_ACCESS_SECRET_V2 }} - name: Upload artifacts uses: actions/upload-artifact@v2 diff --git a/.wordpress-org/screenshot-1.png b/.wordpress-org/screenshot-1.png index 06ee489a..ecda3116 100644 Binary files a/.wordpress-org/screenshot-1.png and b/.wordpress-org/screenshot-1.png differ diff --git a/.wordpress-org/screenshot-2.png b/.wordpress-org/screenshot-2.png index ecda3116..e28a5636 100644 Binary files a/.wordpress-org/screenshot-2.png and b/.wordpress-org/screenshot-2.png differ diff --git a/.wordpress-org/screenshot-3.gif b/.wordpress-org/screenshot-3.gif new file mode 100644 index 00000000..3ac28044 Binary files /dev/null and b/.wordpress-org/screenshot-3.gif differ diff --git a/.wordpress-org/screenshot-3.png b/.wordpress-org/screenshot-3.png deleted file mode 100644 index e28a5636..00000000 Binary files a/.wordpress-org/screenshot-3.png and /dev/null differ diff --git a/.wordpress-org/screenshot-4.png b/.wordpress-org/screenshot-4.png new file mode 100644 index 00000000..06ee489a Binary files /dev/null and b/.wordpress-org/screenshot-4.png differ diff --git a/CHANGELOG.md b/CHANGELOG.md index d7d86429..deea3aed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] - TBD -## [1.3.0] - 2023-01-19 +## [2.0.0] - 2023-05-16 +**Autoshare for Twitter 2.0.0 utilizes [Twitter's v2 API](https://developer.twitter.com/en/products/twitter-api). If you have not already done so, please [migrate your app](https://developer.twitter.com/en/portal/projects-and-apps) to Twitter's v2 API to continue using Autoshare for Twitter. [Learn more about migrating here](https://developer.twitter.com/en/docs/twitter-api/migrate/ready-to-migrate).** + +### Added +- Migrated to Twitter API v2 (props [@iamdharmesh](https://github.com/iamdharmesh), [@jeffpaul](https://github.com/jeffpaul), [@ravinderk](https://github.com/ravinderk), [@Sidsector9](https://github.com/Sidsector9) via [#229](https://github.com/10up/autoshare-for-twitter/pull/229)). + +### Changed +- Bump WordPress "tested up to" version 6.2 (props [@Sidsector9](https://github.com/Sidsector9), [@iamdharmesh](https://github.com/iamdharmesh) via [#228](https://github.com/10up/autoshare-for-twitter/pull/228)). +- Update plugin settings and guidelines to set up a Twitter app (props [@iamdharmesh](https://github.com/iamdharmesh), [@jeffpaul](https://github.com/jeffpaul), [@ravinderk](https://github.com/ravinderk) [@Sidsector9](https://github.com/Sidsector9) via [#229](https://github.com/10up/autoshare-for-twitter/pull/229)). +- Updated documentation (props [@jeffpaul](https://github.com/jeffpaul), [@iamdharmesh](https://github.com/iamdharmesh) via [#231](https://github.com/10up/autoshare-for-twitter/pull/231)). + +### Security +- Bump `simple-git` from 3.15.1 to 3.16.0 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#221](https://github.com/10up/autoshare-for-twitter/pull/221)). +- Bump `http-cache-semantics` from 4.1.0 to 4.1.1 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#222](https://github.com/10up/autoshare-for-twitter/pull/222)). +- Bump `@sideway/formula` from 3.0.0 to 3.0.1 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#223](https://github.com/10up/autoshare-for-twitter/pull/223)). +- Bump `webpack` from 5.74.0 to 5.76.0 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#224](https://github.com/10up/autoshare-for-twitter/pull/224)). + +## [1.3.0] - 2023-01-20 ### Added - "Tweet now" functionality (props [@Sidsector9](https://github.com/Sidsector9), [@iamdharmesh](https://github.com/iamdharmesh), [@cadic](https://github.com/cadic), [@jeffpaul](https://github.com/jeffpaul), [@linawiezkowiak](https://github.com/linawiezkowiak), [@oszkarnagy](https://github.com/oszkarnagy) via [#188](https://github.com/10up/autoshare-for-twitter/pull/188)). - Toggle for adding/removing featured image from the tweet (props [@Sidsector9](https://github.com/Sidsector9), [@iamdharmesh](https://github.com/iamdharmesh), [@cadic](https://github.com/cadic), [@jeffpaul](https://github.com/jeffpaul), [@linawiezkowiak](https://github.com/linawiezkowiak), [@oszkarnagy](https://github.com/oszkarnagy) via [#188](https://github.com/10up/autoshare-for-twitter/pull/188)). @@ -180,6 +197,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Initial closed source release (props [@scottlee](https://github.com/scottlee/)). [Unreleased]: https://github.com/10up/autoshare-for-twitter/compare/trunk...develop +[2.0.0]: https://github.com/10up/autoshare-for-twitter/compare/1.3.0...2.0.0 [1.3.0]: https://github.com/10up/autoshare-for-twitter/compare/1.2.1...1.3.0 [1.2.1]: https://github.com/10up/autoshare-for-twitter/compare/1.2.0...1.2.1 [1.2.0]: https://github.com/10up/autoshare-for-twitter/compare/1.1.2...1.2.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d7a60fd..ff5075e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,11 +34,12 @@ The develop branch is the development branch which means it contains the next ve 4. Props: update `CREDITS.md` file with any new contributors, confirm maintainers are accurate. 5. New files: Check to be sure any new files/paths that are unnecessary in the production version are included in `.distignore`. 6. Readme updates: Make any other readme changes as necessary. `README.md` is geared toward GitHub and `readme.txt` contains WordPress.org-specific content. The two are slightly different. -7. Merge: Make a non-fast-forward merge from your release branch to `develop` (or merge the pull request), then do the same for `develop` into `trunk` (`git checkout trunk && git merge --no-ff develop`). `trunk` contains the stable development version. +7. Merge: Make a non-fast-forward merge from your release branch to `develop` (or merge the pull request), then do the same for `develop` into `trunk`, ensuring you pull the most recent changes into `develop` first (`git checkout develop && git pull origin develop && git checkout trunk && git merge --no-ff develop`). `trunk` contains the stable development version. 8. Push: Push your `trunk` branch to GitHub (e.g. `git push origin trunk`). -9. Test the pre-release ZIP locally by downloading it from the **Build release zip** action artifact to ensure the plugin doesn't break after release. -10. Release: Create a [new release](https://github.com/10up/autoshare-for-twitter/releases/new), naming the tag and the release with the new version number, and targeting the `trunk` branch. Paste the changelog from `CHANGELOG.md` into the body of the release and include a link to the [closed issues on the milestone](https://github.com/10up/autoshare-for-twitter/milestone/#?closed=1). -11. SVN: Wait for the [GitHub Action](https://github.com/10up/autoshare-for-twitter/actions/workflows/deploy-to-wpdotorg.yml) to finish deploying to the WordPress.org repository. If all goes well, users with SVN commit access for that plugin will receive an emailed diff of changes. -12. Check WordPress.org: Ensure that the changes are live on https://wordpress.org/plugins/autoshare-for-twitter/. This may take a few minutes. -13. Close the milestone: Edit the [milestone](https://github.com/10up/autoshare-for-twitter/milestone/#) with release date (in the `Due date (optional)` field) and link to GitHub release (in the `Description` field), then close the milestone. -14. Punt incomplete items: If any open issues or PRs which were milestoned for `X.Y.Z` do not make it into the release, update their milestone to `X+1.0.0`, `X.Y+1.0`, `X.Y.Z+1`, or `Future Release` +9. [Compare](https://github.com/10up/autoshare-for-twitter/compare/trunk...develop) `trunk` to `develop` to ensure no additional changes were missed. +10. Test the pre-release ZIP locally by [downloading](https://github.com/10up/autoshare-for-twitter/actions/workflows/build-release-zip.yml) it from the Build release zip action artifact and installing it locally. Ensure this zip has all the files we expect, that it installs and activates correctly and that all basic functionality is working. +11. Release: Create a [new release](https://github.com/10up/autoshare-for-twitter/releases/new), naming the tag and the release with the new version number, and targeting the `trunk` branch. Paste the changelog from `CHANGELOG.md` into the body of the release and include a link to the [closed issues on the milestone](https://github.com/10up/autoshare-for-twitter/milestone/#?closed=1). +12. SVN: Wait for the [GitHub Action](https://github.com/10up/autoshare-for-twitter/actions/workflows/deploy-to-wpdotorg.yml) to finish deploying to the WordPress.org repository. If all goes well, users with SVN commit access for that plugin will receive an emailed diff of changes. +13. Check WordPress.org: Ensure that the changes are live on [WordPress.org](https://wordpress.org/plugins/autoshare-for-twitter/). This may take a few minutes. +14. Close the milestone: Edit the [milestone](https://github.com/10up/autoshare-for-twitter/milestone/#) with release date (in the `Due date (optional)` field) and link to GitHub release (in the `Description` field), then close the milestone. +15. Punt incomplete items: If any open issues or PRs which were milestoned for `X.Y.Z` do not make it into the release, update their milestone to `X+1.0.0`, `X.Y+1.0`, `X.Y.Z+1`, or `Future Release` diff --git a/README.md b/README.md index 10af0ffa..aa41b66e 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,54 @@ ## Overview +Autoshare for Twitter automatically tweets your posts as soon as they’re published. Once you hit the Publish button, the plugin sends your post’s title, featured image, and link to Twitter, along with a custom message. + +| Create post screen with Autoshare for Twitter options | Published post screen with Autoshare for Twitter options. | +| -------------- | ---------------- | +| [![Create post screen with Autoshare for Twitter options](.wordpress-org/screenshot-1.png)](.wordpress-org/screenshot-1.png) | [![Published post screen with Autoshare for Twitter options.](.wordpress-org/screenshot-2.png)](.wordpress-org/screenshot-2.png) | + +Unlike a myriad of other social media, multitool solutions, Autoshare for Twitter is built solely for Twitter. It focuses on doing one thing and does it well, with the code and interface craftsmanship we apply to every project. + +With Autoshare for Twitter, developers can further customize nearly everything about the tweets, including the image, author, and link, using an extensive set of hooks built into the code. Among its other features, the WordPress plugin: + +* Works in both the classic and new block editors. +* Becomes part of the pre-publish checklist step that’s part of the new block editor. +* Posts a high-quality featured image with your tweet. +* Counts characters to keep you under the tweet limit. +* Adds a link to the tweet in the block editor sidebar. + +| Autoshare For Twitter block editor sidebar panel | Autoshare for Twitter Settings, found under `Settings` > `Autoshare for Twitter`. | +| --------------- | --------------- | +|[![Autoshare For Twitter block editor sidebar panel](.wordpress-org/screenshot-3.gif)](.wordpress-org/screenshot-3.gif) | [![Autoshare for Twitter Settings, found under `Settings` > `Autoshare for Twitter`.](.wordpress-org/screenshot-4.png)](.wordpress-org/screenshot-4.png)| + **Disclaimer:** _TWITTER, TWEET, RETWEET and the Twitter logo are trademarks of Twitter, Inc. or its affiliates._ +## Requirements + +- PHP 7.4+ +- [WordPress](http://wordpress.org) 5.7+ + +## Installation + +1. Install the plugin via the plugin installer, either by searching for it or uploading a .ZIP file. +2. Activate the plugin. +3. Save Twitter connection settings, found under `Settings` > `Autoshare for Twitter`. + +## Plugin Compatibility + +### Distributor + +When using with 10up's [Distributor plugin](https://github.com/10up/distributor), posts that are distributed will not be autoshared if they are already tweeted from the origin site. Autoshare for Twitter tracks posts that have been tweeted in post meta to avoid "double tweeting". To avoid this behavior, use the `dt_blacklisted_meta` filter to exclude the 'autoshare_for_twitter_status' meta value from being distributed : + +```php +add_filter( 'dt_blacklisted_meta', function( $blacklisted_metas ) { + $blacklisted_metas[] = 'autoshare_for_twitter_status'; + return $blacklisted_metas; +} ) +``` + +## Developers + **Note:** Posts and pages are supported by default. Developers can use the `autoshare_for_twitter_default_post_types` filter to change the default supported post types (for more, see #25). The plugin namespace changed to just 'autoshare' as of version 1.0.0. Custom post types can now be opted into autoshare features like so: @@ -41,38 +87,6 @@ function enable_autoshare_by_default_for_core_post_type( $enabled, $post_type ) add_filter( 'autoshare_for_twitter_enabled_default', 'enable_autoshare_by_default_for_core_post_type', 10, 2 ); ``` -## Plugin Compatibility - -### Distributor - -When using with 10up's [Distributor plugin](https://github.com/10up/distributor), posts that are distributed will not be autoshared if they are already tweeted from the origin site. Autoshare for Twitter tracks posts that have been tweeted in post meta to avoid "double tweeting". To avoid this behavior, use the `dt_blacklisted_meta` filter to exclude the 'autoshare_for_twitter_status' meta value from being distributed : - -```php -add_filter( 'dt_blacklisted_meta', function( $blacklisted_metas ) { - $blacklisted_metas[] = 'autoshare_for_twitter_status'; - return $blacklisted_metas; -} ) -``` - -| Autoshare for Twitter Settings, found under `Settings` > `Autoshare for Twitter`. | -| --------------- | -|[![Autoshare for Twitter Settings, found under `Settings` > `Autoshare for Twitter`.](.wordpress-org/screenshot-1.png)](.wordpress-org/screenshot-1.png)| - -| Create post screen with Autoshare for Twitter options | Published post screen with Autoshare for Twitter options. | -| -------------- | ---------------- | -| [![Create post screen with Autoshare for Twitter options](.wordpress-org/screenshot-2.png)](.wordpress-org/screenshot-2.png) | [![Published post screen with Autoshare for Twitter options.](.wordpress-org/screenshot-3.png)](.wordpress-org/screenshot-3.png) | - -## Requirements - -- PHP 7.4+ -- [WordPress](http://wordpress.org) 5.7+ - -## Installation - -1. Install the plugin via the plugin installer, either by searching for it or uploading a .ZIP file. -2. Activate the plugin. -3. Save Twitter connection settings, found under `Settings` > `Autoshare for Twitter`. - ## FAQs ### Does this plugin work with Gutenberg? diff --git a/assets/js/admin-autoshare-for-twitter-classic-editor.js b/assets/js/admin-autoshare-for-twitter-classic-editor.js new file mode 100644 index 00000000..473f6da0 --- /dev/null +++ b/assets/js/admin-autoshare-for-twitter-classic-editor.js @@ -0,0 +1,246 @@ +/** + * Handles the Autoshare JS. + * + * @todo soooo much dependency :facepalm: + */ +(function($) { + 'use strict'; + + var $tweetPost = $('#autoshare-for-twitter-enable'), + $icon = $('#autoshare-for-twitter-icon'), + $tweetText = $('#autoshare-for-twitter-text'), + $editLink = $('#autoshare-for-twitter-edit'), + $editBody = $('#autoshare-for-twitter-override-body'), + $hideLink = $('.cancel-tweet-text'), + $allowTweetImage = $('#autoshare-for-twitter-tweet-allow-image'), + errorMessageContainer = document.getElementById('autoshare-for-twitter-error-message'), + counterWrap = document.getElementById('autoshare-for-twitter-counter-wrap'), + allowTweetImageWrap = $('.autoshare-for-twitter-tweet-allow-image-wrap'), + limit = 280; + const { __, sprintf } = wp.i18n; + + // Add enabled class if checked + if ($tweetPost.prop('checked')) { + $icon.addClass('enabled'); + } + + // Event handlers. + $tweetPost.on('click', handleRequest); + $tweetText.change(handleRequest); + $tweetPost.change(toggleAllowImageVisibility); + $allowTweetImage.change(handleRequest); + $editLink.on('click', function() { + $editBody.slideToggle(); + updateRemainingField(); + $(this).hide(); + }); + $tweetText.on('keyup', function() { + updateRemainingField(); + }); + $hideLink.on('click', function(e) { + e.preventDefault(); + $('#autoshare-for-twitter-override-body').slideToggle(); + $editLink.show(); + }); + + // Runs on page load to auto-enable posts to be tweeted + window.onload = function(event) { + if ('' === adminAutoshareForTwitter.currentStatus) { + handleRequest(event, true); + } + updateRemainingField(); + }; + + /** + * Callback for failed requests. + */ + function onRequestFail(error) { + var errorText = ''; + if ('statusText' in error && 'status' in error) { + errorText = `${adminAutoshareForTwitter.errorText} ${error.status}: ${error.statusText}`; + } else { + errorText = adminAutoshareForTwitter.unkonwnErrorText; + } + + errorMessageContainer.innerText = errorText; + + $icon.removeClass('pending'); + $tweetPost.prop('checked', false); + $('#submit').attr('disabled', true); + } + + /** + * AJAX handler + * @param event + */ + function handleRequest(event, status = $tweetPost.prop('checked')) { + var data = {}; + data[adminAutoshareForTwitter.enableAutoshareKey] = status; + data[adminAutoshareForTwitter.tweetBodyKey] = $tweetText.val(); + data[adminAutoshareForTwitter.allowTweetImageKey] = $allowTweetImage.prop('checked'); + $('#submit').attr('disabled', true); + + wp.apiFetch({ + url: adminAutoshareForTwitter.restUrl, + data: data, + method: 'POST', + parse: false, // We'll check the response for errors. + }) + .then(function(response) { + if (!response.ok) { + throw response; + } + + return response.json(); + }) + .then(function(data) { + errorMessageContainer.innerText = ''; + + $icon.removeClass('pending'); + if (data.enabled) { + $icon.removeClass('disabled'); + $icon.addClass('enabled'); + $tweetPost.prop('checked', true); + } else { + $icon.removeClass('enabled'); + $icon.addClass('disabled'); + $tweetPost.prop('checked', false); + } + + if (data.allowImage) { + $allowTweetImage.prop('checked', true); + } else { + $allowTweetImage.prop('checked', false); + } + + $('#submit').attr('disabled', false); + }) + .catch(onRequestFail); + } + + /** + * Updates the counter + */ + function updateRemainingField() { + let permalinkLength = 0; + if ( $('#sample-permalink').length ) { + permalinkLength = $('#sample-permalink').text().length + } + // +5 because of the space between body and URL and the ellipsis. + permalinkLength += 5; + + var count = $tweetText.val().length + permalinkLength; + $tweetText.attr('maxlength', limit - permalinkLength); + + $(counterWrap).text(count); + + // Toggle the .over-limit class. + if (limit <= count) { + counterWrap.classList.remove('near-limit'); + counterWrap.classList.add('over-limit'); + /* translators: %d is tweet message character count */ + $(counterWrap).text( sprintf( __( '%d - Too Long!', 'autoshare-for-twitter' ), count ) ); + } else if (240 <= count) { + counterWrap.classList.remove('over-limit'); + counterWrap.classList.add('near-limit'); + /* translators: %d is tweet message character count */ + $(counterWrap).text( sprintf( __( '%d - Getting Long!', 'autoshare-for-twitter' ), count ) ); + } else { + counterWrap.classList.remove('near-limit'); + counterWrap.classList.remove('over-limit'); + } + } + + // Update the counter when the permalink is changed. + $( '#titlediv' ).on( 'focus', '.edit-slug', function() { + updateRemainingField(); + }); + + /** + * Helper for toggling classes to indicate something is happening. + */ + function pendingStatus() { + $icon.toggleClass('pending'); + $icon.removeClass('enabled'); + $icon.removeClass('disabled'); + } + + // Show/Hide "Use featured image in Tweet" checkbox. + if ( allowTweetImageWrap && wp.media.featuredImage ) { + toggleAllowImageVisibility(); + // Listen event for add/remove featured image. + wp.media.featuredImage.frame().on( 'select', toggleAllowImageVisibility ); + $('#postimagediv').on( 'click', '#remove-post-thumbnail', toggleAllowImageVisibility ); + } + + /** + * Show/Hide "Use featured image in Tweet" checkbox. + */ + function toggleAllowImageVisibility( event ) { + let hasMedia = wp.media.featuredImage.get(); + // Handle remove post thumbnail click + if( event && event.target && 'remove-post-thumbnail' === event.target.id && 'click' === event.type ) { + hasMedia = -1; + } + + const tweetNow = $('#tweet_now').length; + const autoshareEnabled = $tweetPost.prop('checked'); + // Autoshare is enabled and post has featured image. + if ( hasMedia > 0 && ( autoshareEnabled || tweetNow ) ) { + allowTweetImageWrap.show(); + } else { + allowTweetImageWrap.hide(); + } + } + + // Tweet Now functionality. + $('#tweet_now').on('click', function() { + $("#autoshare-for-twitter-error-message").html(''); + $(this).addClass("disabled"); + $(".autoshare-for-twitter-tweet-now-wrapper span.spinner").addClass("is-active"); + + const postId = $("#post_ID").val(); + const body = new FormData(); + body.append( 'action', adminAutoshareForTwitter.retweetAction ); + body.append( 'nonce', adminAutoshareForTwitter.nonce ); + body.append( 'post_id', postId ); + body.append( 'is_classic', 1 ); + + // Send request to Tweet now. + fetch( ajaxurl, { + method: 'POST', + body, + } ) + .then((response) => response.json()) + .then((response) => { + if ( + response && response.data && + ( ( response.success && response.data.message ) || ( false === response.success && false === response.data.is_retweeted) ) + ) { + $('.autoshare-for-twitter-status-logs-wrapper').html(response.data.message); + } else { + $("#autoshare-for-twitter-error-message").html(adminAutoshareForTwitter.unknownErrorText); + } + }) + .catch((error) => { + if(error.message){ + $("#autoshare-for-twitter-error-message").html(error.message); + } else { + $("#autoshare-for-twitter-error-message").html(adminAutoshareForTwitter.unknownErrorText); + } + }) + .finally(() => { + $(this).removeClass("disabled"); + $(".autoshare-for-twitter-tweet-now-wrapper span.spinner").removeClass("is-active"); + }); + }); + + // Toggle Tweet Now panel + jQuery("#autoshare_for_twitter_metabox .tweet-now-button").on("click", function(e){ + e.preventDefault(); + $editBody.show(); + jQuery(this).find('span').toggleClass('dashicons-arrow-up-alt2'); + jQuery(".autoshare-for-twitter-tweet-now-wrapper").slideToggle(); + }); + +})(jQuery); diff --git a/assets/js/admin-autoshare-for-twitter.js b/assets/js/admin-autoshare-for-twitter.js index cf38e319..c7718511 100644 --- a/assets/js/admin-autoshare-for-twitter.js +++ b/assets/js/admin-autoshare-for-twitter.js @@ -1,245 +1,14 @@ -/** - * Handles the Autoshare JS. - * - * @todo soooo much dependency :facepalm: - */ (function($) { 'use strict'; - var $tweetPost = $('#autoshare-for-twitter-enable'), - $icon = $('#autoshare-for-twitter-icon'), - $tweetText = $('#autoshare-for-twitter-text'), - $editLink = $('#autoshare-for-twitter-edit'), - $editBody = $('#autoshare-for-twitter-override-body'), - $hideLink = $('.cancel-tweet-text'), - $allowTweetImage = $('#autoshare-for-twitter-tweet-allow-image'), - errorMessageContainer = document.getElementById('autoshare-for-twitter-error-message'), - counterWrap = document.getElementById('autoshare-for-twitter-counter-wrap'), - allowTweetImageWrap = $('.autoshare-for-twitter-tweet-allow-image-wrap'), - limit = 280; - const { __, sprintf } = wp.i18n; - - // Add enabled class if checked - if ($tweetPost.prop('checked')) { - $icon.addClass('enabled'); - } - - // Event handlers. - $tweetPost.on('click', handleRequest); - $tweetText.change(handleRequest); - $tweetPost.change(toggleAllowImageVisibility); - $allowTweetImage.change(handleRequest); - $editLink.on('click', function() { - $editBody.slideToggle(); - updateRemainingField(); - $(this).hide(); - }); - $tweetText.on('keyup', function() { - updateRemainingField(); - }); - $hideLink.on('click', function(e) { - e.preventDefault(); - $('#autoshare-for-twitter-override-body').slideToggle(); - $editLink.show(); - }); - - // Runs on page load to auto-enable posts to be tweeted - window.onload = function(event) { - if ('' === adminAutoshareForTwitter.currentStatus) { - handleRequest(event, true); - } - updateRemainingField(); - }; - - /** - * Callback for failed requests. - */ - function onRequestFail(error) { - var errorText = ''; - if ('statusText' in error && 'status' in error) { - errorText = `${adminAutoshareForTwitter.errorText} ${error.status}: ${error.statusText}`; - } else { - errorText = adminAutoshareForTwitter.unkonwnErrorText; - } - - errorMessageContainer.innerText = errorText; - - $icon.removeClass('pending'); - $tweetPost.prop('checked', false); - $('#submit').attr('disabled', true); - } - - /** - * AJAX handler - * @param event - */ - function handleRequest(event, status = $tweetPost.prop('checked')) { - var data = {}; - data[adminAutoshareForTwitter.enableAutoshareKey] = status; - data[adminAutoshareForTwitter.tweetBodyKey] = $tweetText.val(); - data[adminAutoshareForTwitter.allowTweetImageKey] = $allowTweetImage.prop('checked'); - $('#submit').attr('disabled', true); - - wp.apiFetch({ - url: adminAutoshareForTwitter.restUrl, - data: data, - method: 'POST', - parse: false, // We'll check the response for errors. - }) - .then(function(response) { - if (!response.ok) { - throw response; - } - - return response.json(); - }) - .then(function(data) { - errorMessageContainer.innerText = ''; - - $icon.removeClass('pending'); - if (data.enabled) { - $icon.removeClass('disabled'); - $icon.addClass('enabled'); - $tweetPost.prop('checked', true); - } else { - $icon.removeClass('enabled'); - $icon.addClass('disabled'); - $tweetPost.prop('checked', false); - } - - if (data.allowImage) { - $allowTweetImage.prop('checked', true); - } else { - $allowTweetImage.prop('checked', false); - } - - $('#submit').attr('disabled', false); - }) - .catch(onRequestFail); - } - - /** - * Updates the counter - */ - function updateRemainingField() { - let permalinkLength = 0; - if ( $('#sample-permalink').length ) { - permalinkLength = $('#sample-permalink').text().length - } - // +5 because of the space between body and URL and the ellipsis. - permalinkLength += 5; - - var count = $tweetText.val().length + permalinkLength; - $tweetText.attr('maxlength', limit - permalinkLength); - - $(counterWrap).text(count); - - // Toggle the .over-limit class. - if (limit <= count) { - counterWrap.classList.remove('near-limit'); - counterWrap.classList.add('over-limit'); - /* translators: %d is tweet message character count */ - $(counterWrap).text( sprintf( __( '%d - Too Long!', 'autoshare-for-twitter' ), count ) ); - } else if (240 <= count) { - counterWrap.classList.remove('over-limit'); - counterWrap.classList.add('near-limit'); - /* translators: %d is tweet message character count */ - $(counterWrap).text( sprintf( __( '%d - Getting Long!', 'autoshare-for-twitter' ), count ) ); - } else { - counterWrap.classList.remove('near-limit'); - counterWrap.classList.remove('over-limit'); - } - } - - // Update the counter when the permalink is changed. - $( '#titlediv' ).on( 'focus', '.edit-slug', function() { - updateRemainingField(); - }); - - /** - * Helper for toggling classes to indicate something is happening. - */ - function pendingStatus() { - $icon.toggleClass('pending'); - $icon.removeClass('enabled'); - $icon.removeClass('disabled'); - } - - // Show/Hide "Use featured image in Tweet" checkbox. - if ( allowTweetImageWrap && wp.media.featuredImage ) { - toggleAllowImageVisibility(); - // Listen event for add/remove featured image. - wp.media.featuredImage.frame().on( 'select', toggleAllowImageVisibility ); - $('#postimagediv').on( 'click', '#remove-post-thumbnail', toggleAllowImageVisibility ); - } - - /** - * Show/Hide "Use featured image in Tweet" checkbox. - */ - function toggleAllowImageVisibility( event ) { - let hasMedia = wp.media.featuredImage.get(); - // Handle remove post thumbnail click - if( event && event.target && 'remove-post-thumbnail' === event.target.id && 'click' === event.type ) { - hasMedia = -1; - } - - const tweetNow = $('#tweet_now').length; - const autoshareEnabled = $tweetPost.prop('checked'); - // Autoshare is enabled and post has featured image. - if ( hasMedia > 0 && ( autoshareEnabled || tweetNow ) ) { - allowTweetImageWrap.show(); - } else { - allowTweetImageWrap.hide(); - } - } - - // Tweet Now functionality. - $('#tweet_now').on('click', function() { - $("#autoshare-for-twitter-error-message").html(''); - $(this).addClass("disabled"); - $(".autoshare-for-twitter-tweet-now-wrapper span.spinner").addClass("is-active"); - - const postId = $("#post_ID").val(); - const body = new FormData(); - body.append( 'action', adminAutoshareForTwitter.retweetAction ); - body.append( 'nonce', adminAutoshareForTwitter.nonce ); - body.append( 'post_id', postId ); - body.append( 'is_classic', 1 ); - - // Send request to Tweet now. - fetch( ajaxurl, { - method: 'POST', - body, - } ) - .then((response) => response.json()) - .then((response) => { - if ( - response && response.data && - ( ( response.success && response.data.message ) || ( false === response.success && false === response.data.is_retweeted) ) - ) { - $('.autoshare-for-twitter-status-logs-wrapper').html(response.data.message); - } else { - $("#autoshare-for-twitter-error-message").html(adminAutoshareForTwitter.unknownErrorText); - } - }) - .catch((error) => { - if(error.message){ - $("#autoshare-for-twitter-error-message").html(error.message); - } else { - $("#autoshare-for-twitter-error-message").html(adminAutoshareForTwitter.unknownErrorText); - } - }) - .finally(() => { - $(this).removeClass("disabled"); - $(".autoshare-for-twitter-tweet-now-wrapper span.spinner").removeClass("is-active"); - }); - }); - - // Toggle Tweet Now panel - jQuery("#autoshare_for_twitter_metabox .tweet-now-button").on("click", function(e){ - e.preventDefault(); - $editBody.show(); - jQuery(this).find('span').toggleClass('dashicons-arrow-up-alt2'); - jQuery(".autoshare-for-twitter-tweet-now-wrapper").slideToggle(); - }); + // Dismiss migrate to Twitter API v2 notice + $( function() { + $( '.ast_notice' ).on( 'click', '.notice-dismiss', function( event, el ) { + var $notice = $(this).parent('.notice.is-dismissible'); + var dismiss_url = $notice.attr('data-dismiss-url'); + if ( dismiss_url ) { + $.get( dismiss_url ); + } + }); + } ); })(jQuery); diff --git a/autoshare-for-twitter.php b/autoshare-for-twitter.php index b6cd7b50..b89b570a 100644 --- a/autoshare-for-twitter.php +++ b/autoshare-for-twitter.php @@ -3,7 +3,7 @@ * Plugin Name: Autoshare for Twitter * Description: Automatically tweets the post title or custom message and a link to the post. * Disclaimer: TWITTER, TWEET, RETWEET and the Twitter logo are trademarks of Twitter, Inc. or its affiliates. - * Version: 1.3.0 + * Version: 2.0.0 * Requires at least: 5.7 * Requires PHP: 7.4 * Author: 10up @@ -20,7 +20,7 @@ } define( 'AUTOSHARE_FOR_TWITTER', __FILE__ ); -define( 'AUTOSHARE_FOR_TWITTER_VERSION', '1.3.0' ); +define( 'AUTOSHARE_FOR_TWITTER_VERSION', '2.0.0' ); define( 'AUTOSHARE_FOR_TWITTER_URL', plugin_dir_url( __FILE__ ) ); define( 'AUTOSHARE_FOR_TWITTER_PATH', plugin_dir_path( __FILE__ ) ); define( 'AUTOSHARE_FOR_TWITTER_INC', AUTOSHARE_FOR_TWITTER_PATH . 'includes/' ); @@ -41,3 +41,14 @@ * Play nice with others. */ do_action( 'autoshare_for_twitter_loaded' ); + +/** + * Register an activation hook that we can hook into. + */ +register_activation_hook( + __FILE__, + function () { + // Don't need to show migration notice to new users. + update_option( 'autoshare_migrate_to_v2_api_notice_dismissed', true ); + } +); diff --git a/composer.json b/composer.json index c6362de0..92db6e5c 100644 --- a/composer.json +++ b/composer.json @@ -15,10 +15,10 @@ ], "require-dev": { "wp-coding-standards/wpcs": "^2.2", - "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", "10up/phpcs-composer": "dev-master", - "phpunit/phpunit": "9.5.x-dev", - "yoast/phpunit-polyfills": "1.x-dev" + "phpunit/phpunit": "9.6.x-dev", + "yoast/phpunit-polyfills": "2.x-dev" }, "scripts": { "test": "phpunit", @@ -29,12 +29,15 @@ }, "minimum-stability": "dev", "config": { - "autoloader-suffix": "10upAutoshareForTwitterV130", + "platform": { + "php": "7.4" + }, + "autoloader-suffix": "10upAutoshareForTwitterV200", "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true } }, "require": { - "abraham/twitteroauth": "2.0.0" + "abraham/twitteroauth": "4.0.1" } } diff --git a/composer.lock b/composer.lock index b5e742d6..a6dc3497 100644 --- a/composer.lock +++ b/composer.lock @@ -4,32 +4,33 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7813b96ab9db2d3c052d9d767ff6fd02", + "content-hash": "cc6e4242cfc2df2ee3c988aa552f8c64", "packages": [ { "name": "abraham/twitteroauth", - "version": "2.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/abraham/twitteroauth.git", - "reference": "96f49e67baec10f5e5cb703d87be16ba01a798a5" + "reference": "b9302599e416e5c00742cf7f4455220897f8291d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/96f49e67baec10f5e5cb703d87be16ba01a798a5", - "reference": "96f49e67baec10f5e5cb703d87be16ba01a798a5", + "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/b9302599e416e5c00742cf7f4455220897f8291d", + "reference": "b9302599e416e5c00742cf7f4455220897f8291d", "shasum": "" }, "require": { "composer/ca-bundle": "^1.2", "ext-curl": "*", - "php": "^7.2 || ^7.3 || ^7.4 || ^8.0" + "php": "^7.4 || ^8.0 || ^8.1" }, "require-dev": { "php-vcr/php-vcr": "^1", "php-vcr/phpunit-testlistener-vcr": "dev-php-8", "phpmd/phpmd": "^2", - "phpunit/phpunit": "^8", + "phpunit/phpunit": "^8 || ^9", + "rector/rector": "^0.12.19 || ^0.13.0", "squizlabs/php_codesniffer": "^3" }, "type": "library", @@ -65,7 +66,7 @@ "issues": "https://github.com/abraham/twitteroauth/issues", "source": "https://github.com/abraham/twitteroauth" }, - "time": "2020-12-02T01:27:06+00:00" + "time": "2022-08-18T23:30:33+00:00" }, { "name": "composer/ca-bundle", @@ -73,12 +74,12 @@ "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "27284c08ba8518c92516784a034817bfa0ab1cc2" + "reference": "74780ccf8c19d6acb8d65c5f39cd72110e132bbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/27284c08ba8518c92516784a034817bfa0ab1cc2", - "reference": "27284c08ba8518c92516784a034817bfa0ab1cc2", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/74780ccf8c19d6acb8d65c5f39cd72110e132bbd", + "reference": "74780ccf8c19d6acb8d65c5f39cd72110e132bbd", "shasum": "" }, "require": { @@ -126,7 +127,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/main" + "source": "https://github.com/composer/ca-bundle/tree/1.3.5" }, "funding": [ { @@ -142,7 +143,7 @@ "type": "tidelift" } ], - "time": "2022-10-12T12:09:58+00:00" + "time": "2023-01-11T08:27:00+00:00" } ], "packages-dev": [ @@ -152,18 +153,19 @@ "source": { "type": "git", "url": "https://github.com/10up/phpcs-composer.git", - "reference": "2f5c3608bc03fe1ca65acf462dd7b5008f6829a0" + "reference": "2d03ba19ad5259275aa4f2287340e3d7d270196b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/10up/phpcs-composer/zipball/2f5c3608bc03fe1ca65acf462dd7b5008f6829a0", - "reference": "2f5c3608bc03fe1ca65acf462dd7b5008f6829a0", + "url": "https://api.github.com/repos/10up/phpcs-composer/zipball/2d03ba19ad5259275aa4f2287340e3d7d270196b", + "reference": "2d03ba19ad5259275aa4f2287340e3d7d270196b", "shasum": "" }, "require": { + "automattic/vipwpcs": "^2.3", "dealerdirect/phpcodesniffer-composer-installer": "*", "phpcompatibility/phpcompatibility-wp": "^2", - "squizlabs/php_codesniffer": "^3.4.0", + "squizlabs/php_codesniffer": "3.7.1", "wp-coding-standards/wpcs": "*" }, "default-branch": true, @@ -182,36 +184,84 @@ "issues": "https://github.com/10up/phpcs-composer/issues", "source": "https://github.com/10up/phpcs-composer/tree/master" }, - "time": "2021-01-08T03:03:06+00:00" + "time": "2023-04-27T01:31:26+00:00" + }, + { + "name": "automattic/vipwpcs", + "version": "2.3.3", + "source": { + "type": "git", + "url": "https://github.com/Automattic/VIP-Coding-Standards.git", + "reference": "6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b", + "reference": "6cd0a6a82bc0ac988dbf9d6a7c2e293dc8ac640b", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7", + "php": ">=5.4", + "sirbrillig/phpcs-variable-analysis": "^2.11.1", + "squizlabs/php_codesniffer": "^3.5.5", + "wp-coding-standards/wpcs": "^2.3" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.0", + "phpcompatibility/php-compatibility": "^9", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", + "keywords": [ + "phpcs", + "standards", + "wordpress" + ], + "support": { + "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", + "source": "https://github.com/Automattic/VIP-Coding-Standards", + "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" + }, + "time": "2021-09-29T16:20:23+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "dev-master", + "version": "v0.7.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "9838aa941e2c71d7b627be577ba1fdaf32f4f4f0" + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/9838aa941e2c71d7b627be577ba1fdaf32f4f4f0", - "reference": "9838aa941e2c71d7b627be577ba1fdaf32f4f4f0", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", + "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", "shasum": "" }, "require": { "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4", + "php": ">=5.3", "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" }, "require-dev": { "composer/composer": "*", - "ext-json": "*", - "ext-zip": "*", "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" + "phpcompatibility/php-compatibility": "^9.0" }, - "default-branch": true, "type": "composer-plugin", "extra": { "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" @@ -234,7 +284,7 @@ }, { "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", @@ -258,10 +308,10 @@ "tests" ], "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "source": "https://github.com/PHPCSStandards/composer-installer" + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" }, - "time": "2022-10-03T16:10:17+00:00" + "time": "2022-02-04T12:51:07+00:00" }, { "name": "doctrine/instantiator", @@ -269,27 +319,28 @@ "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.16 || ^1", "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30 || ^5.4" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -315,7 +366,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.x" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -331,7 +382,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "myclabs/deep-copy", @@ -339,12 +390,12 @@ "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "928a96f585b86224ebc78f8f09d0482cf15b04f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/928a96f585b86224ebc78f8f09d0482cf15b04f5", + "reference": "928a96f585b86224ebc78f8f09d0482cf15b04f5", "shasum": "" }, "require": { @@ -352,11 +403,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "default-branch": true, @@ -383,7 +435,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.x" }, "funding": [ { @@ -391,7 +443,7 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T17:24:01+00:00" }, { "name": "nikic/php-parser", @@ -399,12 +451,12 @@ "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "2f1fd784fe5560675722a1e5cbbcece5f43bf3a0" + "reference": "0ffddce52d816f72d0efc4d9b02e276d3309ef01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2f1fd784fe5560675722a1e5cbbcece5f43bf3a0", - "reference": "2f1fd784fe5560675722a1e5cbbcece5f43bf3a0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ffddce52d816f72d0efc4d9b02e276d3309ef01", + "reference": "0ffddce52d816f72d0efc4d9b02e276d3309ef01", "shasum": "" }, "require": { @@ -415,6 +467,7 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "default-branch": true, "bin": [ "bin/php-parse" ], @@ -447,7 +500,7 @@ "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/4.x" }, - "time": "2022-09-10T20:41:13+00:00" + "time": "2023-03-06T22:12:36+00:00" }, { "name": "phar-io/manifest", @@ -632,16 +685,16 @@ }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "ddabec839cc003651f2ce695c938686d1086cf43" + "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/ddabec839cc003651f2ce695c938686d1086cf43", - "reference": "ddabec839cc003651f2ce695c938686d1086cf43", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/bba5a9dfec7fcfbd679cfaf611d86b4d3759da26", + "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26", "shasum": "" }, "require": { @@ -678,13 +731,14 @@ "paragonie", "phpcs", "polyfill", - "standards" + "standards", + "static analysis" ], "support": { "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" }, - "time": "2021-02-15T10:24:51+00:00" + "time": "2022-10-25T01:46:02+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", @@ -747,19 +801,19 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "74b7413e8d9788df77e296adabd7c1f6ca801a99" + "reference": "db887088b40ae43d17b9913886df860a7035145d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/74b7413e8d9788df77e296adabd7c1f6ca801a99", - "reference": "74b7413e8d9788df77e296adabd7c1f6ca801a99", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/db887088b40ae43d17b9913886df860a7035145d", + "reference": "db887088b40ae43d17b9913886df860a7035145d", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -774,8 +828,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -808,6 +862,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2" }, "funding": [ @@ -816,7 +871,7 @@ "type": "github" } ], - "time": "2022-10-21T12:10:51+00:00" + "time": "2023-04-04T09:22:25+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1061,20 +1116,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.x-dev", + "version": "9.6.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7847a4a920f686db261da1ccc92120800822661f" + "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7847a4a920f686db261da1ccc92120800822661f", - "reference": "7847a4a920f686db261da1ccc92120800822661f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", + "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -1103,8 +1158,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -1112,7 +1167,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -1143,7 +1198,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.7" }, "funding": [ { @@ -1159,7 +1215,7 @@ "type": "tidelift" } ], - "time": "2022-10-19T10:44:50+00:00" + "time": "2023-04-14T08:58:40+00:00" }, { "name": "sebastian/cli-parser", @@ -1531,12 +1587,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "3fade0c8462024d0426a00dc1ad0a2fda0df733f" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/3fade0c8462024d0426a00dc1ad0a2fda0df733f", - "reference": "3fade0c8462024d0426a00dc1ad0a2fda0df733f", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1586,7 +1642,7 @@ "type": "github" } ], - "time": "2022-04-14T11:24:33+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -1904,12 +1960,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e3a614438af7f71eaa6fc8e406be8a3aa5c34595" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e3a614438af7f71eaa6fc8e406be8a3aa5c34595", - "reference": "e3a614438af7f71eaa6fc8e406be8a3aa5c34595", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -1951,7 +2007,7 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -1959,7 +2015,7 @@ "type": "github" } ], - "time": "2022-07-30T08:13:09+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -1967,12 +2023,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "b7a390ae3651f7ba3675d8364bff396e87931554" + "reference": "20bdda85c7c585ab265c0c37ec052a019bae29c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/b7a390ae3651f7ba3675d8364bff396e87931554", - "reference": "b7a390ae3651f7ba3675d8364bff396e87931554", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/20bdda85c7c585ab265c0c37ec052a019bae29c4", + "reference": "20bdda85c7c585ab265c0c37ec052a019bae29c4", "shasum": "" }, "require": { @@ -2014,7 +2070,7 @@ "type": "github" } ], - "time": "2022-06-14T05:05:56+00:00" + "time": "2023-03-25T08:11:39+00:00" }, { "name": "sebastian/type", @@ -2022,12 +2078,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "4d34b23933f255b0822758a44272222cac593eb4" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/4d34b23933f255b0822758a44272222cac593eb4", - "reference": "4d34b23933f255b0822758a44272222cac593eb4", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -2070,7 +2126,7 @@ "type": "github" } ], - "time": "2022-10-01T05:56:17+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -2125,18 +2181,77 @@ ], "time": "2020-09-28T06:39:44+00:00" }, + { + "name": "sirbrillig/phpcs-variable-analysis", + "version": "2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", + "reference": "dc5582dc5a93a235557af73e523c389aac9a8e88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/dc5582dc5a93a235557af73e523c389aac9a8e88", + "reference": "dc5582dc5a93a235557af73e523c389aac9a8e88", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "squizlabs/php_codesniffer": "^3.5.6" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", + "phpcsstandards/phpcsdevcs": "^1.1", + "phpstan/phpstan": "^1.7", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0", + "sirbrillig/phpcs-import-detection": "^1.1", + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0@beta" + }, + "default-branch": true, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "VariableAnalysis\\": "VariableAnalysis/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Sam Graham", + "email": "php-codesniffer-variableanalysis@illusori.co.uk" + }, + { + "name": "Payton Swick", + "email": "payton@foolord.com" + } + ], + "description": "A PHPCS sniff to detect problems with variables.", + "keywords": [ + "phpcs", + "static analysis" + ], + "support": { + "issues": "https://github.com/sirbrillig/phpcs-variable-analysis/issues", + "source": "https://github.com/sirbrillig/phpcs-variable-analysis", + "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" + }, + "time": "2023-03-31T16:46:32+00:00" + }, { "name": "squizlabs/php_codesniffer", - "version": "dev-master", + "version": "3.7.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "cd5acaa651df870e8a3207926f236400361219e0" + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/cd5acaa651df870e8a3207926f236400361219e0", - "reference": "cd5acaa651df870e8a3207926f236400361219e0", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", "shasum": "" }, "require": { @@ -2148,7 +2263,6 @@ "require-dev": { "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, - "default-branch": true, "bin": [ "bin/phpcs", "bin/phpcbf" @@ -2173,15 +2287,14 @@ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", - "standards", - "static analysis" + "standards" ], "support": { "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2022-10-21T05:57:32+00:00" + "time": "2022-06-18T07:21:10+00:00" }, { "name": "theseer/tokenizer", @@ -2286,16 +2399,16 @@ }, { "name": "yoast/phpunit-polyfills", - "version": "dev-develop", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "b0c727ed3fb2a6c4528c676af69651ec4f579655" + "reference": "3b59adeef77fb1c03ff5381dbb9d68b0aaff3171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/b0c727ed3fb2a6c4528c676af69651ec4f579655", - "reference": "b0c727ed3fb2a6c4528c676af69651ec4f579655", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/3b59adeef77fb1c03ff5381dbb9d68b0aaff3171", + "reference": "3b59adeef77fb1c03ff5381dbb9d68b0aaff3171", "shasum": "" }, "require": { @@ -2303,14 +2416,12 @@ "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0" }, "require-dev": { - "yoast/yoastcs": "^2.2.1" + "yoast/yoastcs": "^2.3.0" }, - "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.x-dev", - "dev-develop": "1.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -2344,13 +2455,12 @@ "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2022-08-03T05:59:50+00:00" + "time": "2023-03-30T23:39:05+00:00" } ], "aliases": [], "minimum-stability": "dev", "stability-flags": { - "dealerdirect/phpcodesniffer-composer-installer": 20, "10up/phpcs-composer": 20, "phpunit/phpunit": 20, "yoast/phpunit-polyfills": 20 @@ -2359,5 +2469,8 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.1.0" + "platform-overrides": { + "php": "7.4" + }, + "plugin-api-version": "2.3.0" } diff --git a/includes/admin/assets.php b/includes/admin/assets.php index dcb0aa15..5dc4568a 100644 --- a/includes/admin/assets.php +++ b/includes/admin/assets.php @@ -48,6 +48,14 @@ function enqueue_shared_assets() { [], AUTOSHARE_FOR_TWITTER_VERSION ); + + wp_enqueue_script( + 'admin_autoshare_for_twitter', + trailingslashit( AUTOSHARE_FOR_TWITTER_URL ) . 'assets/js/admin-autoshare-for-twitter.js', + [ 'jquery' ], + AUTOSHARE_FOR_TWITTER_VERSION, + true + ); } /** @@ -127,22 +135,15 @@ function maybe_enqueue_classic_editor_assets( $hook ) { ); } - $handle = 'admin_autoshare_for_twitter'; + $handle = 'admin_autoshare_for_twitter_classic_editor'; wp_enqueue_script( $handle, - trailingslashit( AUTOSHARE_FOR_TWITTER_URL ) . 'assets/js/admin-autoshare-for-twitter.js', + trailingslashit( AUTOSHARE_FOR_TWITTER_URL ) . 'assets/js/admin-autoshare-for-twitter-classic-editor.js', [ 'jquery', 'wp-api-fetch' ], AUTOSHARE_FOR_TWITTER_VERSION, true ); - wp_enqueue_style( - $handle, - trailingslashit( AUTOSHARE_FOR_TWITTER_URL ) . 'assets/css/admin-autoshare-for-twitter.css', - [], - AUTOSHARE_FOR_TWITTER_VERSION - ); - localize_data( $handle ); } diff --git a/includes/admin/post-meta.php b/includes/admin/post-meta.php index 12c2fb39..673e1d40 100644 --- a/includes/admin/post-meta.php +++ b/includes/admin/post-meta.php @@ -317,7 +317,7 @@ function get_tweet_status_message( $post ) { case 'error': $response_array[] = [ - 'message' => __( 'Failed to tweet: ', 'autoshare-for-twitter' ) . $tweet_meta['message'], + 'message' => __( 'Failed to tweet; ', 'autoshare-for-twitter' ) . $tweet_meta['message'], 'status' => $status, ]; @@ -434,11 +434,19 @@ function markup_published( $status_meta ) { * @return string */ function markup_error( $status_meta ) { + $learn_more = ''; + if ( 'When authenticating requests to the Twitter API v2 endpoints, you must use keys and tokens from a Twitter developer App that is attached to a Project. You can create a project via the developer portal.' === $status_meta['message'] ) { + $learn_more = sprintf( + ' %s', + esc_url( 'https://developer.twitter.com/en/docs/twitter-api/migrate/ready-to-migrate' ), + esc_html__( 'Learn more here.', 'autoshare-for-twitter' ) + ); + } return sprintf( '
%s
%s
', esc_html__( 'Failed to tweet', 'autoshare-for-twitter' ), - esc_html( $status_meta['message'] ) + esc_html( $status_meta['message'] ) . $learn_more ); } diff --git a/includes/admin/post-transition.php b/includes/admin/post-transition.php index 1159e316..344576ae 100644 --- a/includes/admin/post-transition.php +++ b/includes/admin/post-transition.php @@ -190,14 +190,23 @@ function validate_response( $response ) { if ( ! empty( $response->id ) ) { $validated_response = array( 'id' => $response->id, - 'created_at' => $response->created_at, + 'created_at' => gmdate( 'c' ), // Twitter API v2 doesn't return created_at. ); } else { + $errors = $response->errors; + if ( empty( $response->errors ) && ! empty( $response->detail ) ) { + $errors = array( + (object) array( + 'code' => $response->status, + 'message' => $response->detail, + ), + ); + } $validated_response = new \WP_Error( 'autoshare_for_twitter_failed', __( 'Something happened during Twitter update.', 'autoshare-for-twitter' ), - $response->errors + $errors ); } @@ -223,9 +232,12 @@ function update_autoshare_for_twitter_meta_from_response( $post_id, $data ) { // Twitter sent back an error. Most likely a duplicate message. } elseif ( is_wp_error( $data ) ) { $error_message = $data->error_data['autoshare_for_twitter_failed'][0]; - $response = array( + // translators: %d is the error code. + $error_code_text = $error_message->code ? sprintf( __( 'Error: %d. ', 'autoshare-for-twitter' ), $error_message->code ) : ''; + + $response = array( 'status' => 'error', - 'message' => sanitize_text_field( 'Error: ' . $error_message->code . '. ' . $error_message->message ), + 'message' => sanitize_text_field( $error_code_text . $error_message->message ), ); // The default fallback message. diff --git a/includes/admin/settings.php b/includes/admin/settings.php index 5999a0fc..da35a26c 100644 --- a/includes/admin/settings.php +++ b/includes/admin/settings.php @@ -125,56 +125,56 @@ function register_settings() { // API Key. add_settings_field( 'autoshare-api_key', - __( 'API key', 'autoshare-for-twitter' ), + __( 'API Key', 'autoshare-for-twitter' ), __NAMESPACE__ . '\text_field_cb', 'autoshare-for-twitter', 'autoshare-cred_section', [ 'name' => 'api_key', 'class' => 'large-text', - 'placeholder' => __( 'paste your API key here', 'autoshare-for-twitter' ), + 'placeholder' => __( 'paste your API Key here', 'autoshare-for-twitter' ), ] ); // API Secret. add_settings_field( 'autoshare-api_secret', - __( 'API secret', 'autoshare-for-twitter' ), + __( 'API Key Secret', 'autoshare-for-twitter' ), __NAMESPACE__ . '\text_field_cb', 'autoshare-for-twitter', 'autoshare-cred_section', [ 'name' => 'api_secret', 'class' => 'large-text', - 'placeholder' => __( 'paste your API secret key here', 'autoshare-for-twitter' ), + 'placeholder' => __( 'paste your API Key Secret here', 'autoshare-for-twitter' ), ] ); // Access Token. add_settings_field( 'autoshare-access_token', - __( 'Access token', 'autoshare-for-twitter' ), + __( 'Access Token', 'autoshare-for-twitter' ), __NAMESPACE__ . '\text_field_cb', 'autoshare-for-twitter', 'autoshare-cred_section', [ 'name' => 'access_token', 'class' => 'large-text', - 'placeholder' => __( 'paste your Access token secret here', 'autoshare-for-twitter' ), + 'placeholder' => __( 'paste your Access Token here', 'autoshare-for-twitter' ), ] ); // Access Secret. add_settings_field( 'autoshare-access_secret', - __( 'Access secret', 'autoshare-for-twitter' ), + __( 'Access Token Secret', 'autoshare-for-twitter' ), __NAMESPACE__ . '\text_field_cb', 'autoshare-for-twitter', 'autoshare-cred_section', [ 'name' => 'access_secret', 'class' => 'large-text', - 'placeholder' => __( 'paste your Access token secret here', 'autoshare-for-twitter' ), + 'placeholder' => __( 'paste your Access Token Secret here', 'autoshare-for-twitter' ), ] ); @@ -190,7 +190,6 @@ function register_settings() { 'placeholder' => __( 'enter your Twitter handle here', 'autoshare-for-twitter' ), ] ); - } /** @@ -326,17 +325,20 @@ function cred_section_cb() {

-

API key and API secret key values and paste them below. In case you skipped the onboarding process, you can create a project and an app by following Step 2. Otherwise, please skip Step 2.', 'autoshare-for-twitter' ); ?>

- -

-

+

- -

-

-

-

- -

+

-

+

diff --git a/includes/class-publish-tweet.php b/includes/class-publish-tweet.php index 9852c81e..f2dd365f 100644 --- a/includes/class-publish-tweet.php +++ b/includes/class-publish-tweet.php @@ -54,7 +54,7 @@ class Publish_Tweet { /** * The TwitterOAuth client. * - * @var object The TwitterOAuth client. + * @var TwitterOAuth The TwitterOAuth client. */ protected $client; @@ -88,8 +88,8 @@ public function connection_test() {} /** * POST a status update. * - * @param string $body The tweet body. - * @param WP_Post $post The post object. + * @param string $body The tweet body. + * @param \WP_Post $post The post object. * * @return object */ @@ -101,14 +101,16 @@ public function status_update( $body, $post ) { } $update_data = array( - 'status' => $body, // URL encoding handled by buildHttpQuery vai TwitterOAuth. + 'text' => $body, // URL encoding handled by buildHttpQuery vai TwitterOAuth. ); $is_image_allowed = Utils\get_autoshare_for_twitter_meta( $post->ID, TWEET_ALLOW_IMAGE ); if ( 'no' !== $is_image_allowed ) { $media_id = $this->get_upload_data_media_id( $post ); if ( $media_id ) { - $update_data['media_ids'] = [ $media_id ]; + $update_data['media'] = array( + 'media_ids' => [ (string) $media_id ], + ); } } @@ -119,7 +121,7 @@ public function status_update( $body, $post ) { * @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update * * @param array Data sent to the Twitter endpoint. - * @param WP_Post The post associated with the tweet. + * @param \WP_Post The post associated with the tweet. */ $update_data = apply_filters( 'autoshare_for_twitter_tweet', $update_data, $post ); @@ -128,7 +130,7 @@ public function status_update( $body, $post ) { * * @param null|mixed Any non-null value will suppress the request to the Twitter endpoint. * @param array Data to send to the Twitter endpoint. - * @param WP_Post The post associated with the tweet. + * @param \WP_Post The post associated with the tweet. */ $response = apply_filters( 'autoshare_for_twitter_pre_status_update', null, $update_data, $post ); @@ -137,17 +139,24 @@ public function status_update( $body, $post ) { } $this->client->setTimeouts( 10, 30 ); + $this->client->setApiVersion( '2' ); $response = $this->client->post( - 'statuses/update', - $update_data + 'tweets', + $update_data, + true ); + // Twitter API V2 wraps response in data. + if ( isset( $response->data ) ) { + $response = $response->data; + } + /** * Fires after the request to the Twitter endpoint had been made. * * @param array|object The response from the Twitter endpoint. * @param array Data to send to the Twitter endpoint. - * @param WP_Post The post associated with the tweet. + * @param \WP_Post The post associated with the tweet. */ do_action( 'autoshare_for_twitter_after_status_update', $response, $update_data, $post ); @@ -219,7 +228,7 @@ public function get_largest_acceptable_image( $full_image, $sizes ) { * * @since 1.0.0 * - * @param WP_Post $post The post associated with the tweet. + * @param \WP_Post $post The post associated with the tweet. * @return null|int The Twitter media ID or null if no image is to be sent. */ public function get_upload_data_media_id( $post ) { @@ -230,7 +239,7 @@ public function get_upload_data_media_id( $post ) { * @since 1.0.0 * * @param null|int An attachment ID, null to fall back to the featured image, or false to send no image. - * @param WP_Post The post associated with the tweet. + * @param \WP_Post The post associated with the tweet. */ $attachment_id = apply_filters( 'autoshare_for_twitter_attached_image', null, $post ); @@ -286,6 +295,7 @@ public function upload( $image ) { } $this->client->setTimeouts( 10, 60 ); + $this->client->setApiVersion( '1.1' ); $response = $this->client->upload( 'media/upload', array( 'media' => $image ) ); if ( ! is_object( $response ) || ! isset( $response->media_id ) ) { diff --git a/includes/core.php b/includes/core.php index d68f92e1..2b082c2f 100644 --- a/includes/core.php +++ b/includes/core.php @@ -41,6 +41,8 @@ function setup() { add_action( 'init', __NAMESPACE__ . '\set_post_type_supports_with_custom_columns' ); add_filter( 'autoshare_for_twitter_enabled_default', __NAMESPACE__ . '\maybe_enable_autoshare_by_default' ); add_filter( 'autoshare_for_twitter_attached_image', __NAMESPACE__ . '\maybe_disable_upload_image', 10, 2 ); + add_action( 'admin_init', __NAMESPACE__ . '\handle_notice_dismiss' ); + add_action( 'admin_notices', __NAMESPACE__ . '\migrate_to_twitter_v2_api' ); } /** @@ -166,3 +168,49 @@ function modify_post_type_add_tweet_status( $column_name, $post_id ) { ); } } + +/** + * Display admin notice to migrate to Twitter v2 API. + * + * @since 2.0.0 + */ +function migrate_to_twitter_v2_api() { + $show_notice = get_option( 'autoshare_migrate_to_v2_api_notice_dismissed', false ); + if ( $show_notice ) { + return; + } + $dismiss_url = wp_nonce_url( add_query_arg( 'autoshare_dismiss_notice', '1' ), 'ast_dismiss_migrate_notice', '_ast_dismiss_nonce' ); + ?> +
+

+ tags for Twitter V2 API, 3$-4$: Opening and closing tags for migrate app, 5$-6$: Opening and closing tags for learn more. + wp_kses_post( __( 'Autoshare for Twitter now utilizes the %1$sTwitter v2 API%2$s. If you have not already done so, please %3$smigrate your app%4$s to Twitter v2 API to continue using Autoshare for Twitter. %5$sLearn more about migrating here%6$s.', 'autoshare-for-twitter' ) ), + '', + '', + '', + '', + '', + '' + ); + ?> +

+
+ =12.0" } @@ -3670,9 +3670,9 @@ } }, "node_modules/@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", "peer": true }, "node_modules/@sideway/pinpoint": { @@ -8102,9 +8102,9 @@ "dev": true }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/http-errors": { @@ -9611,9 +9611,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": { "json5": "lib/cli.js" }, @@ -13855,9 +13855,9 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-git": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.15.1.tgz", - "integrity": "sha512-73MVa5984t/JP4JcQt0oZlKGr42ROYWC3BcUZfuHtT3IHKPspIvL0cZBnvPXF7LL3S/qVeVHVdYYmJ3LOTw4Rg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz", + "integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==", "dev": true, "dependencies": { "@kwsites/file-exists": "^1.1.1", @@ -15375,9 +15375,9 @@ "peer": true }, "node_modules/webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -15879,9 +15879,10 @@ }, "dependencies": { "@10up/cypress-wp-utils": { - "version": "git+ssh://git@github.com/10up/cypress-wp-utils.git#cd1db18bd6f86a1002a8105d654781ac325040db", - "dev": true, - "from": "@10up/cypress-wp-utils@github:10up/cypress-wp-utils#build" + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@10up/cypress-wp-utils/-/cypress-wp-utils-0.1.0.tgz", + "integrity": "sha512-6yige9N0kqG0XM4HBQBPcr2k7TwUV+4PLESvQEvsDyIkvRvLzL1Fnbork+s1+hvni+2qL6Ghjhjjd2npTNbqRg==", + "dev": true }, "@10up/eslint-config": { "version": "1.0.9", @@ -18515,9 +18516,9 @@ } }, "@sideway/formula": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", - "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", "peer": true }, "@sideway/pinpoint": { @@ -21996,9 +21997,9 @@ "dev": true }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "http-errors": { @@ -23117,9 +23118,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonfile": { "version": "6.1.0", @@ -26413,9 +26414,9 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-git": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.15.1.tgz", - "integrity": "sha512-73MVa5984t/JP4JcQt0oZlKGr42ROYWC3BcUZfuHtT3IHKPspIvL0cZBnvPXF7LL3S/qVeVHVdYYmJ3LOTw4Rg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz", + "integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==", "dev": true, "requires": { "@kwsites/file-exists": "^1.1.1", @@ -27612,9 +27613,9 @@ "peer": true }, "webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", diff --git a/package.json b/package.json index c37e8b07..0b0c82bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@10up/autoshare-for-twitter", - "version": "1.3.0", + "version": "2.0.0", "description": "Automatically tweets a post title, URL, and optional description.", "scripts": { "watch": "webpack -w --devtool eval-cheap-module-source-map --output-pathinfo --mode development --config webpack.gutenberg.config.js", @@ -37,7 +37,7 @@ }, "homepage": "https://github.com/10up/autoshare#readme", "devDependencies": { - "@10up/cypress-wp-utils": "github:10up/cypress-wp-utils#build", + "@10up/cypress-wp-utils": "^0.1.0", "@10up/eslint-config": "^1.0.9", "@babel/core": "^7.6.0", "@babel/preset-env": "^7.6.0", @@ -53,7 +53,7 @@ "lint-staged": "^9.2.5", "node-wp-i18n": "^1.2.3", "svg-react-loader": "^0.4.6", - "webpack": "^5.74.0", + "webpack": "^5.76.0", "webpack-cli": "^4.10.0" }, "dependencies": { diff --git a/readme.txt b/readme.txt index 0da5d05f..768a0b81 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ === Autoshare for Twitter === Contributors: 10up, johnwatkins0, adamsilverstein, scottlee, dinhtungdu, jeffpaul, dharm1025 -Tags: twitter, tweet, autoshare, auto-share, auto share, share, social media +Tags: twitter, tweet, autoshare, auto-share, auto share, share, sharing, social media, posse Requires at least: 5.7 -Tested up to: 6.1 +Tested up to: 6.2 Requires PHP: 7.4 -Stable tag: 1.3.0 +Stable tag: 2.0.0 License: GPL-2.0-or-later License URI: https://spdx.org/licenses/GPL-2.0-or-later.html @@ -12,7 +12,39 @@ Automatically tweets the post title or custom message and a link to the post. == Description == -Automatically tweets the post title or custom message and a link to the post. +Autoshare for Twitter automatically tweets your posts as soon as they’re published. Once you hit the Publish button, the plugin sends your post’s title, featured image, and link to Twitter, along with a custom message. + +Unlike a myriad of other social media, multitool solutions, Autoshare for Twitter is built solely for Twitter. It focuses on doing one thing and does it well, with the code and interface craftsmanship we apply to every project. + +With Autoshare for Twitter, developers can further customize nearly everything about the tweets, including the image, author, and link, using an extensive set of hooks built into the code. Among its other features, the WordPress plugin: + +* Works in both the classic and new block editors. +* Becomes part of the pre-publish checklist step that’s part of the new block editor. +* Posts a high-quality featured image with your tweet. +* Counts characters to keep you under the tweet limit. +* Adds a link to the tweet in the block editor sidebar. + +**Disclaimer:** *TWITTER, TWEET, RETWEET and the Twitter logo are trademarks of Twitter, Inc. or its affiliates.* + +== Installation == +1. Install the plugin via the plugin installer, either by searching for it or uploading a .ZIP file. +2. Activate the plugin. +3. Save Twitter connection settings, found under `Settings` > `Autoshare for Twitter`. + +== Plugin Compatibility == + += Distributor = + +When using with 10up's [Distributor plugin](https://github.com/10up/distributor), posts that are distributed will not be autoshared if they are already tweeted from the origin site. Autoshare for Twitter tracks posts that have been tweeted in post meta to avoid "double tweeting". To avoid this behavior, use the `dt_blacklisted_meta` filter to exclude the 'autoshare_for_twitter_status' meta value from being distributed : + +```php +add_filter( 'dt_blacklisted_meta', function( $blacklisted_metas ) { + $blacklisted_metas[] = 'autoshare_for_twitter_status'; + return $blacklisted_metas; +} ) +``` + +== Developers == **Note:** Posts and pages are supported by default. Developers can use the `autoshare_for_twitter_default_post_types` filter to change the default supported post types @@ -44,13 +76,6 @@ add_filter( 'autoshare_for_twitter_enabled_default', 'enable_autoshare_by_defaul Additional technical details can be found in [our GitHub repository](https://github.com/10up/autoshare-for-twitter#overview). -**Disclaimer:** *TWITTER, TWEET, RETWEET and the Twitter logo are trademarks of Twitter, Inc. or its affiliates.* - -== Installation == -1. Install the plugin via the plugin installer, either by searching for it or uploading a .ZIP file. -2. Activate the plugin. -3. Save Twitter connection settings, found under `Settings` > `Autoshare for Twitter`. - == Frequently Asked Questions == = Does this plugin work with Gutenberg? = @@ -59,12 +84,25 @@ Yes, yes it does! For more details on this, see [#44](https://github.com/10up/a == Screenshots == -1. Autoshare for Twitter Settings, found under `Settings` > `Autoshare for Twitter`. -2. Create post screen with Autoshare for Twitter options. -3. Published post screen with Autoshare for Twitter options. +1. Create post screen with Autoshare for Twitter options. +2. Published post screen with Autoshare for Twitter options. +3. Autoshare For Twitter sidebar panel. +4. Autoshare for Twitter Settings, found under `Settings` > `Autoshare for Twitter`. == Changelog == -= 1.3.0 - 2023-01-19 = += 2.0.0 - 2023-05-16 = +**Autoshare for Twitter 2.0.0 utilizes [Twitter's v2 API](https://developer.twitter.com/en/products/twitter-api). If you have not already done so, please [migrate your app](https://developer.twitter.com/en/portal/projects-and-apps) to Twitter's v2 API to continue using Autoshare for Twitter. [Learn more about migrating here](https://developer.twitter.com/en/docs/twitter-api/migrate/ready-to-migrate).** + +* **Added:** Migrated to Twitter API v2 (props [@iamdharmesh](https://github.com/iamdharmesh), [@jeffpaul](https://github.com/jeffpaul), [@ravinderk](https://github.com/ravinderk), [@Sidsector9](https://github.com/Sidsector9) via [#229](https://github.com/10up/autoshare-for-twitter/pull/229)). +* **Changed:** Bump WordPress "tested up to" version 6.2 (props [@Sidsector9](https://github.com/Sidsector9), [@iamdharmesh](https://github.com/iamdharmesh) via [#228](https://github.com/10up/autoshare-for-twitter/pull/228)). +* **Changed:** Update plugin settings and guidelines to set up a Twitter app (props [@iamdharmesh](https://github.com/iamdharmesh), [@jeffpaul](https://github.com/jeffpaul), [@ravinderk](https://github.com/ravinderk) [@Sidsector9](https://github.com/Sidsector9) via [#229](https://github.com/10up/autoshare-for-twitter/pull/229)). +* **Changed:** Updated documentation (props [@jeffpaul](https://github.com/jeffpaul), [@iamdharmesh](https://github.com/iamdharmesh), via [#231](https://github.com/10up/autoshare-for-twitter/pull/231)). +* **Security:** Bump `simple-git` from 3.15.1 to 3.16.0 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#221](https://github.com/10up/autoshare-for-twitter/pull/221)). +* **Security:** Bump `http-cache-semantics` from 4.1.0 to 4.1.1 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#222](https://github.com/10up/autoshare-for-twitter/pull/222)). +* **Security:** Bump `@sideway/formula` from 3.0.0 to 3.0.1 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#223](https://github.com/10up/autoshare-for-twitter/pull/223)). +* **Security:** Bump `webpack` from 5.74.0 to 5.76.0 (props [@dependabot](https://github.com/apps/dependabot), [@iamdharmesh](https://github.com/iamdharmesh) via [#224](https://github.com/10up/autoshare-for-twitter/pull/224)). + += 1.3.0 - 2023-01-20 = * **Added:** "Tweet now" functionality (props [@Sidsector9](https://github.com/Sidsector9), [@iamdharmesh](https://github.com/iamdharmesh), [@cadic](https://github.com/cadic), [@jeffpaul](https://github.com/jeffpaul), [@linawiezkowiak](https://github.com/linawiezkowiak), [@oszkarnagy](https://github.com/oszkarnagy) via [#188](https://github.com/10up/autoshare-for-twitter/pull/188)). * **Added:** Toggle for adding/removing featured image from the tweet (props [@Sidsector9](https://github.com/Sidsector9), [@iamdharmesh](https://github.com/iamdharmesh), [@cadic](https://github.com/cadic), [@jeffpaul](https://github.com/jeffpaul), [@linawiezkowiak](https://github.com/linawiezkowiak), [@oszkarnagy](https://github.com/oszkarnagy) via [#188](https://github.com/10up/autoshare-for-twitter/pull/188)). * **Added:** Show Twitter status logs for the draft post if the post has been switched back to Draft from Published, and has already been Tweeted (props [@iamdharmesh](https://github.com/iamdharmesh), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul), [@linawiezkowiak](https://github.com/linawiezkowiak), [@oszkarnagy](https://github.com/oszkarnagy) via [#215](https://github.com/10up/autoshare-for-twitter/pull/215)). @@ -183,6 +221,8 @@ Yes, yes it does! For more details on this, see [#44](https://github.com/10up/a * Initial private release (props [@scottlee](https://profiles.wordpress.org/scottlee/)) == Upgrade Notice == += 2.0.0 = +Autoshare for Twitter 2.0.0 utilizes [Twitter's v2 API](https://developer.twitter.com/en/products/twitter-api). If you have not already done so, please [migrate your app](https://developer.twitter.com/en/portal/projects-and-apps) to Twitter's v2 API to continue using Autoshare for Twitter. [Learn more about migrating here](https://developer.twitter.com/en/docs/twitter-api/migrate/ready-to-migrate). = 1.2.1 = This release bumps the WordPress minimum from 5.3 to 5.7 and PHP minimum from 7.2 to 7.4. diff --git a/src/js/AutoshareForTwitterPostStatusInfo.js b/src/js/AutoshareForTwitterPostStatusInfo.js index 44ddd2a6..ddc61bfa 100644 --- a/src/js/AutoshareForTwitterPostStatusInfo.js +++ b/src/js/AutoshareForTwitterPostStatusInfo.js @@ -8,6 +8,17 @@ import { useHasFeaturedImage, useAllowTweetImage, useSaveTwitterData } from './h import { getIconByStatus } from './utils'; +// Error message component. +const ErrorMessage = ( { errorMessage } ) => { + return ( + + { errorMessage } + { ' ' } + { ( errorMessage?.includes( 'When authenticating requests to the Twitter API v2 endpoints, you must use keys and tokens from a Twitter developer App that is attached to a Project. You can create a project via the developer portal.' ) ) && { __( 'Learn more here.' ) } } + + ); +}; + export function AutoshareForTwitterPostStatusInfo() { const hasFeaturedImage = useHasFeaturedImage(); const [ allowTweetImage, setAllowTweetImage ] = useAllowTweetImage(); @@ -58,7 +69,7 @@ export function AutoshareForTwitterPostStatusInfo() { return (
- { TweetIcon }{ statusMessage.url ? { statusMessage.message } : statusMessage.message } + { TweetIcon }{ statusMessage.url ? { statusMessage.message } : }
); } ) } diff --git a/tests/phpunit/integration/TestPostMeta.php b/tests/phpunit/integration/TestPostMeta.php index b669f7fc..57f4c4d7 100644 --- a/tests/phpunit/integration/TestPostMeta.php +++ b/tests/phpunit/integration/TestPostMeta.php @@ -119,7 +119,7 @@ public function test_get_tweet_status_message() { [ 'message' => [ [ - 'message' => 'Failed to tweet: There was an error.', + 'message' => 'Failed to tweet; There was an error.', 'status' => 'error', ], ],