From 7750458133663a8bae9a36cc36ab29e563675620 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Sat, 4 May 2024 19:23:31 +0000 Subject: [PATCH] Bootstrap/Load: Add support for custom ports in multisite site addresses. This allows a Multisite network to use an address that includes a port name, such as `example.com:1234`, and adds support for this to the local development environment too. You can now run a Multisite installation on the local development environment, for example at `localhost:8889`. This also fixes some bugs with running a single site installation on a port, and updates the testing infrastructure so that the whole test suite runs both with and without a port number. Props djzone, scribu, nacin, ipstenu, F J Kaiser, jeremyfelt, johnjamesjacoby, spacedmonkey, PerS, Clorith, Blackbam, enrico.sorcinelli, Jules Colle, obliviousharmony, desrosj, johnbillion Fixes #21077, #52088 git-svn-id: https://develop.svn.wordpress.org/trunk@58097 602fd350-edb4-49c9-b593-d223f7449a82 --- .env | 4 ++ .github/workflows/phpunit-tests-run.yml | 8 ++- .github/workflows/phpunit-tests.yml | 20 ++++++ src/wp-admin/includes/network.php | 22 +----- src/wp-admin/network/site-info.php | 14 +++- src/wp-includes/embed.php | 3 +- src/wp-includes/feed.php | 10 ++- src/wp-includes/media.php | 13 +++- src/wp-includes/ms-site.php | 6 +- .../tests/admin/wpCommentsListTable.php | 12 ++-- .../tests/admin/wpPostCommentsListTable.php | 12 ++-- .../tests/admin/wpPrivacyRequestsTable.php | 2 +- tests/phpunit/tests/date/getPermalink.php | 4 +- tests/phpunit/tests/dependencies/scripts.php | 6 +- tests/phpunit/tests/functions/referer.php | 4 +- tests/phpunit/tests/functions/wpNonceAys.php | 2 +- .../phpunit/tests/general/feedLinksExtra.php | 8 +-- tests/phpunit/tests/kses.php | 67 ++++++++++--------- .../tests/media/getAdjacentImageLink.php | 8 +-- .../phpunit/tests/media/getNextImageLink.php | 4 +- .../tests/media/getPreviousImageLink.php | 4 +- tests/phpunit/tests/media/nextImageLink.php | 4 +- .../phpunit/tests/media/previousImageLink.php | 4 +- tests/phpunit/tests/multisite/site.php | 44 +++++++++++- .../tests/multisite/wpMsUsersListTable.php | 4 +- tests/phpunit/tests/pluggable/wpMail.php | 5 +- .../tests/post/wpGetAttachmentLink.php | 2 +- ...pPrivacyGeneratePersonalDataExportFile.php | 8 +-- .../tests/rest-api/rest-schema-setup.php | 4 ++ .../rest-api/rest-widgets-controller.php | 2 +- tests/phpunit/tests/user/wpListAuthors.php | 2 +- tests/phpunit/tests/user/wpListUsers.php | 24 +++---- tools/local-env/default.template | 6 ++ tools/local-env/scripts/install.js | 4 +- 34 files changed, 223 insertions(+), 123 deletions(-) diff --git a/.env b/.env index b673e401c2eaf..70cd4153b3757 100644 --- a/.env +++ b/.env @@ -53,6 +53,9 @@ LOCAL_DB_TYPE=mysql ## LOCAL_DB_VERSION=8.0 +# Whether or not to enable multisite. +LOCAL_MULTISITE=false + # The debug settings to add to `wp-config.php`. LOCAL_WP_DEBUG=true LOCAL_WP_DEBUG_LOG=true @@ -60,6 +63,7 @@ LOCAL_WP_DEBUG_DISPLAY=true LOCAL_SCRIPT_DEBUG=true LOCAL_WP_ENVIRONMENT_TYPE=local LOCAL_WP_DEVELOPMENT_MODE=core +LOCAL_WP_TESTS_DOMAIN=example.org # The URL to use when running e2e tests. WP_BASE_URL=http://localhost:${LOCAL_PORT} diff --git a/.github/workflows/phpunit-tests-run.yml b/.github/workflows/phpunit-tests-run.yml index 68f9d003a4fcf..9978fd9bf70fb 100644 --- a/.github/workflows/phpunit-tests-run.yml +++ b/.github/workflows/phpunit-tests-run.yml @@ -40,6 +40,11 @@ on: required: false type: 'string' default: 'phpunit.xml.dist' + tests-domain: + description: 'The domain to use for the tests' + required: false + type: 'string' + default: 'example.org' report: description: 'Whether to report results to WordPress.org Hosting Tests' required: false @@ -50,6 +55,7 @@ env: LOCAL_DB_TYPE: ${{ inputs.db-type }} LOCAL_DB_VERSION: ${{ inputs.db-version }} LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }} + LOCAL_WP_TESTS_DOMAIN: ${{ inputs.tests-domain }} PHPUNIT_CONFIG: ${{ inputs.phpunit-config }} PUPPETEER_SKIP_DOWNLOAD: ${{ true }} @@ -74,7 +80,7 @@ jobs: # - Checks out the WordPress Test reporter repository. # - Submit the test results to the WordPress.org host test results. phpunit-tests: - name: PHP ${{ inputs.php }} / ${{ 'mariadb' == inputs.db-type && 'MariaDB' || 'MySQL' }} ${{ inputs.db-version }}${{ inputs.multisite && ' multisite' || '' }}${{ inputs.memcached && ' with memcached' || '' }}${{ inputs.report && ' (test reporting enabled)' || '' }} + name: PHP ${{ inputs.php }} / ${{ 'mariadb' == inputs.db-type && 'MariaDB' || 'MySQL' }} ${{ inputs.db-version }}${{ inputs.multisite && ' multisite' || '' }}${{ inputs.memcached && ' with memcached' || '' }}${{ inputs.report && ' (test reporting enabled)' || '' }} ${{ 'example.org' != inputs.tests-domain && inputs.tests-domain || '' }} runs-on: ${{ inputs.os }} timeout-minutes: 20 diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml index 5cbd87631505e..3bc72f8e8c528 100644 --- a/.github/workflows/phpunit-tests.yml +++ b/.github/workflows/phpunit-tests.yml @@ -48,6 +48,7 @@ jobs: php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3' ] db-type: [ 'mysql' ] db-version: [ '5.7', '8.0', '8.1', '8.2', '8.3' ] + tests-domain: [ 'example.org' ] multisite: [ false, true ] memcached: [ false ] @@ -57,19 +58,37 @@ jobs: php: '7.4' db-type: 'mysql' db-version: '5.7' + tests-domain: 'example.org' multisite: false memcached: true - os: ubuntu-latest php: '7.4' db-type: 'mysql' db-version: '5.7' + tests-domain: 'example.org' multisite: true memcached: true + # Include jobs with a port on the test domain for both single and multisite. + - os: ubuntu-latest + php: '7.4' + db-type: 'mysql' + db-version: '5.7' + tests-domain: 'example.org:8889' + multisite: false + memcached: false + - os: ubuntu-latest + php: '7.4' + db-type: 'mysql' + db-version: '5.7' + tests-domain: 'example.org:8889' + multisite: true + memcached: false # Report test results to the Host Test Results. - os: ubuntu-latest php: '7.4' db-type: 'mysql' db-version: '5.7' + tests-domain: 'example.org' multisite: false memcached: false report: true @@ -81,6 +100,7 @@ jobs: multisite: ${{ matrix.multisite }} memcached: ${{ matrix.memcached }} phpunit-config: ${{ matrix.multisite && 'tests/phpunit/multisite.xml' || 'phpunit.xml.dist' }} + tests-domain: ${{ matrix.tests-domain }} report: ${{ matrix.report || false }} # diff --git a/src/wp-admin/includes/network.php b/src/wp-admin/includes/network.php index 67a9e0289e56b..9577172a803ba 100644 --- a/src/wp-admin/includes/network.php +++ b/src/wp-admin/includes/network.php @@ -148,26 +148,8 @@ function network_step1( $errors = false ) { die(); } - $hostname = get_clean_basedomain(); - $has_ports = strstr( $hostname, ':' ); - if ( ( false !== $has_ports && ! in_array( $has_ports, array( ':80', ':443' ), true ) ) ) { - wp_admin_notice( - '' . __( 'Error:' ) . ' ' . __( 'You cannot install a network of sites with your server address.' ), - array( - 'additional_classes' => array( 'error' ), - ) - ); - - echo '

