} refs - The refs to be merged.
- * @returns {RefCallback} The merged ref callback.
- */
-export default function useMergeRefs( refs ) {
- const element = useRef( null );
- const didElementChange = useRef( false );
- const previousRefs = useRef( refs );
- const currentRefs = useRef( refs );
-
- // Update on render before the ref callback is called, so the ref callback
- // always has access to the current refs.
- currentRefs.current = refs;
-
- // If any of the refs change, call the previous ref with `null` and the new
- // ref with the node, except when the element changes in the same cycle, in
- // which case the ref callbacks will already have been called.
- useLayoutEffect( () => {
- refs.forEach( ( ref, index ) => {
- const previousRef = previousRefs.current[ index ];
-
- if (
- typeof ref === 'function' &&
- ref !== previousRef &&
- didElementChange.current === false
- ) {
- previousRef( null );
- ref( element.current );
- }
- } );
-
- previousRefs.current = refs;
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, refs );
-
- // No dependencies, must be reset after every render so ref callbacks are
- // correctly called after a ref change.
- useLayoutEffect( () => {
- didElementChange.current = false;
- } );
-
- // There should be no dependencies so that `callback` is only called when
- // the node changes.
- return useCallback( value => {
- // Update the element so it can be used when calling ref callbacks on a
- // dependency change.
- element.current = value;
- didElementChange.current = true;
-
- // When an element changes, the current ref callback should be called
- // with the new element and the previous one with `null`.
- const refsToUpdate = value ? currentRefs.current : previousRefs.current;
-
- // Update the latest refs.
- refsToUpdate.forEach( ref => {
- if ( typeof ref === 'function' ) {
- ref( value );
- } else if ( ref && ref.hasOwnProperty( 'current' ) ) {
- ref.current = value;
- }
- } );
- }, [] );
-}
diff --git a/projects/plugins/jetpack/extensions/blocks/story/player/modal/frame.js b/projects/plugins/jetpack/extensions/blocks/story/player/modal/frame.js
index 0789d71044b2e..71755b6b8c9bf 100644
--- a/projects/plugins/jetpack/extensions/blocks/story/player/modal/frame.js
+++ b/projects/plugins/jetpack/extensions/blocks/story/player/modal/frame.js
@@ -2,10 +2,12 @@
* WordPress dependencies
*/
import { ESCAPE, SPACE } from '@wordpress/keycodes';
-import { useFocusReturn, useConstrainedTabbing, useFocusOnMount } from '@wordpress/compose';
-
-// TODO: replace with `import { useMergeRefs } from '@wordpress/compose';` when package is upgraded to ^3.24.4
-import useMergeRefs from '../lib/use-merge-refs';
+import {
+ useFocusReturn,
+ useConstrainedTabbing,
+ useFocusOnMount,
+ useMergeRefs,
+} from '@wordpress/compose';
export default function ModalFrame( {
overlayClassName,
diff --git a/projects/plugins/jetpack/extensions/shared/jetpack-plugin-sidebar.scss b/projects/plugins/jetpack/extensions/shared/jetpack-plugin-sidebar.scss
index 7a942fca29665..f951066f2b862 100644
--- a/projects/plugins/jetpack/extensions/shared/jetpack-plugin-sidebar.scss
+++ b/projects/plugins/jetpack/extensions/shared/jetpack-plugin-sidebar.scss
@@ -19,9 +19,7 @@
}
.edit-post-pinned-plugins {
- .components-icon-button, // Gutenberg < 7.2.0. @TODO: Remove once we drop support
- .components-button.has-icon // Gutenberg >= 7.2.0
- {
+ .components-button.has-icon {
&:not( .is-toggled ),
&:hover,
&.is-toggled,
diff --git a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-users-endpoint.php b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-users-endpoint.php
index e0bd3cc9f5f79..d5cb1a378971a 100644
--- a/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-users-endpoint.php
+++ b/projects/plugins/jetpack/json-endpoints/class.wpcom-json-api-list-users-endpoint.php
@@ -142,12 +142,6 @@ public function callback( $path = '', $blog_id = 0 ) {
if ( $authors_only ) {
$query['capability'] = array( 'edit_posts' );
- // To-do: remove this once Jetpack requires WordPress 5.9.
- global $wp_version;
- if ( version_compare( $wp_version, '5.9-alpha', '<' ) ) {
- $query['who'] = 'authors';
- unset( $query['capability'] );
- }
}
if ( ! empty( $args['search'] ) ) {
diff --git a/projects/plugins/jetpack/modules/shortcodes/slideshow.php b/projects/plugins/jetpack/modules/shortcodes/slideshow.php
index 68e64e83dab81..e2e780da32dfc 100644
--- a/projects/plugins/jetpack/modules/shortcodes/slideshow.php
+++ b/projects/plugins/jetpack/modules/shortcodes/slideshow.php
@@ -216,39 +216,20 @@ public function slideshow_js( $attr ) {
// Enqueue scripts.
$this->enqueue_scripts();
- $output = '';
-
- if ( defined( 'JSON_HEX_AMP' ) ) {
- // This is nice to have, but not strictly necessary since we use _wp_specialchars() below.
- $gallery = wp_json_encode( $attr['gallery'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ); // phpcs:ignore PHPCompatibility
- } else {
- $gallery = wp_json_encode( $attr['gallery'] );
- }
-
- $output .= '' . esc_html__( 'This slideshow requires JavaScript.', 'jetpack' ) . '
';
+ $output = '' . esc_html__( 'This slideshow requires JavaScript.', 'jetpack' ) . '
';
/*
- * The input to json_encode() above can contain '"'.
- *
- * For calls to json_encode() lacking the JSON_HEX_AMP option,
- * that '"' is left unaltered. Running '"' through esc_attr()
- * also leaves it unaltered since esc_attr() does not double-encode.
- *
- * This means we end up with an attribute like
- * `data-gallery="{"foo":"""}"`,
- * which is interpreted by the browser as `{"foo":"""}`,
- * which cannot be JSON decoded.
- *
- * The preferred workaround is to include the JSON_HEX_AMP (and friends)
- * options, but these are not available until 5.3.0.
- * Alternatively, we can use _wp_specialchars( , , , true ) instead of
- * esc_attr(), which will double-encode.
- *
- * Since we can't rely on JSON_HEX_AMP, we do both.
- *
- * @todo Update when minimum is PHP 5.3+
+ * Checking for JSON_HEX_AMP and friends here allows us to get rid of
+ * '"', that can sometimes be included in the JSON input in some languages like French.
*/
- $gallery_attributes = _wp_specialchars( wp_check_invalid_utf8( $gallery ), ENT_QUOTES, false, true );
+ $gallery_attributes = _wp_specialchars(
+ wp_check_invalid_utf8(
+ wp_json_encode( $attr['gallery'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT )
+ ),
+ ENT_QUOTES,
+ false,
+ true
+ );
$output .= sprintf(
'',
diff --git a/projects/plugins/jetpack/modules/widget-visibility/widget-conditions.php b/projects/plugins/jetpack/modules/widget-visibility/widget-conditions.php
index dad9a2415f938..78f9da83a7443 100644
--- a/projects/plugins/jetpack/modules/widget-visibility/widget-conditions.php
+++ b/projects/plugins/jetpack/modules/widget-visibility/widget-conditions.php
@@ -239,13 +239,6 @@ public static function widget_admin_setup() {
'fields' => array( 'ID', 'display_name' ),
);
- // To-do: remove this once Jetpack requires WordPress 5.9.
- global $wp_version;
- if ( version_compare( $wp_version, '5.9-alpha', '<' ) ) {
- $authors_args['who'] = 'authors';
- unset( $authors_args['capability'] );
- }
-
$authors = get_users( $authors_args );
foreach ( $authors as $author ) {
diff --git a/projects/plugins/jetpack/modules/widgets/authors.php b/projects/plugins/jetpack/modules/widgets/authors.php
index ecdb86d9fa8c2..d56f2ec321ca4 100644
--- a/projects/plugins/jetpack/modules/widgets/authors.php
+++ b/projects/plugins/jetpack/modules/widgets/authors.php
@@ -125,13 +125,6 @@ public function widget( $args, $instance ) {
)
);
- // To-do: remove this once Jetpack requires WordPress 5.9.
- global $wp_version;
- if ( version_compare( $wp_version, '5.9-alpha', '<' ) ) {
- $get_author_params['who'] = 'authors';
- unset( $get_author_params['capability'] );
- }
-
$authors = get_users( $get_author_params );
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
diff --git a/projects/plugins/jetpack/tests/action-phpunit.sh b/projects/plugins/jetpack/tests/action-phpunit.sh
index cc4ba9853a081..a349522c8b5d0 100755
--- a/projects/plugins/jetpack/tests/action-phpunit.sh
+++ b/projects/plugins/jetpack/tests/action-phpunit.sh
@@ -2,5 +2,4 @@
set -eo pipefail
-. tests/maybe-downgrade-phpunit.sh
exec phpunit "$@"
diff --git a/projects/plugins/jetpack/tests/action-test-coverage.sh b/projects/plugins/jetpack/tests/action-test-coverage.sh
index 2bdeb4b30b1c8..10200d6ff03ed 100755
--- a/projects/plugins/jetpack/tests/action-test-coverage.sh
+++ b/projects/plugins/jetpack/tests/action-test-coverage.sh
@@ -2,8 +2,6 @@
set -eo pipefail
-. tests/maybe-downgrade-phpunit.sh
-
PLUGINDIR="$PWD"
cd "$MONOREPO_BASE/projects/plugins/jetpack"
diff --git a/projects/plugins/jetpack/tests/action-test-php.sh b/projects/plugins/jetpack/tests/action-test-php.sh
index 33789244ce591..bc3ee23ff869f 100755
--- a/projects/plugins/jetpack/tests/action-test-php.sh
+++ b/projects/plugins/jetpack/tests/action-test-php.sh
@@ -2,8 +2,6 @@
set -eo pipefail
-. tests/maybe-downgrade-phpunit.sh
-
echo "::group::Jetpack tests"
phpunit
echo "::endgroup::"
diff --git a/projects/plugins/jetpack/tests/maybe-downgrade-phpunit.sh b/projects/plugins/jetpack/tests/maybe-downgrade-phpunit.sh
deleted file mode 100644
index e51a8d397b2f4..0000000000000
--- a/projects/plugins/jetpack/tests/maybe-downgrade-phpunit.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-# Detect versions of WordPress that still require an ancient version of PHPUnit, and
-# if necessary downgrade to a version that will work.
-# @todo: Remove this once we drop support for WordPress 5.8. Also probably merge find-test-root.php back into bootstrap.php.
-TEST_ROOT=$(php -r 'echo require "tests/php/find-test-root.php";')
-if grep -q --fixed $'version_compare( $phpunit_version, \'8.0\', \'>=\' )' "$TEST_ROOT/includes/bootstrap.php" &&
- ! phpunit --version | grep -q '^PHPUnit [567]\.'
-then
- echo "The version of WordPress under test requires PHPUnit < 8.0, while the installed version is"
- phpunit --version
-
- TMP1="$( composer.json
- echo "$TMP2" > composer.lock
-
- printf 'Now using '
- phpunit --version
-else
- printf 'Using '
- phpunit --version
-fi
diff --git a/projects/plugins/jetpack/tests/php/bootstrap.php b/projects/plugins/jetpack/tests/php/bootstrap.php
index 2f3b87ee8d03d..319cf416bfc8d 100644
--- a/projects/plugins/jetpack/tests/php/bootstrap.php
+++ b/projects/plugins/jetpack/tests/php/bootstrap.php
@@ -17,7 +17,46 @@
*/
define( 'TESTING_IN_JETPACK', true );
-$test_root = require __DIR__ . '/find-test-root.php';
+// Support for:
+// 1. `WP_DEVELOP_DIR` environment variable.
+// 2. Plugin installed inside of WordPress.org developer checkout.
+// 3. Tests checked out to /tmp.
+if ( false !== getenv( 'WP_DEVELOP_DIR' ) ) {
+ // Defined on command line.
+ $test_root = getenv( 'WP_DEVELOP_DIR' );
+ if ( file_exists( "$test_root/tests/phpunit/" ) ) {
+ $test_root .= '/tests/phpunit/';
+ }
+} elseif ( file_exists( '../../../../tests/phpunit/includes/bootstrap.php' ) ) {
+ // Installed inside wordpress-develop.
+ $test_root = '../../../../tests/phpunit';
+} elseif ( file_exists( '/vagrant/www/wordpress-develop/public_html/tests/phpunit/includes/bootstrap.php' ) ) {
+ // VVV.
+ $test_root = '/vagrant/www/wordpress-develop/public_html/tests/phpunit';
+} elseif ( file_exists( '/srv/www/wordpress-trunk/public_html/tests/phpunit/includes/bootstrap.php' ) ) {
+ // VVV 3.0.
+ $test_root = '/srv/www/wordpress-trunk/public_html/tests/phpunit';
+} elseif ( file_exists( '/tmp/wordpress-develop/tests/phpunit/includes/bootstrap.php' ) ) {
+ // Manual checkout & Jetpack's docker environment.
+ $test_root = '/tmp/wordpress-develop/tests/phpunit';
+} elseif ( file_exists( '/tmp/wordpress-tests-lib/includes/bootstrap.php' ) ) {
+ // Legacy tests.
+ $test_root = '/tmp/wordpress-tests-lib';
+}
+
+if ( ! isset( $test_root ) || ! file_exists( $test_root . '/includes/bootstrap.php' ) ) {
+ fprintf(
+ STDERR,
+ <<<'EOF'
+Failed to automatically locate WordPress or wordpress-develop to run tests.
+
+Set the WP_DEVELOP_DIR environment variable to point to a copy of WordPress
+or wordpress-develop.
+EOF
+ );
+ exit( 1 );
+}
+
echo "Using test root $test_root\n";
$jp_autoloader = __DIR__ . '/../../vendor/autoload.php';
@@ -32,34 +71,6 @@
require $jp_autoloader;
-// WordPress until recently required PHPUnit 7.5 or earlier and hacks around a few things to
-// make it work with PHP 8. Unfortunately for MockObjects they do it via
-// composer.json rather than bootstrap.php, so we have to manually do it here.
-// @todo: Remove this once either WP backports their bootstrap changes to 5.8.1 or they release 5.8.2.
-if ( version_compare( PHP_VERSION, '8.0', '>=' ) &&
- ( ! class_exists( PHPUnit\Runner\Version::class ) || version_compare( PHPUnit\Runner\Version::id(), '9.3', '<' ) )
-) {
- if ( ! class_exists( PHPUnit\Framework\MockObject\InvocationMocker::class, false ) &&
- file_exists( "$test_root/includes/phpunit7/MockObject/InvocationMocker.php" )
- ) {
- // phpcs:disable WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath
- require "$test_root/includes/phpunit7/MockObject/Builder/NamespaceMatch.php";
- require "$test_root/includes/phpunit7/MockObject/Builder/ParametersMatch.php";
- require "$test_root/includes/phpunit7/MockObject/InvocationMocker.php";
- require "$test_root/includes/phpunit7/MockObject/MockMethod.php";
- // phpcs:enable
- } else {
- fprintf(
- STDOUT,
- "Warning: PHPUnit <9.3 is not compatible with PHP 8.0+, and the hack could not be loaded.\n Class %s exists: %s\n File %s exists: %s\n",
- PHPUnit\Framework\MockObject\InvocationMocker::class,
- class_exists( PHPUnit\Framework\MockObject\InvocationMocker::class, false ) ? 'yes (bad)' : 'no (good)',
- "$test_root/includes/phpunit7/MockObject/InvocationMocker.php",
- file_exists( "$test_root/includes/phpunit7/MockObject/InvocationMocker.php" ) ? 'yes (good)' : 'no (bad)'
- );
- }
-}
-
if ( '1' !== getenv( 'WP_MULTISITE' ) && ( ! defined( 'WP_TESTS_MULTISITE' ) || ! WP_TESTS_MULTISITE ) ) {
echo 'To run Jetpack multisite, use -c tests/php.multisite.xml' . PHP_EOL;
echo "Disregard Core's -c tests/phpunit/multisite.xml notice below." . PHP_EOL;
diff --git a/projects/plugins/jetpack/tests/php/find-test-root.php b/projects/plugins/jetpack/tests/php/find-test-root.php
deleted file mode 100644
index 232f36b9fae2c..0000000000000
--- a/projects/plugins/jetpack/tests/php/find-test-root.php
+++ /dev/null
@@ -1,48 +0,0 @@
-setExpectedDeprecated( $file_path );
$mock = $this->getMockBuilder( stdClass::class )