' . sprintf( - /* translators: %s: Port number. */ - __( 'You cannot use port numbers such as %s.' ), - '' . $has_ports . '' - ) . '

'; - echo '' . __( 'Go to Dashboard' ) . ''; - echo ''; - require_once ABSPATH . 'wp-admin/admin-footer.php'; - die(); - } + // Strip standard port from hostname. + $hostname = preg_replace( '/(?::80|:443)$/', '', get_clean_basedomain() ); echo '
'; diff --git a/src/wp-admin/network/site-info.php b/src/wp-admin/network/site-info.php index defcc26e44060..46f67cced5c52 100644 --- a/src/wp-admin/network/site-info.php +++ b/src/wp-admin/network/site-info.php @@ -66,8 +66,14 @@ } $blog_data['scheme'] = $update_parsed_url['scheme']; + + // Make sure to not lose the port if it was provided. $blog_data['domain'] = $update_parsed_url['host']; - $blog_data['path'] = $update_parsed_url['path']; + if ( isset( $update_parsed_url['port'] ) ) { + $blog_data['domain'] .= ':' . $update_parsed_url['port']; + } + + $blog_data['path'] = $update_parsed_url['path']; } $existing_details = get_site( $id ); @@ -88,16 +94,18 @@ $old_home_url = trailingslashit( esc_url( get_option( 'home' ) ) ); $old_home_parsed = parse_url( $old_home_url ); + $old_home_host = $old_home_parsed['host'] . ( isset( $old_home_parsed['port'] ) ? ':' . $old_home_parsed['port'] : '' ); - if ( $old_home_parsed['host'] === $existing_details->domain && $old_home_parsed['path'] === $existing_details->path ) { + if ( $old_home_host === $existing_details->domain && $old_home_parsed['path'] === $existing_details->path ) { $new_home_url = untrailingslashit( sanitize_url( $blog_data['scheme'] . '://' . $new_details->domain . $new_details->path ) ); update_option( 'home', $new_home_url ); } $old_site_url = trailingslashit( esc_url( get_option( 'siteurl' ) ) ); $old_site_parsed = parse_url( $old_site_url ); + $old_site_host = $old_site_parsed['host'] . ( isset( $old_site_parsed['port'] ) ? ':' . $old_site_parsed['port'] : '' ); - if ( $old_site_parsed['host'] === $existing_details->domain && $old_site_parsed['path'] === $existing_details->path ) { + if ( $old_site_host === $existing_details->domain && $old_site_parsed['path'] === $existing_details->path ) { $new_site_url = untrailingslashit( sanitize_url( $blog_data['scheme'] . '://' . $new_details->domain . $new_details->path ) ); update_option( 'siteurl', $new_site_url ); } diff --git a/src/wp-includes/embed.php b/src/wp-includes/embed.php index 6c767cfcab433..915314a7676d8 100644 --- a/src/wp-includes/embed.php +++ b/src/wp-includes/embed.php @@ -627,12 +627,13 @@ function get_oembed_response_data_for_url( $url, $args ) { wp_parse_url( $url ), array( 'host' => '', + 'port' => null, 'path' => '/', ) ); $qv = array( - 'domain' => $url_parts['host'], + 'domain' => $url_parts['host'] . ( $url_parts['port'] ? ':' . $url_parts['port'] : '' ), 'path' => '/', 'update_site_meta_cache' => false, ); diff --git a/src/wp-includes/feed.php b/src/wp-includes/feed.php index 4532697ea5526..ec7c3ca9a9d44 100644 --- a/src/wp-includes/feed.php +++ b/src/wp-includes/feed.php @@ -660,8 +660,14 @@ function rss2_site_icon() { * @return string Correct link for the atom:self element. */ function get_self_link() { - $host = parse_url( home_url() ); - return set_url_scheme( 'http://' . $host['host'] . wp_unslash( $_SERVER['REQUEST_URI'] ) ); + $parsed = parse_url( home_url() ); + + $domain = $parsed['host']; + if ( isset( $parsed['port'] ) ) { + $domain .= ':' . $parsed['port']; + } + + return set_url_scheme( 'http://' . $domain . wp_unslash( $_SERVER['REQUEST_URI'] ) ); } /** diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index b360c6dd34463..76fb2b63c7e51 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -1363,8 +1363,17 @@ function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attac * If currently on HTTPS, prefer HTTPS URLs when we know they're supported by the domain * (which is to say, when they share the domain name of the current request). */ - if ( is_ssl() && ! str_starts_with( $image_baseurl, 'https' ) && parse_url( $image_baseurl, PHP_URL_HOST ) === $_SERVER['HTTP_HOST'] ) { - $image_baseurl = set_url_scheme( $image_baseurl, 'https' ); + if ( is_ssl() && ! str_starts_with( $image_baseurl, 'https' ) ) { + // Since the `Host:` header might contain a port we should + // compare it against the image URL using the same port. + $parsed = parse_url( $image_baseurl ); + $domain = $parsed['host']; + if ( isset( $parsed['port'] ) ) { + $domain .= ':' . $parsed['port']; + } + if ( $_SERVER['HTTP_HOST'] === $domain ) { + $image_baseurl = set_url_scheme( $image_baseurl, 'https' ); + } } /* diff --git a/src/wp-includes/ms-site.php b/src/wp-includes/ms-site.php index 65e7d8d78d57d..6e197587902a5 100644 --- a/src/wp-includes/ms-site.php +++ b/src/wp-includes/ms-site.php @@ -524,11 +524,7 @@ function wp_prepare_site_data( $data, $defaults, $old_site = null ) { function wp_normalize_site_data( $data ) { // Sanitize domain if passed. if ( array_key_exists( 'domain', $data ) ) { - $data['domain'] = trim( $data['domain'] ); - $data['domain'] = preg_replace( '/\s+/', '', sanitize_user( $data['domain'], true ) ); - if ( is_subdomain_install() ) { - $data['domain'] = str_replace( '@', '', $data['domain'] ); - } + $data['domain'] = preg_replace( '/[^a-z0-9\-.:]+/i', '', $data['domain'] ); } // Sanitize path if passed. diff --git a/tests/phpunit/tests/admin/wpCommentsListTable.php b/tests/phpunit/tests/admin/wpCommentsListTable.php index 8ba12eed0e24d..230bd3d2c30e5 100644 --- a/tests/phpunit/tests/admin/wpCommentsListTable.php +++ b/tests/phpunit/tests/admin/wpCommentsListTable.php @@ -204,12 +204,12 @@ public function test_get_views_should_return_views_by_default() { $this->table->prepare_items(); $expected = array( - 'all' => 'All (0)', - 'mine' => 'Mine (0)', - 'moderated' => 'Pending (0)', - 'approved' => 'Approved (0)', - 'spam' => 'Spam (0)', - 'trash' => 'Trash (0)', + 'all' => 'All (0)', + 'mine' => 'Mine (0)', + 'moderated' => 'Pending (0)', + 'approved' => 'Approved (0)', + 'spam' => 'Spam (0)', + 'trash' => 'Trash (0)', ); $this->assertSame( $expected, $this->table->get_views() ); } diff --git a/tests/phpunit/tests/admin/wpPostCommentsListTable.php b/tests/phpunit/tests/admin/wpPostCommentsListTable.php index f69657dd873a5..975bbf2a7c71e 100644 --- a/tests/phpunit/tests/admin/wpPostCommentsListTable.php +++ b/tests/phpunit/tests/admin/wpPostCommentsListTable.php @@ -26,12 +26,12 @@ public function test_get_views_should_return_views_by_default() { $this->table->prepare_items(); $expected = array( - 'all' => 'All (0)', - 'mine' => 'Mine (0)', - 'moderated' => 'Pending (0)', - 'approved' => 'Approved (0)', - 'spam' => 'Spam (0)', - 'trash' => 'Trash (0)', + 'all' => 'All (0)', + 'mine' => 'Mine (0)', + 'moderated' => 'Pending (0)', + 'approved' => 'Approved (0)', + 'spam' => 'Spam (0)', + 'trash' => 'Trash (0)', ); $this->assertSame( $expected, $this->table->get_views() ); } diff --git a/tests/phpunit/tests/admin/wpPrivacyRequestsTable.php b/tests/phpunit/tests/admin/wpPrivacyRequestsTable.php index d729a56bafd24..3be4062190ce9 100644 --- a/tests/phpunit/tests/admin/wpPrivacyRequestsTable.php +++ b/tests/phpunit/tests/admin/wpPrivacyRequestsTable.php @@ -200,7 +200,7 @@ public function data_columns_should_be_sortable() { */ public function test_get_views_should_return_views_by_default() { $expected = array( - 'all' => 'All (0)', + 'all' => 'All (0)', ); $this->assertSame( $expected, $this->get_mocked_class_instance()->get_views() ); diff --git a/tests/phpunit/tests/date/getPermalink.php b/tests/phpunit/tests/date/getPermalink.php index ff7ddcdb27270..70e99bd9e527a 100644 --- a/tests/phpunit/tests/date/getPermalink.php +++ b/tests/phpunit/tests/date/getPermalink.php @@ -35,10 +35,10 @@ public function test_should_return_correct_date_permalink_with_changed_time_zone ) ); - $this->assertSame( 'http://example.org/2018/07/22/21/13/23', get_permalink( $post_id ) ); + $this->assertSame( 'http://' . WP_TESTS_DOMAIN . '/2018/07/22/21/13/23', get_permalink( $post_id ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set date_default_timezone_set( $timezone ); - $this->assertSame( 'http://example.org/2018/07/22/21/13/23', get_permalink( $post_id ) ); + $this->assertSame( 'http://' . WP_TESTS_DOMAIN . '/2018/07/22/21/13/23', get_permalink( $post_id ) ); } } diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 72908c82ef439..268af359356bc 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -495,6 +495,8 @@ protected function add_test_inline_script( $handle, $position ) { * @return array[] */ public function data_provider_to_test_various_strategy_dependency_chains() { + $wp_tests_domain = WP_TESTS_DOMAIN; + return array( 'async-dependent-with-one-blocking-dependency' => array( 'set_up' => function () { @@ -881,8 +883,8 @@ public function data_provider_to_test_various_strategy_dependency_chains() { wp_enqueue_script( 'theme-functions', 'https://example.com/theme-functions.js', array( 'jquery' ), null, array( 'strategy' => 'defer' ) ); }, 'expected_markup' => << - + + HTML , diff --git a/tests/phpunit/tests/functions/referer.php b/tests/phpunit/tests/functions/referer.php index d73360a0a0445..7d0efb31a1697 100644 --- a/tests/phpunit/tests/functions/referer.php +++ b/tests/phpunit/tests/functions/referer.php @@ -31,7 +31,9 @@ public function _fake_subfolder_install() { } public function filter_allowed_redirect_hosts( $hosts ) { - $hosts[] = 'another.' . WP_TESTS_DOMAIN; + // Make sure we're only using the hostname and not anything else that might be in the WP_TESTS_DOMAIN. + $parsed = parse_url( 'http://' . WP_TESTS_DOMAIN ); + $hosts[] = 'another.' . $parsed['host']; return $hosts; } diff --git a/tests/phpunit/tests/functions/wpNonceAys.php b/tests/phpunit/tests/functions/wpNonceAys.php index 02ccbd9b528e0..b7f864d23b1dd 100644 --- a/tests/phpunit/tests/functions/wpNonceAys.php +++ b/tests/phpunit/tests/functions/wpNonceAys.php @@ -27,7 +27,7 @@ public function test_wp_nonce_ays() { */ public function test_wp_nonce_ays_log_out() { $this->expectException( 'WPDieException' ); - $this->expectExceptionMessageMatches( '#You are attempting to log out of Test Blog

Do you really want to log out\?#m' ); + $this->expectExceptionMessageMatches( '#You are attempting to log out of Test Blog

Do you really want to log out\?#m' ); $this->expectExceptionCode( 403 ); wp_nonce_ays( 'log-out' ); diff --git a/tests/phpunit/tests/general/feedLinksExtra.php b/tests/phpunit/tests/general/feedLinksExtra.php index 3bea946e1aff1..2711b338e10d5 100644 --- a/tests/phpunit/tests/general/feedLinksExtra.php +++ b/tests/phpunit/tests/general/feedLinksExtra.php @@ -440,7 +440,7 @@ public function test_feed_links_extra_should_respect_comments_open() { $expected = '' . "\n"; + $expected .= ' href="http://' . WP_TESTS_DOMAIN . '/?feed=rss2&p=' . self::$post_no_comment_id . '" />' . "\n"; $this->assertSame( $expected, get_echo( 'feed_links_extra' ) ); } @@ -455,7 +455,7 @@ public function test_feed_links_extra_should_respect_pings_open() { $expected = '' . "\n"; + $expected .= ' href="http://' . WP_TESTS_DOMAIN . '/?feed=rss2&p=' . self::$post_no_comment_id . '" />' . "\n"; $this->assertSame( $expected, get_echo( 'feed_links_extra' ) ); } @@ -470,7 +470,7 @@ public function test_feed_links_extra_should_respect_post_comment_count() { $expected = '' . "\n"; + $expected .= ' href="http://' . WP_TESTS_DOMAIN . '/?feed=rss2&p=' . self::$post_with_comment_id . '" />' . "\n"; $this->assertSame( $expected, get_echo( 'feed_links_extra' ) ); } @@ -507,7 +507,7 @@ static function () { $expected = '' . "\n"; + $expected .= ' href="http://' . WP_TESTS_DOMAIN . '/?feed=foo&p=' . self::$post_with_comment_id . '" />' . "\n"; $this->assertSame( $expected, get_echo( 'feed_links_extra' ) ); } diff --git a/tests/phpunit/tests/kses.php b/tests/phpunit/tests/kses.php index 12a7bbac29a42..06128970f1f5c 100644 --- a/tests/phpunit/tests/kses.php +++ b/tests/phpunit/tests/kses.php @@ -1732,83 +1732,83 @@ public function test_wp_kses_object_tag_allowed( $html, $expected ) { public function data_wp_kses_object_tag_allowed() { return array( 'valid value for type' => array( - '', - '', + '', + '', ), 'invalid value for type' => array( - '', + '', '', ), 'multiple type attributes, last invalid' => array( - '', - '', + '', + '', ), 'multiple type attributes, first uppercase, last invalid' => array( - '', - '', + '', + '', ), 'multiple type attributes, last upper case and invalid' => array( - '', - '', + '', + '', ), 'multiple type attributes, first invalid' => array( - '', + '', '', ), 'multiple type attributes, first upper case and invalid' => array( - '', + '', '', ), 'multiple type attributes, first invalid, last uppercase' => array( - '', + '', '', ), 'multiple object tags, last invalid' => array( - '', - '', + '', + '', ), 'multiple object tags, first invalid' => array( - '', - '', + '', + '', ), 'type attribute with partially incorrect value' => array( - '', + '', '', ), 'type attribute with empty value' => array( - '', + '', '', ), 'type attribute with no value' => array( - '', + '', '', ), 'no type attribute' => array( - '', + '', '', ), 'different protocol in url' => array( - '', - '', + '', + '', ), 'query string on url' => array( - '', + '', '', ), 'fragment on url' => array( - '', + '', '', ), 'wrong extension' => array( - '', + '', '', ), 'protocol-relative url' => array( - '', + '', '', ), 'unsupported protocol' => array( - '', + '', '', ), 'relative url' => array( @@ -1816,8 +1816,8 @@ public function data_wp_kses_object_tag_allowed() { '', ), 'url with port number-like path' => array( - '', - '', + '', + '', ), ); } @@ -1868,7 +1868,14 @@ public function data_wp_kses_object_data_url_with_port_number_allowed() { * @return array $param with a modified `url`. */ public function wp_kses_upload_dir_filter( $param ) { - $url_with_port_number = is_string( $param['url'] ) ? str_replace( 'example.org', 'example.org:8888', $param['url'] ) : $param['url']; + // Take care to replace the entire domain, including cases where it already has a port number. + $parsed = parse_url( $param['url'] ); + $replace_domain = $parsed['host']; + if ( isset( $parsed['port'] ) ) { + $replace_domain .= ':' . $parsed['port']; + } + + $url_with_port_number = is_string( $param['url'] ) ? str_replace( $replace_domain, 'example.org:8888', $param['url'] ) : $param['url']; $param['url'] = $url_with_port_number; return $param; } diff --git a/tests/phpunit/tests/media/getAdjacentImageLink.php b/tests/phpunit/tests/media/getAdjacentImageLink.php index 7f413cab2ed92..c1e8894995271 100644 --- a/tests/phpunit/tests/media/getAdjacentImageLink.php +++ b/tests/phpunit/tests/media/getAdjacentImageLink.php @@ -32,24 +32,24 @@ public function data_get_adjacent_image_link() { 'when has previous link' => array( 'current_attachment_index' => 3, 'expected_attachment_index' => 2, - 'expected' => '', + 'expected' => '', ), 'with text when has previous link' => array( 'current_attachment_index' => 3, 'expected_attachment_index' => 2, - 'expected' => 'Some text', + 'expected' => 'Some text', 'args' => array( 'text' => 'Some text' ), ), 'when has next link' => array( 'current_attachment_index' => 4, 'expected_attachment_index' => 5, - 'expected' => '', + 'expected' => '', 'args' => array( 'prev' => false ), ), 'with text when has next link' => array( 'current_attachment_index' => 4, 'expected_attachment_index' => 5, - 'expected' => 'Some text', + 'expected' => 'Some text', 'args' => array( 'prev' => false, 'text' => 'Some text', diff --git a/tests/phpunit/tests/media/getNextImageLink.php b/tests/phpunit/tests/media/getNextImageLink.php index b26f1fcd69ec7..3d4ccacc1b307 100644 --- a/tests/phpunit/tests/media/getNextImageLink.php +++ b/tests/phpunit/tests/media/getNextImageLink.php @@ -31,12 +31,12 @@ public function data_get_next_image_link() { 'when has next link' => array( 'current_attachment_index' => 4, 'expected_attachment_index' => 5, - 'expected' => '', + 'expected' => '', ), 'with text when has next link' => array( 'current_attachment_index' => 4, 'expected_attachment_index' => 5, - 'expected' => 'Some text', + 'expected' => 'Some text', 'args' => array( 'text' => 'Some text' ), ), diff --git a/tests/phpunit/tests/media/getPreviousImageLink.php b/tests/phpunit/tests/media/getPreviousImageLink.php index 36652e75ad622..b2b49d28bca41 100644 --- a/tests/phpunit/tests/media/getPreviousImageLink.php +++ b/tests/phpunit/tests/media/getPreviousImageLink.php @@ -31,12 +31,12 @@ public function data_get_previous_image_link() { 'when has previous link' => array( 'current_attachment_index' => 3, 'expected_attachment_index' => 2, - 'expected' => '', + 'expected' => '', ), 'with text when has previous link' => array( 'current_attachment_index' => 3, 'expected_attachment_index' => 2, - 'expected' => 'Some text', + 'expected' => 'Some text', 'args' => array( 'text' => 'Some text' ), ), diff --git a/tests/phpunit/tests/media/nextImageLink.php b/tests/phpunit/tests/media/nextImageLink.php index 569e1900ce634..5e2282e43c485 100644 --- a/tests/phpunit/tests/media/nextImageLink.php +++ b/tests/phpunit/tests/media/nextImageLink.php @@ -30,12 +30,12 @@ public function data_next_image_link() { 'when has next link' => array( 'current_attachment_index' => 4, 'expected_attachment_index' => 5, - 'expected' => '', + 'expected' => '', ), 'with text when has next link' => array( 'current_attachment_index' => 4, 'expected_attachment_index' => 5, - 'expected' => 'Some text', + 'expected' => 'Some text', 'args' => array( 'text' => 'Some text' ), ), diff --git a/tests/phpunit/tests/media/previousImageLink.php b/tests/phpunit/tests/media/previousImageLink.php index c75e08353793e..ae1b18fe3c708 100644 --- a/tests/phpunit/tests/media/previousImageLink.php +++ b/tests/phpunit/tests/media/previousImageLink.php @@ -30,12 +30,12 @@ public function data_previous_image_link() { 'when has previous link' => array( 'current_attachment_index' => 3, 'expected_attachment_index' => 2, - 'expected' => '', + 'expected' => '', ), 'with text when has previous link' => array( 'current_attachment_index' => 3, 'expected_attachment_index' => 2, - 'expected' => 'Some text', + 'expected' => 'Some text', 'args' => array( 'text' => 'Some text' ), ), diff --git a/tests/phpunit/tests/multisite/site.php b/tests/phpunit/tests/multisite/site.php index 3a2d339c0a150..714035999faaa 100644 --- a/tests/phpunit/tests/multisite/site.php +++ b/tests/phpunit/tests/multisite/site.php @@ -1140,6 +1140,22 @@ public function data_wp_insert_site() { 'lang_id' => 1, ), ), + array( + array( + 'domain' => 'example.com:8888', + ), + array( + 'domain' => 'example.com:8888', + 'path' => '/', + 'network_id' => 1, + 'public' => 1, + 'archived' => 0, + 'mature' => 0, + 'spam' => 0, + 'deleted' => 0, + 'lang_id' => 0, + ), + ), ); } @@ -1242,6 +1258,16 @@ public function data_wp_update_site() { 'lang_id' => 1, ), ), + array( + array( + 'domain' => 'example.com:8888', + 'network_id' => 2, + ), + array( + 'domain' => 'example.com:8888', + 'site_id' => 2, + ), + ), ); } @@ -1358,7 +1384,23 @@ public function data_wp_normalize_site_data() { 'domain' => '/another-invalid-domain.com', ), array( - 'domain' => 'another-invalid-domain.com', + 'domain' => 'yetanother-invalid-domain.com', + ), + ), + array( + array( + 'domain' => 'with-port.com:8888', + ), + array( + 'domain' => 'with-port.com:8888', + ), + ), + array( + array( + 'domain' => 'subdomain.with-port.com:8888', + ), + array( + 'domain' => 'subdomain.with-port.com:8888', ), ), array( diff --git a/tests/phpunit/tests/multisite/wpMsUsersListTable.php b/tests/phpunit/tests/multisite/wpMsUsersListTable.php index be17e7ae36470..11f4d847f2f35 100644 --- a/tests/phpunit/tests/multisite/wpMsUsersListTable.php +++ b/tests/phpunit/tests/multisite/wpMsUsersListTable.php @@ -98,8 +98,8 @@ public function test_get_views_should_return_views_by_default() { $super = count( get_super_admins() ); $expected = array( - 'all' => 'All (' . $all . ')', - 'super' => 'Super Admin (' . $super . ')', + 'all' => 'All (' . $all . ')', + 'super' => 'Super Admin (' . $super . ')', ); $this->assertSame( $expected, $this->table->get_views() ); diff --git a/tests/phpunit/tests/pluggable/wpMail.php b/tests/phpunit/tests/pluggable/wpMail.php index f7af48bc067e8..7b88d739add22 100644 --- a/tests/phpunit/tests/pluggable/wpMail.php +++ b/tests/phpunit/tests/pluggable/wpMail.php @@ -221,11 +221,14 @@ public function test_wp_mail_with_from_header_missing_space() { * @ticket 30266 */ public function test_wp_mail_with_empty_from_header() { + // Make sure that we don't add any ports to the from header. + $url_parts = parse_url( 'http://' . WP_TESTS_DOMAIN ); + $to = 'address@tld.com'; $subject = 'Testing'; $message = 'Test Message'; $headers = 'From: '; - $expected = 'From: WordPress '; + $expected = 'From: WordPress '; wp_mail( $to, $subject, $message, $headers ); diff --git a/tests/phpunit/tests/post/wpGetAttachmentLink.php b/tests/phpunit/tests/post/wpGetAttachmentLink.php index 141b8a2427af4..2f900a0bca356 100644 --- a/tests/phpunit/tests/post/wpGetAttachmentLink.php +++ b/tests/phpunit/tests/post/wpGetAttachmentLink.php @@ -61,7 +61,7 @@ public function data_should_apply_attributes_filter() { return array( 'no new attributes' => array( 'attributes' => array(), - 'expected' => "", + 'expected' => "", ), 'one new attribute' => array( 'attributes' => array( diff --git a/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php b/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php index 2957771321921..bf00985132005 100644 --- a/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php +++ b/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php @@ -374,7 +374,7 @@ public function test_json_contents( $groups, array $expected_content = array() ) $expected .= 'null}'; } else { // "About" group: to avoid time difference, use the report's "on" timestamp. - $about_group = '{"about":{"group_label":"About","group_description":"Overview of export report.","items":{"about-1":[{"name":"Report generated for","value":"' . $request->email . '"},{"name":"For site","value":"Test Blog"},{"name":"At URL","value":"http:\/\/example.org"},{"name":"On","value":"{{TIMESTAMP}}"}]}}'; + $about_group = '{"about":{"group_label":"About","group_description":"Overview of export report.","items":{"about-1":[{"name":"Report generated for","value":"' . $request->email . '"},{"name":"For site","value":"Test Blog"},{"name":"At URL","value":"http:\/\/' . WP_TESTS_DOMAIN . '"},{"name":"On","value":"{{TIMESTAMP}}"}]}}'; $expected .= $this->replace_timestamp_placeholder( $actual_json, $about_group ); if ( isset( $expected_content['json'] ) ) { $expected .= $expected_content['json']; @@ -469,7 +469,7 @@ public function data_contents() { 'should contain only about when empty array' => array( 'groups' => array(), 'expected_content' => array( - 'html' => '

About

Overview of export report.

Report generated forexport-requester@example.com
For siteTest Blog
At URLhttp://example.org
On{{TIMESTAMP}}
', + 'html' => '

About

Overview of export report.

Report generated forexport-requester@example.com
For siteTest Blog
At URLhttp://' . WP_TESTS_DOMAIN . '
On{{TIMESTAMP}}
', ), ), // Happy path. @@ -513,7 +513,7 @@ public function data_contents() { ), ), 'expected_content' => array( - 'html' => '

About

Overview of export report.

Report generated forexport-requester@example.com
For siteTest Blog
At URLhttp://example.org
On{{TIMESTAMP}}

User

User’s profile data.

User ID1
User Login Nameuser_login
User Nice NameUser Name
User Emailexport-requester@example.com
User Registration Date2020-01-31 19:29:29
User Display NameUser Name
User NicknameUser
', + 'html' => '

Table of Contents

About

Overview of export report.

Report generated forexport-requester@example.com
For siteTest Blog
At URLhttp://' . WP_TESTS_DOMAIN . '
On{{TIMESTAMP}}

User

User’s profile data.

User ID1
User Login Nameuser_login
User Nice NameUser Name
User Emailexport-requester@example.com
User Registration Date2020-01-31 19:29:29
User Display NameUser Name
User NicknameUser
', 'json' => ',"user":{"group_label":"User","group_description":"User’s profile data.","items":{"user-1":[{"name":"User ID","value":1},{"name":"User Login Name","value":"user_login"},{"name":"User Nice Name","value":"User Name"},{"name":"User Email","value":"export-requester@example.com"},{"name":"User Registration Date","value":"2020-01-31 19:29:29"},{"name":"User Display Name","value":"User Name"},{"name":"User Nickname","value":"User"}]}}', ), ), @@ -623,7 +623,7 @@ public function data_contents() { ), ), 'expected_content' => array( - 'html' => '

Table of Contents

About

Overview of export report.

Report generated forexport-requester@example.com
For siteTest Blog
At URLhttp://example.org
On{{TIMESTAMP}}

User

User’s profile data.

User ID1
User Login Nameuser_login
User Nice NameUser Name
User Emailexport-requester@example.com
User Registration Date2020-01-31 19:29:29
User Display NameUser Name
User NicknameUser

Comments (2)

User’s comment data.

Comment AuthorUser Name
Comment Author Emailexport-requester@example.com
Comment Author IP::1
Comment Author User AgentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Comment Date2020-01-31 19:55:19
Comment ContentTest
Comment URLhttp://localhost:8888/46894/2020/01/31/hello-world/#comment-2
Comment AuthorUser Name
Comment Author Emailexport-requester@example.com
Comment Author IP::1
Comment Author User AgentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Comment Date2020-01-31 20:55:19
Comment ContentTest #2
Comment URLhttp://localhost:8888/46894/2020/01/31/hello-world/#comment-3
', + 'html' => '

Table of Contents

About

Overview of export report.

Report generated forexport-requester@example.com
For siteTest Blog
At URLhttp://' . WP_TESTS_DOMAIN . '
On{{TIMESTAMP}}

User

User’s profile data.

User ID1
User Login Nameuser_login
User Nice NameUser Name
User Emailexport-requester@example.com
User Registration Date2020-01-31 19:29:29
User Display NameUser Name
User NicknameUser

Comments (2)

User’s comment data.

Comment AuthorUser Name
Comment Author Emailexport-requester@example.com
Comment Author IP::1
Comment Author User AgentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Comment Date2020-01-31 19:55:19
Comment ContentTest
Comment URLhttp://localhost:8888/46894/2020/01/31/hello-world/#comment-2
Comment AuthorUser Name
Comment Author Emailexport-requester@example.com
Comment Author IP::1
Comment Author User AgentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Comment Date2020-01-31 20:55:19
Comment ContentTest #2
Comment URLhttp://localhost:8888/46894/2020/01/31/hello-world/#comment-3
', 'json' => ',"user":{"group_label":"User","group_description":"User’s profile data.","items":{"user-1":[{"name":"User ID","value":1},{"name":"User Login Name","value":"user_login"},{"name":"User Nice Name","value":"User Name"},{"name":"User Email","value":"export-requester@example.com"},{"name":"User Registration Date","value":"2020-01-31 19:29:29"},{"name":"User Display Name","value":"User Name"},{"name":"User Nickname","value":"User"}]}},"comments":{"group_label":"Comments","group_description":"User’s comment data.","items":{"comment-2":[{"name":"Comment Author","value":"User Name"},{"name":"Comment Author Email","value":"export-requester@example.com"},{"name":"Comment Author IP","value":"::1"},{"name":"Comment Author User Agent","value":"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/79.0.3945.130 Safari\/537.36"},{"name":"Comment Date","value":"2020-01-31 19:55:19"},{"name":"Comment Content","value":"Test"},{"name":"Comment URL","value":"http:\/\/localhost:8888\/46894\/2020\/01\/31\/hello-world\/#comment-2<\/a>"}],"comment-3":[{"name":"Comment Author","value":"User Name"},{"name":"Comment Author Email","value":"export-requester@example.com"},{"name":"Comment Author IP","value":"::1"},{"name":"Comment Author User Agent","value":"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/79.0.3945.130 Safari\/537.36"},{"name":"Comment Date","value":"2020-01-31 20:55:19"},{"name":"Comment Content","value":"Test #2"},{"name":"Comment URL","value":"http:\/\/localhost:8888\/46894\/2020\/01\/31\/hello-world\/#comment-3<\/a>"}]}}', ), ), diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php index a81ef0d4338df..3296f15905c44 100644 --- a/tests/phpunit/tests/rest-api/rest-schema-setup.php +++ b/tests/phpunit/tests/rest-api/rest-schema-setup.php @@ -210,6 +210,10 @@ private function is_builtin_route( $route ) { } public function test_build_wp_api_client_fixtures() { + if ( 'example.org' !== WP_TESTS_DOMAIN ) { + $this->markTestSkipped( 'This test can only be run on example.org' ); + } + // Set up data for individual endpoint responses. We need to specify // lots of different fields on these objects, otherwise the generated // fixture file will be different between runs of PHPUnit tests, which diff --git a/tests/phpunit/tests/rest-api/rest-widgets-controller.php b/tests/phpunit/tests/rest-api/rest-widgets-controller.php index 69672a722627c..c0a311f25f0a9 100644 --- a/tests/phpunit/tests/rest-api/rest-widgets-controller.php +++ b/tests/phpunit/tests/rest-api/rest-widgets-controller.php @@ -391,7 +391,7 @@ public function test_get_items() { 'id' => 'rss-1', 'id_base' => 'rss', 'sidebar' => 'sidebar-1', - 'rendered' => 'RSS RSS test', + 'rendered' => 'RSS RSS test', ), array( 'id' => 'testwidget', diff --git a/tests/phpunit/tests/user/wpListAuthors.php b/tests/phpunit/tests/user/wpListAuthors.php index 90a22e39d9edf..f05e534b551cc 100644 --- a/tests/phpunit/tests/user/wpListAuthors.php +++ b/tests/phpunit/tests/user/wpListAuthors.php @@ -279,7 +279,7 @@ public function test_wp_list_authors_feed_image() { wp_list_authors( array( 'echo' => false, - 'feed_image' => WP_TESTS_DOMAIN . '/path/to/a/graphic.png', + 'feed_image' => 'http://' . WP_TESTS_DOMAIN . '/path/to/a/graphic.png', ) ) ); diff --git a/tests/phpunit/tests/user/wpListUsers.php b/tests/phpunit/tests/user/wpListUsers.php index 2d76ad16b27b8..56bcdb5485792 100644 --- a/tests/phpunit/tests/user/wpListUsers.php +++ b/tests/phpunit/tests/user/wpListUsers.php @@ -119,30 +119,30 @@ public function data_should_create_a_user_list() { 'args' => array( 'feed' => 'User feed', ), - 'expected' => '
  • jane (User feed)
  • ' . - '
  • michelle (User feed)
  • ' . - '
  • paul (User feed)
  • ' . - '
  • zack (User feed)
  • ', + 'expected' => '
  • jane (User feed)
  • ' . + '
  • michelle (User feed)
  • ' . + '
  • paul (User feed)
  • ' . + '
  • zack (User feed)
  • ', ), 'the feed of each user and an image' => array( 'args' => array( 'feed' => 'User feed with image', 'feed_image' => 'http://example.org/image.jpg', ), - 'expected' => '
  • jane User feed with image
  • ' . - '
  • michelle User feed with image
  • ' . - '
  • paul User feed with image
  • ' . - '
  • zack User feed with image
  • ', + 'expected' => '
  • jane User feed with image
  • ' . + '
  • michelle User feed with image
  • ' . + '
  • paul User feed with image
  • ' . + '
  • zack User feed with image
  • ', ), 'a feed of the specified type' => array( 'args' => array( 'feed' => 'User feed as atom', 'feed_type' => 'atom', ), - 'expected' => '
  • jane (User feed as atom)
  • ' . - '
  • michelle (User feed as atom)
  • ' . - '
  • paul (User feed as atom)
  • ' . - '
  • zack (User feed as atom)
  • ', + 'expected' => '
  • jane (User feed as atom)
  • ' . + '
  • michelle (User feed as atom)
  • ' . + '
  • paul (User feed as atom)
  • ' . + '
  • zack (User feed as atom)
  • ', ), 'no output via echo' => array( 'args' => array( diff --git a/tools/local-env/default.template b/tools/local-env/default.template index a5638656a4997..995913fb453a2 100644 --- a/tools/local-env/default.template +++ b/tools/local-env/default.template @@ -15,6 +15,12 @@ server { absolute_redirect off; + if (!-e $request_filename) { + rewrite /wp-admin$ $scheme://$host$request_uri/ permanent; + rewrite ^(/[^/]+)?(/wp-.*) $2 last; + rewrite ^(/[^/]+)?(/.*\.php) $2 last; + } + location / { try_files $uri $uri/ /index.php?$args; } diff --git a/tools/local-env/scripts/install.js b/tools/local-env/scripts/install.js index 891d43cc42cab..7bc2915fd44b7 100644 --- a/tools/local-env/scripts/install.js +++ b/tools/local-env/scripts/install.js @@ -29,6 +29,7 @@ const testConfig = readFileSync( 'wp-tests-config-sample.php', 'utf8' ) .replace( 'yourusernamehere', 'root' ) .replace( 'yourpasswordhere', 'password' ) .replace( 'localhost', 'mysql' ) + .replace( "'WP_TESTS_DOMAIN', 'example.org'", `'WP_TESTS_DOMAIN', '${process.env.LOCAL_WP_TESTS_DOMAIN}'` ) .concat( "\ndefine( 'FS_METHOD', 'direct' );\n" ); writeFileSync( 'wp-tests-config.php', testConfig ); @@ -37,7 +38,8 @@ writeFileSync( 'wp-tests-config.php', testConfig ); wait_on( { resources: [ `tcp:localhost:${process.env.LOCAL_PORT}`] } ) .then( () => { wp_cli( 'db reset --yes' ); - wp_cli( `core install --title="WordPress Develop" --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:${process.env.LOCAL_PORT}` ); + const installCommand = process.env.LOCAL_MULTISITE === 'true' ? 'multisite-install' : 'install'; + wp_cli( `core ${ installCommand } --title="WordPress Develop" --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:${process.env.LOCAL_PORT}` ); } ); /**