diff --git a/.env b/.env index 8af24c4816363..9affb93f5321e 100644 --- a/.env +++ b/.env @@ -6,7 +6,6 @@ # # Below, the following substitutions can be made: # - '{version}': any major.minor PHP version from 5.2 onwards. -# - '{phpunit_version}': any major PHPUnit version starting with 4. ## # The site will be available at http://localhost:LOCAL_PORT @@ -18,27 +17,6 @@ LOCAL_DIR=src # The PHP version to use. Valid options are 'latest', and '{version}-fpm'. LOCAL_PHP=latest -## -# The PHPUnit version to use when running tests. -# -# Support for new PHPUnit versions is not backported to past versions, so some old WordPress branches require an older -# version to run tests. -# -# Valid versions are: -# - 'latest' for the highest version of PHPUnit supported on the highest version of PHP supported. -# - '{version}-fpm' for the highest version of PHPUnit supported on the specified version of PHP. -# - '{phpunit_version}-php-{version}-fpm' for a specific version of PHPUnit on the specified version of PHP. This format -# is only available for PHP versions 5.6 and higher. -# -# For the full list of available options, see https://hub.docker.com/r/wordpressdevelop/phpunit/tags. -# -# For full documentation on PHPUnit compatibility and WordPress versions, see -# https://make.wordpress.org/core/handbook/references/phpunit-compatibility-and-wordpress-versions/. -# -# This defaults to the value assigned to the value of LOCAL_PHP. -## -LOCAL_PHPUNIT=${LOCAL_PHP} - # Whether or not to enable XDebug. LOCAL_PHP_XDEBUG=false diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml index 8edb2f281f7d2..164642e1ad785 100644 --- a/.github/workflows/coding-standards.yml +++ b/.github/workflows/coding-standards.yml @@ -146,3 +146,14 @@ jobs: - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ phpcs, jshint ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/end-to-end-tests.yml b/.github/workflows/end-to-end-tests.yml index 9358fc9520b1e..16ad0c0f99fbb 100644 --- a/.github/workflows/end-to-end-tests.yml +++ b/.github/workflows/end-to-end-tests.yml @@ -116,3 +116,14 @@ jobs: - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ e2e-tests ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/javascript-tests.yml b/.github/workflows/javascript-tests.yml index b1226baccac0b..a13a3b095e0c7 100644 --- a/.github/workflows/javascript-tests.yml +++ b/.github/workflows/javascript-tests.yml @@ -85,3 +85,14 @@ jobs: - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ test-js ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/php-compatibility.yml b/.github/workflows/php-compatibility.yml index b5316fd1a639c..2121ddeb143d9 100644 --- a/.github/workflows/php-compatibility.yml +++ b/.github/workflows/php-compatibility.yml @@ -87,3 +87,14 @@ jobs: - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ php-compatibility ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml index 641965103f47d..ef328a5761f2a 100644 --- a/.github/workflows/phpunit-tests.yml +++ b/.github/workflows/phpunit-tests.yml @@ -66,19 +66,19 @@ jobs: strategy: fail-fast: false matrix: - php: [ '5.6.20', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1' ] + php: [ '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1' ] os: [ ubuntu-latest ] memcached: [ false ] split_slow: [ false ] multisite: [ false, true ] include: # Additional "slow" jobs for PHP 5.6. - - php: '5.6.20' + - php: '5.6' os: ubuntu-latest memcached: false multisite: false split_slow: true - - php: '5.6.20' + - php: '5.6' os: ubuntu-latest memcached: false multisite: true @@ -127,7 +127,6 @@ jobs: - name: "Get last Monday's date" id: get-date run: echo "::set-output name=date::$(/bin/date -u --date='last Mon' "+%F")" - shell: bash - name: Get Composer cache directory id: composer-cache @@ -192,41 +191,41 @@ jobs: - name: Run slow PHPUnit tests if: ${{ matrix.split_slow }} - run: npm run test:php-composer -- --verbose -c ${{ env.PHPUNIT_CONFIG }} --group ${{ env.SLOW_TESTS }} + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --group ${{ env.SLOW_TESTS }} - name: Run PHPUnit tests for single site excluding slow tests if: ${{ matrix.php < '7.0' && ! matrix.split_slow && ! matrix.multisite }} - run: npm run test:php-composer -- --verbose -c ${{ env.PHPUNIT_CONFIG }} --exclude-group ${{ env.SLOW_TESTS }},ajax,ms-files,ms-required + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --exclude-group ${{ env.SLOW_TESTS }},ajax,ms-files,ms-required - name: Run PHPUnit tests for Multisite excluding slow tests if: ${{ matrix.php < '7.0' && ! matrix.split_slow && matrix.multisite }} - run: npm run test:php-composer -- --verbose -c ${{ env.PHPUNIT_CONFIG }} --exclude-group ${{ env.SLOW_TESTS }},ajax,ms-files,ms-excluded,oembed-headers + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --exclude-group ${{ env.SLOW_TESTS }},ajax,ms-files,ms-excluded,oembed-headers - name: Run PHPUnit tests if: ${{ matrix.php >= '7.0' }} continue-on-error: ${{ matrix.php == '8.1' }} - run: npm run test:php-composer -- --verbose -c ${{ env.PHPUNIT_CONFIG }} + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} - name: Run AJAX tests if: ${{ ! matrix.split_slow }} continue-on-error: ${{ matrix.php == '8.1' }} - run: npm run test:php-composer -- --verbose -c ${{ env.PHPUNIT_CONFIG }} --group ajax + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --group ajax - name: Run ms-files tests as a multisite install if: ${{ matrix.multisite && ! matrix.split_slow }} continue-on-error: ${{ matrix.php == '8.1' }} - run: npm run test:php-composer -- --verbose -c tests/phpunit/multisite.xml --group ms-files + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c tests/phpunit/multisite.xml --group ms-files - name: Run external HTTP tests if: ${{ ! matrix.multisite && ! matrix.split_slow }} continue-on-error: ${{ matrix.php == '8.1' }} - run: npm run test:php-composer -- --verbose -c phpunit.xml.dist --group external-http + run: node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit --verbose -c phpunit.xml.dist --group external-http # __fakegroup__ is excluded to force PHPUnit to ignore the settings in phpunit.xml.dist. - name: Run (xDebug) tests if: ${{ ! matrix.split_slow }} continue-on-error: ${{ matrix.php == '8.1' }} - run: LOCAL_PHP_XDEBUG=true npm run test:php-composer -- -v --group xdebug --exclude-group __fakegroup__ + run: LOCAL_PHP_XDEBUG=true node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit -v --group xdebug --exclude-group __fakegroup__ - name: Ensure version-controlled files are not modified or deleted run: git diff --exit-code @@ -243,3 +242,14 @@ jobs: env: WPT_REPORT_API_KEY: "${{ secrets.WPT_REPORT_API_KEY }}" run: docker-compose run --rm -e WPT_REPORT_API_KEY -e WPT_PREPARE_DIR=/var/www -e WPT_TEST_DIR=/var/www php php test-runner/report.php + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ test-php ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/slack-notifications.yml b/.github/workflows/slack-notifications.yml index 8639425cd12d0..0e435eb5b7382 100644 --- a/.github/workflows/slack-notifications.yml +++ b/.github/workflows/slack-notifications.yml @@ -1,6 +1,7 @@ ## -# Posts messages to the Making WordPress Core Slack Instance by -# submitting data to Slack webhook URLs received by Slack Workflows. +# A reusable workflow for posting messages to the Making WordPress +# Core Slack Instance by submitting data to Slack webhook URLs +# received by Slack Workflows. ## name: Slack Notifications @@ -18,9 +19,26 @@ on: types: - completed branches: - - master - - trunk - - '[3-9].[0-9]' + - '[3-4].[0-9]' + - '5.[0-8]' + + workflow_call: + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: + description: 'The Slack webhook URL for a successful build.' + required: true + SLACK_GHA_CANCELLED_WEBHOOK: + description: 'The Slack webhook URL for a cancelled build.' + required: true + SLACK_GHA_FIXED_WEBHOOK: + description: 'The Slack webhook URL for a fixed build.' + required: true + SLACK_GHA_FAILURE_WEBHOOK: + description: 'The Slack webhook URL for a failed build.' + required: true + +env: + CURRENT_BRANCH: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch || github.ref_name }} jobs: # Gathers the details needed for Slack notifications. @@ -29,8 +47,11 @@ jobs: # submit data to Slack webhook URLs configured to post messages. # # Performs the following steps: + # - Retrieves the workflow ID (if necessary). + # - Retrieves the workflow URL (if necessary). # - Retrieves the previous workflow run and stores its conclusion. # - Sets the previous conclusion as an output. + # - Prepares the commit message. # - Constructs and stores a message payload as an output. prepare: name: Prepare notifications @@ -41,35 +62,70 @@ jobs: payload: ${{ steps.create-payload.outputs.payload }} steps: + - name: Get the workflow ID + id: current-workflow-id + if: ${{ github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} + uses: actions/github-script@441359b1a30438de65712c2fbca0abe4816fa667 # v5.0.0 + with: + script: | + const workflow_run = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.run_id }}, + }); + return workflow_run.data.workflow_id; + - name: Get details about the previous workflow run id: previous-result - uses: actions/github-script@a3e7071a34d7e1f219a8a4de9a5e0a34d1ee1293 # v4.0.2 + uses: actions/github-script@441359b1a30438de65712c2fbca0abe4816fa667 # v5.0.0 with: script: | - const workflow_runs = await github.actions.listWorkflowRuns({ + const previous_runs = await github.rest.actions.listWorkflowRuns({ owner: context.repo.owner, repo: context.repo.repo, - workflow_id: ${{ github.event.workflow_run.workflow_id }}, - branch: '${{ github.event.workflow_run.head_branch }}', + workflow_id: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.workflow_id || steps.current-workflow-id.outputs.result }}, + branch: '${{ env.CURRENT_BRANCH }}', per_page: 1, page: 2, }); - return workflow_runs.data.workflow_runs[0].conclusion; + return previous_runs.data.workflow_runs[0].conclusion; - name: Store previous conclusion as an output id: previous-conclusion run: echo "::set-output name=previous_conclusion::${{ steps.previous-result.outputs.result }}" + - name: Get the commit message + id: current-commit-message + uses: actions/github-script@441359b1a30438de65712c2fbca0abe4816fa667 # v5.0.0 + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }} + with: + script: | + const commit_details = await github.rest.repos.getCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: '${{ github.sha }}' + }); + return commit_details.data.commit.message; + + - name: Prepare commit message. + id: commit-message + run: | + COMMIT_MESSAGE=$(cat <<'EOF' | awk 'NR==1' | sed 's/`/\\`/g' | sed 's/\"/\\\\\\"/g' | sed 's/\$/\\$/g' + ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_commit.message || ( github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' ) && fromJson( steps.current-commit-message.outputs.result ) || github.event.head_commit.message }} + EOF + ) + echo "::set-output name=commit_message_escaped::${COMMIT_MESSAGE}" + - name: Construct payload and store as an output id: create-payload - run: echo "::set-output name=payload::{\"workflow_name\":\"${{ github.event.workflow_run.name }}\",\"ref_name\":\"${{ github.event.workflow_run.head_branch }}\",\"run_url\":\"${{ github.event.workflow_run.html_url }}\"}" + run: echo "::set-output name=payload::{\"workflow_name\":\"${{ github.event_name == 'workflow_run' && github.event.workflow_run.name || github.workflow }}\",\"ref_name\":\"${{ env.CURRENT_BRANCH }}\",\"run_url\":\"https://github.com/WordPress/wordpress-develop/actions/runs/${{ github.event_name == 'workflow_run' && github.event.workflow_run.id || github.run_id }}\",\"commit_message\":\"${{ steps.commit-message.outputs.commit_message_escaped }}\"}" # Posts notifications when a workflow fails. failure: name: Failure notifications runs-on: ubuntu-latest needs: [ prepare ] - if: ${{ github.event.workflow_run.conclusion == 'failure' }} + if: ${{ github.event_name == 'push' && failure() || github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure' }} steps: - name: Post failure notifications to Slack @@ -84,7 +140,7 @@ jobs: name: Fixed notifications runs-on: ubuntu-latest needs: [ prepare ] - if: ${{ needs.prepare.outputs.previous_conclusion == 'failure' && github.event.workflow_run.conclusion == 'success' }} + if: ${{ needs.prepare.outputs.previous_conclusion == 'failure' && ( github.event_name == 'push' && success() || github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' ) }} steps: - name: Post failure notifications to Slack @@ -99,7 +155,7 @@ jobs: name: Success notifications runs-on: ubuntu-latest needs: [ prepare ] - if: ${{ github.event.workflow_run.conclusion == 'success' }} + if: ${{ github.event_name == 'push' && success() || github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' }} steps: - name: Post success notifications to Slack @@ -114,7 +170,7 @@ jobs: name: Cancelled notifications runs-on: ubuntu-latest needs: [ prepare ] - if: ${{ github.event.workflow_run.conclusion == 'cancelled' }} + if: ${{ github.event_name == 'push' && cancelled() || github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'cancelled' }} steps: - name: Post cancelled notifications to Slack diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml index 3c804c5ca6459..cbf18067e9c00 100644 --- a/.github/workflows/test-coverage.yml +++ b/.github/workflows/test-coverage.yml @@ -90,7 +90,6 @@ jobs: - name: "Get last Monday's date" id: get-date run: echo "::set-output name=date::$(/bin/date -u --date='last Mon' "+%F")" - shell: bash - name: Get Composer cache directory id: composer-cache @@ -144,7 +143,7 @@ jobs: - name: Run tests as a single site if: ${{ ! matrix.multisite }} - run: npm run test:php-composer -- --verbose -c phpunit.xml.dist --coverage-clover wp-code-coverage-single-clover-${{ github.sha }}.xml + run: npm run test:php -- --verbose -c phpunit.xml.dist --coverage-clover wp-code-coverage-single-clover-${{ github.sha }}.xml - name: Ensure version-controlled files are not modified during the tests run: git diff --exit-code @@ -158,7 +157,7 @@ jobs: - name: Run tests as a multisite install if: ${{ matrix.multisite }} - run: npm run test:php-composer -- --verbose -c tests/phpunit/multisite.xml --coverage-clover wp-code-coverage-multisite-clover-${{ github.sha }}.xml + run: npm run test:php -- --verbose -c tests/phpunit/multisite.xml --coverage-clover wp-code-coverage-multisite-clover-${{ github.sha }}.xml - name: Ensure version-controlled files are not modified during the tests run: git diff --exit-code @@ -169,3 +168,14 @@ jobs: with: file: wp-code-coverage-multisite-clover-${{ github.sha }}.xml flags: multisite,php + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ test-coverage-report ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/test-npm.yml b/.github/workflows/test-npm.yml index 3774ee2851876..207882513aec9 100644 --- a/.github/workflows/test-npm.yml +++ b/.github/workflows/test-npm.yml @@ -154,3 +154,14 @@ jobs: - name: Ensure version-controlled files are not modified or deleted during building and cleaning run: git diff --exit-code + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ test-npm, test-npm-macos ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/.github/workflows/test-old-branches.yml b/.github/workflows/test-old-branches.yml index 2bb5664a987be..7051b727d964b 100644 --- a/.github/workflows/test-old-branches.yml +++ b/.github/workflows/test-old-branches.yml @@ -69,3 +69,14 @@ jobs: workflow_id: '${{ matrix.workflow }}', ref: '${{ matrix.branch }}' }); + + slack-notifications: + name: Slack Notifications + uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@master + needs: [ dispatch-workflows-for-old-branches ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + secrets: + SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }} + SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }} + SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }} + SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }} diff --git a/Gruntfile.js b/Gruntfile.js index 7aa793a089fc3..369079dc1db22 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -123,6 +123,7 @@ module.exports = function(grunt) { ], 'webpack-assets': [ WORKING_DIR + 'wp-includes/assets/*', + WORKING_DIR + 'wp-includes/css/dist/', '!' + WORKING_DIR + 'wp-includes/assets/script-loader-packages.php' ], dynamic: { diff --git a/docker-compose.yml b/docker-compose.yml index 12f7772607e35..7fe9b524c7aab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,10 +37,10 @@ services: - wpdevnet environment: - LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} - LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} - PHP_FPM_UID: ${PHP_FPM_UID-1000} - PHP_FPM_GID: ${PHP_FPM_GID-1000} + - LOCAL_PHP_XDEBUG=${LOCAL_PHP_XDEBUG-false} + - LOCAL_PHP_MEMCACHED=${LOCAL_PHP_MEMCACHED-false} + - PHP_FPM_UID=${PHP_FPM_UID-1000} + - PHP_FPM_GID=${PHP_FPM_GID-1000} volumes: - ./tools/local-env/php-config.ini:/usr/local/etc/php/conf.d/php-config.ini @@ -81,10 +81,10 @@ services: - wpdevnet environment: - LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} - LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} - PHP_FPM_UID: ${PHP_FPM_UID-1000} - PHP_FPM_GID: ${PHP_FPM_GID-1000} + - LOCAL_PHP_XDEBUG=${LOCAL_PHP_XDEBUG-false} + - LOCAL_PHP_MEMCACHED=${LOCAL_PHP_MEMCACHED-false} + - PHP_FPM_UID=${PHP_FPM_UID-1000} + - PHP_FPM_GID=${PHP_FPM_GID-1000} volumes: - ./:/var/www @@ -92,41 +92,9 @@ services: # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly. init: true - ## - # The PHPUnit container. - ## - phpunit: - image: wordpressdevelop/phpunit:${LOCAL_PHPUNIT-latest} - - networks: - - wpdevnet - - environment: - LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} - LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} - LOCAL_DIR: ${LOCAL_DIR-src} - WP_MULTISITE: ${WP_MULTISITE-false} - PHP_FPM_UID: ${PHP_FPM_UID-1000} - PHP_FPM_GID: ${PHP_FPM_GID-1000} - GITHUB_REF: ${GITHUB_REF-false} - GITHUB_EVENT_NAME: ${GITHUB_EVENT_NAME-false} - - volumes: - - ./tools/local-env/phpunit-config.ini:/usr/local/etc/php/conf.d/phpunit-config.ini - - ./:/var/www - - phpunit-uploads:/var/www/${LOCAL_DIR-src}/wp-content/uploads - - # The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly. - init: true - - depends_on: - - mysql - volumes: # So that sites aren't wiped every time containers are restarted, MySQL uses a persistent volume. mysql: {} - # Using a volume for the uploads directory improves PHPUnit performance. - phpunit-uploads: {} networks: # Creating our own network allows us to connect between containers using their service name. diff --git a/package-lock.json b/package-lock.json index 90ffcd5180e4f..ff9f23a55ca6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,26 +13,26 @@ } }, "@babel/compat-data": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", - "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", "dev": true }, "@babel/core": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", - "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", + "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.5", - "@babel/helper-compilation-targets": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helpers": "^7.14.6", - "@babel/parser": "^7.14.6", + "@babel/generator": "^7.15.0", + "@babel/helper-compilation-targets": "^7.15.0", + "@babel/helper-module-transforms": "^7.15.0", + "@babel/helpers": "^7.14.8", + "@babel/parser": "^7.15.0", "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5", + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -42,9 +42,9 @@ }, "dependencies": { "@babel/parser": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", - "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", "dev": true }, "json5": { @@ -65,12 +65,12 @@ } }, "@babel/generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", - "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", + "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", "dev": true, "requires": { - "@babel/types": "^7.14.5", + "@babel/types": "^7.15.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -95,12 +95,12 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", - "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", + "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.15.0", "@babel/helper-validator-option": "^7.14.5", "browserslist": "^4.16.6", "semver": "^6.3.0" @@ -115,16 +115,16 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz", - "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", + "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-function-name": "^7.14.5", - "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-split-export-declaration": "^7.14.5" } }, @@ -201,12 +201,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", - "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", + "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.0" } }, "@babel/helper-module-imports": { @@ -218,19 +218,19 @@ } }, "@babel/helper-module-transforms": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", - "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", + "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", - "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-replace-supers": "^7.15.0", + "@babel/helper-simple-access": "^7.14.8", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.9", "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" } }, "@babel/helper-optimise-call-expression": { @@ -260,24 +260,24 @@ } }, "@babel/helper-replace-supers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", - "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", + "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" } }, "@babel/helper-simple-access": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", - "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", + "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.14.8" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -299,9 +299,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", - "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==" + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==" }, "@babel/helper-validator-option": { "version": "7.14.5", @@ -322,14 +322,14 @@ } }, "@babel/helpers": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", - "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", + "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", "dev": true, "requires": { "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/traverse": "^7.15.0", + "@babel/types": "^7.15.0" } }, "@babel/highlight": { @@ -372,9 +372,9 @@ } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", - "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", + "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5", @@ -721,18 +721,18 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", - "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", + "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-classes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", - "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", + "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", @@ -840,14 +840,14 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", - "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", + "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-module-transforms": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-simple-access": "^7.14.8", "babel-plugin-dynamic-import-node": "^2.3.3" } }, @@ -875,9 +875,9 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", - "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", + "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" @@ -930,25 +930,25 @@ } }, "@babel/plugin-transform-react-display-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.5.tgz", - "integrity": "sha512-07aqY1ChoPgIxsuDviptRpVkWCSbXWmzQqcgy65C6YSFOfPFvb/DX3bBRHh7pCd/PMEEYHYWUTSVkCbkVainYQ==", + "version": "7.15.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", + "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.5.tgz", - "integrity": "sha512-7RylxNeDnxc1OleDm0F5Q/BSL+whYRbOAR+bwgCxIr0L32v7UFh/pz1DLMZideAUxKT6eMoS2zQH6fyODLEi8Q==", + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", + "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-module-imports": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/types": "^7.14.9" } }, "@babel/plugin-transform-react-jsx-development": { @@ -989,9 +989,9 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", - "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz", + "integrity": "sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.14.5", @@ -1057,12 +1057,12 @@ } }, "@babel/plugin-transform-typescript": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz", - "integrity": "sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz", + "integrity": "sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.6", + "@babel/helper-create-class-features-plugin": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-typescript": "^7.14.5" } @@ -1087,17 +1087,17 @@ } }, "@babel/preset-env": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.7.tgz", - "integrity": "sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz", + "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.7", - "@babel/helper-compilation-targets": "^7.14.5", + "@babel/compat-data": "^7.15.0", + "@babel/helper-compilation-targets": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-validator-option": "^7.14.5", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-async-generator-functions": "^7.14.7", + "@babel/plugin-proposal-async-generator-functions": "^7.14.9", "@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-class-static-block": "^7.14.5", "@babel/plugin-proposal-dynamic-import": "^7.14.5", @@ -1130,7 +1130,7 @@ "@babel/plugin-transform-async-to-generator": "^7.14.5", "@babel/plugin-transform-block-scoped-functions": "^7.14.5", "@babel/plugin-transform-block-scoping": "^7.14.5", - "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.9", "@babel/plugin-transform-computed-properties": "^7.14.5", "@babel/plugin-transform-destructuring": "^7.14.7", "@babel/plugin-transform-dotall-regex": "^7.14.5", @@ -1141,10 +1141,10 @@ "@babel/plugin-transform-literals": "^7.14.5", "@babel/plugin-transform-member-expression-literals": "^7.14.5", "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.15.0", "@babel/plugin-transform-modules-systemjs": "^7.14.5", "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", "@babel/plugin-transform-new-target": "^7.14.5", "@babel/plugin-transform-object-super": "^7.14.5", "@babel/plugin-transform-parameters": "^7.14.5", @@ -1159,11 +1159,11 @@ "@babel/plugin-transform-unicode-escapes": "^7.14.5", "@babel/plugin-transform-unicode-regex": "^7.14.5", "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.14.5", + "@babel/types": "^7.15.0", "babel-plugin-polyfill-corejs2": "^0.2.2", "babel-plugin-polyfill-corejs3": "^0.2.2", "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.15.0", + "core-js-compat": "^3.16.0", "semver": "^6.3.0" }, "dependencies": { @@ -1203,14 +1203,14 @@ } }, "@babel/preset-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz", - "integrity": "sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz", + "integrity": "sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.14.5" + "@babel/plugin-transform-typescript": "^7.15.0" } }, "@babel/runtime": { @@ -1222,12 +1222,12 @@ } }, "@babel/runtime-corejs3": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz", - "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.3.tgz", + "integrity": "sha512-30A3lP+sRL6ml8uhoJSs+8jwpKzbw8CqBvDc1laeptxPm5FahumJxirigcbD2qTs71Sonvj1cyZB0OKGAmxQ+A==", "dev": true, "requires": { - "core-js-pure": "^3.15.0", + "core-js-pure": "^3.16.0", "regenerator-runtime": "^0.13.4" } }, @@ -1243,44 +1243,44 @@ }, "dependencies": { "@babel/parser": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", - "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", "dev": true } } }, "@babel/traverse": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", - "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", + "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.5", + "@babel/generator": "^7.15.0", "@babel/helper-function-name": "^7.14.5", "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.7", - "@babel/types": "^7.14.5", + "@babel/parser": "^7.15.0", + "@babel/types": "^7.15.0", "debug": "^4.1.0", "globals": "^11.1.0" }, "dependencies": { "@babel/parser": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", - "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", + "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", "dev": true } } }, "@babel/types": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", - "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", + "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", "requires": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" } }, @@ -1425,10 +1425,21 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, + "@es-joy/jsdoccomment": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.6.0.tgz", + "integrity": "sha512-zT1EtysKMITJ7vE4RvOJqitxk/Str6It8hq+fykxkwLuTyzgak+TnVuVSIyovT/qrEz3i46ypCSXgNtIDYwNOg==", + "dev": true, + "requires": { + "comment-parser": "^1.1.5", + "esquery": "^1.4.0", + "jsdoctypeparser": "^9.0.0" + } + }, "@eslint/eslintrc": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", - "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -1443,9 +1454,9 @@ }, "dependencies": { "globals": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", - "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -1656,6 +1667,12 @@ } } }, + "@gar/promisify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", + "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", + "dev": true + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -2154,6 +2171,27 @@ "fastq": "^1.6.0" } }, + "@npmcli/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "@npmcli/move-file": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", @@ -2182,15 +2220,15 @@ } }, "@polka/url": { - "version": "1.0.0-next.15", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz", - "integrity": "sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==", + "version": "1.0.0-next.20", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.20.tgz", + "integrity": "sha512-88p7+M0QGxKpmnkfXjS4V26AnoC/eiqZutE8GLdaI5X12NY75bXSdTY9NkmYb2Xyk1O+MmkuO6Frmsj84V6I8Q==", "dev": true }, "@popperjs/core": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz", - "integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==" + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.3.tgz", + "integrity": "sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==" }, "@sideway/address": { "version": "4.1.1", @@ -2364,9 +2402,9 @@ "dev": true }, "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -2411,9 +2449,9 @@ }, "dependencies": { "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -2616,10 +2654,16 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/mdast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.4.tgz", - "integrity": "sha512-gIdhbLDFlspL53xzol2hVzrXAbzt71erJHoOwQZWssjaiouOotf03lNtMmFm9VfFkvnLWccSVjUAZGQ5Kqw+jA==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", + "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", "dev": true, "requires": { "@types/unist": "*" @@ -2671,9 +2715,9 @@ "dev": true }, "@types/react": { - "version": "16.14.11", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.11.tgz", - "integrity": "sha512-Don0MtsZZ3fjwTJ2BsoqkyOy7e176KplEAKOpr/4XDdzinlyJBn9yfsKn5mcSgn4kh1B22+3tBnzBC1z63ybtQ==", + "version": "16.14.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.14.tgz", + "integrity": "sha512-uwIWDYW8LznHzEMJl7ag9St1RsK0gw/xaFZ5+uI1ZM1HndwUgmPH3/wQkSb87GkOVg7shUxnpNW8DcN0AzvG5Q==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -2729,9 +2773,9 @@ } }, "@types/unist": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.5.tgz", - "integrity": "sha512-wnra4Vw9dopnuybR6HBywJ/URYpYrKLoepBTEtgfJup8Ahoi2zJECPP2cwiXp7btTvOT2CULv87aQRA4eZSP6g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, "@types/webpack": { @@ -2757,9 +2801,9 @@ } }, "@types/webpack-sources": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.1.tgz", - "integrity": "sha512-MjM1R6iuw8XaVbtkCBz0N349cyqBjJHCbQiOeppe3VBeFvxqs74RKHAVt9LkxTnUWc7YLZOEsUfPUnmK6SBPKQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", "dev": true, "requires": { "@types/node": "*", @@ -2801,13 +2845,13 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.3.tgz", - "integrity": "sha512-jW8sEFu1ZeaV8xzwsfi6Vgtty2jf7/lJmQmDkDruBjYAbx5DA8JtbcMnP0rNPUG+oH5GoQBTSp+9613BzuIpYg==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.30.0.tgz", + "integrity": "sha512-NgAnqk55RQ/SD+tZFD9aPwNSeHmDHHe5rtUyhIq0ZeCWZEvo4DK9rYz7v9HDuQZFvn320Ot+AikaCKMFKLlD0g==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.28.3", - "@typescript-eslint/scope-manager": "4.28.3", + "@typescript-eslint/experimental-utils": "4.30.0", + "@typescript-eslint/scope-manager": "4.30.0", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.0", @@ -2842,23 +2886,23 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.3.tgz", - "integrity": "sha512-zZYl9TnrxwEPi3FbyeX0ZnE8Hp7j3OCR+ELoUfbwGHGxWnHg9+OqSmkw2MoCVpZksPCZYpQzC559Ee9pJNHTQw==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.30.0.tgz", + "integrity": "sha512-K8RNIX9GnBsv5v4TjtwkKtqMSzYpjqAQg/oSphtxf3xxdt6T0owqnpojztjjTcatSteH3hLj3t/kklKx87NPqw==", "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.3", - "@typescript-eslint/types": "4.28.3", - "@typescript-eslint/typescript-estree": "4.28.3", + "@typescript-eslint/scope-manager": "4.30.0", + "@typescript-eslint/types": "4.30.0", + "@typescript-eslint/typescript-estree": "4.30.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "eslint-scope": { @@ -2874,14 +2918,14 @@ } }, "@typescript-eslint/parser": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.3.tgz", - "integrity": "sha512-ZyWEn34bJexn/JNYvLQab0Mo5e+qqQNhknxmc8azgNd4XqspVYR5oHq9O11fLwdZMRcj4by15ghSlIEq+H5ltQ==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.30.0.tgz", + "integrity": "sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.28.3", - "@typescript-eslint/types": "4.28.3", - "@typescript-eslint/typescript-estree": "4.28.3", + "@typescript-eslint/scope-manager": "4.30.0", + "@typescript-eslint/types": "4.30.0", + "@typescript-eslint/typescript-estree": "4.30.0", "debug": "^4.3.1" }, "dependencies": { @@ -2903,29 +2947,29 @@ } }, "@typescript-eslint/scope-manager": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.3.tgz", - "integrity": "sha512-/8lMisZ5NGIzGtJB+QizQ5eX4Xd8uxedFfMBXOKuJGP0oaBBVEMbJVddQKDXyyB0bPlmt8i6bHV89KbwOelJiQ==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.30.0.tgz", + "integrity": "sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.3", - "@typescript-eslint/visitor-keys": "4.28.3" + "@typescript-eslint/types": "4.30.0", + "@typescript-eslint/visitor-keys": "4.30.0" } }, "@typescript-eslint/types": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.3.tgz", - "integrity": "sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.30.0.tgz", + "integrity": "sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz", - "integrity": "sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.30.0.tgz", + "integrity": "sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.3", - "@typescript-eslint/visitor-keys": "4.28.3", + "@typescript-eslint/types": "4.30.0", + "@typescript-eslint/visitor-keys": "4.30.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -2980,12 +3024,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz", - "integrity": "sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg==", + "version": "4.30.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.30.0.tgz", + "integrity": "sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.3", + "@typescript-eslint/types": "4.30.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -3169,59 +3213,96 @@ "resolved": "https://registry.npmjs.org/@webcomponents/template/-/template-1.4.4.tgz", "integrity": "sha512-QqCmmywIKJTilkl6UIPLxEBBuqhDaOBpvQyKOnUEwl9lJuVHBrVlhMIhhnp9VSZJ6xEUnp+PiX8DST1k0q/v4Q==" }, + "@wojtekmaj/enzyme-adapter-react-17": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.6.3.tgz", + "integrity": "sha512-Kp1ZJxtHkKEnUksaWrcMABNTOgL4wOt8VI6k2xOek2aH9PtZcWRXJNUEgnKrdJrqg5UqIjRslbVF9uUqwQJtFg==", + "dev": true, + "requires": { + "@wojtekmaj/enzyme-adapter-utils": "^0.1.1", + "enzyme-shallow-equal": "^1.0.0", + "has": "^1.0.0", + "object.assign": "^4.1.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.0", + "react-is": "^17.0.2", + "react-test-renderer": "^17.0.0" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, + "@wojtekmaj/enzyme-adapter-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-utils/-/enzyme-adapter-utils-0.1.1.tgz", + "integrity": "sha512-bNPWtN/d8huKOkC6j1E3EkSamnRrHHT7YuR6f9JppAQqtoAm3v4/vERe4J14jQKmHLCyEBHXrlgb7H6l817hVg==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.0", + "has": "^1.0.0", + "object.assign": "^4.1.0", + "object.fromentries": "^2.0.0", + "prop-types": "^15.7.0" + } + }, "@wordpress/a11y": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/a11y/-/a11y-3.1.1.tgz", - "integrity": "sha512-IA5z5LAgYYYTJpKM4c/yuYcaKT3aZOHFmEKOyNsUwZfU1OKYbSaytVCY0SqxiV+S4/kYUaCWyw+e8Ujx4IKaNA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/a11y/-/a11y-3.1.2.tgz", + "integrity": "sha512-VUrJN4UcDdYLYVOjArMbSsHNrIPmoAfrSsJi09xpRFBJXUq67sLLPh5+yy01uptbV1aOqcIbRagyj0Zaq8I70g==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/dom-ready": "^3.1.1", - "@wordpress/i18n": "^4.1.1" + "@wordpress/dom-ready": "^3.1.2", + "@wordpress/i18n": "^4.1.2" } }, "@wordpress/annotations": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/annotations/-/annotations-2.1.5.tgz", - "integrity": "sha512-mvedje+pZnxZMvnZSCi+3Z8x7xBOIlZI8IpD8H+rJPiRn/5wc6MBng/REoO1oP6KY6oMtot4l7YCcYAJpu+cvw==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/annotations/-/annotations-2.1.6.tgz", + "integrity": "sha512-z79UvFGm8GiwJZWEIgE9mzIEzoGVRPo31qwjnotFq3uHjAhKsRZk3ppmaLRNZUbJfobNOvDEyD8VT8V033Gp2A==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/data": "^5.1.5", + "@wordpress/data": "^5.1.6", "@wordpress/hooks": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/rich-text": "^4.1.5", + "@wordpress/i18n": "^4.1.2", + "@wordpress/rich-text": "^4.1.6", "lodash": "^4.17.21", "rememo": "^3.0.0", "uuid": "^8.3.0" } }, "@wordpress/api-fetch": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-5.1.1.tgz", - "integrity": "sha512-pThYQhoKiePeGgb5aZnc4A9YT5WktfZkejSk4JIfFxdzXF7YXunyMoA9Aib2YvY94IkItLzBeTl/jDk9yYL2hw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-5.1.2.tgz", + "integrity": "sha512-qdYENoku3IHfq9tHQismlOnCXerps3Vf9oHjoicUT7ukUBLawEfJWM8LeMJmuFoMRh4mc5ceuhUmTnmEfbcwIQ==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/i18n": "^4.1.1", - "@wordpress/url": "^3.1.1" + "@wordpress/i18n": "^4.1.2", + "@wordpress/url": "^3.1.2" } }, "@wordpress/autop": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/autop/-/autop-3.1.1.tgz", - "integrity": "sha512-ZwZy1DNyXQWX1k4cN3lAzVgcAii6bzFXUS08Zj8kaQf+hNE+BwX5cNb/TK98QQQYNAoiCnt4DiWiD1nxwM+EdA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/autop/-/autop-3.1.2.tgz", + "integrity": "sha512-EbQ/lJwK20GjMXa0pszW8RVdIWghrQcjM1GE/IjPhSWuReD8h0R+3LpB+noZpuy4ccqiz3/Enksq9LBlnFUMvg==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/babel-plugin-import-jsx-pragma": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@wordpress/babel-plugin-import-jsx-pragma/-/babel-plugin-import-jsx-pragma-3.0.5.tgz", - "integrity": "sha512-1xzZGFV5Bwox4XcE59I88q0/robJ35LoQNkKPC4tmfzd1XaAoJCZpp5T8LSJJtKKloeoO1JstrvMf3ltZLQ5IA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/babel-plugin-import-jsx-pragma/-/babel-plugin-import-jsx-pragma-3.1.0.tgz", + "integrity": "sha512-518mL3goaSeXtJCQcPK9OYHUUiA0sjXuoGWHBwRalkyTIQZZy5ZZzlwrlSc9ESZcOw9BZ+Uo8CJRjV2OWnx+Zw==", "dev": true }, "@wordpress/babel-preset-default": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-6.2.0.tgz", - "integrity": "sha512-uNdR8TjUZgTF43psvAPGW/jnKMD+Mr8XiVhJGcVjrKwDoVBvHjtoKSpfafvkrESIHmMz2HgB4+NdqFHL5hhZlg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-6.2.1.tgz", + "integrity": "sha512-io2HbPtmLdfu3WdZg6X6T1oRVCrOTVrTouqSeUxyAZ954fNh8xyB7Q8rfHfxUZHPgGypnbzZOKBiCpUlnBRs7A==", "dev": true, "requires": { "@babel/core": "^7.13.10", @@ -3232,97 +3313,84 @@ "@babel/runtime": "^7.13.10", "@wordpress/babel-plugin-import-jsx-pragma": "^3.0.5", "@wordpress/browserslist-config": "^4.0.1", - "@wordpress/element": "^3.1.1", - "@wordpress/warning": "^2.1.1", + "@wordpress/element": "^3.1.2", + "@wordpress/warning": "^2.1.2", "browserslist": "^4.16.6", "core-js": "^3.12.1" } }, "@wordpress/base-styles": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-3.5.4.tgz", - "integrity": "sha512-5JfLnkQMqaefuoMkqUJMBC8m9RpXJqaaOykxuy9y3uk+s2ENbMGXSUjbzw+anO3SIRORKnHmRkgofcSoqvWV5w==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-3.6.0.tgz", + "integrity": "sha512-6/vXAmc9FSX7Y17UjKgUJoVU++Pv1U1G8uMx7iClRUaLetc7/jj2DD9PTyX/cdJjHr32e3yXuLVT9wfEbo6SEg==", "dev": true }, "@wordpress/blob": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/blob/-/blob-3.1.1.tgz", - "integrity": "sha512-yuT184YYi690FgsV7+1PgWPV7t6eQFhi/sAkzQ6cc+iZFaIELvX5gBcqomB3tc3GuXnhwmKTjQDzuzaepX4BoQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/blob/-/blob-3.1.2.tgz", + "integrity": "sha512-xtuw2+fPok3Ep+fKJlNuatMzag19FUzLziDPa5XLtfncVo+WKg/Tnz+gj138EwYtrjVKnxGlGolps1zqFzH4Bg==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/block-directory": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/@wordpress/block-directory/-/block-directory-2.1.20.tgz", - "integrity": "sha512-22RezQMYfF78N2yPFabAx44U/3DlrHgT6i77wqzZktGw97PaWJtbw9pJkCxDbve3hDjb6EuAkXF1LpRxpLkGjw==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/@wordpress/block-directory/-/block-directory-2.1.21.tgz", + "integrity": "sha512-CCfQDyY7LpWkPxvmA7Dv9KAeSK1WiYIAZKt8FZNXJhnzZHuADsUcZy/7otopcMGHqCYycHcg+ygkpfzNyve5lA==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/data-controls": "^2.1.5", - "@wordpress/edit-post": "^4.1.20", - "@wordpress/editor": "^10.1.16", - "@wordpress/element": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/data-controls": "^2.1.6", + "@wordpress/edit-post": "^4.1.21", + "@wordpress/editor": "^10.1.17", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/html-entities": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/notices": "^3.1.5", - "@wordpress/plugins": "^3.1.5", - "@wordpress/url": "^3.1.1", + "@wordpress/html-entities": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/notices": "^3.1.6", + "@wordpress/plugins": "^3.1.6", + "@wordpress/url": "^3.1.2", "lodash": "^4.17.21" - }, - "dependencies": { - "@wordpress/data-controls": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.5.tgz", - "integrity": "sha512-B2OEPuT6u0MqhzndzSuyWILHdkoRg6tFgw5/+iDXkuZNCqY1PldbLC7Ymt1IgcoLDd83K6CfqknQHvTUVerklw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1" - } - } } }, "@wordpress/block-editor": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-6.1.13.tgz", - "integrity": "sha512-I2NEN+7fUTNiJ/NDkap5NuVT6T9CP+KcpZYziYvYWomcP1iCwBFo78EqBY4mqdhcczWfl1ykjhljPq2DW4ELPg==", + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/@wordpress/block-editor/-/block-editor-6.1.14.tgz", + "integrity": "sha512-4qiAPqrBSOIO6fanm+jG2nTaNuPc1vfqq+KLHnWWfEZtAA06tuKeW/C8XbHT5NdCBzdSL9sytVw+94gOJVeTww==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/blob": "^3.1.1", - "@wordpress/block-serialization-default-parser": "^4.1.1", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/data-controls": "^2.1.5", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/blob": "^3.1.2", + "@wordpress/block-serialization-default-parser": "^4.1.2", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/data-controls": "^2.1.6", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/html-entities": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/html-entities": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keyboard-shortcuts": "^2.1.6", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/notices": "^3.1.5", - "@wordpress/rich-text": "^4.1.5", - "@wordpress/shortcode": "^3.1.1", + "@wordpress/keyboard-shortcuts": "^2.1.7", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/notices": "^3.1.6", + "@wordpress/rich-text": "^4.1.6", + "@wordpress/shortcode": "^3.1.2", "@wordpress/token-list": "^2.1.1", - "@wordpress/url": "^3.1.1", - "@wordpress/wordcount": "^3.1.1", + "@wordpress/url": "^3.1.2", + "@wordpress/wordcount": "^3.1.2", "classnames": "^2.2.5", "css-mediaquery": "^0.1.2", "diff": "^4.0.2", @@ -3336,54 +3404,41 @@ "rememo": "^3.0.0", "tinycolor2": "^1.4.2", "traverse": "^0.6.6" - }, - "dependencies": { - "@wordpress/data-controls": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.5.tgz", - "integrity": "sha512-B2OEPuT6u0MqhzndzSuyWILHdkoRg6tFgw5/+iDXkuZNCqY1PldbLC7Ymt1IgcoLDd83K6CfqknQHvTUVerklw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1" - } - } } }, "@wordpress/block-library": { - "version": "3.2.18", - "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-3.2.18.tgz", - "integrity": "sha512-f61TICHWTIjvWnf8X5NvzYUDZ+RdJ944JLxWKJEhWGljk5iw0Cis+fZbPGK0QQoo8PzKXxqsTNj0oKRYpq92Pw==", + "version": "3.2.19", + "resolved": "https://registry.npmjs.org/@wordpress/block-library/-/block-library-3.2.19.tgz", + "integrity": "sha512-F/Dbg9YYmoQQ9LdtanA1Nn6Bi6z7a5mC9gUankzbl6657Aqw7EcBwvbKfuG3n1TOjbbJZpA2wCCYTge6XNXLWA==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/autop": "^3.1.1", - "@wordpress/blob": "^3.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/date": "^4.1.1", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", - "@wordpress/escape-html": "^2.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/autop": "^3.1.2", + "@wordpress/blob": "^3.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/date": "^4.1.2", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", + "@wordpress/escape-html": "^2.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/notices": "^3.1.5", - "@wordpress/primitives": "^2.1.1", - "@wordpress/reusable-blocks": "^2.1.16", - "@wordpress/rich-text": "^4.1.5", - "@wordpress/server-side-render": "^2.1.11", - "@wordpress/url": "^3.1.1", - "@wordpress/viewport": "^3.1.5", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/notices": "^3.1.6", + "@wordpress/primitives": "^2.1.2", + "@wordpress/reusable-blocks": "^2.1.17", + "@wordpress/rich-text": "^4.1.6", + "@wordpress/server-side-render": "^2.1.12", + "@wordpress/url": "^3.1.2", + "@wordpress/viewport": "^3.1.6", "classnames": "^2.2.5", "fast-average-color": "4.3.0", "lodash": "^4.17.21", @@ -3395,33 +3450,33 @@ } }, "@wordpress/block-serialization-default-parser": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/block-serialization-default-parser/-/block-serialization-default-parser-4.1.1.tgz", - "integrity": "sha512-WBpsFmXy9JK0Jx3CyAe4GFFdIqt7ZRcCD88Wrhf4oJrPbJutdsGMjaSpP3SOwWTh+xeJGiyePjwa3+1Zw0KHcw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/block-serialization-default-parser/-/block-serialization-default-parser-4.1.2.tgz", + "integrity": "sha512-jJoXfn6hYYReEl211alNoTFA5Hdgu9LMTkTQJF2g8cGJS5UpDw1lcpJP0hmpfhwzTmUUemy5RXM7noOa2c/RUw==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/blocks": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/@wordpress/blocks/-/blocks-9.1.7.tgz", - "integrity": "sha512-mar6I4F5sXIWSxE7bJkqanMo9cvYnS49Tg7hR0vY0gZAPTMmSeuL0Lz5i5fvquhURZtnyfryJ4qEvWix3B8/2w==", + "version": "9.1.8", + "resolved": "https://registry.npmjs.org/@wordpress/blocks/-/blocks-9.1.8.tgz", + "integrity": "sha512-RYemYN+q5/M0k5mESBkQbsB101p9hWSOTSlGLzEPBj7yXJp/OnyQVdc2hAr6CQgX16CxOyRRXx1CYQdiOtXGYg==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/autop": "^3.1.1", - "@wordpress/blob": "^3.1.1", - "@wordpress/block-serialization-default-parser": "^4.1.1", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", + "@wordpress/autop": "^3.1.2", + "@wordpress/blob": "^3.1.2", + "@wordpress/block-serialization-default-parser": "^4.1.2", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/html-entities": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/html-entities": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/shortcode": "^3.1.1", + "@wordpress/shortcode": "^3.1.2", "hpq": "^1.3.0", "lodash": "^4.17.21", "rememo": "^3.0.0", @@ -3432,35 +3487,35 @@ } }, "@wordpress/browserslist-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@wordpress/browserslist-config/-/browserslist-config-4.0.1.tgz", - "integrity": "sha512-mmLxc21NWxZSSPvD592tmzpBlme+nB0fbG1xO+EldS4vQkeWIQUZlNbrMijZM/hpFaBqDEJCAZFUPUpw1XwBWg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/browserslist-config/-/browserslist-config-4.1.0.tgz", + "integrity": "sha512-RSJhgY2xmz6yAdDNhz/NvAO6JS+91vv9cVL7VDG2CftbyjTXBef05vWt3FzZhfeF0xUrYdpZL1PVpxmJiKvbEg==", "dev": true }, "@wordpress/components": { - "version": "14.1.10", - "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-14.1.10.tgz", - "integrity": "sha512-MQ1wgJcLtZJcu2jztR2USELbEamqcPTEnZJmJMpdFYg2cR5b3puj3X0ehPjq3G7kSNCRu1J6mPEv5iADbLM6Yg==", + "version": "14.1.11", + "resolved": "https://registry.npmjs.org/@wordpress/components/-/components-14.1.11.tgz", + "integrity": "sha512-umsDXCtH0eqOaAVXq/N3f5QO4u9ovo2F+RMg7c566Q+StOgCVw0jRnKuyKQtBb1CEv4IIYIDWp/pL3cId8Vz2w==", "requires": { "@babel/runtime": "^7.13.10", "@emotion/cache": "^10.0.27", "@emotion/core": "^10.1.1", "@emotion/css": "^10.0.22", "@emotion/styled": "^10.0.23", - "@wordpress/a11y": "^3.1.1", - "@wordpress/compose": "^4.1.5", - "@wordpress/date": "^4.1.1", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/compose": "^4.1.6", + "@wordpress/date": "^4.1.2", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/primitives": "^2.1.1", - "@wordpress/rich-text": "^4.1.5", - "@wordpress/warning": "^2.1.1", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/primitives": "^2.1.2", + "@wordpress/rich-text": "^4.1.6", + "@wordpress/warning": "^2.1.2", "classnames": "^2.2.5", "dom-scroll-into-view": "^1.2.1", "downshift": "^6.0.15", @@ -3482,17 +3537,17 @@ } }, "@wordpress/compose": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-4.1.5.tgz", - "integrity": "sha512-owW4MkWLUIkm0ocehNaLB2TDdGYN//2+7BJuDnTnQ3EUYBwn6bPOM5LNjSOXNJBW7LqiLEIfXghQQId+IYAJXg==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-4.1.6.tgz", + "integrity": "sha512-rzSHBvMMwkR70+qOmSGnZpOEa2fnseGbylR3DEN3IAlscxdAn08Ejyz+bZSQ8GgQ6Uq2OkwvYjHjPUD2llpQ/g==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/priority-queue": "^2.1.1", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/priority-queue": "^2.1.2", "clipboard": "^2.0.1", "lodash": "^4.17.21", "memize": "^1.1.0", @@ -3502,37 +3557,24 @@ } }, "@wordpress/core-data": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@wordpress/core-data/-/core-data-3.1.11.tgz", - "integrity": "sha512-eEuJJ+YzarWOjNfam01IKUN97aTn3s3sVc8Rxg9QR8SvX1UK829dw6i3htv7uhMhJgNf3WzUZl7hli5Jc2/Qdg==", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@wordpress/core-data/-/core-data-3.1.12.tgz", + "integrity": "sha512-GUvuWc5SQi0eBKi6gaWDz3Xg8eQyAM4YmYPpWNhWP8oNeAwsLL/RM2kXv6O4ssnGGlS/W3zJtLFTy7yDo0c74Q==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/blocks": "^9.1.7", - "@wordpress/data": "^5.1.5", - "@wordpress/data-controls": "^2.1.5", - "@wordpress/element": "^3.1.1", - "@wordpress/html-entities": "^3.1.1", - "@wordpress/i18n": "^4.1.1", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/blocks": "^9.1.8", + "@wordpress/data": "^5.1.6", + "@wordpress/data-controls": "^2.1.6", + "@wordpress/element": "^3.1.2", + "@wordpress/html-entities": "^3.1.2", + "@wordpress/i18n": "^4.1.2", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/url": "^3.1.1", + "@wordpress/url": "^3.1.2", "equivalent-key-map": "^0.2.2", "lodash": "^4.17.21", "rememo": "^3.0.0", "uuid": "^8.3.0" - }, - "dependencies": { - "@wordpress/data-controls": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.5.tgz", - "integrity": "sha512-B2OEPuT6u0MqhzndzSuyWILHdkoRg6tFgw5/+iDXkuZNCqY1PldbLC7Ymt1IgcoLDd83K6CfqknQHvTUVerklw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1" - } - } } }, "@wordpress/custom-templated-path-webpack-plugin": { @@ -3545,45 +3587,45 @@ } }, "@wordpress/customize-widgets": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/@wordpress/customize-widgets/-/customize-widgets-1.0.19.tgz", - "integrity": "sha512-3nQMd0Rxy0PIPL3Q6F+ZnHoWVahcWUKvzLnHpdJSx37CGXDJcA4Mx6fl+KLJSUE1ADccZhtKYQRtVIxexaj2ng==", + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/@wordpress/customize-widgets/-/customize-widgets-1.0.20.tgz", + "integrity": "sha512-2zHmZ3IcnkXMD+n1FPRjZTvfTkxt1onxe4oqfQjpobdYjPTSMl3HKaYuHB1lBaVN7qw4sOk/3WgB9cH1kqWpqg==", "requires": { "@babel/runtime": "^7.11.2", - "@wordpress/a11y": "^3.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/block-library": "^3.2.18", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/block-library": "^3.2.19", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keyboard-shortcuts": "^2.1.6", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/media-utils": "^2.1.1", - "@wordpress/widgets": "^1.1.18", + "@wordpress/keyboard-shortcuts": "^2.1.7", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/media-utils": "^2.1.2", + "@wordpress/widgets": "^1.1.19", "classnames": "^2.2.6", "lodash": "^4.17.21" } }, "@wordpress/data": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data/-/data-5.1.5.tgz", - "integrity": "sha512-Vw8vJx68znQiUYfoCHFzzBZSw9Q7ESC5lMrI8SUnUdqfSxPaaFa67aKoWOTrSMW9utkXQxTL5OOWj2ZXdgLl2Q==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/data/-/data-5.1.6.tgz", + "integrity": "sha512-KKcAcYh6XuRXkQvIQOv1/ci5Tj1kXEE2gwNzujN4SytJZmQTNP2EEE8u9bBnhEPoS7bORzlqeNQuMW0Rz74qgg==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/element": "^3.1.1", + "@wordpress/compose": "^4.1.6", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/element": "^3.1.2", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/priority-queue": "^2.1.1", - "@wordpress/redux-routine": "^4.1.1", + "@wordpress/priority-queue": "^2.1.2", + "@wordpress/redux-routine": "^4.1.2", "equivalent-key-map": "^0.2.2", "is-promise": "^4.0.0", "lodash": "^4.17.21", @@ -3594,20 +3636,20 @@ } }, "@wordpress/data-controls": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.3.tgz", - "integrity": "sha512-gDNufBbLiGhoIMIcNCL9seKP4ZVuDiO/Fx479RwAWSWdSdUFgJtvwkzdVUF5zFZwLIaeMXTPwrNWV97zl7rDtQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.6.tgz", + "integrity": "sha512-AON1ZQLGhVQsJQIeW+4D1aB31TBJbDIQUMwnimiMkJ2n0M9V1Q0hvW4P7URC1k2aouNstnF2/TJ4xFPPRINf4Q==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.3", - "@wordpress/deprecated": "^3.1.1" + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/data": "^5.1.6", + "@wordpress/deprecated": "^3.1.2" } }, "@wordpress/date": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/date/-/date-4.1.1.tgz", - "integrity": "sha512-TA452SZO6Z35c7HLEmSLT0xb/zbUraKHCmkzgkZbhTRVPnZ824VCTb3ebWko9hoNZ0n6bxDE+ntMwM/YKfzDhw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/date/-/date-4.1.2.tgz", + "integrity": "sha512-t1cM1eLCQkLJeypcnFQIBJW0+aS8ZUvZLNSxlMH0jVybF9+bjVIbKY+aRkGwP4OMxxrdQkvF2qFj349bn3nz3Q==", "requires": { "@babel/runtime": "^7.13.10", "moment": "^2.22.1", @@ -3643,75 +3685,147 @@ } }, "@wordpress/deprecated": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-3.1.1.tgz", - "integrity": "sha512-0hILlCNhf0DukFo3hMWybf9q507cxnIHhC1GQ1crZtTqzKS2QY2C1/77V4YGPdBShUj5j1dPriYCzfB5jFFgqQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-3.1.2.tgz", + "integrity": "sha512-kURIhVWssN6lv4YZNMqeFU8ZHk1Dh3SNbHHDs/Ah4Qcql9uHJisF89lLIQBCs063wgkeXfFxdvM/BXD4kfK6fw==", "requires": { "@babel/runtime": "^7.13.10", "@wordpress/hooks": "^3.1.1" } }, "@wordpress/dom": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@wordpress/dom/-/dom-3.1.4.tgz", - "integrity": "sha512-25LZXu7mf3kcj+RfDf36spnw8OvRL+2gHVPw7ivvTXSLMSj0I2G2DZzDPRIEYww/zW1VUanoTyRWjQ4mNuSzyA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@wordpress/dom/-/dom-3.1.5.tgz", + "integrity": "sha512-EDX1BXtIEHw3LjAunASJO9lnbU2KU1gi4UBrjaa+Cem4u6npmfYHh6XkXO2ryA21yjx7rCWPbD0id6E7qlJ4Tw==", "requires": { "@babel/runtime": "^7.13.10", "lodash": "^4.17.21" } }, "@wordpress/dom-ready": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-3.1.1.tgz", - "integrity": "sha512-Kc0jxOgOBKDdJ5OOA1iNHXog5D3QzNrv4IBt4UYYDy59XnuzJEwDSeWQE9gP6ssRx4/qzJxi5KGr3pNZzDwqTg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/dom-ready/-/dom-ready-3.1.2.tgz", + "integrity": "sha512-g2zmgC/+6JYgWYzUMByRmjRAXs75q57wnNdYUTXmRFrtLs2+PNa1bUuYWZop15rTZbxuvP6ScVnPxZ5tyQLRUw==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/e2e-test-utils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils/-/e2e-test-utils-5.3.0.tgz", - "integrity": "sha512-01Fba6bN4E+SX0D5sko0p1C6JTyH9SPZZlev7US3XSRQy5AQPiBdMniKEvyaGjql1jNMbuNFJ+ueB88Qd6tVMw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@wordpress/e2e-test-utils/-/e2e-test-utils-5.4.3.tgz", + "integrity": "sha512-DDLIO/QZipMLpqfiYB570nVtxOGlC9ByZkyd/+dqjwViBc7ST9pWMQzQPahlGjkArU2EMB96fvPumPnjrReZOA==", "dev": true, "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/url": "^3.1.1", + "@wordpress/api-fetch": "^5.2.2", + "@wordpress/keycodes": "^3.2.2", + "@wordpress/url": "^3.2.2", + "form-data": "^4.0.0", "lodash": "^4.17.21", "node-fetch": "^2.6.0" + }, + "dependencies": { + "@wordpress/api-fetch": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-5.2.2.tgz", + "integrity": "sha512-WwJHOe6qiI4Oa1BSSo+Fpietdtm/0UgaN5A9k/TlEkARqIE+Fh56sfbC3JbjJDfQxz9TsAxMm+WWO5aNapantQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@wordpress/i18n": "^4.2.2", + "@wordpress/url": "^3.2.2" + } + }, + "@wordpress/hooks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-3.2.0.tgz", + "integrity": "sha512-nVR6V9kPxl8+aYQzQJdoDt+aKBKHHD0zplcYZbu2MHxjmHMvppAeL9mjzVhQZj/3n10NR2Ftk94mHQzHWfhCCg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10" + } + }, + "@wordpress/i18n": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.2.2.tgz", + "integrity": "sha512-6PrfTDpeW5dfWyuqUx4Z5ApKFbh45CAbCs/G3PuZLlKJlXs/8p2Oq6Zxs0gLZk1QfHkw0t5qMx61lDlxWQhuPw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@wordpress/hooks": "^3.2.0", + "gettext-parser": "^1.3.1", + "lodash": "^4.17.21", + "memize": "^1.1.0", + "sprintf-js": "^1.1.1", + "tannin": "^1.2.0" + } + }, + "@wordpress/keycodes": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.2.2.tgz", + "integrity": "sha512-z4B4vby+iGciJ9gvUBIozsseDkdQXDNuWm5szMnG5g1Nn7UGDWmfCNc9IHNs3alXySmAFev6d0T/o/zgm9BBvQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "@wordpress/i18n": "^4.2.2", + "lodash": "^4.17.21" + } + }, + "@wordpress/url": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-3.2.2.tgz", + "integrity": "sha512-TYWE7V9F8nj0ZkCJy1eFD0crdDTS7iB3cVNW2yIDOn1RTWJJtzINXQFMASokVsjuh+NetAIOu8ru2mIfoRMG8Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.13.10", + "lodash": "^4.17.21", + "react-native-url-polyfill": "^1.1.2" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } } }, "@wordpress/edit-post": { - "version": "4.1.20", - "resolved": "https://registry.npmjs.org/@wordpress/edit-post/-/edit-post-4.1.20.tgz", - "integrity": "sha512-W420fWlb025GsXIZEawCF4O8B7vtwzGu1UmwvdM3kOcsq09yvSAoIuoiPNzQDJhkK1DcsBvglH6vEYA6uEbwPA==", + "version": "4.1.21", + "resolved": "https://registry.npmjs.org/@wordpress/edit-post/-/edit-post-4.1.21.tgz", + "integrity": "sha512-tthVG2vA/cEkM5Ksb+AWlfYdRQRh3TE45C0NPMTjRTQaETJjZGZp1VCVl6f+EBMIiW90mzgOfP6t0bvDHBtcFg==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/block-library": "^3.2.18", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/data-controls": "^2.1.5", - "@wordpress/editor": "^10.1.16", - "@wordpress/element": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/block-library": "^3.2.19", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/data-controls": "^2.1.6", + "@wordpress/editor": "^10.1.17", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/interface": "^3.1.11", - "@wordpress/keyboard-shortcuts": "^2.1.6", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/media-utils": "^2.1.1", - "@wordpress/notices": "^3.1.5", - "@wordpress/plugins": "^3.1.5", - "@wordpress/primitives": "^2.1.1", - "@wordpress/url": "^3.1.1", - "@wordpress/viewport": "^3.1.5", - "@wordpress/warning": "^2.1.1", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/interface": "^3.1.12", + "@wordpress/keyboard-shortcuts": "^2.1.7", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/media-utils": "^2.1.2", + "@wordpress/notices": "^3.1.6", + "@wordpress/plugins": "^3.1.6", + "@wordpress/primitives": "^2.1.2", + "@wordpress/url": "^3.1.2", + "@wordpress/viewport": "^3.1.6", + "@wordpress/warning": "^2.1.2", "classnames": "^2.2.5", "framer-motion": "^4.1.3", "lodash": "^4.17.21", @@ -3720,17 +3834,6 @@ "uuid": "8.3.0" }, "dependencies": { - "@wordpress/data-controls": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.5.tgz", - "integrity": "sha512-B2OEPuT6u0MqhzndzSuyWILHdkoRg6tFgw5/+iDXkuZNCqY1PldbLC7Ymt1IgcoLDd83K6CfqknQHvTUVerklw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1" - } - }, "uuid": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", @@ -3739,144 +3842,119 @@ } }, "@wordpress/edit-widgets": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/@wordpress/edit-widgets/-/edit-widgets-2.1.20.tgz", - "integrity": "sha512-nCG4DCqfU1a87BI5YQi6MjWMsLNSZ/NWaC8xGECmZF7m+jGJ3WcXDNz1wISUjRPlfTB88uDfxirK7x9RTL5zLA==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/@wordpress/edit-widgets/-/edit-widgets-2.1.21.tgz", + "integrity": "sha512-dkINHh3yPJnCtqXfcKX0+Wf85ztGJLEnt35pUdcif6fkxDvBciYX6maezo+m+r6TgI0J9wUO2t9+G6kX6bda0Q==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/block-library": "^3.2.18", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/data-controls": "^2.1.5", - "@wordpress/element": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/block-library": "^3.2.19", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/data-controls": "^2.1.6", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/interface": "^3.1.11", - "@wordpress/keyboard-shortcuts": "^2.1.6", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/media-utils": "^2.1.1", - "@wordpress/notices": "^3.1.5", - "@wordpress/plugins": "^3.1.5", - "@wordpress/reusable-blocks": "^2.1.16", - "@wordpress/server-side-render": "^2.1.11", - "@wordpress/url": "^3.1.1", - "@wordpress/widgets": "^1.1.18", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/interface": "^3.1.12", + "@wordpress/keyboard-shortcuts": "^2.1.7", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/media-utils": "^2.1.2", + "@wordpress/notices": "^3.1.6", + "@wordpress/plugins": "^3.1.6", + "@wordpress/reusable-blocks": "^2.1.17", + "@wordpress/server-side-render": "^2.1.12", + "@wordpress/url": "^3.1.2", + "@wordpress/widgets": "^1.1.19", "classnames": "^2.2.5", "lodash": "^4.17.21", "rememo": "^3.0.0", "uuid": "^8.3.0" - }, - "dependencies": { - "@wordpress/data-controls": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.5.tgz", - "integrity": "sha512-B2OEPuT6u0MqhzndzSuyWILHdkoRg6tFgw5/+iDXkuZNCqY1PldbLC7Ymt1IgcoLDd83K6CfqknQHvTUVerklw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1" - } - } } }, "@wordpress/editor": { - "version": "10.1.16", - "resolved": "https://registry.npmjs.org/@wordpress/editor/-/editor-10.1.16.tgz", - "integrity": "sha512-QXvV6BxSKAapQeocBn5m83FPzO4x+UFw8EUuM37fiZ0VLeqRuv0Ec2HhxW3WrimeZGEhlG7M1vboGQ2U7VJtmw==", + "version": "10.1.17", + "resolved": "https://registry.npmjs.org/@wordpress/editor/-/editor-10.1.17.tgz", + "integrity": "sha512-ALvuojonwMEjWN1tbQR+mZF3ggR/fdkvOKe4esxRL3U10eTfcsSw6qA2QzB8zHrjb1cZd/90gZWixAdE398f+w==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/autop": "^3.1.1", - "@wordpress/blob": "^3.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/data-controls": "^2.1.5", - "@wordpress/date": "^4.1.1", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/element": "^3.1.1", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/autop": "^3.1.2", + "@wordpress/blob": "^3.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/data-controls": "^2.1.6", + "@wordpress/date": "^4.1.2", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/html-entities": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/html-entities": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keyboard-shortcuts": "^2.1.6", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/media-utils": "^2.1.1", - "@wordpress/notices": "^3.1.5", - "@wordpress/reusable-blocks": "^2.1.16", - "@wordpress/rich-text": "^4.1.5", - "@wordpress/server-side-render": "^2.1.11", - "@wordpress/url": "^3.1.1", - "@wordpress/wordcount": "^3.1.1", + "@wordpress/keyboard-shortcuts": "^2.1.7", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/media-utils": "^2.1.2", + "@wordpress/notices": "^3.1.6", + "@wordpress/reusable-blocks": "^2.1.17", + "@wordpress/rich-text": "^4.1.6", + "@wordpress/server-side-render": "^2.1.12", + "@wordpress/url": "^3.1.2", + "@wordpress/wordcount": "^3.1.2", "classnames": "^2.2.5", "lodash": "^4.17.21", "memize": "^1.1.0", "react-autosize-textarea": "^7.1.0", "rememo": "^3.0.0" - }, - "dependencies": { - "@wordpress/data-controls": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/data-controls/-/data-controls-2.1.5.tgz", - "integrity": "sha512-B2OEPuT6u0MqhzndzSuyWILHdkoRg6tFgw5/+iDXkuZNCqY1PldbLC7Ymt1IgcoLDd83K6CfqknQHvTUVerklw==", - "requires": { - "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1" - } - } } }, "@wordpress/element": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-3.1.1.tgz", - "integrity": "sha512-OaqKQVEV3CCTdrx/G7fMbmxhrxjApobHUAGAVYCCR1MIqScfluYJRLWFLx8tlkl/Qm/UbF9IfdXS1lphufvYog==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/element/-/element-3.1.2.tgz", + "integrity": "sha512-6ZDhwXkkohcocZSXp+IE4Xn774+PNHJTNsEOLJRAeDo/clIvly5HoczX03z1GLgvEB3VYik8qHaqrouNIcjZvA==", "requires": { "@babel/runtime": "^7.13.10", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", - "@wordpress/escape-html": "^2.1.1", + "@wordpress/escape-html": "^2.1.2", "lodash": "^4.17.21", "react": "^16.13.1", "react-dom": "^16.13.1" } }, "@wordpress/escape-html": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-2.1.1.tgz", - "integrity": "sha512-ZIkLxGLBhXkZu3t0yF82/brPV5aCOGCXGiH0EMV8GCohhXCNIfQwwFrZ5gd5NyNX5Q8alTLsiA84azJd+n0XiQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/escape-html/-/escape-html-2.1.2.tgz", + "integrity": "sha512-nEKvwzjMkuyV5MBnD5Um/McydurQ65mLjV1NG8bVlljZlP6/263qdZ5otH2uwr6cf2Lz1meupmi9sV3ef4TalQ==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/eslint-plugin": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@wordpress/eslint-plugin/-/eslint-plugin-9.0.6.tgz", - "integrity": "sha512-ytkG93uzlHlItPR2MDkhUXtnnyw80rwSFZDovsHvMKrB9JjDem2pZnnUjwIOl+zb/9nittUJw6HA5AwCBDw+MQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@wordpress/eslint-plugin/-/eslint-plugin-9.1.1.tgz", + "integrity": "sha512-GduOwoTTHh132RHTfLU82ujOmzuLpkA9izq+gzKtzhoDGzcpORXIht7tnbB8fzima4PYIiePz2LmuMCSuP18RA==", "dev": true, "requires": { "@typescript-eslint/eslint-plugin": "^4.15.0", "@typescript-eslint/parser": "^4.15.0", - "@wordpress/prettier-config": "^1.0.5", + "@wordpress/prettier-config": "^1.1.0", "babel-eslint": "^10.1.0", "cosmiconfig": "^7.0.0", "eslint-config-prettier": "^7.1.0", - "eslint-plugin-import": "^2.22.1", + "eslint-plugin-import": "^2.23.4", "eslint-plugin-jest": "^24.1.3", - "eslint-plugin-jsdoc": "^30.7.13", + "eslint-plugin-jsdoc": "^34.1.0", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.3.0", "eslint-plugin-react": "^7.22.0", @@ -3887,9 +3965,9 @@ }, "dependencies": { "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -3917,24 +3995,24 @@ } }, "@wordpress/format-library": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@wordpress/format-library/-/format-library-2.1.13.tgz", - "integrity": "sha512-svWUeJATHapPXeh7wEGCHKy4eoYwERe1JQF7Rxir/s3Z1jAOmmzWDOxXKBcUVUGZp31laAQ3czJ7BzuPuyurlw==", + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/@wordpress/format-library/-/format-library-2.1.14.tgz", + "integrity": "sha512-INmmTyJX0FDBkG8PTJqvIBi+yTfYHpdpkWqP/JswG7kslrG++elm4jyrA2EsV1anZyxDfsSrP3aSCy+arYkTgA==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", - "@wordpress/html-entities": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/keycodes": "^3.1.1", - "@wordpress/rich-text": "^4.1.5", - "@wordpress/url": "^3.1.1", + "@wordpress/a11y": "^3.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", + "@wordpress/html-entities": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/keycodes": "^3.1.2", + "@wordpress/rich-text": "^4.1.6", + "@wordpress/url": "^3.1.2", "lodash": "^4.17.21" } }, @@ -3947,17 +4025,17 @@ } }, "@wordpress/html-entities": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-3.1.1.tgz", - "integrity": "sha512-LDeSO//QV0rm7u4SoYz2wa9fM0VhvInwWI8+mT+7jPubkgC+2DfaPte7ahofPz4/lQd9MAQ9NgvGXWTw2x0/vw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/html-entities/-/html-entities-3.1.2.tgz", + "integrity": "sha512-pPbEBxUTZm9YA/ynq50UEGmefaqFIW4g07KrxDQfa+xm0jb3kFZOtxFqdX7gXNofNCn/f5v4jlpFGmmYYpJMaw==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/i18n": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.1.1.tgz", - "integrity": "sha512-Ra/hxR8WCLqDp2P49Ibr9ANhZZZ8WHnsO+4WG3XDarJ3lmzux0TcRThDKRCcYHsW3pzieARmrEa/BOlYD7ZEjQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.1.2.tgz", + "integrity": "sha512-Bp0BnGoN2XQyhFjACh74f3fDIQx/AnBIyZsDIhSlNYedFjuJ9b4M246/YTmCDlRHyCqLyG/OuS0hEZKksKAoRQ==", "requires": { "@babel/runtime": "^7.13.10", "@wordpress/hooks": "^3.1.1", @@ -3969,30 +4047,30 @@ } }, "@wordpress/icons": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-4.0.2.tgz", - "integrity": "sha512-WAD6RDbxtutbm2p+Hwe4zc5nl2fiVZSMIj4f6VUqWaVjAdSjy9NxMsUtum6OmyYwRNSvPLFyYUlRfdUJ4AVCaA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-4.0.3.tgz", + "integrity": "sha512-I68iAysutXkYP6JrvnPlha/DKtNhtI1u88PuroZC/RgG+R0WwmxphB/bPoj92BCYDjgrMI8P625Ivttuh1spFA==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/element": "^3.1.1", - "@wordpress/primitives": "^2.1.1" + "@wordpress/element": "^3.1.2", + "@wordpress/primitives": "^2.1.2" } }, "@wordpress/interface": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@wordpress/interface/-/interface-3.1.11.tgz", - "integrity": "sha512-oyDHaIzYRYLiARBS0sEvpKbNmSrv1KaVp9IugUFDOGwT6NE6l9n2+3j600G8mZBpfg3iL222rMFi40LOc6f5Kg==", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@wordpress/interface/-/interface-3.1.12.tgz", + "integrity": "sha512-t7ksL3IIlWB47+r8UJ9CyAZZVlEVbA7lN9aqA5Ly6+QPIPwtvATDDM1agiUjGPwGLAsFSoZyda9MDjfVNDvXmw==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/plugins": "^3.1.5", - "@wordpress/viewport": "^3.1.5", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/plugins": "^3.1.6", + "@wordpress/viewport": "^3.1.6", "classnames": "^2.2.5", "lodash": "^4.17.21" } @@ -4006,9 +4084,9 @@ } }, "@wordpress/jest-console": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@wordpress/jest-console/-/jest-console-4.0.5.tgz", - "integrity": "sha512-njpD0WUBd36FDVgFK7oTBTnxPIyy3e5bJdoJkYjqjw5WlRm2RtCeV0Kc5Lss1ZbtMX9oaSiZ9ih62pHXXFeKdQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/jest-console/-/jest-console-4.1.0.tgz", + "integrity": "sha512-MAbEfYUH+odlYYtPNKoKnWzSZKZjSc2r2kvFJ7FR920ZdteEgSAPIOvjyv4r4UbJy3ZuKemnXHuVtcTAKca5Tw==", "dev": true, "requires": { "@babel/runtime": "^7.13.10", @@ -4017,39 +4095,39 @@ } }, "@wordpress/jest-preset-default": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@wordpress/jest-preset-default/-/jest-preset-default-7.0.5.tgz", - "integrity": "sha512-Kf8TmGLqYb0hO44wiG57dRAROugGiplFIUG9jZnELTyppKkI/Q3ePJXVf+JmZsyzBw86OaNqSCAipTp5jWHhgw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/jest-preset-default/-/jest-preset-default-7.1.0.tgz", + "integrity": "sha512-N6OwVfvNodRTgIkmBor6YOGx3FbLdvPp9ZTGHJ1uw1u+HUuPwVWN9nhcGTnuP8Ht2RWyN5VpN2Peo5+dz5gp0w==", "dev": true, "requires": { - "@wordpress/jest-console": "^4.0.5", + "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", + "@wordpress/jest-console": "^4.1.0", "babel-jest": "^26.6.3", "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.2", "enzyme-to-json": "^3.4.4" } }, "@wordpress/keyboard-shortcuts": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@wordpress/keyboard-shortcuts/-/keyboard-shortcuts-2.1.6.tgz", - "integrity": "sha512-YyF0Iy6F9udYwsxHKsWFLcIUQzfbr9MS3qcm0YmhszZCtLEwKmfcL6s3n4KTFD7EosDXcxyivoifLdiWY3R27w==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@wordpress/keyboard-shortcuts/-/keyboard-shortcuts-2.1.7.tgz", + "integrity": "sha512-V04mCe0Uwxhe2qIkfJ4h5//KsngZA25G/3kI0Ab6vL2N8OrQZQojZ4fnCK3x/P7mvdjXKQn78+vjnp3KiMvRqg==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/element": "^3.1.1", - "@wordpress/keycodes": "^3.1.1", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/element": "^3.1.2", + "@wordpress/keycodes": "^3.1.2", "lodash": "^4.17.21", "rememo": "^3.0.0" } }, "@wordpress/keycodes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.1.1.tgz", - "integrity": "sha512-lLJTl/PJv0F5c02YfFdzS/sspmMM3kWYcix8sXsAQgjzLkOMizSQySBa3bpT2t5auN0YQ34YVyeupVfoY+evOQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/keycodes/-/keycodes-3.1.2.tgz", + "integrity": "sha512-8N0JiHquULMezdWEAu/MjaW5cQ4EN8z61HkA4/sIIB8JPd2TvNEkE1SeEotzpPICcBitEoQzclQ3uOUPld0WAg==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/i18n": "^4.1.1", + "@wordpress/i18n": "^4.1.2", "lodash": "^4.17.21" } }, @@ -4082,108 +4160,139 @@ } }, "@wordpress/list-reusable-blocks": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@wordpress/list-reusable-blocks/-/list-reusable-blocks-2.1.10.tgz", - "integrity": "sha512-benX4UNOuXZR6Vzkxe48QR/eusqyCs44yCJjh1foem6kdVyMeduwEx88WALVIJq34Y6X3l3bHpQRcVVtEpdEAA==", + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@wordpress/list-reusable-blocks/-/list-reusable-blocks-2.1.11.tgz", + "integrity": "sha512-/y9YbYKL0E0jGs0QJHzdAK3OHrpWec9/dt2oy/RkB6+r+SjHUMBbCyxtL67SPhqZAliXDO10tJSih0OFK0gULw==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", "lodash": "^4.17.21" } }, "@wordpress/media-utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/media-utils/-/media-utils-2.1.1.tgz", - "integrity": "sha512-pp39/OYrr9yhvpgPfRk/ZCNE3kCZ3L9NC9fvwnNiMR5BjfkWPseezXRknnWpAdHccELAcu6WBxzXAZLoGH1/vQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/media-utils/-/media-utils-2.1.2.tgz", + "integrity": "sha512-LhZ52JdLz4Lwr1H1YB90pAHTlAowv9R2HwQXjjmKmkSfGwCOhd6xigSRnDVKEjJxT4sUsVVCJdnb4Og/SVk0Nw==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/blob": "^3.1.1", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/blob": "^3.1.2", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", "lodash": "^4.17.21" } }, "@wordpress/notices": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/notices/-/notices-3.1.5.tgz", - "integrity": "sha512-xA8z/xFog7OAkSHp6t2cFrJDK5j4o8lsJvhrjpyomIU8xMDMQgCM3wRJ4gr7xniF0VS//C8wzjFXkws9v/wf+w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/notices/-/notices-3.1.6.tgz", + "integrity": "sha512-I+xDHCY7n5I/mBeZvlker7BoMtRFgaHBe/XySGJv2V2D3ZxgpAGXeVv13v+ohSvhaEjFhll+RgszpZOW/8SMLA==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/a11y": "^3.1.1", - "@wordpress/data": "^5.1.5", + "@wordpress/a11y": "^3.1.2", + "@wordpress/data": "^5.1.6", "lodash": "^4.17.21" } }, "@wordpress/npm-package-json-lint-config": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@wordpress/npm-package-json-lint-config/-/npm-package-json-lint-config-4.0.5.tgz", - "integrity": "sha512-kckj06QsUe7fSGYWiOhsXbAgU2sL9s/gy7GynvQCqOPPiLGpJ8PvCx8OLMaT0T75CXFqieGvfS8Dtf+d84mFvg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/npm-package-json-lint-config/-/npm-package-json-lint-config-4.1.0.tgz", + "integrity": "sha512-FjXL5GbpmI/wXXcpCf2sKosVIVuWjUuHmDbwcMzd0SClcudo9QjDRdVe35We+js8eQLPgB9hsG4Cty6cAFFxsQ==", "dev": true }, "@wordpress/nux": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@wordpress/nux/-/nux-4.1.10.tgz", - "integrity": "sha512-DONHYpLwZV7hAh4C0ZVJTBgKyItcq7zC2UTyXASA2jKj1KDWTQGf0SgxdK5KZLUz43/GlqfTBadl3IaFl9gpvA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@wordpress/nux/-/nux-4.1.11.tgz", + "integrity": "sha512-GRuQW4guMp12NjdUQPpQHJ+YoLt9lzigWO5za5sPXtWzgpYjzzTGIvBrC8hU5s5dXAlvHzZ0yk6swCEBXGqVDw==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", "lodash": "^4.17.21", "rememo": "^3.0.0" } }, "@wordpress/plugins": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/plugins/-/plugins-3.1.5.tgz", - "integrity": "sha512-40wMKFrtpiQvkjZw5iefYLVyp5BuruzhV8DUfTSxWs5vlj/9O1hNtKGk58ynqSOsiltV9O5cVgjiq+hJiJNXhA==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/plugins/-/plugins-3.1.6.tgz", + "integrity": "sha512-I2ZE6M/IzkLDDy0YOWLqMebutuubeYCk5Y3QkSRVmQYiuTP0o6q2vO8iJjfL87L8wxB3BgkZwNxusFB1not+lw==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/element": "^3.1.1", + "@wordpress/compose": "^4.1.6", + "@wordpress/element": "^3.1.2", "@wordpress/hooks": "^3.1.1", - "@wordpress/icons": "^4.0.2", + "@wordpress/icons": "^4.0.3", "lodash": "^4.17.21", "memize": "^1.1.0" } }, "@wordpress/postcss-plugins-preset": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-3.1.4.tgz", - "integrity": "sha512-yfzn2AKjHuFAPJL7NlUaga2KEWfBO5Pv9zhu0Km44pV/4Z/lUKu5m8Tqcllx6kUiERakMyvaXkAm0e0p+7oh5w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wordpress/postcss-plugins-preset/-/postcss-plugins-preset-3.2.0.tgz", + "integrity": "sha512-vYzlqr92pq9cIdN6eO5/h1hyDjEIUUvRlm3Tgd822dPPr6EpkM8uJ82quObE1pPt4JfmXYhTj+gMgOUzRNLHJg==", "dev": true, "requires": { - "@wordpress/base-styles": "^3.5.4", + "@wordpress/base-styles": "^3.6.0", "autoprefixer": "^10.2.5" }, "dependencies": { "autoprefixer": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.3.1.tgz", - "integrity": "sha512-L8AmtKzdiRyYg7BUXJTzigmhbQRCXFKz6SA1Lqo0+AR2FBbQ4aTAPFSDlOutnFkjhiz8my4agGXog1xlMjPJ6A==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.3.3.tgz", + "integrity": "sha512-yRzjxfnggrP/+qVHlUuZz5FZzEbkT+Yt0/Df6ScEMnbbZBLzYB2W0KLxoQCW+THm1SpOsM1ZPcTHAwuvmibIsQ==", "dev": true, "requires": { - "browserslist": "^4.16.6", - "caniuse-lite": "^1.0.30001243", - "colorette": "^1.2.2", + "browserslist": "^4.16.8", + "caniuse-lite": "^1.0.30001252", + "colorette": "^1.3.0", "fraction.js": "^4.1.1", "normalize-range": "^0.1.2", "postcss-value-parser": "^4.1.0" } }, + "browserslist": { + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", + "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001251", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.811", + "escalade": "^3.1.1", + "node-releases": "^1.1.75" + } + }, + "caniuse-lite": { + "version": "1.0.30001252", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz", + "integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==", + "dev": true + }, "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.826", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.826.tgz", + "integrity": "sha512-bpLc4QU4B8PYmdO4MSu2ZBTMD8lAaEXRS43C09lB31BvYwuk9UxgBRXbY5OJBw7VuMGcg2MZG5FyTaP9u4PQnw==", + "dev": true + }, + "node-releases": { + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", "dev": true }, "postcss-value-parser": { @@ -4195,33 +4304,33 @@ } }, "@wordpress/prettier-config": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@wordpress/prettier-config/-/prettier-config-1.0.5.tgz", - "integrity": "sha512-kZ1EzXmDKOe+QxSJJSu70zx+x2g1awqYJjX7Z947K0affv4l8/oPA+k3SgNi3U9Q5Sbwtb5xLgDr9k0HGJSw7g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/prettier-config/-/prettier-config-1.1.0.tgz", + "integrity": "sha512-cMYc/dtuiRo9VAb+m8S2Mvv/jELvoJAtcPsq6HT6XMppXC9slZ5z0q1A4PNf3ewMvvHtodjwkl2oHbO+vaAYzg==", "dev": true }, "@wordpress/primitives": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/primitives/-/primitives-2.1.1.tgz", - "integrity": "sha512-iX31v/302zOrxEVwFUbbwr4BKZcxR+XQ53wuShc8CzcydAYj5JUFdEuwG6Z9jRGJAX2AgizSP6Fex4ercgFLXA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/primitives/-/primitives-2.1.2.tgz", + "integrity": "sha512-Eof+TK+zoKIr6w4lMlwxq+HvP+nKXBoidukjP3YhNUPOdB7H27+X6/V/IJd/Zza2xKN2ExkJybssBAGqi5NS6g==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/element": "^3.1.1", + "@wordpress/element": "^3.1.2", "classnames": "^2.2.5" } }, "@wordpress/priority-queue": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-2.1.1.tgz", - "integrity": "sha512-e4x4B+1F2wXejqjNr6L3LTf5aO7gzy/9MWy5pUgg1rlo8z+B73OyOUmK39WOnzFtzmwTbFqgzzCwY5JqIaZe2g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/priority-queue/-/priority-queue-2.1.2.tgz", + "integrity": "sha512-qXZzmfTRH6ssSZpCbJEHnj/w9W8bjpYm8V1tLKUqBXEYkHbII4O2FIL21LGI5aFhPPWsHG7tlYz3Z4lA/MHALQ==", "requires": { "@babel/runtime": "^7.13.10" } }, "@wordpress/redux-routine": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/redux-routine/-/redux-routine-4.1.1.tgz", - "integrity": "sha512-wjHASkmDPiOhnTZGn43kBj5RDVnSTRpj3EHL8boUGmOMiEFm/bUAfefhyvlo9ksBF4ZQm2pJjJTWtp5zE1drgg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/redux-routine/-/redux-routine-4.1.2.tgz", + "integrity": "sha512-1wOH4zdp58VNeMCoTNRHc1wHTGL3ZWqx8kCCqeA3NhULnRBx2RkI/v6nemKCho5QRbMdIWWUYXffFsLbDOUOSg==", "requires": { "@babel/runtime": "^7.13.10", "is-promise": "^4.0.0", @@ -4230,37 +4339,37 @@ } }, "@wordpress/reusable-blocks": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@wordpress/reusable-blocks/-/reusable-blocks-2.1.16.tgz", - "integrity": "sha512-CEVKQcUS7VJH7qUMRzRQqmVZB3JpZ0dKphjWYS0NacJIN2Jlm1HLJS1Sxf4Ayv0SKmYgQp2NE5Zas4aki8wPfA==", - "requires": { - "@wordpress/block-editor": "^6.1.13", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/notices": "^3.1.5", - "@wordpress/url": "^3.1.1", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@wordpress/reusable-blocks/-/reusable-blocks-2.1.17.tgz", + "integrity": "sha512-54tZPQppe4kmDeivxsUk5ZZhTlSY8jum+5OEcYs0jJVctEXhRVh7rU3p2hqSWWriNghqVz4i3cuJ57tqt/tIsw==", + "requires": { + "@wordpress/block-editor": "^6.1.14", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/notices": "^3.1.6", + "@wordpress/url": "^3.1.2", "lodash": "^4.17.21" } }, "@wordpress/rich-text": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-4.1.5.tgz", - "integrity": "sha512-P5861BnBe+lITv3N8KtOAaIjeYAmFPbOUB9VWD26AzAY4DrTQZDGVcblRjvy3aykmyHF6xQ5UvA+tPcjumQrkg==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/rich-text/-/rich-text-4.1.6.tgz", + "integrity": "sha512-wF60RXrGIQ0xgAvMSNwh1dP8lM4RRMWbRS5ZKOf1ld2s7oTsezEodBwCIHhFkHeraM/ORbeFoBPFsLbGf3oXwQ==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/dom": "^3.1.4", - "@wordpress/element": "^3.1.1", - "@wordpress/escape-html": "^2.1.1", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/dom": "^3.1.5", + "@wordpress/element": "^3.1.2", + "@wordpress/escape-html": "^2.1.2", "@wordpress/is-shallow-equal": "^4.1.1", - "@wordpress/keycodes": "^3.1.1", + "@wordpress/keycodes": "^3.1.2", "classnames": "^2.2.5", "lodash": "^4.17.21", "memize": "^1.1.0", @@ -4268,13 +4377,13 @@ } }, "@wordpress/scripts": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@wordpress/scripts/-/scripts-16.1.4.tgz", - "integrity": "sha512-onjnFkshfGO5ecKEI7gG22F851/GVZTjffXamPaJBYiv2a1u05bDD8i9fjJduBcyQP2O2Qy1B8droC4uL7Epvw==", + "version": "16.1.5", + "resolved": "https://registry.npmjs.org/@wordpress/scripts/-/scripts-16.1.5.tgz", + "integrity": "sha512-EF63cT5UGbWEMEJBBhxvcoNAuJIooKlqAAaMq5wN1urzsJRpQOTHTV658onoKFfgAxWB78CD7svuwIqNPGQdIw==", "dev": true, "requires": { "@svgr/webpack": "^5.2.0", - "@wordpress/babel-preset-default": "^6.2.0", + "@wordpress/babel-preset-default": "^6.2.1", "@wordpress/dependency-extraction-webpack-plugin": "^3.1.4", "@wordpress/eslint-plugin": "^9.0.6", "@wordpress/jest-preset-default": "^7.0.5", @@ -4328,11 +4437,12 @@ }, "dependencies": { "cacache": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", - "integrity": "sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "dev": true, "requires": { + "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -4359,9 +4469,9 @@ "dev": true }, "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", "dev": true }, "enhanced-resolve": { @@ -4399,9 +4509,9 @@ } }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -4497,9 +4607,9 @@ } }, "postcss": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz", - "integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz", + "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==", "dev": true, "requires": { "colorette": "^1.2.2", @@ -4809,9 +4919,9 @@ } }, "webpack-sources": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.0.tgz", - "integrity": "sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", "dev": true, "requires": { "source-list-map": "^2.0.1", @@ -4827,27 +4937,27 @@ } }, "@wordpress/server-side-render": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-2.1.11.tgz", - "integrity": "sha512-TY2OcJRfGpnhCaeAsh7/tHVNOLzToZ1lJ07zfIePCVQ6lNuQvBpLWXuEf7EGXH6jc2AyRS8ler3zCxHX2MaIBA==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@wordpress/server-side-render/-/server-side-render-2.1.12.tgz", + "integrity": "sha512-NrxFv/u6xzs97Pgyb0BbhB2f7pAII2trD8nyDY+/JfjNcTguulthRh9kmmPWp/vo6kgyEO1xyo6yHUnHLnh/vQ==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", - "@wordpress/deprecated": "^3.1.1", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/url": "^3.1.1", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", + "@wordpress/deprecated": "^3.1.2", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/url": "^3.1.2", "lodash": "^4.17.21" } }, "@wordpress/shortcode": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/shortcode/-/shortcode-3.1.1.tgz", - "integrity": "sha512-NiYTV42zkav0XUbRKAzoPcN3+GlwNlSXYZFLoNz+WInamTcXR5ZxQr4TE7F3DuoDNgyjwpE7vXbDJ0HFWRkgWw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/shortcode/-/shortcode-3.1.2.tgz", + "integrity": "sha512-pZQf4nu4iQdyQIz3OnphvPcKTL9jlEIR1a58icis+PDnqbr0gv4PGwS3Hbamlm4p7+bkxm5Pskfj3n3ykqwGLQ==", "requires": { "@babel/runtime": "^7.13.10", "lodash": "^4.17.21", @@ -4855,9 +4965,9 @@ } }, "@wordpress/stylelint-config": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@wordpress/stylelint-config/-/stylelint-config-19.0.5.tgz", - "integrity": "sha512-VI89jNS4wqr6Bd2PklGiTlrzrTH2RLQe2mHkWsYABVcFBFlsv6bTDQbO2c4xX1jd/9yYH7lEyvuzb3sHnyxMSA==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@wordpress/stylelint-config/-/stylelint-config-19.1.0.tgz", + "integrity": "sha512-K/wB9rhB+pH5WvDh3fV3DN5C3Bud+jPGXmnPY8fOXKMYI3twCFozK/j6sVuaJHqGp/0kKEF0hkkGh+HhD30KGQ==", "dev": true, "requires": { "stylelint-config-recommended": "^3.0.0", @@ -4875,9 +4985,9 @@ } }, "@wordpress/url": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-3.1.1.tgz", - "integrity": "sha512-I+yEw+a66wZ+FrpYU1F78/3c5p7/323UIrfnPUN51hIJcatsqJyQZW9Z1CNZeN5SuCobha0GPq4lw8517+VUMw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-3.1.2.tgz", + "integrity": "sha512-hT214NQG2p+FiL4jdKPJItHMEeA70uqvhKlnPOa7qqf9u+6QMnhVplxFxWSIu5cB7glmx5JQG4EMR2Ohz3jgTg==", "requires": { "@babel/runtime": "^7.13.10", "lodash": "^4.17.21", @@ -4885,47 +4995,47 @@ } }, "@wordpress/viewport": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@wordpress/viewport/-/viewport-3.1.5.tgz", - "integrity": "sha512-Jgt8HnotByCGfHJi5UKg7M9wcnzjfS8TdpMG8psi/d3bq9sLSZM6yQWdbat2MF93aqtYenF4/Wbev5nKPdKRUw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@wordpress/viewport/-/viewport-3.1.6.tgz", + "integrity": "sha512-SwIL26Nd691mO8R21GUrODjVqJx1Y1DVNHbX9VusJxvf7citc94dZnXXHiQ8zc7vlg5ryMBF49/EFn8rZ8Zn8w==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/data": "^5.1.5", + "@wordpress/compose": "^4.1.6", + "@wordpress/data": "^5.1.6", "lodash": "^4.17.21" } }, "@wordpress/warning": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-2.1.1.tgz", - "integrity": "sha512-EX+/6P2bWO0zRrKJYx1yck0rY2K5z5aPb67DTU+2ggcowW8JRP7hBzGdzhXqoE32oMS7RO97nG3uD9sZtn2DJA==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-2.1.2.tgz", + "integrity": "sha512-MqMo5AYffG/Gi3h1uRFJGBxp4TGmxw+7A4W81oe7VC9linJYhbNyeyvaMlL02m06KG2szWwl4fn0bdhyre433w==" }, "@wordpress/widgets": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/@wordpress/widgets/-/widgets-1.1.18.tgz", - "integrity": "sha512-qUg595IecNXmu/8sS5l7NJdcMJbToj+0bjOQzj3bZDapQuASpWHl9YjrrNNRwt1koq9CXp65E14dNuDFj0RKeQ==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@wordpress/widgets/-/widgets-1.1.19.tgz", + "integrity": "sha512-6ojIQVbeeS3fhXs+nNdmKIc6BtYnPoPq6qXLcTFGV9yXPJs8zX5RRdI3ziEFeV/IILCoIk4fmbw87ncIQwahQA==", "requires": { "@babel/runtime": "^7.13.10", - "@wordpress/api-fetch": "^5.1.1", - "@wordpress/block-editor": "^6.1.13", - "@wordpress/blocks": "^9.1.7", - "@wordpress/components": "^14.1.10", - "@wordpress/compose": "^4.1.5", - "@wordpress/core-data": "^3.1.11", - "@wordpress/data": "^5.1.5", - "@wordpress/element": "^3.1.1", - "@wordpress/i18n": "^4.1.1", - "@wordpress/icons": "^4.0.2", - "@wordpress/notices": "^3.1.5", - "@wordpress/url": "^3.1.1", + "@wordpress/api-fetch": "^5.1.2", + "@wordpress/block-editor": "^6.1.14", + "@wordpress/blocks": "^9.1.8", + "@wordpress/components": "^14.1.11", + "@wordpress/compose": "^4.1.6", + "@wordpress/core-data": "^3.1.12", + "@wordpress/data": "^5.1.6", + "@wordpress/element": "^3.1.2", + "@wordpress/i18n": "^4.1.2", + "@wordpress/icons": "^4.0.3", + "@wordpress/notices": "^3.1.6", + "@wordpress/url": "^3.1.2", "classnames": "^2.2.5", "lodash": "^4.17.21" } }, "@wordpress/wordcount": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@wordpress/wordcount/-/wordcount-3.1.1.tgz", - "integrity": "sha512-O7T3lONKZYlPxkvIhZp5wEDl61yJs1h87VrDSkv3ZdOtEgpRF1La6pA/GN/BvBOUQL9ZAbqXUmQgUZ8hHd31eA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@wordpress/wordcount/-/wordcount-3.1.2.tgz", + "integrity": "sha512-jFumH3IJzbEtGupxfre7asRMF6zHmNPeOlNgJw7luaeE1YFwgXkCtflDFf2Y6fC09xJmwuDPwxLnoII8RLhNtQ==", "requires": { "@babel/runtime": "^7.13.10", "lodash": "^4.17.21" @@ -5264,9 +5374,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -5275,11 +5385,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -5307,27 +5418,19 @@ } }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - } + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -5409,9 +5512,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -5420,11 +5523,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -5452,19 +5556,19 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -5515,9 +5619,9 @@ }, "dependencies": { "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", @@ -5525,11 +5629,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -5564,17 +5669,17 @@ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" }, "dependencies": { "call-bind": { @@ -5648,9 +5753,9 @@ }, "dependencies": { "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -5659,11 +5764,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -5701,19 +5807,19 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" }, "dependencies": { "call-bind": { @@ -5939,9 +6045,9 @@ "dev": true }, "axe-core": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.1.tgz", - "integrity": "sha512-3WVgVPs/7OnKU3s+lqMtkv3wQlg3WxK1YifmpJSDO0E1aPBrZWlrrTO6cxRqCXLuX2aYgCljqXIQd0VnRidV0g==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.3.tgz", + "integrity": "sha512-/lqqLAmuIPi79WYfRpy2i8z+x+vxU3zX2uAm0gs1q52qTuKwolOj1P8XbufpXcsydrpKx2yGn2wzAnxCMV86QA==", "dev": true }, "axios": { @@ -6010,9 +6116,9 @@ }, "dependencies": { "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -6172,9 +6278,9 @@ } }, "babel-plugin-polyfill-corejs3": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz", - "integrity": "sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz", + "integrity": "sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==", "dev": true, "requires": { "@babel/helper-define-polyfill-provider": "^0.2.2", @@ -6836,7 +6942,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -7469,9 +7575,9 @@ "dev": true }, "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", "dev": true } } @@ -7526,9 +7632,9 @@ "dev": true }, "domutils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", - "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "requires": { "dom-serializer": "^1.0.1", @@ -7900,9 +8006,9 @@ "dev": true }, "comment-parser": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.6.tgz", - "integrity": "sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.5.tgz", + "integrity": "sha512-RePCE4leIhBlmrqiYTvaqEeGYg7qpSl4etaIabKtdOQVi+mSTIBBklGUwIr79GXYnl3LpMwmDw4KeR2stNc6FA==", "dev": true }, "commondir": { @@ -8232,21 +8338,58 @@ } }, "core-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz", - "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.0.tgz", + "integrity": "sha512-zXT4rclS9jM6tikbAUKAGLonuRKOJ2ZvBnZCEOJAbzuTLw4kKcuA5plNt8juzdU6O/py/EgAehzvLh0VXEdBbQ==", "dev": true }, "core-js-compat": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz", - "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.17.0.tgz", + "integrity": "sha512-haEcBrfU3hu83JXWpcLHzeg8Ypf05LGK4GIjzLiYgFJYXuxrkdN2MrDBeHt/t5/ZFmIzLcdsT2x8Xw654wXsuw==", "dev": true, "requires": { - "browserslist": "^4.16.6", + "browserslist": "^4.16.8", "semver": "7.0.0" }, "dependencies": { + "browserslist": { + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", + "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001251", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.811", + "escalade": "^3.1.1", + "node-releases": "^1.1.75" + } + }, + "caniuse-lite": { + "version": "1.0.30001252", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz", + "integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==", + "dev": true + }, + "colorette": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.826", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.826.tgz", + "integrity": "sha512-bpLc4QU4B8PYmdO4MSu2ZBTMD8lAaEXRS43C09lB31BvYwuk9UxgBRXbY5OJBw7VuMGcg2MZG5FyTaP9u4PQnw==", + "dev": true + }, + "node-releases": { + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", + "dev": true + }, "semver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", @@ -8256,9 +8399,9 @@ } }, "core-js-pure": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.2.tgz", - "integrity": "sha512-D42L7RYh1J2grW8ttxoY1+17Y4wXZeKe7uyplAI3FkNQyI5OgBIAjUfFiTPfL1rs0qLpxaabITNbjKl1Sp82tA==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.17.0.tgz", + "integrity": "sha512-O5RvMRWW+I0hfR227mrIwU+gPLVaa4kPEq+9b8FcjuFed4QckOvYc94c2KSI/X5dlvcsj/V1Sp5F5cecYpNQOQ==", "dev": true }, "core-js-url-browser": { @@ -8449,15 +8592,15 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", "dev": true }, "json5": { @@ -8481,9 +8624,9 @@ } }, "postcss": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz", - "integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz", + "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==", "dev": true, "requires": { "colorette": "^1.2.2", @@ -8498,12 +8641,12 @@ "dev": true }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -9390,9 +9533,9 @@ } }, "domhandler": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", - "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", + "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", "dev": true, "requires": { "domelementtype": "^2.2.0" @@ -9491,20 +9634,34 @@ } }, "downshift": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.3.tgz", - "integrity": "sha512-RA1MuaNcTbt0j+sVLhSs8R2oZbBXYAtdQP/V+uHhT3DoDteZzJPjlC+LQVm9T07Wpvo84QXaZtUCePLDTDwGXg==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.7.tgz", + "integrity": "sha512-cVprZg/9Lvj/uhYRxELzlu1aezRcgPWBjTvspiGTVEU64gF5pRdSRKFVLcxqsZC637cLAGMbL40JavEfWnqgNg==", "requires": { - "@babel/runtime": "^7.13.10", + "@babel/runtime": "^7.14.8", "compute-scroll-into-view": "^1.0.17", "prop-types": "^15.7.2", - "react-is": "^17.0.2" + "react-is": "^17.0.2", + "tslib": "^2.3.0" }, "dependencies": { + "@babel/runtime": { + "version": "7.15.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", + "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -9745,54 +9902,6 @@ "string.prototype.trim": "^1.2.1" } }, - "enzyme-adapter-react-16": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.6.tgz", - "integrity": "sha512-yFlVJCXh8T+mcQo8M6my9sPgeGzj85HSHi6Apgf1Cvq/7EL/J9+1JoJmJsRxZgyTvPMAqOEpRSu/Ii/ZpyOk0g==", - "dev": true, - "requires": { - "enzyme-adapter-utils": "^1.14.0", - "enzyme-shallow-equal": "^1.0.4", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.values": "^1.1.2", - "prop-types": "^15.7.2", - "react-is": "^16.13.1", - "react-test-renderer": "^16.0.0-0", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "enzyme-adapter-utils": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz", - "integrity": "sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg==", - "dev": true, - "requires": { - "airbnb-prop-types": "^2.16.0", - "function.prototype.name": "^1.1.3", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.fromentries": "^2.0.3", - "prop-types": "^15.7.2", - "semver": "^5.7.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "enzyme-shallow-equal": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", @@ -9962,13 +10071,13 @@ } }, "eslint": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", - "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.2", + "@eslint/eslintrc": "^0.4.3", "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -10078,9 +10187,9 @@ } }, "globals": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", - "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -10137,36 +10246,40 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "ms": "2.0.0" + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, "eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", "dev": true, "requires": { "debug": "^3.2.7", @@ -10237,26 +10350,26 @@ } }, "eslint-plugin-import": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", - "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "version": "2.24.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz", + "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==", "dev": true, "requires": { "array-includes": "^3.1.3", "array.prototype.flat": "^1.2.4", "debug": "^2.6.9", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.6.2", "find-up": "^2.0.0", "has": "^1.0.3", - "is-core-module": "^2.4.0", + "is-core-module": "^2.6.0", "minimatch": "^3.0.4", - "object.values": "^1.1.3", + "object.values": "^1.1.4", "pkg-up": "^2.0.0", "read-pkg-up": "^3.0.0", "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" + "tsconfig-paths": "^3.11.0" }, "dependencies": { "call-bind": { @@ -10279,9 +10392,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -10290,11 +10403,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -10331,28 +10445,28 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", "dev": true, "requires": { "has": "^1.0.3" } }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "locate-path": { @@ -10455,26 +10569,28 @@ } }, "eslint-plugin-jest": { - "version": "24.3.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.3.6.tgz", - "integrity": "sha512-WOVH4TIaBLIeCX576rLcOgjNXqP+jNlCiEmRgFTfQtJ52DpwnIQKAVGlGPAN7CZ33bW6eNfHD6s8ZbEUTQubJg==", + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.4.0.tgz", + "integrity": "sha512-8qnt/hgtZ94E9dA6viqfViKBfkJwFHXgJmTWlMGDgunw1XJEGqm3eiPjDsTanM3/u/3Az82nyQM9GX7PM/QGmg==", "dev": true, "requires": { "@typescript-eslint/experimental-utils": "^4.0.1" } }, "eslint-plugin-jsdoc": { - "version": "30.7.13", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.7.13.tgz", - "integrity": "sha512-YM4WIsmurrp0rHX6XiXQppqKB8Ne5ATiZLJe2+/fkp9l9ExXFr43BbAbjZaVrpCT+tuPYOZ8k1MICARHnURUNQ==", + "version": "34.8.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-34.8.2.tgz", + "integrity": "sha512-UOU9A40Cl806JMtla2vF+RM6sNqfLPbhLv9FZqhcC7+LmChD3DVaWqM7ADxpF0kMyZNWe1QKUnqGnXaA3NTn+w==", "dev": true, "requires": { - "comment-parser": "^0.7.6", + "@es-joy/jsdoccomment": "^0.6.0", + "comment-parser": "1.1.5", "debug": "^4.3.1", + "esquery": "^1.4.0", "jsdoctypeparser": "^9.0.0", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "regextras": "^0.7.1", - "semver": "^7.3.4", + "semver": "^7.3.5", "spdx-expression-parse": "^3.0.1" }, "dependencies": { @@ -10492,6 +10608,15 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -10534,23 +10659,24 @@ } }, "eslint-plugin-prettier": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", - "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", + "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } }, "eslint-plugin-react": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz", - "integrity": "sha512-KJJIx2SYx7PBx3ONe/mEeMz4YE0Lcr7feJTCMyyKb/341NcjuAgim3Acgan89GfPv7nxXK2+0slu0CWXYM4x+Q==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.25.1.tgz", + "integrity": "sha512-P4j9K1dHoFXxDNP05AtixcJEvIT6ht8FhYKsrkY0MPCPaUMYijhpWwNiRDZVtA8KFuZOkGSeft6QwH8KuVpJug==", "dev": true, "requires": { "array-includes": "^3.1.3", "array.prototype.flatmap": "^1.2.4", "doctrine": "^2.1.0", + "estraverse": "^5.2.0", "has": "^1.0.3", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.0.4", @@ -10573,9 +10699,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -10584,11 +10710,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -10609,6 +10736,12 @@ } } }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", @@ -10616,19 +10749,19 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -11427,9 +11560,9 @@ "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==" }, "fastq": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", - "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -11503,9 +11636,9 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "json5": { @@ -11529,12 +11662,12 @@ } }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -11834,9 +11967,9 @@ } }, "flatted": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", - "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", "dev": true }, "flush-write-stream": { @@ -11930,9 +12063,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -11945,9 +12078,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -12064,9 +12197,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", @@ -12074,11 +12207,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -12104,17 +12238,17 @@ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -13343,6 +13477,21 @@ "has-symbol-support-x": "^1.4.1" } }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + } + } + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -13590,9 +13739,9 @@ "dev": true }, "domutils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", - "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "requires": { "dom-serializer": "^1.0.1", @@ -14179,7 +14328,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, "requires": { "get-intrinsic": "^1.1.0", "has": "^1.0.3", @@ -14190,7 +14338,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -14295,9 +14442,12 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } }, "is-binary-path": { "version": "2.1.0", @@ -14308,11 +14458,12 @@ } }, "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "dependencies": { "call-bind": { @@ -14501,9 +14652,12 @@ } }, "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-obj": { "version": "2.0.0", @@ -14618,9 +14772,12 @@ "dev": true }, "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-subset": { "version": "0.1.1", @@ -15074,9 +15231,9 @@ } }, "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, "npm-run-path": { @@ -16210,9 +16367,9 @@ "dev": true }, "jsdom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", - "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "requires": { "abab": "^2.0.5", @@ -16240,7 +16397,7 @@ "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.5.0", - "ws": "^7.4.5", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" }, "dependencies": { @@ -17815,9 +17972,9 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "json5": { @@ -17841,12 +17998,12 @@ } }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -18108,9 +18265,9 @@ "optional": true }, "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true }, "nanomatch": { @@ -18410,28 +18567,37 @@ } }, "npm-package-json-lint": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-5.1.0.tgz", - "integrity": "sha512-gPGpoFTbt0H4uPlubAKqHORg4+GObXqeYJh5ovkkSv76ua+t29vzRP4Qhm+9N/Q59Z3LT0tCmpoDlbTcNB7Jcg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-5.2.3.tgz", + "integrity": "sha512-rSgc4eVhtfwrU7AWwovqFWy8OEkgQL99vD3vWJmqtU9gxxJxKzi6Wqgo3gF7lhrBpyVcnlKxy/L2JCsvjWruDA==", "dev": true, "requires": { - "ajv": "^6.12.2", + "ajv": "^6.12.6", "ajv-errors": "^1.0.1", - "chalk": "^4.0.0", + "chalk": "^4.1.2", "cosmiconfig": "^6.0.0", - "debug": "^4.1.1", - "globby": "^11.0.0", - "ignore": "^5.1.4", - "is-plain-obj": "^2.1.0", - "jsonc-parser": "^2.2.1", - "log-symbols": "^4.0.0", - "meow": "^6.1.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "ignore": "^5.1.8", + "is-plain-obj": "^3.0.0", + "jsonc-parser": "^2.3.1", + "log-symbols": "^4.1.0", + "meow": "^6.1.1", "plur": "^4.0.0", - "semver": "^7.3.2", + "semver": "^7.3.5", "slash": "^3.0.0", - "strip-json-comments": "^3.1.0" + "strip-json-comments": "^3.1.1" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -18449,6 +18615,40 @@ "quick-lru": "^4.0.1" } }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -18473,6 +18673,12 @@ "slash": "^3.0.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -18480,9 +18686,15 @@ "dev": true }, "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true + }, + "jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", "dev": true }, "locate-path": { @@ -18519,6 +18731,12 @@ "yargs-parser": "^18.1.3" } }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -18583,6 +18801,15 @@ "strip-indent": "^3.0.0" } }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -18592,6 +18819,15 @@ "min-indent": "^1.0.0" } }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -18773,9 +19009,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", @@ -18783,11 +19019,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -18813,17 +19050,17 @@ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -18874,9 +19111,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -18885,11 +19122,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -18917,19 +19155,19 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -19732,9 +19970,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -19968,15 +20206,15 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -20007,12 +20245,12 @@ } }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -21014,6 +21252,16 @@ "resolved": "https://registry.npmjs.org/react-resize-aware/-/react-resize-aware-3.1.0.tgz", "integrity": "sha512-bIhHlxVTX7xKUz14ksXMEHjzCZPTpQZKZISY3nbTD273pDKPABGFNFBP6Tr42KECxzC5YQiKpMchjTVJCqaxpA==" }, + "react-shallow-renderer": { + "version": "16.14.1", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz", + "integrity": "sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0" + } + }, "react-spring": { "version": "8.0.27", "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-8.0.27.tgz", @@ -21024,15 +21272,33 @@ } }, "react-test-renderer": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", - "integrity": "sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", + "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", "dev": true, "requires": { "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.8.6", - "scheduler": "^0.19.1" + "react-is": "^17.0.2", + "react-shallow-renderer": "^16.13.1", + "scheduler": "^0.20.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } } }, "react-use-gesture": { @@ -21267,9 +21533,9 @@ } }, "redux": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", - "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.1.tgz", + "integrity": "sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw==", "requires": { "@babel/runtime": "^7.9.2" } @@ -21415,9 +21681,9 @@ } }, "unified": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.1.tgz", - "integrity": "sha512-juWjuI8Z4xFg8pJbnEZ41b5xjGUWGHqXALmBZ3FC3WX0PIx1CZBIIJ6mXbYMcf6Yw4Fi0rFUTA1cdz/BglbOhA==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", + "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==", "dev": true, "requires": { "bail": "^1.0.0", @@ -22059,9 +22325,9 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "json5": { @@ -22085,12 +22351,12 @@ } }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -22448,7 +22714,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -22545,12 +22810,12 @@ "dev": true }, "sirv": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.12.tgz", - "integrity": "sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg==", + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.17.tgz", + "integrity": "sha512-qx9go5yraB7ekT7bCMqUHJ5jEaOC/GXBxUWv+jeWnb7WzHUFdcQPGWk7YmAwFBaQBrogpuSqd/azbC2lZRqqmw==", "dev": true, "requires": { - "@polka/url": "^1.0.0-next.15", + "@polka/url": "^1.0.0-next.20", "mime": "^2.3.1", "totalist": "^1.0.0" } @@ -23387,9 +23652,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -23398,11 +23663,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -23428,19 +23694,19 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -23503,9 +23769,9 @@ } }, "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -23514,11 +23780,12 @@ "get-intrinsic": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.3", "is-string": "^1.0.6", - "object-inspect": "^1.10.3", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -23546,19 +23813,19 @@ "dev": true }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" } }, "object-inspect": { @@ -23708,9 +23975,9 @@ }, "dependencies": { "tslib": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", - "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -23833,9 +24100,9 @@ } }, "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -23934,6 +24201,15 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -24004,13 +24280,13 @@ "dev": true }, "normalize-package-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", - "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", - "resolve": "^1.20.0", + "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" } @@ -24125,16 +24401,6 @@ "strip-indent": "^3.0.0" } }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -24232,9 +24498,9 @@ } }, "stylelint-scss": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.19.0.tgz", - "integrity": "sha512-Ic5bsmpS4wVucOw44doC1Yi9f5qbeVL4wPFiEOaUElgsOuLEN6Ofn/krKI8BeNL2gAn53Zu+IcVV4E345r6rBw==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-3.20.1.tgz", + "integrity": "sha512-OTd55O1TTAC5nGKkVmUDLpz53LlK39R3MImv1CfuvsK7/qugktqiZAeQLuuC4UBhzxCnsc7fp9u/gfRZwFAIkA==", "dev": true, "requires": { "lodash": "^4.17.15", @@ -24363,9 +24629,9 @@ }, "dependencies": { "ajv": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz", - "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==", + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -24441,9 +24707,9 @@ "dev": true }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "requires": { "chownr": "^2.0.0", @@ -24618,9 +24884,9 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "json5": { @@ -24650,12 +24916,12 @@ } }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -24903,25 +25169,15 @@ "dev": true }, "tsconfig-paths": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz", - "integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", "dev": true, "requires": { - "json5": "^2.2.0", + "@types/json5": "^0.0.29", + "json5": "^1.0.1", "minimist": "^1.2.0", "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "tslib": { @@ -25397,9 +25653,9 @@ }, "dependencies": { "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, "json5": { @@ -25423,12 +25679,12 @@ } }, "schema-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.0.tgz", - "integrity": "sha512-tTEaeYkyIhEZ9uWgAjDerWov3T9MgX8dhhy2r0IGeeX4W8ngtGl1++dUve/RUqzuaASSh7shwCDJjEzthxki8w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", + "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } @@ -26436,9 +26692,9 @@ } }, "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" }, "whatwg-mimetype": { "version": "2.3.0", diff --git a/package.json b/package.json index d680c53851aef..172cb074be67b 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,12 @@ "last 2 Opera versions" ], "devDependencies": { - "@wordpress/babel-preset-default": "6.2.0", + "@wordpress/babel-preset-default": "6.2.1", "@wordpress/custom-templated-path-webpack-plugin": "2.0.5", "@wordpress/dependency-extraction-webpack-plugin": "3.1.4", - "@wordpress/e2e-test-utils": "5.3.0", + "@wordpress/e2e-test-utils": "5.4.3", "@wordpress/library-export-default-webpack-plugin": "2.0.5", - "@wordpress/scripts": "16.1.4", + "@wordpress/scripts": "16.1.5", "autoprefixer": "^9.8.6", "chalk": "4.1.1", "check-node-version": "4.1.0", @@ -77,58 +77,58 @@ "webpack-livereload-plugin": "2.3.0" }, "dependencies": { - "@wordpress/a11y": "3.1.1", - "@wordpress/annotations": "2.1.5", - "@wordpress/api-fetch": "5.1.1", - "@wordpress/autop": "3.1.1", - "@wordpress/blob": "3.1.1", - "@wordpress/block-directory": "2.1.20", - "@wordpress/block-editor": "6.1.13", - "@wordpress/block-library": "3.2.18", - "@wordpress/block-serialization-default-parser": "4.1.1", - "@wordpress/blocks": "9.1.7", - "@wordpress/components": "14.1.10", - "@wordpress/compose": "4.1.5", - "@wordpress/core-data": "3.1.11", - "@wordpress/customize-widgets": "1.0.19", - "@wordpress/data": "5.1.5", - "@wordpress/data-controls": "2.1.3", - "@wordpress/date": "4.1.1", - "@wordpress/deprecated": "3.1.1", - "@wordpress/dom": "3.1.4", - "@wordpress/dom-ready": "3.1.1", - "@wordpress/edit-post": "4.1.20", - "@wordpress/edit-widgets": "2.1.20", - "@wordpress/editor": "10.1.16", - "@wordpress/element": "3.1.1", - "@wordpress/escape-html": "2.1.1", - "@wordpress/format-library": "2.1.13", + "@wordpress/a11y": "3.1.2", + "@wordpress/annotations": "2.1.6", + "@wordpress/api-fetch": "5.1.2", + "@wordpress/autop": "3.1.2", + "@wordpress/blob": "3.1.2", + "@wordpress/block-directory": "2.1.21", + "@wordpress/block-editor": "6.1.14", + "@wordpress/block-library": "3.2.19", + "@wordpress/block-serialization-default-parser": "4.1.2", + "@wordpress/blocks": "9.1.8", + "@wordpress/components": "14.1.11", + "@wordpress/compose": "4.1.6", + "@wordpress/core-data": "3.1.12", + "@wordpress/customize-widgets": "1.0.20", + "@wordpress/data": "5.1.6", + "@wordpress/data-controls": "2.1.6", + "@wordpress/date": "4.1.2", + "@wordpress/deprecated": "3.1.2", + "@wordpress/dom": "3.1.5", + "@wordpress/dom-ready": "3.1.2", + "@wordpress/edit-post": "4.1.21", + "@wordpress/edit-widgets": "2.1.21", + "@wordpress/editor": "10.1.17", + "@wordpress/element": "3.1.2", + "@wordpress/escape-html": "2.1.2", + "@wordpress/format-library": "2.1.14", "@wordpress/hooks": "3.1.1", - "@wordpress/html-entities": "3.1.1", - "@wordpress/i18n": "4.1.1", - "@wordpress/icons": "4.0.2", - "@wordpress/interface": "3.1.11", + "@wordpress/html-entities": "3.1.2", + "@wordpress/i18n": "4.1.2", + "@wordpress/icons": "4.0.3", + "@wordpress/interface": "3.1.12", "@wordpress/is-shallow-equal": "4.1.1", - "@wordpress/keyboard-shortcuts": "2.1.6", - "@wordpress/keycodes": "3.1.1", - "@wordpress/list-reusable-blocks": "2.1.10", - "@wordpress/media-utils": "2.1.1", - "@wordpress/notices": "3.1.5", - "@wordpress/nux": "4.1.10", - "@wordpress/plugins": "3.1.5", - "@wordpress/primitives": "2.1.1", - "@wordpress/priority-queue": "2.1.1", - "@wordpress/redux-routine": "4.1.1", - "@wordpress/reusable-blocks": "2.1.16", - "@wordpress/rich-text": "4.1.5", - "@wordpress/server-side-render": "2.1.11", - "@wordpress/shortcode": "3.1.1", + "@wordpress/keyboard-shortcuts": "2.1.7", + "@wordpress/keycodes": "3.1.2", + "@wordpress/list-reusable-blocks": "2.1.11", + "@wordpress/media-utils": "2.1.2", + "@wordpress/notices": "3.1.6", + "@wordpress/nux": "4.1.11", + "@wordpress/plugins": "3.1.6", + "@wordpress/primitives": "2.1.2", + "@wordpress/priority-queue": "2.1.2", + "@wordpress/redux-routine": "4.1.2", + "@wordpress/reusable-blocks": "2.1.17", + "@wordpress/rich-text": "4.1.6", + "@wordpress/server-side-render": "2.1.12", + "@wordpress/shortcode": "3.1.2", "@wordpress/token-list": "2.1.1", - "@wordpress/url": "3.1.1", - "@wordpress/viewport": "3.1.5", - "@wordpress/warning": "2.1.1", - "@wordpress/widgets": "1.1.18", - "@wordpress/wordcount": "3.1.1", + "@wordpress/url": "3.1.2", + "@wordpress/viewport": "3.1.6", + "@wordpress/warning": "2.1.2", + "@wordpress/widgets": "1.1.19", + "@wordpress/wordcount": "3.1.2", "backbone": "1.4.0", "clipboard": "2.0.8", "core-js-url-browser": "3.6.4", @@ -150,7 +150,7 @@ "regenerator-runtime": "0.13.7", "twemoji": "13.1.0", "underscore": "1.13.1", - "whatwg-fetch": "3.0.0" + "whatwg-fetch": "3.6.2" }, "scripts": { "build": "grunt build", @@ -170,8 +170,7 @@ "env:cli": "node ./tools/local-env/scripts/docker.js run cli", "env:logs": "node ./tools/local-env/scripts/docker.js logs", "env:pull": "node ./tools/local-env/scripts/docker.js pull", - "test:php": "node ./tools/local-env/scripts/docker.js run --rm phpunit phpunit", - "test:php-composer": "node ./tools/local-env/scripts/docker.js run --rm phpunit php ./vendor/bin/phpunit", + "test:php": "node ./tools/local-env/scripts/docker.js run -T php composer update -W && node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit", "test:e2e": "node ./tests/e2e/run-tests.js", "wp-packages-update": "wp-scripts packages-update" } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index a5b2efb9e8278..dedf053d632aa 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -231,23 +231,18 @@ - + - - - - - - - + + + + - - + - - + @@ -286,6 +281,7 @@ + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5669bb3506d62..20267a5e9113d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,6 +6,10 @@ colors="true" beStrictAboutTestsThatDoNotTestAnything="true" beStrictAboutOutputDuringTests="true" + convertErrorsToExceptions="true" + convertWarningsToExceptions="true" + convertNoticesToExceptions="true" + convertDeprecationsToExceptions="true" > diff --git a/src/js/_enqueues/admin/common.js b/src/js/_enqueues/admin/common.js index 636237f0b4f2d..9c583f3d79efe 100644 --- a/src/js/_enqueues/admin/common.js +++ b/src/js/_enqueues/admin/common.js @@ -1695,6 +1695,25 @@ $( function() { } } ); + // Close sidebar when focus moves outside of toggle and sidebar. + $( '#wp-admin-bar-menu-toggle, #adminmenumain' ).on( 'focusout', function() { + var focusIsInToggle, focusIsInSidebar; + + if ( ! $wpwrap.hasClass( 'wp-responsive-open' ) ) { + return; + } + + // A brief delay is required to allow focus to switch to another element. + setTimeout( function() { + focusIsInToggle = $.contains( $( '#wp-admin-bar-menu-toggle' )[0], $( ':focus' )[0] ); + focusIsInSidebar = $.contains( $( '#adminmenumain' )[0], $( ':focus' )[0] ); + + if ( ! focusIsInToggle && ! focusIsInSidebar ) { + $( '#wp-admin-bar-menu-toggle' ).trigger( 'click.wp-responsive' ); + } + }, 10 ); + } ); + // Add menu events. $adminmenu.on( 'click.wp-responsive', 'li.wp-has-submenu > a', function( event ) { if ( ! $adminmenu.data('wp-responsive') ) { diff --git a/src/js/_enqueues/lib/image-edit.js b/src/js/_enqueues/lib/image-edit.js index 099398b4e3407..18d3099f62cf5 100644 --- a/src/js/_enqueues/lib/image-edit.js +++ b/src/js/_enqueues/lib/image-edit.js @@ -893,7 +893,7 @@ pop = this.intval( $('#imgedit-undone-' + postid).val() ); if ( pop < history.length ) { - if ( confirm( $('#imgedit-leaving-' + postid).html() ) ) { + if ( confirm( $('#imgedit-leaving-' + postid).text() ) ) { return false; } return true; diff --git a/src/js/_enqueues/vendor/jquery/ui/accordion.js b/src/js/_enqueues/vendor/jquery/ui/accordion.js index c1b3f26e8e456..0c1035d82e21d 100644 --- a/src/js/_enqueues/vendor/jquery/ui/accordion.js +++ b/src/js/_enqueues/vendor/jquery/ui/accordion.js @@ -1,5 +1,5 @@ /*! - * jQuery UI Accordion 1.12.1 + * jQuery UI Accordion 1.13.0 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -9,9 +9,9 @@ //>>label: Accordion //>>group: Widgets -// jscs:disable maximumLineLength +/* eslint-disable max-len */ //>>description: Displays collapsible content panels for presenting information in a limited amount of space. -// jscs:enable maximumLineLength +/* eslint-enable max-len */ //>>docs: http://api.jqueryui.com/accordion/ //>>demos: http://jqueryui.com/accordion/ //>>css.structure: ../../themes/base/core.css @@ -19,6 +19,8 @@ //>>css.theme: ../../themes/base/theme.css ( function( factory ) { + "use strict"; + if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. @@ -31,10 +33,11 @@ // Browser globals factory( jQuery ); } -}( function( $ ) { +} )( function( $ ) { +"use strict"; return $.widget( "ui.accordion", { - version: "1.12.1", + version: "1.13.0", options: { active: 0, animate: {}, @@ -45,7 +48,9 @@ return $.widget( "ui.accordion", { }, collapsible: false, event: "click", - header: "> li > :first-child, > :not(li):even", + header: function( elem ) { + return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() ); + }, heightStyle: "auto", icons: { activeHeader: "ui-icon-triangle-1-s", @@ -276,7 +281,11 @@ return $.widget( "ui.accordion", { var prevHeaders = this.headers, prevPanels = this.panels; - this.headers = this.element.find( this.options.header ); + if ( typeof this.options.header === "function" ) { + this.headers = this.options.header( this.element ); + } else { + this.headers = this.element.find( this.options.header ); + } this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", "ui-state-default" ); @@ -607,4 +616,4 @@ return $.widget( "ui.accordion", { } } ); -} ) ); +} ); diff --git a/src/js/_enqueues/vendor/jquery/ui/autocomplete.js b/src/js/_enqueues/vendor/jquery/ui/autocomplete.js index f5f58213f19ef..7116629005d8c 100644 --- a/src/js/_enqueues/vendor/jquery/ui/autocomplete.js +++ b/src/js/_enqueues/vendor/jquery/ui/autocomplete.js @@ -1,5 +1,5 @@ /*! - * jQuery UI Autocomplete 1.12.1 + * jQuery UI Autocomplete 1.13.0 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -17,6 +17,8 @@ //>>css.theme: ../../themes/base/theme.css ( function( factory ) { + "use strict"; + if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. @@ -30,10 +32,11 @@ // Browser globals factory( jQuery ); } -}( function( $ ) { +} )( function( $ ) { +"use strict"; $.widget( "ui.autocomplete", { - version: "1.12.1", + version: "1.13.0", defaultElement: "", options: { appendTo: null, @@ -196,11 +199,6 @@ $.widget( "ui.autocomplete", { this.previous = this._value(); }, blur: function( event ) { - if ( this.cancelBlur ) { - delete this.cancelBlur; - return; - } - clearTimeout( this.searching ); this.close( event ); this._change( event ); @@ -216,31 +214,24 @@ $.widget( "ui.autocomplete", { role: null } ) .hide() + + // Support: IE 11 only, Edge <= 14 + // For other browsers, we preventDefault() on the mousedown event + // to keep the dropdown from taking focus from the input. This doesn't + // work for IE/Edge, causing problems with selection and scrolling (#9638) + // Happily, IE and Edge support an "unselectable" attribute that + // prevents an element from receiving focus, exactly what we want here. + .attr( { + "unselectable": "on" + } ) .menu( "instance" ); this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); this._on( this.menu.element, { mousedown: function( event ) { - // prevent moving focus out of the text field + // Prevent moving focus out of the text field event.preventDefault(); - - // IE doesn't prevent moving focus even with event.preventDefault() - // so we set a flag to know when we should ignore the blur event - this.cancelBlur = true; - this._delay( function() { - delete this.cancelBlur; - - // Support: IE 8 only - // Right clicking a menu item or selecting text from the menu items will - // result in focus moving out of the input. However, we've already received - // and ignored the blur event because of the cancelBlur flag set above. So - // we restore focus to ensure that the menu closes properly based on the user's - // next actions. - if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) { - this.element.trigger( "focus" ); - } - } ); }, menufocus: function( event, ui ) { var label, item; @@ -271,7 +262,7 @@ $.widget( "ui.autocomplete", { // Announce the value in the liveRegion label = ui.item.attr( "aria-label" ) || item.value; - if ( label && $.trim( label ).length ) { + if ( label && String.prototype.trim.call( label ).length ) { this.liveRegion.children().hide(); $( "
" ).text( label ).appendTo( this.liveRegion ); } @@ -383,7 +374,7 @@ $.widget( "ui.autocomplete", { _initSource: function() { var array, url, that = this; - if ( $.isArray( this.options.source ) ) { + if ( Array.isArray( this.options.source ) ) { array = this.options.source; this.source = function( request, response ) { response( $.ui.autocomplete.filter( array, request.term ) ); @@ -455,7 +446,7 @@ $.widget( "ui.autocomplete", { _response: function() { var index = ++this.requestIndex; - return $.proxy( function( content ) { + return function( content ) { if ( index === this.requestIndex ) { this.__response( content ); } @@ -464,7 +455,7 @@ $.widget( "ui.autocomplete", { if ( !this.pending ) { this._removeClass( "ui-autocomplete-loading" ); } - }, this ); + }.bind( this ); }, __response: function( content ) { @@ -624,7 +615,7 @@ $.widget( "ui.autocomplete", { var editable = element.prop( "contentEditable" ); if ( editable === "inherit" ) { - return this._isContentEditable( element.parent() ); + return this._isContentEditable( element.parent() ); } return editable === "true"; @@ -675,4 +666,4 @@ $.widget( "ui.autocomplete", $.ui.autocomplete, { return $.ui.autocomplete; -} ) ); +} ); diff --git a/src/js/_enqueues/vendor/jquery/ui/button.js b/src/js/_enqueues/vendor/jquery/ui/button.js index 17348b716628b..cb9c8c0c6bbd9 100644 --- a/src/js/_enqueues/vendor/jquery/ui/button.js +++ b/src/js/_enqueues/vendor/jquery/ui/button.js @@ -1,5 +1,5 @@ /*! - * jQuery UI Button 1.12.1 + * jQuery UI Button 1.13.0 * http://jqueryui.com * * Copyright jQuery Foundation and other contributors @@ -17,6 +17,8 @@ //>>css.theme: ../../themes/base/theme.css ( function( factory ) { + "use strict"; + if ( typeof define === "function" && define.amd ) { // AMD. Register as an anonymous module. @@ -35,10 +37,11 @@ // Browser globals factory( jQuery ); } -}( function( $ ) { +} )( function( $ ) { +"use strict"; $.widget( "ui.button", { - version: "1.12.1", + version: "1.13.0", defaultElement: "" ).addClass( this._triggerClass ). - html( !buttonImage ? buttonText : $( "" ).attr( - { src:buttonImage, alt:buttonText, title:buttonText } ) ) ); + + if ( this._get( inst, "buttonImageOnly" ) ) { + inst.trigger = $( "" ) + .addClass( this._triggerClass ) + .attr( { + src: buttonImage, + alt: buttonText, + title: buttonText + } ); + } else { + inst.trigger = $( "" : "" ); - - buttonPanel = ( showButtonPanel ) ? "
" + ( isRTL ? controls : "" ) + - ( this._isInRange( inst, gotoDate ) ? "" : "" ) + ( isRTL ? "" : controls ) + "
" : ""; + controls = ""; + if ( !inst.inline ) { + controls = $( "
', + _x( 'Cannot Activate', 'plugin' ) + ); + } } else { $action_links[] = sprintf( '', diff --git a/src/wp-admin/includes/class-wp-plugins-list-table.php b/src/wp-admin/includes/class-wp-plugins-list-table.php index 9b74ca3c38ce1..32af4ad8ae71b 100644 --- a/src/wp-admin/includes/class-wp-plugins-list-table.php +++ b/src/wp-admin/includes/class-wp-plugins-list-table.php @@ -739,6 +739,12 @@ public function single_row( $item ) { $restrict_network_active = false; $restrict_network_only = false; + $requires_php = isset( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : null; + $requires_wp = isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : null; + + $compatible_php = is_php_version_compatible( $requires_php ); + $compatible_wp = is_wp_version_compatible( $requires_wp ); + if ( 'mustuse' === $context ) { $is_active = true; } elseif ( 'dropins' === $context ) { @@ -792,14 +798,21 @@ public function single_row( $item ) { } } else { if ( current_user_can( 'manage_network_plugins' ) ) { - $actions['activate'] = sprintf( - '%s', - wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ), - esc_attr( $plugin_id_attr ), - /* translators: %s: Plugin name. */ - esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ), - __( 'Network Activate' ) - ); + if ( $compatible_php && $compatible_wp ) { + $actions['activate'] = sprintf( + '%s', + wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ), + esc_attr( $plugin_id_attr ), + /* translators: %s: Plugin name. */ + esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ), + __( 'Network Activate' ) + ); + } else { + $actions['activate'] = sprintf( + '%s', + _x( 'Cannot Activate', 'plugin' ) + ); + } } if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { @@ -846,14 +859,21 @@ public function single_row( $item ) { } } else { if ( current_user_can( 'activate_plugin', $plugin_file ) ) { - $actions['activate'] = sprintf( - '%s', - wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ), - esc_attr( $plugin_id_attr ), - /* translators: %s: Plugin name. */ - esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ), - __( 'Activate' ) - ); + if ( $compatible_php && $compatible_wp ) { + $actions['activate'] = sprintf( + '%s', + wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ), + esc_attr( $plugin_id_attr ), + /* translators: %s: Plugin name. */ + esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ), + __( 'Activate' ) + ); + } else { + $actions['activate'] = sprintf( + '%s', + _x( 'Cannot Activate', 'plugin' ) + ); + } } if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) { @@ -945,10 +965,8 @@ public function single_row( $item ) { } - $requires_php = isset( $plugin_data['requires_php'] ) ? $plugin_data['requires_php'] : null; - $compatible_php = is_php_version_compatible( $requires_php ); - $class = $is_active ? 'active' : 'inactive'; - $checkbox_id = 'checkbox_' . md5( $plugin_file ); + $class = $is_active ? 'active' : 'inactive'; + $checkbox_id = 'checkbox_' . md5( $plugin_file ); if ( $restrict_network_active || $restrict_network_only || in_array( $status, array( 'mustuse', 'dropins' ), true ) || ! $compatible_php ) { $checkbox = ''; @@ -968,7 +986,9 @@ public function single_row( $item ) { $plugin_name = $plugin_data['Name']; } - if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) ) { + if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) + || ! $compatible_php || ! $compatible_wp + ) { $class .= ' update'; } @@ -1046,9 +1066,13 @@ public function single_row( $item ) { __( 'View details' ) ); } elseif ( ! empty( $plugin_data['PluginURI'] ) ) { + /* translators: %s: Plugin name. */ + $aria_label = sprintf( __( 'Visit plugin site for %s' ), $plugin_name ); + $plugin_meta[] = sprintf( - '%s', + '%s', esc_url( $plugin_data['PluginURI'] ), + esc_attr( $aria_label ), __( 'Visit plugin site' ) ); } @@ -1190,6 +1214,62 @@ public function single_row( $item ) { echo ''; + if ( ! $compatible_php || ! $compatible_wp ) { + printf( + '' . + '' . + '

', + esc_attr( $this->get_column_count() ) + ); + + if ( ! $compatible_php && ! $compatible_wp ) { + _e( 'This plugin doesn’t work with your versions of WordPress and PHP.' ); + if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { + printf( + /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */ + ' ' . __( 'Please update WordPress, and then learn more about updating PHP.' ), + self_admin_url( 'update-core.php' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } elseif ( current_user_can( 'update_core' ) ) { + printf( + /* translators: %s: URL to WordPress Updates screen. */ + ' ' . __( 'Please update WordPress.' ), + self_admin_url( 'update-core.php' ) + ); + } elseif ( current_user_can( 'update_php' ) ) { + printf( + /* translators: %s: URL to Update PHP page. */ + ' ' . __( 'Learn more about updating PHP.' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } + } elseif ( ! $compatible_wp ) { + _e( 'This plugin doesn’t work with your version of WordPress.' ); + if ( current_user_can( 'update_core' ) ) { + printf( + /* translators: %s: URL to WordPress Updates screen. */ + ' ' . __( 'Please update WordPress.' ), + self_admin_url( 'update-core.php' ) + ); + } + } elseif ( ! $compatible_php ) { + _e( 'This plugin doesn’t work with your version of PHP.' ); + if ( current_user_can( 'update_php' ) ) { + printf( + /* translators: %s: URL to Update PHP page. */ + ' ' . __( 'Learn more about updating PHP.' ), + esc_url( wp_get_update_php_url() ) + ); + wp_update_php_annotation( '

', '' ); + } + } + + echo '

'; + } + /** * Fires after each row in the Plugins list table. * diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index f8687efb956c8..213ca201d95f9 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -971,10 +971,13 @@ private function _page_rows( &$children_pages, &$count, $parent, $level, $pagenu * Handles the checkbox column output. * * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post The current WP_Post object. + * @param WP_Post $item The current WP_Post object. */ - public function column_cb( $post ) { + public function column_cb( $item ) { + // Restores the more descriptive, specific name for use within this method. + $post = $item; $show = current_user_can( 'edit_post', $post->ID ); /** @@ -1235,11 +1238,15 @@ public function column_author( $post ) { * Handles the default column output. * * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post The current WP_Post object. + * @param WP_Post $item The current WP_Post object. * @param string $column_name The current column name. */ - public function column_default( $post, $column_name ) { + public function column_default( $item, $column_name ) { + // Restores the more descriptive, specific name for use within this method. + $post = $item; + if ( 'categories' === $column_name ) { $taxonomy = 'category'; } elseif ( 'tags' === $column_name ) { @@ -1395,18 +1402,21 @@ protected function get_default_primary_column_name() { * Generates and displays row action links. * * @since 4.3.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post Post being acted upon. + * @param WP_Post $item Post being acted upon. * @param string $column_name Current column name. * @param string $primary Primary column name. * @return string Row actions output for posts, or an empty string * if the current column is not the primary column. */ - protected function handle_row_actions( $post, $column_name, $primary ) { + protected function handle_row_actions( $item, $column_name, $primary ) { if ( $primary !== $column_name ) { return ''; } + // Restores the more descriptive, specific name for use within this method. + $post = $item; $post_type_object = get_post_type_object( $post->post_type ); $can_edit_post = current_user_can( 'edit_post', $post->ID ); $actions = array(); @@ -1650,7 +1660,7 @@ public function inline_edit() { if ( current_user_can( $post_type_object->cap->edit_others_posts ) ) { $users_opt = array( 'hide_if_only_one_author' => false, - 'who' => 'authors', + 'capability' => array( $post_type_object->cap->edit_posts ), 'name' => 'post_author', 'class' => 'authors', 'multi' => 1, diff --git a/src/wp-admin/includes/class-wp-site-health-auto-updates.php b/src/wp-admin/includes/class-wp-site-health-auto-updates.php index d1c133524d6e2..ebc3547165505 100644 --- a/src/wp-admin/includes/class-wp-site-health-auto-updates.php +++ b/src/wp-admin/includes/class-wp-site-health-auto-updates.php @@ -41,7 +41,7 @@ public function run_tests() { $tests = array_filter( $tests ); $tests = array_map( - function( $test ) { + static function( $test ) { $test = (object) $test; if ( empty( $test->severity ) ) { @@ -156,7 +156,7 @@ public function test_wp_automatic_updates_disabled() { * * @return array|false The test results. False if the auto-updates failed. */ - function test_if_failed_update() { + public function test_if_failed_update() { $failed = get_site_option( 'auto_core_update_failed' ); if ( ! $failed ) { @@ -226,7 +226,7 @@ public function test_vcs_abspath() { // Search all directories we've found for evidence of version control. foreach ( $vcs_dirs as $vcs_dir ) { foreach ( $check_dirs as $check_dir ) { - // phpcs:ignore + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition,Squiz.PHP.DisallowMultipleAssignments if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) { break 2; } @@ -272,7 +272,7 @@ public function test_vcs_abspath() { * * @return array The test results. */ - function test_check_wp_filesystem_method() { + public function test_check_wp_filesystem_method() { // Make sure the `request_filesystem_credentials()` function is available during our REST API call. if ( ! function_exists( 'request_filesystem_credentials' ) ) { require_once ABSPATH . '/wp-admin/includes/file.php'; @@ -306,7 +306,7 @@ function test_check_wp_filesystem_method() { * * @return array|false The test results. False if they're not writeable. */ - function test_all_files_writable() { + public function test_all_files_writable() { global $wp_filesystem; require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z @@ -391,7 +391,7 @@ function test_all_files_writable() { * * @return array|false The test results. False if it isn't a development version. */ - function test_accepts_dev_updates() { + public function test_accepts_dev_updates() { require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z // Only for dev versions. if ( false === strpos( $wp_version, '-' ) ) { @@ -429,7 +429,7 @@ function test_accepts_dev_updates() { * * @return array The test results. */ - function test_accepts_minor_updates() { + public function test_accepts_minor_updates() { if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) { return array( 'description' => sprintf( diff --git a/src/wp-admin/includes/class-wp-site-health.php b/src/wp-admin/includes/class-wp-site-health.php index 0adff0078f204..c45a2ccc63e08 100644 --- a/src/wp-admin/includes/class-wp-site-health.php +++ b/src/wp-admin/includes/class-wp-site-health.php @@ -891,6 +891,10 @@ public function get_test_php_extensions() { 'function' => 'hash', 'required' => false, ), + 'imagick' => array( + 'extension' => 'imagick', + 'required' => false, + ), 'json' => array( 'function' => 'json_last_error', 'required' => true, @@ -916,10 +920,6 @@ public function get_test_php_extensions() { 'function' => 'preg_match', 'required' => false, ), - 'imagick' => array( - 'extension' => 'imagick', - 'required' => false, - ), 'mod_xml' => array( 'extension' => 'libxml', 'required' => false, @@ -941,6 +941,10 @@ public function get_test_php_extensions() { 'function' => 'iconv', 'required' => false, ), + 'intl' => array( + 'extension' => 'intl', + 'required' => false, + ), 'mcrypt' => array( 'extension' => 'mcrypt', 'required' => false, @@ -1878,6 +1882,196 @@ public function get_test_plugin_theme_auto_updates() { return $result; } + /** + * Test available disk space for updates. + * + * @since 5.9.0 + * + * @return array The test results. + */ + public function get_test_available_updates_disk_space() { + $available_space = function_exists( 'disk_free_space' ) ? (int) @disk_free_space( WP_CONTENT_DIR . '/upgrade/' ) : 0; + $available_space_in_mb = $available_space / MB_IN_BYTES; + + $result = array( + 'label' => __( 'Disk space available to safely perform updates' ), + 'status' => 'good', + 'badge' => array( + 'label' => __( 'Security' ), + 'color' => 'blue', + ), + 'description' => sprintf( + /* translators: %s: Available disk space in MB or GB. */ + '

' . __( '%s available disk space was detected, update routines can be performed safely.' ), + size_format( $available_space ) + ), + 'actions' => '', + 'test' => 'available_updates_disk_space', + ); + + if ( $available_space_in_mb < 100 ) { + $result['description'] = __( 'Available disk space is low, less than 100 MB available.' ); + $result['status'] = 'recommended'; + } + + if ( $available_space_in_mb < 20 ) { + $result['description'] = __( 'Available disk space is critically low, less than 20 MB available. Proceed with caution, updates may fail.' ); + $result['status'] = 'critical'; + } + + if ( ! $available_space ) { + $result['description'] = __( 'Could not determine available disk space for updates.' ); + $result['status'] = 'recommended'; + } + + return $result; + } + + /** + * Test if plugin and theme updates temp-backup directories are writable or can be created. + * + * @since 5.9.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @return array The test results. + */ + public function get_test_update_temp_backup_writable() { + global $wp_filesystem; + + $result = array( + 'label' => sprintf( + /* translators: %s: temp-backup */ + __( 'Plugin and theme update %s directory is writable' ), + 'temp-backup' + ), + 'status' => 'good', + 'badge' => array( + 'label' => __( 'Security' ), + 'color' => 'blue', + ), + 'description' => sprintf( + /* translators: %s: wp-content/upgrade/temp-backup */ + '

' . __( 'The %s directory used to improve the stability of plugin and theme updates is writable.' ), + 'wp-content/upgrade/temp-backup' + ), + 'actions' => '', + 'test' => 'update_temp_backup_writable', + ); + + if ( ! $wp_filesystem ) { + if ( ! function_exists( 'WP_Filesystem' ) ) { + require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' ); + } + WP_Filesystem(); + } + $wp_content = $wp_filesystem->wp_content_dir(); + + $upgrade_dir_exists = $wp_filesystem->is_dir( "$wp_content/upgrade" ); + $upgrade_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade" ); + $backup_dir_exists = $wp_filesystem->is_dir( "$wp_content/upgrade/temp-backup" ); + $backup_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade/temp-backup" ); + + $plugins_dir_exists = $wp_filesystem->is_dir( "$wp_content/upgrade/temp-backup/plugins" ); + $plugins_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade/temp-backup/plugins" ); + $themes_dir_exists = $wp_filesystem->is_dir( "$wp_content/upgrade/temp-backup/themes" ); + $themes_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade/temp-backup/themes" ); + + if ( $plugins_dir_exists && ! $plugins_dir_is_writable && $themes_dir_exists && ! $themes_dir_is_writable ) { + $result['status'] = 'critical'; + $result['label'] = sprintf( + /* translators: %s: temp-backup */ + __( 'Plugins and themes %s directories exist but are not writable' ), + 'temp-backup' + ); + $result['description'] = sprintf( + /* translators: 1: wp-content/upgrade/temp-backup/plugins, 2: wp-content/upgrade/temp-backup/themes. */ + '

' . __( 'The %1$s and %2$s directories exist but are not writable. These directories are used to improve the stability of plugin updates. Please make sure the server has write permissions to these directories.' ) . '

', + 'wp-content/upgrade/temp-backup/plugins', + 'wp-content/upgrade/temp-backup/themes' + ); + return $result; + } + + if ( $plugins_dir_exists && ! $plugins_dir_is_writable ) { + $result['status'] = 'critical'; + $result['label'] = sprintf( + /* translators: %s: temp-backup */ + __( 'Plugins %s directory exists but is not writable' ), + 'temp-backup' + ); + $result['description'] = sprintf( + /* translators: %s: wp-content/upgrade/temp-backup/plugins */ + '

' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of plugin updates. Please make sure the server has write permissions to this directory.' ) . '

', + 'wp-content/upgrade/temp-backup/plugins' + ); + return $result; + } + + if ( $themes_dir_exists && ! $themes_dir_is_writable ) { + $result['status'] = 'critical'; + $result['label'] = sprintf( + /* translators: %s: temp-backup */ + __( 'Themes %s directory exists but is not writable' ), + 'temp-backup' + ); + $result['description'] = sprintf( + /* translators: %s: wp-content/upgrade/temp-backup/themes */ + '

' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of theme updates. Please make sure the server has write permissions to this directory.' ) . '

', + 'wp-content/upgrade/temp-backup/themes' + ); + return $result; + } + + if ( ( ! $plugins_dir_exists || ! $themes_dir_exists ) && $backup_dir_exists && ! $backup_dir_is_writable ) { + $result['status'] = 'critical'; + $result['label'] = sprintf( + /* translators: %s: temp-backup */ + __( 'The %s directory exists but is not writable' ), + 'temp-backup' + ); + $result['description'] = sprintf( + /* translators: %s: wp-content/upgrade/temp-backup */ + '

' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of plugin and theme updates. Please make sure the server has write permissions to this directory.' ) . '

', + 'wp-content/upgrade/temp-backup' + ); + return $result; + } + + if ( ! $backup_dir_exists && $upgrade_dir_exists && ! $upgrade_dir_is_writable ) { + $result['status'] = 'critical'; + $result['label'] = sprintf( + /* translators: %s: upgrade */ + __( 'The %s directory exists but is not writable' ), + 'upgrade' + ); + $result['description'] = sprintf( + /* translators: %s: wp-content/upgrade */ + '

' . __( 'The %s directory exists but is not writable. This directory is used for plugin and theme updates. Please make sure the server has write permissions to this directory.' ) . '

', + 'wp-content/upgrade' + ); + return $result; + } + + if ( ! $upgrade_dir_exists && ! $wp_filesystem->is_writable( $wp_content ) ) { + $result['status'] = 'critical'; + $result['label'] = sprintf( + /* translators: %s: upgrade */ + __( 'The %s directory cannot be created' ), + 'upgrade' + ); + $result['description'] = sprintf( + /* translators: 1: wp-content/upgrade, 2: wp-content. */ + '

' . __( 'The %1$s directory does not exist, and the server does not have write permissions in %2$s to create it. This directory is used for plugin and theme updates. Please make sure the server has write permissions in %2$s.' ) . '

', + 'wp-content/upgrade', + 'wp-content' + ); + return $result; + } + + return $result; + } + /** * Test if loopbacks work as expected. * @@ -2262,71 +2456,80 @@ public function get_test_authorization_header() { public static function get_tests() { $tests = array( 'direct' => array( - 'wordpress_version' => array( + 'wordpress_version' => array( 'label' => __( 'WordPress Version' ), 'test' => 'wordpress_version', ), - 'plugin_version' => array( + 'plugin_version' => array( 'label' => __( 'Plugin Versions' ), 'test' => 'plugin_version', ), - 'theme_version' => array( + 'theme_version' => array( 'label' => __( 'Theme Versions' ), 'test' => 'theme_version', ), - 'php_version' => array( + 'php_version' => array( 'label' => __( 'PHP Version' ), 'test' => 'php_version', ), - 'php_extensions' => array( + 'php_extensions' => array( 'label' => __( 'PHP Extensions' ), 'test' => 'php_extensions', ), - 'php_default_timezone' => array( + 'php_default_timezone' => array( 'label' => __( 'PHP Default Timezone' ), 'test' => 'php_default_timezone', ), - 'php_sessions' => array( + 'php_sessions' => array( 'label' => __( 'PHP Sessions' ), 'test' => 'php_sessions', ), - 'sql_server' => array( + 'sql_server' => array( 'label' => __( 'Database Server version' ), 'test' => 'sql_server', ), - 'utf8mb4_support' => array( + 'utf8mb4_support' => array( 'label' => __( 'MySQL utf8mb4 support' ), 'test' => 'utf8mb4_support', ), - 'ssl_support' => array( + 'ssl_support' => array( 'label' => __( 'Secure communication' ), 'test' => 'ssl_support', ), - 'scheduled_events' => array( + 'scheduled_events' => array( 'label' => __( 'Scheduled events' ), 'test' => 'scheduled_events', ), - 'http_requests' => array( + 'http_requests' => array( 'label' => __( 'HTTP Requests' ), 'test' => 'http_requests', ), - 'rest_availability' => array( + 'rest_availability' => array( 'label' => __( 'REST API availability' ), 'test' => 'rest_availability', 'skip_cron' => true, ), - 'debug_enabled' => array( + 'debug_enabled' => array( 'label' => __( 'Debugging enabled' ), 'test' => 'is_in_debug_mode', ), - 'file_uploads' => array( + 'file_uploads' => array( 'label' => __( 'File uploads' ), 'test' => 'file_uploads', ), - 'plugin_theme_auto_updates' => array( + 'plugin_theme_auto_updates' => array( 'label' => __( 'Plugin and theme auto-updates' ), 'test' => 'plugin_theme_auto_updates', ), + 'update_temp_backup_writable' => array( + /* translators: %s: temp-backup */ + 'label' => sprintf( __( 'Updates %s directory access' ), 'temp-backup' ), + 'test' => 'update_temp_backup_writable', + ), + 'available_updates_disk_space' => array( + 'label' => __( 'Available disk space' ), + 'test' => 'available_updates_disk_space', + ), ), 'async' => array( 'dotorg_communication' => array( @@ -2564,7 +2767,7 @@ public function has_late_cron() { * * @return object The test results. */ - function detect_plugin_theme_auto_update_issues() { + public function detect_plugin_theme_auto_update_issues() { $mock_plugin = (object) array( 'id' => 'w.org/plugins/a-fake-plugin', 'slug' => 'a-fake-plugin', @@ -2647,7 +2850,7 @@ function detect_plugin_theme_auto_update_issues() { * * @return object The test results. */ - function can_perform_loopback() { + public function can_perform_loopback() { $body = array( 'site-health' => 'loopback-test' ); $cookies = wp_unslash( $_COOKIE ); $timeout = 10; diff --git a/src/wp-admin/includes/class-wp-terms-list-table.php b/src/wp-admin/includes/class-wp-terms-list-table.php index f6697f13a9d37..4823d29c9d6d1 100644 --- a/src/wp-admin/includes/class-wp-terms-list-table.php +++ b/src/wp-admin/includes/class-wp-terms-list-table.php @@ -77,9 +77,11 @@ public function ajax_user_can() { /** */ public function prepare_items() { - $tags_per_page = $this->get_items_per_page( 'edit_' . $this->screen->taxonomy . '_per_page' ); + $taxonomy = $this->screen->taxonomy; + + $tags_per_page = $this->get_items_per_page( "edit_{$taxonomy}_per_page" ); - if ( 'post_tag' === $this->screen->taxonomy ) { + if ( 'post_tag' === $taxonomy ) { /** * Filters the number of terms displayed per page for the Tags list table. * @@ -98,7 +100,7 @@ public function prepare_items() { * @param int $tags_per_page Number of tags to be displayed. Default 20. */ $tags_per_page = apply_filters_deprecated( 'tagsperpage', array( $tags_per_page ), '2.8.0', 'edit_tags_per_page' ); - } elseif ( 'category' === $this->screen->taxonomy ) { + } elseif ( 'category' === $taxonomy ) { /** * Filters the number of terms displayed per page for the Categories list table. * @@ -112,9 +114,11 @@ public function prepare_items() { $search = ! empty( $_REQUEST['s'] ) ? trim( wp_unslash( $_REQUEST['s'] ) ) : ''; $args = array( - 'search' => $search, - 'page' => $this->get_pagenum(), - 'number' => $tags_per_page, + 'taxonomy' => $taxonomy, + 'search' => $search, + 'page' => $this->get_pagenum(), + 'number' => $tags_per_page, + 'hide_empty' => 0, ); if ( ! empty( $_REQUEST['orderby'] ) ) { @@ -125,13 +129,24 @@ public function prepare_items() { $args['order'] = trim( wp_unslash( $_REQUEST['order'] ) ); } + $args['offset'] = ( $args['page'] - 1 ) * $args['number']; + + // Save the values because 'number' and 'offset' can be subsequently overridden. $this->callback_args = $args; + if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $args['orderby'] ) ) { + // We'll need the full set of terms then. + $args['number'] = 0; + $args['offset'] = $args['number']; + } + + $this->items = get_terms( $args ); + $this->set_pagination_args( array( 'total_items' => wp_count_terms( array( - 'taxonomy' => $this->screen->taxonomy, + 'taxonomy' => $taxonomy, 'search' => $search, ) ), @@ -140,14 +155,6 @@ public function prepare_items() { ); } - /** - * @return bool - */ - public function has_items() { - // @todo Populate $this->items in prepare_items(). - return true; - } - /** */ public function no_items() { @@ -216,45 +223,21 @@ protected function get_sortable_columns() { public function display_rows_or_placeholder() { $taxonomy = $this->screen->taxonomy; - $args = wp_parse_args( - $this->callback_args, - array( - 'taxonomy' => $taxonomy, - 'page' => 1, - 'number' => 20, - 'search' => '', - 'hide_empty' => 0, - ) - ); - - $page = $args['page']; - - // Set variable because $args['number'] can be subsequently overridden. - $number = $args['number']; - - $offset = ( $page - 1 ) * $number; - $args['offset'] = $offset; + $number = $this->callback_args['number']; + $offset = $this->callback_args['offset']; // Convert it to table rows. $count = 0; - if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $args['orderby'] ) ) { - // We'll need the full set of terms then. - $args['number'] = 0; - $args['offset'] = $args['number']; - } - - $terms = get_terms( $args ); - - if ( empty( $terms ) || ! is_array( $terms ) ) { + if ( empty( $this->items ) || ! is_array( $this->items ) ) { echo ''; $this->no_items(); echo ''; return; } - if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $args['orderby'] ) ) { - if ( ! empty( $args['search'] ) ) {// Ignore children on searches. + if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $this->callback_args['orderby'] ) ) { + if ( ! empty( $this->callback_args['search'] ) ) {// Ignore children on searches. $children = array(); } else { $children = _get_term_hierarchy( $taxonomy ); @@ -264,9 +247,9 @@ public function display_rows_or_placeholder() { * Some funky recursion to get the job done (paging & parents mainly) is contained within. * Skip it for non-hierarchical taxonomies for performance sake. */ - $this->_rows( $taxonomy, $terms, $children, $offset, $number, $count ); + $this->_rows( $taxonomy, $this->items, $children, $offset, $number, $count ); } else { - foreach ( $terms as $term ) { + foreach ( $this->items as $term ) { $this->single_row( $term ); } } @@ -364,10 +347,15 @@ public function single_row( $tag, $level = 0 ) { } /** - * @param WP_Term $tag Term object. + * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Term $item Term object. * @return string */ - public function column_cb( $tag ) { + public function column_cb( $item ) { + // Restores the more descriptive, specific name for use within this method. + $tag = $item; + if ( current_user_can( 'delete_term', $tag->term_id ) ) { return sprintf( '' . @@ -456,18 +444,21 @@ protected function get_default_primary_column_name() { * Generates and displays row action links. * * @since 4.3.0 + * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Term $tag Tag being acted upon. + * @param WP_Term $item Tag being acted upon. * @param string $column_name Current column name. * @param string $primary Primary column name. * @return string Row actions output for terms, or an empty string * if the current column is not the primary column. */ - protected function handle_row_actions( $tag, $column_name, $primary ) { + protected function handle_row_actions( $item, $column_name, $primary ) { if ( $primary !== $column_name ) { return ''; } + // Restores the more descriptive, specific name for use within this method. + $tag = $item; $taxonomy = $this->screen->taxonomy; $tax = get_taxonomy( $taxonomy ); $uri = wp_doing_ajax() ? wp_get_referer() : $_SERVER['REQUEST_URI']; @@ -620,11 +611,13 @@ public function column_links( $tag ) { } /** - * @param WP_Term $tag Term object. + * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support. + * + * @param WP_Term $item Term object. * @param string $column_name Name of the column. * @return string */ - public function column_default( $tag, $column_name ) { + public function column_default( $item, $column_name ) { /** * Filters the displayed columns in the terms list table. * @@ -638,11 +631,11 @@ public function column_default( $tag, $column_name ) { * * @since 2.8.0 * - * @param string $string Blank string. + * @param string $string Custom column output. Default empty. * @param string $column_name Name of the column. * @param int $term_id Term ID. */ - return apply_filters( "manage_{$this->screen->taxonomy}_custom_column", '', $column_name, $tag->term_id ); + return apply_filters( "manage_{$this->screen->taxonomy}_custom_column", '', $column_name, $item->term_id ); } /** diff --git a/src/wp-admin/includes/class-wp-upgrader-skin.php b/src/wp-admin/includes/class-wp-upgrader-skin.php index 33f083a3e7f6a..bb7e7bbf3b9e6 100644 --- a/src/wp-admin/includes/class-wp-upgrader-skin.php +++ b/src/wp-admin/includes/class-wp-upgrader-skin.php @@ -165,7 +165,7 @@ public function footer() { /** * @since 2.8.0 * - * @param string|WP_Error $errors + * @param string|WP_Error $errors Errors. */ public function error( $errors ) { if ( ! $this->done_header ) { @@ -186,26 +186,27 @@ public function error( $errors ) { /** * @since 2.8.0 + * @since 5.9.0 Renamed `$string` (a PHP reserved keyword) to `$feedback` for PHP 8 named parameter support. * - * @param string $string - * @param mixed ...$args Optional text replacements. + * @param string $feedback Message data. + * @param mixed ...$args Optional text replacements. */ - public function feedback( $string, ...$args ) { - if ( isset( $this->upgrader->strings[ $string ] ) ) { - $string = $this->upgrader->strings[ $string ]; + public function feedback( $feedback, ...$args ) { + if ( isset( $this->upgrader->strings[ $feedback ] ) ) { + $feedback = $this->upgrader->strings[ $feedback ]; } - if ( strpos( $string, '%' ) !== false ) { + if ( strpos( $feedback, '%' ) !== false ) { if ( $args ) { - $args = array_map( 'strip_tags', $args ); - $args = array_map( 'esc_html', $args ); - $string = vsprintf( $string, $args ); + $args = array_map( 'strip_tags', $args ); + $args = array_map( 'esc_html', $args ); + $feedback = vsprintf( $feedback, $args ); } } - if ( empty( $string ) ) { + if ( empty( $feedback ) ) { return; } - show_message( $string ); + show_message( $feedback ); } /** diff --git a/src/wp-admin/includes/class-wp-upgrader.php b/src/wp-admin/includes/class-wp-upgrader.php index 4cd0d9c5b1a95..225a7d4c6952f 100644 --- a/src/wp-admin/includes/class-wp-upgrader.php +++ b/src/wp-admin/includes/class-wp-upgrader.php @@ -133,11 +133,25 @@ public function __construct( $skin = null ) { * This will set the relationship between the skin being used and this upgrader, * and also add the generic strings to `WP_Upgrader::$strings`. * + * Additionally, it will schedule a weekly task to clean up the temp-backup directory. + * * @since 2.8.0 + * @since 5.9.0 Added the `schedule_temp_backup_cleanup()` task. */ public function init() { $this->skin->set_upgrader( $this ); $this->generic_strings(); + $this->schedule_temp_backup_cleanup(); + } + + /** + * Schedule cleanup of the temp-backup directory. + * + * @since 5.9.0 + */ + protected function schedule_temp_backup_cleanup() { + wp_schedule_event( time(), 'weekly', 'delete_temp_updater_backups' ); + add_action( 'delete_temp_updater_backups', array( $this, 'delete_all_temp_backups' ) ); } /** @@ -166,6 +180,13 @@ public function generic_strings() { $this->strings['maintenance_start'] = __( 'Enabling Maintenance mode…' ); $this->strings['maintenance_end'] = __( 'Disabling Maintenance mode…' ); + + /* translators: %s: temp-backup */ + $this->strings['temp_backup_mkdir_failed'] = sprintf( __( 'Could not create the %s directory.' ), 'temp-backup' ); + /* translators: %s: temp-backup */ + $this->strings['temp_backup_move_failed'] = sprintf( __( 'Could not move old version to the %s directory.' ), 'temp-backup' ); + $this->strings['temp_backup_restore_failed'] = __( 'Could not restore original version.' ); + } /** @@ -244,6 +265,7 @@ public function fs_connect( $directories = array(), $allow_relaxed_file_ownershi * Download a package. * * @since 2.8.0 + * @since 5.2.0 Added the `$check_signatures` parameter. * @since 5.5.0 Added the `$hook_extra` parameter. * * @param string $package The URI of the package. If this is the full path to an @@ -312,6 +334,9 @@ public function unpack_package( $package, $delete_package = true ) { $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder ); if ( ! empty( $upgrade_files ) ) { foreach ( $upgrade_files as $file ) { + if ( 'temp-backup' === $file['name'] ) { + continue; + } $wp_filesystem->delete( $upgrade_folder . $file['name'], true ); } } @@ -378,7 +403,7 @@ protected function flatten_dirlist( $nested_files, $path = '' ) { * * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. * - * @param string $remote_destination The location on the remote filesystem to be cleared + * @param string $remote_destination The location on the remote filesystem to be cleared. * @return bool|WP_Error True upon success, WP_Error on failure. */ public function clear_destination( $remote_destination ) { @@ -439,8 +464,8 @@ public function clear_destination( $remote_destination ) { * Default empty. * @type bool $clear_destination Whether to delete any files already in the destination * folder. Default false. - * @type bool $clear_working Whether to delete the files form the working directory - * after copying to the destination. Default false. + * @type bool $clear_working Whether to delete the files from the working directory + * after copying them to the destination. Default false. * @type bool $abort_if_destination_exists Whether to abort the installation if * the destination folder already exists. Default true. * @type array $hook_extra Extra arguments to pass to the filter hooks called by @@ -492,6 +517,13 @@ public function install_package( $args = array() ) { return $res; } + if ( ! empty( $args['hook_extra']['temp_backup'] ) ) { + $temp_backup = $this->move_to_temp_backup_dir( $args['hook_extra']['temp_backup'] ); + if ( is_wp_error( $temp_backup ) ) { + return $temp_backup; + } + } + // Retain the original source and destinations. $remote_source = $args['source']; $local_destination = $destination; @@ -563,7 +595,8 @@ public function install_package( $args = array() ) { * * @since 2.8.0 * - * @param true|WP_Error $removed Whether the destination was cleared. true upon success, WP_Error on failure. + * @param true|WP_Error $removed Whether the destination was cleared. + * True upon success, WP_Error on failure. * @param string $local_destination The local package destination. * @param string $remote_destination The remote package destination. * @param array $hook_extra Extra arguments passed to hooked filters. @@ -590,8 +623,8 @@ public function install_package( $args = array() ) { } } - // Copy new version of item into place. - $result = copy_dir( $source, $remote_destination ); + // Move new version of item into place. + $result = move_dir( $source, $remote_destination ); if ( is_wp_error( $result ) ) { if ( $args['clear_working'] ) { $wp_filesystem->delete( $remote_source, true ); @@ -648,8 +681,8 @@ public function install_package( $args = array() ) { * Default empty. * @type bool $clear_destination Whether to delete any files already in the * destination folder. Default false. - * @type bool $clear_working Whether to delete the files form the working - * directory after copying to the destination. + * @type bool $clear_working Whether to delete the files from the working + * directory after copying them to the destination. * Default false. * @type bool $abort_if_destination_exists Whether to abort the installation if the destination * folder already exists. When true, `$clear_destination` @@ -736,8 +769,8 @@ public function run( $options ) { } /* - * Download the package (Note, This just returns the filename - * of the file if the package is a local file) + * Download the package. Note: If the package is the full path + * to an existing local file, it will be returned untouched. */ $download = $this->download_package( $options['package'], true, $options['hook_extra'] ); @@ -809,6 +842,20 @@ public function run( $options ) { $this->skin->set_result( $result ); if ( is_wp_error( $result ) ) { + if ( ! empty( $options['hook_extra']['temp_backup'] ) ) { + /* + * Restore the backup on shutdown. + * Actions running on `shutdown` are immune to PHP timeouts, + * so in case the failure was due to a PHP timeout, + * we'll still be able to properly restore the previous version. + */ + add_action( + 'shutdown', + function() use ( $options ) { + $this->restore_temp_backup( $options['hook_extra']['temp_backup'] ); + } + ); + } $this->skin->error( $result ); if ( ! method_exists( $this->skin, 'hide_process_failed' ) || ! $this->skin->hide_process_failed( $result ) ) { @@ -821,6 +868,17 @@ public function run( $options ) { $this->skin->after(); + // Clean up the backup kept in the temp-backup directory. + if ( ! empty( $options['hook_extra']['temp_backup'] ) ) { + // Delete the backup on `shutdown` to avoid a PHP timeout. + add_action( + 'shutdown', + function() use ( $options ) { + $this->delete_temp_backup( $options['hook_extra']['temp_backup'] ); + } + ); + } + if ( ! $options['is_multi'] ) { /** @@ -868,7 +926,7 @@ public function run( $options ) { * * @since 2.8.0 * - * @global WP_Filesystem_Base $wp_filesystem Subclass + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. * * @param bool $enable True to enable maintenance mode, false to disable. */ @@ -946,6 +1004,154 @@ public static function release_lock( $lock_name ) { return delete_option( $lock_name . '.lock' ); } + /** + * Moves the plugin/theme being updated into a temp-backup directory. + * + * @since 5.9.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param array $args Array of data for the temp-backup. Must include a slug, the source, and directory. + * @return bool|WP_Error + */ + public function move_to_temp_backup_dir( $args ) { + global $wp_filesystem; + + if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) { + return false; + } + + $dest_dir = $wp_filesystem->wp_content_dir() . 'upgrade/temp-backup/'; + // Create the temp-backup directory if it doesn't exist. + if ( ( + ! $wp_filesystem->is_dir( $dest_dir ) + && ! $wp_filesystem->mkdir( $dest_dir ) + ) || ( + ! $wp_filesystem->is_dir( $dest_dir . $args['dir'] . '/' ) + && ! $wp_filesystem->mkdir( $dest_dir . $args['dir'] . '/' ) + ) + ) { + return new WP_Error( 'fs_temp_backup_mkdir', $this->strings['temp_backup_mkdir_failed'] ); + } + + $src = trailingslashit( $args['src'] ) . $args['slug']; + $dest = $dest_dir . $args['dir'] . '/' . $args['slug']; + + // Delete the temp-backup directory if it already exists. + if ( $wp_filesystem->is_dir( $dest ) ) { + $wp_filesystem->delete( $dest, true ); + } + + // Move to the temp-backup directory. + if ( ! $wp_filesystem->move( $src, $dest, true ) ) { + return new WP_Error( 'fs_temp_backup_move', $this->strings['temp_backup_move_failed'] ); + } + + return true; + } + + /** + * Restores the plugin/theme from the temp-backup directory. + * + * @since 5.9.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param array $args Array of data for the temp-backup. Must include a slug, the source, and directory. + * @return bool|WP_Error + */ + public function restore_temp_backup( $args ) { + global $wp_filesystem; + + if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) { + return false; + } + + $src = $wp_filesystem->wp_content_dir() . 'upgrade/temp-backup/' . $args['dir'] . '/' . $args['slug']; + $dest = trailingslashit( $args['src'] ) . $args['slug']; + + if ( $wp_filesystem->is_dir( $src ) ) { + // Cleanup. + if ( $wp_filesystem->is_dir( $dest ) && ! $wp_filesystem->delete( $dest, true ) ) { + return new WP_Error( 'fs_temp_backup_delete', $this->strings['temp_backup_restore_failed'] ); + } + + // Move it. + if ( ! $wp_filesystem->move( $src, $dest, true ) ) { + return new WP_Error( 'fs_temp_backup_delete', $this->strings['temp_backup_restore_failed'] ); + } + } + + return true; + } + + /** + * Deletes a temp-backup. + * + * @since 5.9.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param array $args Array of data for the temp-backup. Must include a slug, the source, and directory. + * @return bool + */ + public function delete_temp_backup( $args ) { + global $wp_filesystem; + + if ( empty( $args['slug'] ) || empty( $args['dir'] ) ) { + return false; + } + + return $wp_filesystem->delete( + $wp_filesystem->wp_content_dir() . "upgrade/temp-backup/{$args['dir']}/{$args['slug']}", + true + ); + } + + /** + * Deletes all contents of the temp-backup directory. + * + * @since 5.9.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + */ + public function delete_all_temp_backups() { + /* + * Check if there's a lock, or if currently performing an Ajax request, + * in which case there's a chance we're doing an update. + * Reschedule for an hour from now and exit early. + */ + if ( get_option( 'core_updater.lock' ) || get_option( 'auto_updater.lock' ) || wp_doing_ajax() ) { + wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'delete_temp_updater_backups' ); + return; + } + + add_action( + 'shutdown', + /* + * This action runs on shutdown to make sure there's no plugin updates currently running. + * Using a closure in this case is OK since the action can be removed by removing the parent hook. + */ + function() { + global $wp_filesystem; + + if ( ! $wp_filesystem ) { + include_once ABSPATH . '/wp-admin/includes/file.php'; + WP_Filesystem(); + } + + $dirlist = $wp_filesystem->dirlist( $wp_filesystem->wp_content_dir() . 'upgrade/temp-backup/' ); + + foreach ( array_keys( $dirlist ) as $dir ) { + if ( '.' === $dir || '..' === $dir ) { + continue; + } + + $wp_filesystem->delete( $wp_filesystem->wp_content_dir() . 'upgrade/temp-backup/' . $dir, true ); + } + } + ); + } } /** Plugin_Upgrader class */ diff --git a/src/wp-admin/includes/credits.php b/src/wp-admin/includes/credits.php index c6ff5e79ea238..833b676cec812 100644 --- a/src/wp-admin/includes/credits.php +++ b/src/wp-admin/includes/credits.php @@ -154,7 +154,7 @@ function wp_credits_section_list( $credits = array(), $slug = '' ) { $data2x = get_avatar_data( $person_data[1] . '@md5.gravatar.com', array( 'size' => $size * 2 ) ); echo '' . "\n"; echo esc_html( $person_data[0] ) . "\n\t"; - if ( ! $compact ) { + if ( ! $compact && ! empty( $person_data[3] ) ) { // phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText echo '' . translate( $person_data[3] ) . "\n"; } diff --git a/src/wp-admin/includes/deprecated.php b/src/wp-admin/includes/deprecated.php index 75c0ed3d87b41..27ce1d4e4f110 100644 --- a/src/wp-admin/includes/deprecated.php +++ b/src/wp-admin/includes/deprecated.php @@ -165,7 +165,7 @@ function wp_dropdown_cats( $currentcat = 0, $currentparent = 0, $parent = 0, $le * * @param string $option_group A settings group name. Should correspond to an allowed option key name. * Default allowed option key names include 'general', 'discussion', 'media', - * 'reading', 'writing', 'misc', 'options', and 'privacy'. + * 'reading', 'writing', and 'options'. * @param string $option_name The name of an option to sanitize and save. * @param callable $sanitize_callback A callback function that sanitizes the option's value. */ diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php index 052c235e15724..8a28c63adca5f 100644 --- a/src/wp-admin/includes/file.php +++ b/src/wp-admin/includes/file.php @@ -1112,6 +1112,7 @@ function wp_handle_sideload( &$file, $overrides = false, $time = null ) { * * @since 2.5.0 * @since 5.2.0 Signature Verification with SoftFail was added. + * @since 5.9.0 Support for Content-Disposition filename was added. * * @param string $url The URL of the file to download. * @param int $timeout The timeout for the request to download the file. @@ -1126,7 +1127,11 @@ function download_url( $url, $timeout = 300, $signature_verification = false ) { return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) ); } - $url_filename = basename( parse_url( $url, PHP_URL_PATH ) ); + $url_path = parse_url( $url, PHP_URL_PATH ); + $url_filename = ''; + if ( is_string( $url_path ) && '' !== $url_path ) { + $url_filename = basename( $url_path ); + } $tmpfname = wp_tempnam( $url_filename ); if ( ! $tmpfname ) { @@ -1178,6 +1183,29 @@ function download_url( $url, $timeout = 300, $signature_verification = false ) { return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ), $data ); } + $content_disposition = wp_remote_retrieve_header( $response, 'content-disposition' ); + + if ( $content_disposition ) { + $content_disposition = strtolower( $content_disposition ); + + if ( 0 === strpos( $content_disposition, 'attachment; filename=' ) ) { + $tmpfname_disposition = sanitize_file_name( substr( $content_disposition, 21 ) ); + } else { + $tmpfname_disposition = ''; + } + + // Potential file name must be valid string + if ( $tmpfname_disposition && is_string( $tmpfname_disposition ) && ( 0 === validate_file( $tmpfname_disposition ) ) ) { + if ( rename( $tmpfname, $tmpfname_disposition ) ) { + $tmpfname = $tmpfname_disposition; + } + + if ( ( $tmpfname !== $tmpfname_disposition ) && file_exists( $tmpfname_disposition ) ) { + unlink( $tmpfname_disposition ); + } + } + } + $content_md5 = wp_remote_retrieve_header( $response, 'content-md5' ); if ( $content_md5 ) { @@ -1212,9 +1240,8 @@ function download_url( $url, $timeout = 300, $signature_verification = false ) { // WordPress.org stores signatures at $package_url.sig. $signature_url = false; - $url_path = parse_url( $url, PHP_URL_PATH ); - if ( '.zip' === substr( $url_path, -4 ) || '.tar.gz' === substr( $url_path, -7 ) ) { + if ( is_string( $url_path ) && ( '.zip' === substr( $url_path, -4 ) || '.tar.gz' === substr( $url_path, -7 ) ) ) { $signature_url = str_replace( $url_path, $url_path . '.sig', $url ); } @@ -1243,7 +1270,7 @@ function download_url( $url, $timeout = 300, $signature_verification = false ) { } // Perform the checks. - $signature_verification = verify_file_signature( $tmpfname, $signature, basename( parse_url( $url, PHP_URL_PATH ) ) ); + $signature_verification = verify_file_signature( $tmpfname, $signature, $url_filename ); } if ( is_wp_error( $signature_verification ) ) { @@ -1914,6 +1941,34 @@ function copy_dir( $from, $to, $skip_list = array() ) { return true; } +/** + * Moves a directory from one location to another via the rename() PHP function. + * If the renaming failed, falls back to copy_dir(). + * + * Assumes that WP_Filesystem() has already been called and setup. + * + * @since 5.9.0 + * + * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. + * + * @param string $from Source directory. + * @param string $to Destination directory. + * @return true|WP_Error True on success, WP_Error on failure. + */ +function move_dir( $from, $to ) { + global $wp_filesystem; + + $wp_filesystem->rmdir( $to ); + if ( @rename( $from, $to ) ) { + return true; + } + + $wp_filesystem->mkdir( $to ); + $result = copy_dir( $from, $to ); + + return $result; +} + /** * Initializes and connects the WordPress Filesystem Abstraction classes. * diff --git a/src/wp-admin/includes/media.php b/src/wp-admin/includes/media.php index 7ad34a4566c0e..8768c75ee28c3 100644 --- a/src/wp-admin/includes/media.php +++ b/src/wp-admin/includes/media.php @@ -577,7 +577,7 @@ function wp_iframe( $content_func, ...$args ) { * Fires in the admin header for each specific form tab in the legacy * (pre-3.5.0) media upload popup. * - * The dynamic portion of the hook, `$content_func`, refers to the form + * The dynamic portion of the hook name, `$content_func`, refers to the form * callback for the media upload type. * * @since 2.5.0 @@ -1521,7 +1521,7 @@ function get_attachment_fields_to_edit( $post, $errors = null ) { * * @global WP_Query $wp_the_query WordPress Query object. * - * @param int $post_id Optional. Post ID. + * @param int $post_id Post ID. * @param array $errors Errors for attachment, if any. * @return string */ diff --git a/src/wp-admin/includes/meta-boxes.php b/src/wp-admin/includes/meta-boxes.php index 517a81d049a98..c14ae52ddc02b 100644 --- a/src/wp-admin/includes/meta-boxes.php +++ b/src/wp-admin/includes/meta-boxes.php @@ -87,7 +87,8 @@ function post_submit_meta_box( $post, $args = array() ) { endif; /** - * Fires before the post time/date setting in the Publish meta box. + * Fires after the Save Draft (or Save as Pending) and Preview (or Preview Changes) buttons + * in the Publish meta box. * * @since 4.4.0 * @@ -902,12 +903,14 @@ function post_slug_meta_box( $post ) { */ function post_author_meta_box( $post ) { global $user_ID; + + $post_type_object = get_post_type_object( $post->post_type ); ?> 'authors', + 'capability' => array( $post_type_object->cap->edit_posts ), 'name' => 'post_author_override', 'selected' => empty( $post->ID ) ? $user_ID : $post->post_author, 'include_selected' => true, @@ -1580,7 +1583,7 @@ function register_and_do_post_meta_boxes( $post ) { /** * Fires after all built-in meta boxes have been added, contextually for the given post type. * - * The dynamic portion of the hook, `$post_type`, refers to the post type of the post. + * The dynamic portion of the hook name, `$post_type`, refers to the post type of the post. * * Possible hook names include: * diff --git a/src/wp-admin/includes/misc.php b/src/wp-admin/includes/misc.php index 61d7698310446..70f6edde2b098 100644 --- a/src/wp-admin/includes/misc.php +++ b/src/wp-admin/includes/misc.php @@ -716,7 +716,7 @@ function set_screen_options() { /** * Filters a screen option value before it is set. * - * The dynamic portion of the hook, `$option`, refers to the option name. + * The dynamic portion of the hook name, `$option`, refers to the option name. * * Returning false from the filter will skip saving the current option. * diff --git a/src/wp-admin/includes/ms.php b/src/wp-admin/includes/ms.php index 7796745a2ed93..76af47f8affa1 100644 --- a/src/wp-admin/includes/ms.php +++ b/src/wp-admin/includes/ms.php @@ -736,6 +736,9 @@ function avoid_blog_page_permalink_collision( $data, $postarr ) { if ( ! is_main_site() ) { return $data; } + if ( isset( $data['post_parent'] ) && $data['post_parent'] ) { + return $data; + } $post_name = $data['post_name']; $c = 0; diff --git a/src/wp-admin/includes/plugin.php b/src/wp-admin/includes/plugin.php index 6e332c247e85e..0934d6b8100f7 100644 --- a/src/wp-admin/includes/plugin.php +++ b/src/wp-admin/includes/plugin.php @@ -1278,7 +1278,7 @@ function uninstall_plugin( $plugin ) { // /** - * Add a top-level menu page. + * Adds a top-level menu page. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1350,7 +1350,7 @@ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $func } /** - * Add a submenu page. + * Adds a submenu page. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1474,7 +1474,7 @@ function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, } /** - * Add submenu page to the Tools main menu. + * Adds a submenu page to the Tools main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1498,7 +1498,7 @@ function add_management_page( $page_title, $menu_title, $capability, $menu_slug, } /** - * Add submenu page to the Settings main menu. + * Adds a submenu page to the Settings main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1522,7 +1522,7 @@ function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $f } /** - * Add submenu page to the Appearance main menu. + * Adds a submenu page to the Appearance main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1546,7 +1546,7 @@ function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $fun } /** - * Add submenu page to the Plugins main menu. + * Adds a submenu page to the Plugins main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1570,7 +1570,7 @@ function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $f } /** - * Add submenu page to the Users/Profile main menu. + * Adds a submenu page to the Users/Profile main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1599,7 +1599,7 @@ function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $fun } /** - * Add submenu page to the Dashboard main menu. + * Adds a submenu page to the Dashboard main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1623,7 +1623,7 @@ function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, } /** - * Add submenu page to the Posts main menu. + * Adds a submenu page to the Posts main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1647,7 +1647,7 @@ function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $fun } /** - * Add submenu page to the Media main menu. + * Adds a submenu page to the Media main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1671,7 +1671,7 @@ function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $fun } /** - * Add submenu page to the Links main menu. + * Adds a submenu page to the Links main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1695,7 +1695,7 @@ function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $fun } /** - * Add submenu page to the Pages main menu. + * Adds a submenu page to the Pages main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1719,7 +1719,7 @@ function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $fun } /** - * Add submenu page to the Comments main menu. + * Adds a submenu page to the Comments main menu. * * This function takes a capability which will be used to determine whether * or not a page is included in the menu. @@ -1743,7 +1743,12 @@ function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $ } /** - * Remove a top-level admin menu. + * Removes a top-level admin menu. + * + * Example usage: + * + * - `remove_menu_page( 'tools.php' )` + * - `remove_menu_page( 'plugin_menu_slug' )` * * @since 3.1.0 * @@ -1766,7 +1771,13 @@ function remove_menu_page( $menu_slug ) { } /** - * Remove an admin submenu. + * Removes an admin submenu. + * + * Example usage: + * + * - `remove_submenu_page( 'themes.php', 'nav-menus.php' )` + * - `remove_submenu_page( 'tools.php', 'plugin_submenu_slug' )` + * - `remove_submenu_page( 'plugin_menu_slug', 'plugin_submenu_slug' )` * * @since 3.1.0 * @@ -1794,7 +1805,7 @@ function remove_submenu_page( $menu_slug, $submenu_slug ) { } /** - * Get the URL to access a particular menu page based on the slug it was registered with. + * Gets the URL to access a particular menu page based on the slug it was registered with. * * If the slug hasn't been registered properly, no URL will be returned. * diff --git a/src/wp-admin/includes/privacy-tools.php b/src/wp-admin/includes/privacy-tools.php index ec2caa8aefc62..8b78752a85faa 100644 --- a/src/wp-admin/includes/privacy-tools.php +++ b/src/wp-admin/includes/privacy-tools.php @@ -662,8 +662,7 @@ function wp_privacy_send_personal_data_export_email( $request_id ) { /* translators: Do not translate EXPIRATION, LINK, SITENAME, SITEURL: those are placeholders. */ $email_text = __( -// phpcs:ignore Generic.WhiteSpace.ScopeIndent.Incorrect, PEAR.Functions.FunctionCallSignature.Indent -'Howdy, + 'Howdy, Your request for an export of personal data has been completed. You may download your personal data by clicking on the link below. For privacy diff --git a/src/wp-admin/includes/schema.php b/src/wp-admin/includes/schema.php index 8b1e56f3af9e6..1bb2c27c45362 100644 --- a/src/wp-admin/includes/schema.php +++ b/src/wp-admin/includes/schema.php @@ -390,7 +390,7 @@ function populate_options( array $options = array() ) { * or a valid timezone string (America/New_York). See https://www.php.net/manual/en/timezones.php * for all timezone strings supported by PHP. */ - $offset_or_tz = _x( '0', 'default GMT offset or timezone string' ); // phpcs:ignore WordPress.WP.I18n.NoEmptyStrings + $offset_or_tz = _x( '0', 'default GMT offset or timezone string' ); if ( is_numeric( $offset_or_tz ) ) { $gmt_offset = $offset_or_tz; } elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list(), true ) ) { diff --git a/src/wp-admin/includes/template.php b/src/wp-admin/includes/template.php index 83df709754808..4228d931baebc 100644 --- a/src/wp-admin/includes/template.php +++ b/src/wp-admin/includes/template.php @@ -2145,12 +2145,15 @@ function _post_states( $post, $echo = true ) { if ( ! empty( $post_states ) ) { $state_count = count( $post_states ); - $i = 0; + + $i = 0; $post_states_string .= ' — '; foreach ( $post_states as $state ) { - $sep = ( ++$i === $state_count ) ? '' : ', '; + ++$i; + + $sep = ( $i < $state_count ) ? ', ' : ''; $post_states_string .= "$state$sep"; } @@ -2255,12 +2258,15 @@ function _media_states( $post, $echo = true ) { if ( ! empty( $media_states ) ) { $state_count = count( $media_states ); - $i = 0; + + $i = 0; $media_states_string .= ' — '; foreach ( $media_states as $state ) { - $sep = ( ++$i === $state_count ) ? '' : ', '; + ++$i; + + $sep = ( $i < $state_count ) ? ', ' : ''; $media_states_string .= "$state$sep"; } diff --git a/src/wp-admin/includes/update-core.php b/src/wp-admin/includes/update-core.php index 77ede74c779fc..32664bf6ff306 100644 --- a/src/wp-admin/includes/update-core.php +++ b/src/wp-admin/includes/update-core.php @@ -1658,7 +1658,7 @@ function _upgrade_422_find_genericons_files_in_folder( $directory ) { $dirs = glob( $directory . '*', GLOB_ONLYDIR ); $dirs = array_filter( $dirs, - function( $dir ) { + static function( $dir ) { // Skip any node_modules directories. return false === strpos( $dir, 'node_modules' ); } diff --git a/src/wp-admin/includes/update.php b/src/wp-admin/includes/update.php index aeccc3e049cb7..29a5f0c783878 100644 --- a/src/wp-admin/includes/update.php +++ b/src/wp-admin/includes/update.php @@ -558,7 +558,7 @@ function wp_plugin_update_row( $file, $plugin_data ) { * * @since 2.8.0 * - * @param array $plugin_data { + * @param array $plugin_data { * An array of plugin metadata. * * @type string $name The human-readable name of the plugin. @@ -574,8 +574,8 @@ function wp_plugin_update_row( $file, $plugin_data ) { * @type string $author_name Plugin author's name. * @type bool $update Whether there's an available update. Default null. * } - * @param array $response { - * An array of metadata about the available plugin update. + * @param object $response { + * An object of metadata about the available plugin update. * * @type int $id Plugin ID. * @type string $slug Plugin slug. diff --git a/src/wp-admin/includes/upgrade.php b/src/wp-admin/includes/upgrade.php index 475608efa7908..3be073f7af26a 100644 --- a/src/wp-admin/includes/upgrade.php +++ b/src/wp-admin/includes/upgrade.php @@ -832,6 +832,10 @@ function upgrade_all() { upgrade_560(); } + if ( $wp_current_db_version < 51917 ) { + upgrade_590(); + } + maybe_disable_link_manager(); maybe_disable_automattic_widgets(); @@ -1874,7 +1878,6 @@ function upgrade_370() { * * @ignore * @since 3.7.2 - * @since 3.8.0 * * @global int $wp_current_db_version The old (current) database version. */ @@ -2248,6 +2251,23 @@ function upgrade_560() { } } +/** + * Executes changes made in WordPress 5.9.0. + * + * @ignore + * @since 5.9.0 + */ +function upgrade_590() { + global $wp_current_db_version; + + if ( $wp_current_db_version < 51917 ) { + $crons = _get_cron_array(); + // Remove errant `false` values, see #53950. + $crons = array_filter( $crons ); + _set_cron_array( $crons ); + } +} + /** * Executes network-level upgrade routines. * diff --git a/src/wp-admin/nav-menus.php b/src/wp-admin/nav-menus.php index 272aa9b9e6b23..d340fb6b67708 100644 --- a/src/wp-admin/nav-menus.php +++ b/src/wp-admin/nav-menus.php @@ -316,6 +316,7 @@ check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' ); // Merge new and existing menu locations if any new ones are set. + $new_menu_locations = array(); if ( isset( $_POST['menu-locations'] ) ) { $new_menu_locations = array_map( 'absint', $_POST['menu-locations'] ); $menu_locations = array_merge( $menu_locations, $new_menu_locations ); @@ -353,6 +354,15 @@ break; // There should only be 1. } + set_theme_mod( 'nav_menu_locations', $locations ); + } elseif ( count( $new_menu_locations ) > 0 ) { + // If locations have been selected for the new menu, save those. + $locations = get_nav_menu_locations(); + + foreach ( array_keys( $new_menu_locations ) as $location ) { + $locations[ $location ] = $nav_menu_selected_id; + } + set_theme_mod( 'nav_menu_locations', $locations ); } diff --git a/src/wp-admin/options-permalink.php b/src/wp-admin/options-permalink.php index 4275a4a2c6453..17a9083cb6371 100644 --- a/src/wp-admin/options-permalink.php +++ b/src/wp-admin/options-permalink.php @@ -56,12 +56,18 @@ ) ); -get_current_screen()->set_help_sidebar( - '

' . __( 'For more information:' ) . '

' . - '

' . __( 'Documentation on Permalinks Settings' ) . '

' . - '

' . __( 'Documentation on Using Permalinks' ) . '

' . - '

' . __( 'Support' ) . '

' -); +$help_sidebar_content = '

' . __( 'For more information:' ) . '

' . + '

' . __( 'Documentation on Permalinks Settings' ) . '

' . + '

' . __( 'Documentation on Using Permalinks' ) . '

'; + +if ( $is_nginx ) { + $help_sidebar_content .= '

' . __( 'Documentation on Nginx configuration.' ) . '

'; +} + +$help_sidebar_content .= '

' . __( 'Support' ) . '

'; + +get_current_screen()->set_help_sidebar( $help_sidebar_content ); +unset( $help_sidebar_content ); $home_path = get_home_path(); $iis7_permalinks = iis7_supports_permalinks(); @@ -410,9 +416,7 @@ class="button button-secondary"

- -

Documentation on Nginx configuration.' ); ?>

- diff --git a/src/wp-admin/options-privacy.php b/src/wp-admin/options-privacy.php index 3e4902daf4bf0..0b0ca77ee9e2f 100644 --- a/src/wp-admin/options-privacy.php +++ b/src/wp-admin/options-privacy.php @@ -20,7 +20,7 @@ add_filter( 'admin_body_class', - function( $body_class ) { + static function( $body_class ) { $body_class .= ' privacy-settings '; return $body_class; diff --git a/src/wp-admin/plugin-editor.php b/src/wp-admin/plugin-editor.php index 36dce7795d9d5..800e468f3f9f8 100644 --- a/src/wp-admin/plugin-editor.php +++ b/src/wp-admin/plugin-editor.php @@ -312,10 +312,12 @@ $excluded_referer_basenames = array( 'plugin-editor.php', 'wp-login.php' ); - if ( $referer && ! in_array( basename( parse_url( $referer, PHP_URL_PATH ) ), $excluded_referer_basenames, true ) ) { - $return_url = $referer; - } else { - $return_url = admin_url( '/' ); + $return_url = admin_url( '/' ); + if ( $referer ) { + $referer_path = parse_url( $referer, PHP_URL_PATH ); + if ( is_string( $referer_path ) && ! in_array( basename( $referer_path ), $excluded_referer_basenames, true ) ) { + $return_url = $referer; + } } ?>
diff --git a/src/wp-admin/plugin-install.php b/src/wp-admin/plugin-install.php index 0e01c441610a4..a8b4e333ab138 100644 --- a/src/wp-admin/plugin-install.php +++ b/src/wp-admin/plugin-install.php @@ -63,8 +63,19 @@ /** * Fires before each tab on the Install Plugins screen is loaded. * - * The dynamic portion of the action hook, `$tab`, allows for targeting - * individual tabs, for instance 'install_plugins_pre_plugin-information'. + * The dynamic portion of the hook name, `$tab`, allows for targeting + * individual tabs. + * + * Possible hook names include: + * + * - `install_plugins_pre_beta` + * - `install_plugins_pre_favorites` + * - `install_plugins_pre_featured` + * - `install_plugins_pre_plugin-information` + * - `install_plugins_pre_popular` + * - `install_plugins_pre_recommended` + * - `install_plugins_pre_search` + * - `install_plugins_pre_upload` * * @since 2.7.0 */ @@ -164,8 +175,19 @@ /** * Fires after the plugins list table in each tab of the Install Plugins screen. * - * The dynamic portion of the action hook, `$tab`, allows for targeting - * individual tabs, for instance 'install_plugins_plugin-information'. + * The dynamic portion of the hook name, `$tab`, allows for targeting + * individual tabs. + * + * Possible hook names include: + * + * - `install_plugins_beta` + * - `install_plugins_favorites` + * - `install_plugins_featured` + * - `install_plugins_plugin-information` + * - `install_plugins_popular` + * - `install_plugins_recommended` + * - `install_plugins_search` + * - `install_plugins_upload` * * @since 2.7.0 * diff --git a/src/wp-admin/privacy-policy-guide.php b/src/wp-admin/privacy-policy-guide.php index e5d558e639af2..6581bb412a621 100644 --- a/src/wp-admin/privacy-policy-guide.php +++ b/src/wp-admin/privacy-policy-guide.php @@ -19,7 +19,7 @@ add_filter( 'admin_body_class', - function( $body_class ) { + static function( $body_class ) { $body_class .= ' privacy-settings '; return $body_class; diff --git a/src/wp-admin/theme-editor.php b/src/wp-admin/theme-editor.php index 572a2d82c4631..46926df87ce3b 100644 --- a/src/wp-admin/theme-editor.php +++ b/src/wp-admin/theme-editor.php @@ -343,10 +343,12 @@ $excluded_referer_basenames = array( 'theme-editor.php', 'wp-login.php' ); - if ( $referer && ! in_array( basename( parse_url( $referer, PHP_URL_PATH ) ), $excluded_referer_basenames, true ) ) { - $return_url = $referer; - } else { - $return_url = admin_url( '/' ); + $return_url = admin_url( '/' ); + if ( $referer ) { + $referer_path = parse_url( $referer, PHP_URL_PATH ); + if ( is_string( $referer_path ) && ! in_array( basename( $referer_path ), $excluded_referer_basenames, true ) ) { + $return_url = $referer; + } } ?>
diff --git a/src/wp-admin/theme-install.php b/src/wp-admin/theme-install.php index 4f0ba2ad662de..cd3a607ea91fd 100644 --- a/src/wp-admin/theme-install.php +++ b/src/wp-admin/theme-install.php @@ -221,15 +221,14 @@ // and to ensure tags are translated. $feature_list = get_theme_feature_list( false ); - foreach ( $feature_list as $feature_name => $features ) { + foreach ( $feature_list as $feature_group => $features ) { echo '
'; - $feature_name = esc_html( $feature_name ); - echo '' . $feature_name . ''; + echo '' . esc_html( $feature_group ) . ''; echo '
'; foreach ( $features as $feature => $feature_name ) { $feature = esc_attr( $feature ); echo ' '; - echo ''; + echo ''; } echo '
'; echo '
'; diff --git a/src/wp-admin/update-core.php b/src/wp-admin/update-core.php index 6e23d668666a6..a38e43c46f07e 100644 --- a/src/wp-admin/update-core.php +++ b/src/wp-admin/update-core.php @@ -154,7 +154,7 @@ function list_core_update( $update ) { echo $message; echo '

'; - echo '
'; + echo ''; wp_nonce_field( 'upgrade-core' ); echo '

'; diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 0cd381caf2181..30bc5c8e46859 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -553,7 +553,7 @@ /** * Filters a user contactmethod label. * - * The dynamic portion of the filter hook, `$name`, refers to + * The dynamic portion of the hook name, `$name`, refers to * each of the keys in the contact methods array. * * @since 2.9.0 @@ -767,7 +767,7 @@

- +

diff --git a/src/wp-admin/widgets-form-blocks.php b/src/wp-admin/widgets-form-blocks.php index 7f3b6b2f65934..563bbf2a699d9 100644 --- a/src/wp-admin/widgets-form-blocks.php +++ b/src/wp-admin/widgets-form-blocks.php @@ -18,7 +18,7 @@ $block_editor_context = new WP_Block_Editor_Context(); $preload_paths = array( - array( '/wp/v2/media', 'OPTIONS' ), + array( rest_get_route_for_post_type_items( 'attachment' ), 'OPTIONS' ), '/wp/v2/sidebars?context=edit&per_page=-1', '/wp/v2/widgets?context=edit&per_page=-1&_embed=about', ); @@ -52,7 +52,7 @@ wp_add_inline_script( 'wp-blocks', - sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( 'widgets-editor' ) ) ), + sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ), 'after' ); diff --git a/src/wp-content/themes/twentyeleven/inc/widgets.php b/src/wp-content/themes/twentyeleven/inc/widgets.php index ae28fd41aea38..b84b808a3cae4 100644 --- a/src/wp-content/themes/twentyeleven/inc/widgets.php +++ b/src/wp-content/themes/twentyeleven/inc/widgets.php @@ -17,7 +17,7 @@ class Twenty_Eleven_Ephemera_Widget extends WP_Widget { * * @since Twenty Eleven 2.2 */ - function __construct() { + public function __construct() { parent::__construct( 'widget_twentyeleven_ephemera', __( 'Twenty Eleven Ephemera', 'twentyeleven' ), @@ -40,7 +40,7 @@ function __construct() { * @since Twenty Eleven 1.0 * @deprecated Twenty Eleven 2.2 */ - function Twenty_Eleven_Ephemera_Widget() { + public function Twenty_Eleven_Ephemera_Widget() { self::__construct(); } @@ -52,7 +52,7 @@ function Twenty_Eleven_Ephemera_Widget() { * @param array $args An array of standard parameters for widgets in this theme. * @param array $instance An array of settings for this widget instance. */ - function widget( $args, $instance ) { + public function widget( $args, $instance ) { $cache = wp_cache_get( 'widget_twentyeleven_ephemera', 'widget' ); if ( ! is_array( $cache ) ) { @@ -158,7 +158,7 @@ function widget( $args, $instance ) { * * @since Twenty Eleven 1.0 */ - function update( $new_instance, $old_instance ) { + public function update( $new_instance, $old_instance ) { $instance = $old_instance; $instance['title'] = strip_tags( $new_instance['title'] ); $instance['number'] = (int) $new_instance['number']; @@ -177,7 +177,7 @@ function update( $new_instance, $old_instance ) { * * @since Twenty Eleven 1.0 */ - function flush_widget_cache() { + public function flush_widget_cache() { wp_cache_delete( 'widget_twentyeleven_ephemera', 'widget' ); } @@ -188,7 +188,7 @@ function flush_widget_cache() { * * @since Twenty Eleven 1.0 */ - function form( $instance ) { + public function form( $instance ) { $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : ''; $number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 10; ?> diff --git a/src/wp-content/themes/twentyeleven/style.css b/src/wp-content/themes/twentyeleven/style.css index 46afe60b61da7..f63975c648cec 100644 --- a/src/wp-content/themes/twentyeleven/style.css +++ b/src/wp-content/themes/twentyeleven/style.css @@ -701,6 +701,7 @@ a.assistive-text:focus, top: auto; bottom: -27px; max-width: 195px; + height: 32px; } #branding .only-search + #access div { padding-right: 205px; diff --git a/src/wp-content/themes/twentyfourteen/functions.php b/src/wp-content/themes/twentyfourteen/functions.php index f39296b1ba33f..892d6ac939aef 100644 --- a/src/wp-content/themes/twentyfourteen/functions.php +++ b/src/wp-content/themes/twentyfourteen/functions.php @@ -491,15 +491,24 @@ function twentyfourteen_the_attached_image() { * @since Twenty Fourteen 1.0 */ function twentyfourteen_list_authors() { - $contributor_ids = get_users( - array( - 'fields' => 'ID', - 'orderby' => 'post_count', - 'order' => 'DESC', - 'who' => 'authors', - ) + $args = array( + 'fields' => 'ID', + 'orderby' => 'post_count', + 'order' => 'DESC', + 'capability' => array( 'edit_posts' ), ); + /** + * Filters query arguments for listing authors. + * + * @since 3.3 + * + * @param array $args Query arguments. + */ + $args = apply_filters( 'twentyfourteen_list_authors_query_args', $args ); + + $contributor_ids = get_users( $args ); + foreach ( $contributor_ids as $contributor_id ) : $post_count = count_user_posts( $contributor_id ); diff --git a/src/wp-content/themes/twentyfourteen/inc/widgets.php b/src/wp-content/themes/twentyfourteen/inc/widgets.php index d8d15c2ba4b55..48844a3730a7c 100644 --- a/src/wp-content/themes/twentyfourteen/inc/widgets.php +++ b/src/wp-content/themes/twentyfourteen/inc/widgets.php @@ -262,20 +262,22 @@ public function widget( $args, $instance ) { * Here is where any validation should happen. * * @since Twenty Fourteen 1.0 + * @since Twenty Fourteen 3.3 Renamed `$instance` to `$old_instance` to match + * parent class for PHP 8 named parameter support. * * @param array $new_instance New widget instance. - * @param array $instance Original widget instance. + * @param array $old_instance Original widget instance. * @return array Updated widget instance. */ - function update( $new_instance, $instance ) { - $instance['title'] = strip_tags( $new_instance['title'] ); - $instance['number'] = empty( $new_instance['number'] ) ? 2 : absint( $new_instance['number'] ); + public function update( $new_instance, $old_instance ) { + $old_instance['title'] = strip_tags( $new_instance['title'] ); + $old_instance['number'] = empty( $new_instance['number'] ) ? 2 : absint( $new_instance['number'] ); if ( in_array( $new_instance['format'], $this->formats, true ) ) { - $instance['format'] = $new_instance['format']; + $old_instance['format'] = $new_instance['format']; } - return $instance; + return $old_instance; } /** @@ -285,7 +287,7 @@ function update( $new_instance, $instance ) { * * @param array $instance */ - function form( $instance ) { + public function form( $instance ) { $title = ! empty( $instance['title'] ) ? esc_attr( $instance['title'] ) : ''; $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 2; $format = isset( $instance['format'] ) ? $instance['format'] : ''; diff --git a/src/wp-content/themes/twentyseventeen/style.css b/src/wp-content/themes/twentyseventeen/style.css index b6007aed24c61..b3621b79e38c0 100644 --- a/src/wp-content/themes/twentyseventeen/style.css +++ b/src/wp-content/themes/twentyseventeen/style.css @@ -3822,7 +3822,7 @@ p > object:only-child { width: 100%; } - .panel-content .recent-posts .entry-header { + .twentyseventeen-front-page .panel-content .recent-posts .entry-header { margin-bottom: 1.5em; } diff --git a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-customize.php b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-customize.php index d41b494584a73..ca666df11d382 100644 --- a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-customize.php +++ b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-customize.php @@ -186,7 +186,7 @@ public static function register( $wp_customize ) { 'settings' => 'accent_hue', 'description' => __( 'Apply a custom color for links, buttons, featured images.', 'twentytwenty' ), 'mode' => 'hue', - 'active_callback' => function() use ( $wp_customize ) { + 'active_callback' => static function() use ( $wp_customize ) { return ( 'custom' === $wp_customize->get_setting( 'accent_hue_active' )->value() ); }, ) diff --git a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-non-latin-languages.php b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-non-latin-languages.php index a0845a4a70d98..0c4951ef4842e 100644 --- a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-non-latin-languages.php +++ b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-non-latin-languages.php @@ -118,7 +118,7 @@ public static function get_non_latin_css( $type = 'front-end' ) { $elements = apply_filters( 'twentytwenty_get_localized_font_family_elements', array( - 'front-end' => array( 'body', 'input', 'textarea', 'button', '.button', '.faux-button', '.wp-block-button__link', '.wp-block-file__button', '.has-drop-cap:not(:focus)::first-letter', '.has-drop-cap:not(:focus)::first-letter', '.entry-content .wp-block-archives', '.entry-content .wp-block-categories', '.entry-content .wp-block-cover-image', '.entry-content .wp-block-latest-comments', '.entry-content .wp-block-latest-posts', '.entry-content .wp-block-pullquote', '.entry-content .wp-block-quote.is-large', '.entry-content .wp-block-quote.is-style-large', '.entry-content .wp-block-archives *', '.entry-content .wp-block-categories *', '.entry-content .wp-block-latest-posts *', '.entry-content .wp-block-latest-comments *', '.entry-content p', '.entry-content ol', '.entry-content ul', '.entry-content dl', '.entry-content dt', '.entry-content cite', '.entry-content figcaption', '.entry-content .wp-caption-text', '.comment-content p', '.comment-content ol', '.comment-content ul', '.comment-content dl', '.comment-content dt', '.comment-content cite', '.comment-content figcaption', '.comment-content .wp-caption-text', '.widget_text p', '.widget_text ol', '.widget_text ul', '.widget_text dl', '.widget_text dt', '.widget-content .rssSummary', '.widget-content cite', '.widget-content figcaption', '.widget-content .wp-caption-text' ), + 'front-end' => array( 'body', 'input', 'textarea', 'button', '.button', '.faux-button', '.wp-block-button__link', '.wp-block-file__button', '.has-drop-cap:not(:focus)::first-letter', '.entry-content .wp-block-archives', '.entry-content .wp-block-categories', '.entry-content .wp-block-cover-image', '.entry-content .wp-block-latest-comments', '.entry-content .wp-block-latest-posts', '.entry-content .wp-block-pullquote', '.entry-content .wp-block-quote.is-large', '.entry-content .wp-block-quote.is-style-large', '.entry-content .wp-block-archives *', '.entry-content .wp-block-categories *', '.entry-content .wp-block-latest-posts *', '.entry-content .wp-block-latest-comments *', '.entry-content p', '.entry-content ol', '.entry-content ul', '.entry-content dl', '.entry-content dt', '.entry-content cite', '.entry-content figcaption', '.entry-content .wp-caption-text', '.comment-content p', '.comment-content ol', '.comment-content ul', '.comment-content dl', '.comment-content dt', '.comment-content cite', '.comment-content figcaption', '.comment-content .wp-caption-text', '.widget_text p', '.widget_text ol', '.widget_text ul', '.widget_text dl', '.widget_text dt', '.widget-content .rssSummary', '.widget-content cite', '.widget-content figcaption', '.widget-content .wp-caption-text' ), 'block-editor' => array( '.editor-styles-wrapper > *', '.editor-styles-wrapper p', '.editor-styles-wrapper ol', '.editor-styles-wrapper ul', '.editor-styles-wrapper dl', '.editor-styles-wrapper dt', '.editor-post-title__block .editor-post-title__input', '.editor-styles-wrapper .wp-block h1', '.editor-styles-wrapper .wp-block h2', '.editor-styles-wrapper .wp-block h3', '.editor-styles-wrapper .wp-block h4', '.editor-styles-wrapper .wp-block h5', '.editor-styles-wrapper .wp-block h6', '.editor-styles-wrapper .has-drop-cap:not(:focus)::first-letter', '.editor-styles-wrapper cite', '.editor-styles-wrapper figcaption', '.editor-styles-wrapper .wp-caption-text' ), 'classic-editor' => array( 'body#tinymce.wp-editor', 'body#tinymce.wp-editor p', 'body#tinymce.wp-editor ol', 'body#tinymce.wp-editor ul', 'body#tinymce.wp-editor dl', 'body#tinymce.wp-editor dt', 'body#tinymce.wp-editor figcaption', 'body#tinymce.wp-editor .wp-caption-text', 'body#tinymce.wp-editor .wp-caption-dd', 'body#tinymce.wp-editor cite', 'body#tinymce.wp-editor table' ), ) diff --git a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-svg-icons.php b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-svg-icons.php index d735037543f6b..714b3a14542d2 100644 --- a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-svg-icons.php +++ b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-svg-icons.php @@ -223,7 +223,7 @@ public static function get_social_link_svg( $uri ) { 'twitch' => array( 'twitch.tv', ), - 'whatsapp' => array( + 'whatsapp' => array( 'wa.me', 'whatsapp.com', ), diff --git a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-walker-page.php b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-walker-page.php index dcdc8445ad95e..eb927ec938e54 100644 --- a/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-walker-page.php +++ b/src/wp-content/themes/twentytwenty/classes/class-twentytwenty-walker-page.php @@ -20,16 +20,21 @@ class TwentyTwenty_Walker_Page extends Walker_Page { * Outputs the beginning of the current element in the tree. * * @since Twenty Twenty 1.0 + * @since Twenty Twenty 1.9 Renamed `$page` to `$data_object` and `$current_page` to `$current_object_id` + * to match parent class for PHP 8 named parameter support. * * @see Walker::start_el() * - * @param string $output Used to append additional content. Passed by reference. - * @param WP_Post $page Page data object. - * @param int $depth Optional. Depth of page. Used for padding. Default 0. - * @param array $args Optional. Array of arguments. Default empty array. - * @param int $current_page Optional. Page ID. Default 0. + * @param string $output Used to append additional content. Passed by reference. + * @param WP_Post $data_object Page data object. + * @param int $depth Optional. Depth of page. Used for padding. Default 0. + * @param array $args Optional. Array of arguments. Default empty array. + * @param int $current_object_id Optional. ID of the current page. Default 0. */ - public function start_el( &$output, $page, $depth = 0, $args = array(), $current_page = 0 ) { + public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) { + // Restores the more descriptive, specific name for use within this method. + $page = $data_object; + $current_page_id = $current_object_id; if ( isset( $args['item_spacing'] ) && 'preserve' === $args['item_spacing'] ) { $t = "\t"; @@ -50,12 +55,12 @@ public function start_el( &$output, $page, $depth = 0, $args = array(), $current $css_class[] = 'page_item_has_children'; } - if ( ! empty( $current_page ) ) { - $_current_page = get_post( $current_page ); + if ( ! empty( $current_page_id ) ) { + $_current_page = get_post( $current_page_id ); if ( $_current_page && in_array( $page->ID, $_current_page->ancestors, true ) ) { $css_class[] = 'current_page_ancestor'; } - if ( $page->ID === $current_page ) { + if ( $page->ID === $current_page_id ) { $css_class[] = 'current_page_item'; } elseif ( $_current_page && $page->ID === $_current_page->post_parent ) { $css_class[] = 'current_page_parent'; @@ -65,7 +70,7 @@ public function start_el( &$output, $page, $depth = 0, $args = array(), $current } /** This filter is documented in wp-includes/class-walker-page.php */ - $css_classes = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) ); + $css_classes = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page_id ) ); $css_classes = $css_classes ? ' class="' . esc_attr( $css_classes ) . '"' : ''; if ( '' === $page->post_title ) { @@ -78,10 +83,10 @@ public function start_el( &$output, $page, $depth = 0, $args = array(), $current $atts = array(); $atts['href'] = get_permalink( $page->ID ); - $atts['aria-current'] = ( $page->ID === $current_page ) ? 'page' : ''; + $atts['aria-current'] = ( $page->ID === $current_page_id ) ? 'page' : ''; /** This filter is documented in wp-includes/class-walker-page.php */ - $atts = apply_filters( 'page_menu_link_attributes', $atts, $page, $depth, $args, $current_page ); + $atts = apply_filters( 'page_menu_link_attributes', $atts, $page, $depth, $args, $current_page_id ); $attributes = ''; foreach ( $atts as $attr => $value ) { diff --git a/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-customize.php b/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-customize.php index b880a03afbe32..4a0fe6f7af502 100644 --- a/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-customize.php +++ b/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-customize.php @@ -92,7 +92,7 @@ public function register( $wp_customize ) { array( 'capability' => 'edit_theme_options', 'default' => 'excerpt', - 'sanitize_callback' => function( $value ) { + 'sanitize_callback' => static function( $value ) { return 'excerpt' === $value || 'full' === $value ? $value : 'excerpt'; }, ) diff --git a/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-dark-mode.php b/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-dark-mode.php index 4034eaae25db4..4de201c1b92a6 100644 --- a/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-dark-mode.php +++ b/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-dark-mode.php @@ -153,7 +153,7 @@ public function customizer_controls( $wp_customize ) { array( 'section' => 'colors', 'priority' => 100, - 'active_callback' => function() { + 'active_callback' => static function() { return 127 >= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) ); }, ) @@ -165,7 +165,7 @@ public function customizer_controls( $wp_customize ) { array( 'capability' => 'edit_theme_options', 'default' => false, - 'sanitize_callback' => function( $value ) { + 'sanitize_callback' => static function( $value ) { return (bool) $value; }, ) @@ -188,7 +188,7 @@ public function customizer_controls( $wp_customize ) { 'label' => esc_html__( 'Dark Mode support', 'twentytwentyone' ), 'priority' => 110, 'description' => $description, - 'active_callback' => function( $value ) { + 'active_callback' => static function( $value ) { return 127 < Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) ); }, ) diff --git a/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-svg-icons.php b/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-svg-icons.php index 34a408f7c7df2..3a82cf76ab4c4 100644 --- a/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-svg-icons.php +++ b/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-svg-icons.php @@ -45,44 +45,44 @@ class Twenty_Twenty_One_SVG_Icons { * @var array */ protected static $social_icons = array( - '500px' => '', - 'amazon' => '', - 'bandcamp' => '', - 'behance' => '', - 'codepen' => '', - 'deviantart' => '', - 'dribbble' => '', - 'dropbox' => '', - 'etsy' => '', - 'facebook' => '', - 'feed' => '', - 'flickr' => '', - 'foursquare' => '', - 'goodreads' => '', - 'google' => '', - 'github' => '', - 'instagram' => '', - 'lastfm' => '', - 'linkedin' => '', - 'mail' => '', - 'mastodon' => '', - 'medium' => '', - 'meetup' => '', - 'pinterest' => '', - 'pocket' => '', - 'reddit' => '', - 'skype' => '', - 'snapchat' => '', - 'soundcloud' => '', - 'spotify' => '', - 'tumblr' => '', - 'twitch' => '', - 'twitter' => '', - 'vimeo' => '', - 'vk' => '', - 'wordpress' => '', - 'yelp' => '', - 'youtube' => '', + '500px' => '', + 'amazon' => '', + 'bandcamp' => '', + 'behance' => '', + 'codepen' => '', + 'deviantart' => '', + 'dribbble' => '', + 'dropbox' => '', + 'etsy' => '', + 'facebook' => '', + 'feed' => '', + 'flickr' => '', + 'foursquare' => '', + 'goodreads' => '', + 'google' => '', + 'github' => '', + 'instagram' => '', + 'lastfm' => '', + 'linkedin' => '', + 'mail' => '', + 'mastodon' => '', + 'medium' => '', + 'meetup' => '', + 'pinterest' => '', + 'pocket' => '', + 'reddit' => '', + 'skype' => '', + 'snapchat' => '', + 'soundcloud' => '', + 'spotify' => '', + 'tumblr' => '', + 'twitch' => '', + 'twitter' => '', + 'vimeo' => '', + 'vk' => '', + 'wordpress' => '', + 'yelp' => '', + 'youtube' => '', ); /** diff --git a/src/wp-content/themes/twentytwentyone/functions.php b/src/wp-content/themes/twentytwentyone/functions.php index df98fef838270..74d1d339f5963 100644 --- a/src/wp-content/themes/twentytwentyone/functions.php +++ b/src/wp-content/themes/twentytwentyone/functions.php @@ -74,7 +74,7 @@ function twenty_twenty_one_setup() { register_nav_menus( array( 'primary' => esc_html__( 'Primary menu', 'twentytwentyone' ), - 'footer' => __( 'Secondary menu', 'twentytwentyone' ), + 'footer' => esc_html__( 'Secondary menu', 'twentytwentyone' ), ) ); diff --git a/src/wp-content/themes/twentytwentyone/inc/menu-functions.php b/src/wp-content/themes/twentytwentyone/inc/menu-functions.php index 0299c58c41b08..c461047c77c6f 100644 --- a/src/wp-content/themes/twentytwentyone/inc/menu-functions.php +++ b/src/wp-content/themes/twentytwentyone/inc/menu-functions.php @@ -87,11 +87,15 @@ function twenty_twenty_one_nav_menu_social_icons( $item_output, $item, $depth, $ * @return stdClass */ function twenty_twenty_one_add_menu_description_args( $args, $item, $depth ) { - $args->link_after = ''; + if ( '' !== $args->link_after ) { + $args->link_after = ''; + } + if ( 0 === $depth && isset( $item->description ) && $item->description ) { // The extra element is here for styling purposes: Allows the description to not be underlined on hover. $args->link_after = '

' . $item->description . '

'; } + return $args; } add_filter( 'nav_menu_item_args', 'twenty_twenty_one_add_menu_description_args', 10, 3 ); diff --git a/src/wp-content/themes/twentytwentyone/inc/template-functions.php b/src/wp-content/themes/twentytwentyone/inc/template-functions.php index 839a77a36865b..2bee7d6f95fad 100644 --- a/src/wp-content/themes/twentytwentyone/inc/template-functions.php +++ b/src/wp-content/themes/twentytwentyone/inc/template-functions.php @@ -315,7 +315,7 @@ function twenty_twenty_one_get_non_latin_css( $type = 'front-end' ) { $elements = apply_filters( 'twenty_twenty_one_get_localized_font_family_elements', array( - 'front-end' => array( 'body', 'input', 'textarea', 'button', '.button', '.faux-button', '.wp-block-button__link', '.wp-block-file__button', '.has-drop-cap:not(:focus)::first-letter', '.has-drop-cap:not(:focus)::first-letter', '.entry-content .wp-block-archives', '.entry-content .wp-block-categories', '.entry-content .wp-block-cover-image', '.entry-content .wp-block-latest-comments', '.entry-content .wp-block-latest-posts', '.entry-content .wp-block-pullquote', '.entry-content .wp-block-quote.is-large', '.entry-content .wp-block-quote.is-style-large', '.entry-content .wp-block-archives *', '.entry-content .wp-block-categories *', '.entry-content .wp-block-latest-posts *', '.entry-content .wp-block-latest-comments *', '.entry-content p', '.entry-content ol', '.entry-content ul', '.entry-content dl', '.entry-content dt', '.entry-content cite', '.entry-content figcaption', '.entry-content .wp-caption-text', '.comment-content p', '.comment-content ol', '.comment-content ul', '.comment-content dl', '.comment-content dt', '.comment-content cite', '.comment-content figcaption', '.comment-content .wp-caption-text', '.widget_text p', '.widget_text ol', '.widget_text ul', '.widget_text dl', '.widget_text dt', '.widget-content .rssSummary', '.widget-content cite', '.widget-content figcaption', '.widget-content .wp-caption-text' ), + 'front-end' => array( 'body', 'input', 'textarea', 'button', '.button', '.faux-button', '.wp-block-button__link', '.wp-block-file__button', '.has-drop-cap:not(:focus)::first-letter', '.entry-content .wp-block-archives', '.entry-content .wp-block-categories', '.entry-content .wp-block-cover-image', '.entry-content .wp-block-latest-comments', '.entry-content .wp-block-latest-posts', '.entry-content .wp-block-pullquote', '.entry-content .wp-block-quote.is-large', '.entry-content .wp-block-quote.is-style-large', '.entry-content .wp-block-archives *', '.entry-content .wp-block-categories *', '.entry-content .wp-block-latest-posts *', '.entry-content .wp-block-latest-comments *', '.entry-content p', '.entry-content ol', '.entry-content ul', '.entry-content dl', '.entry-content dt', '.entry-content cite', '.entry-content figcaption', '.entry-content .wp-caption-text', '.comment-content p', '.comment-content ol', '.comment-content ul', '.comment-content dl', '.comment-content dt', '.comment-content cite', '.comment-content figcaption', '.comment-content .wp-caption-text', '.widget_text p', '.widget_text ol', '.widget_text ul', '.widget_text dl', '.widget_text dt', '.widget-content .rssSummary', '.widget-content cite', '.widget-content figcaption', '.widget-content .wp-caption-text' ), 'block-editor' => array( '.editor-styles-wrapper > *', '.editor-styles-wrapper p', '.editor-styles-wrapper ol', '.editor-styles-wrapper ul', '.editor-styles-wrapper dl', '.editor-styles-wrapper dt', '.editor-post-title__block .editor-post-title__input', '.editor-styles-wrapper .wp-block h1', '.editor-styles-wrapper .wp-block h2', '.editor-styles-wrapper .wp-block h3', '.editor-styles-wrapper .wp-block h4', '.editor-styles-wrapper .wp-block h5', '.editor-styles-wrapper .wp-block h6', '.editor-styles-wrapper .has-drop-cap:not(:focus)::first-letter', '.editor-styles-wrapper cite', '.editor-styles-wrapper figcaption', '.editor-styles-wrapper .wp-caption-text' ), 'classic-editor' => array( 'body#tinymce.wp-editor', 'body#tinymce.wp-editor p', 'body#tinymce.wp-editor ol', 'body#tinymce.wp-editor ul', 'body#tinymce.wp-editor dl', 'body#tinymce.wp-editor dt', 'body#tinymce.wp-editor figcaption', 'body#tinymce.wp-editor .wp-caption-text', 'body#tinymce.wp-editor .wp-caption-dd', 'body#tinymce.wp-editor cite', 'body#tinymce.wp-editor table' ), ) diff --git a/src/wp-includes/PHPMailer/Exception.php b/src/wp-includes/PHPMailer/Exception.php index a50a8991f7a1d..52eaf95158a37 100644 --- a/src/wp-includes/PHPMailer/Exception.php +++ b/src/wp-includes/PHPMailer/Exception.php @@ -35,6 +35,6 @@ class Exception extends \Exception */ public function errorMessage() { - return '' . htmlspecialchars($this->getMessage()) . "
\n"; + return '' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "
\n"; } } diff --git a/src/wp-includes/PHPMailer/PHPMailer.php b/src/wp-includes/PHPMailer/PHPMailer.php index 5618251950c95..5228ef015961f 100644 --- a/src/wp-includes/PHPMailer/PHPMailer.php +++ b/src/wp-includes/PHPMailer/PHPMailer.php @@ -103,14 +103,14 @@ class PHPMailer * * @var string */ - public $From = 'root@localhost'; + public $From = ''; /** * The From name of the message. * * @var string */ - public $FromName = 'Root User'; + public $FromName = ''; /** * The envelope sender of the message. @@ -689,7 +689,7 @@ class PHPMailer protected $boundary = []; /** - * The array of available languages. + * The array of available text strings for the current language. * * @var array */ @@ -750,7 +750,7 @@ class PHPMailer * * @var string */ - const VERSION = '6.5.0'; + const VERSION = '6.5.1'; /** * Error severity: message only, continue processing. @@ -1188,25 +1188,33 @@ protected function addAnAddress($kind, $address, $name = '') * * @return array */ - public static function parseAddresses($addrstr, $useimap = true) + public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591) { $addresses = []; if ($useimap && function_exists('imap_rfc822_parse_adrlist')) { //Use this built-in parser if it's available $list = imap_rfc822_parse_adrlist($addrstr, ''); + // Clear any potential IMAP errors to get rid of notices being thrown at end of script. + imap_errors(); foreach ($list as $address) { if ( - ('.SYNTAX-ERROR.' !== $address->host) && static::validateAddress( - $address->mailbox . '@' . $address->host - ) + '.SYNTAX-ERROR.' !== $address->host && + static::validateAddress($address->mailbox . '@' . $address->host) ) { //Decode the name part if it's present and encoded if ( property_exists($address, 'personal') && - extension_loaded('mbstring') && - preg_match('/^=\?.*\?=$/', $address->personal) + //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled + defined('MB_CASE_UPPER') && + preg_match('/^=\?.*\?=$/s', $address->personal) ) { + $origCharset = mb_internal_encoding(); + mb_internal_encoding($charset); + //Undo any RFC2047-encoded spaces-as-underscores + $address->personal = str_replace('_', '=20', $address->personal); + //Decode the name $address->personal = mb_decode_mimeheader($address->personal); + mb_internal_encoding($origCharset); } $addresses[] = [ @@ -1234,9 +1242,16 @@ public static function parseAddresses($addrstr, $useimap = true) $email = trim(str_replace('>', '', $email)); $name = trim($name); if (static::validateAddress($email)) { + //Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled //If this name is encoded, decode it - if (preg_match('/^=\?.*\?=$/', $name)) { + if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) { + $origCharset = mb_internal_encoding(); + mb_internal_encoding($charset); + //Undo any RFC2047-encoded spaces-as-underscores + $name = str_replace('_', '=20', $name); + //Decode the name $name = mb_decode_mimeheader($name); + mb_internal_encoding($origCharset); } $addresses[] = [ //Remove any surrounding quotes and spaces from the name @@ -1510,12 +1525,7 @@ public function preSend() && ini_get('mail.add_x_header') === '1' && stripos(PHP_OS, 'WIN') === 0 ) { - trigger_error( - 'Your version of PHP is affected by a bug that may result in corrupted messages.' . - ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' . - ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.', - E_USER_WARNING - ); + trigger_error($this->lang('buggy_php'), E_USER_WARNING); } try { @@ -1726,7 +1736,7 @@ protected function sendmailSend($header, $body) fwrite($mail, $header); fwrite($mail, $body); $result = pclose($mail); - $addrinfo = static::parseAddresses($toAddr); + $addrinfo = static::parseAddresses($toAddr, true, $this->charSet); $this->doCallback( ($result === 0), [[$addrinfo['address'], $addrinfo['name']]], @@ -1886,7 +1896,7 @@ protected function mailSend($header, $body) if ($this->SingleTo && count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); - $addrinfo = static::parseAddresses($toAddr); + $addrinfo = static::parseAddresses($toAddr, true, $this->charSet); $this->doCallback( $result, [[$addrinfo['address'], $addrinfo['name']]], @@ -2183,14 +2193,15 @@ public function smtpClose() /** * Set the language for error messages. - * Returns false if it cannot load the language file. * The default language is English. * * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") + * Optionally, the language code can be enhanced with a 4-character + * script annotation and/or a 2-character country annotation. * @param string $lang_path Path to the language file directory, with trailing separator (slash).D * Do not set this from user input! * - * @return bool + * @return bool Returns true if the requested language was loaded, false otherwise. */ public function setLanguage($langcode = 'en', $lang_path = '') { @@ -2213,44 +2224,77 @@ public function setLanguage($langcode = 'en', $lang_path = '') //Define full set of translatable strings in English $PHPMAILER_LANG = [ 'authenticate' => 'SMTP Error: Could not authenticate.', + 'buggy_php' => 'Your version of PHP is affected by a bug that may result in corrupted messages.' . + ' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' . + ' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.', 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', 'data_not_accepted' => 'SMTP Error: data not accepted.', 'empty_message' => 'Message body empty', 'encoding' => 'Unknown encoding: ', 'execute' => 'Could not execute: ', + 'extension_missing' => 'Extension missing: ', 'file_access' => 'Could not access file: ', 'file_open' => 'File Error: Could not open file: ', 'from_failed' => 'The following From address failed: ', 'instantiate' => 'Could not instantiate mail function.', 'invalid_address' => 'Invalid address: ', + 'invalid_header' => 'Invalid header name or value', 'invalid_hostentry' => 'Invalid hostentry: ', 'invalid_host' => 'Invalid host: ', 'mailer_not_supported' => ' mailer is not supported.', 'provide_address' => 'You must provide at least one recipient email address.', 'recipients_failed' => 'SMTP Error: The following recipients failed: ', 'signing' => 'Signing Error: ', + 'smtp_code' => 'SMTP code: ', + 'smtp_code_ex' => 'Additional SMTP info: ', 'smtp_connect_failed' => 'SMTP connect() failed.', + 'smtp_detail' => 'Detail: ', 'smtp_error' => 'SMTP server error: ', 'variable_set' => 'Cannot set or reset variable: ', - 'extension_missing' => 'Extension missing: ', ]; if (empty($lang_path)) { //Calculate an absolute path so it can work if CWD is not here $lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR; } + //Validate $langcode - if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) { + $foundlang = true; + $langcode = strtolower($langcode); + if ( + !preg_match('/^(?P[a-z]{2})(?P ', '>=', '<', '<=', * 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. Default '='. @@ -104,11 +104,11 @@ class WP_Date_Query { * @type string $day Optional when passing array.The day of the month. Accepts numbers 1-31. * Default (string:empty)|(array:last day of month). * } - * @type string $column Optional. Used to add a clause comparing a column other than the - * column specified in the top-level `$column` parameter. Accepts - * 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', - * 'comment_date', 'comment_date_gmt'. Default is the value of - * top-level `$column`. + * @type string $column Optional. Used to add a clause comparing a column other than + * the column specified in the top-level `$column` parameter. + * See WP_Date_Query::validate_column() and + * the {@see 'date_query_valid_columns'} filter for the list + * of accepted values. Default is the value of top-level `$column`. * @type string $compare Optional. The comparison operator. Accepts '=', '!=', '>', '>=', * '<', '<=', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. 'IN', * 'NOT IN', 'BETWEEN', and 'NOT BETWEEN'. Comparisons support @@ -140,9 +140,9 @@ class WP_Date_Query { * } * } * } - * @param string $default_column Optional. Default column to query against. Default 'post_date'. - * Accepts 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', - * 'comment_date', 'comment_date_gmt'. + * @param string $default_column Optional. Default column to query against. See WP_Date_Query::validate_column() + * and the {@see 'date_query_valid_columns'} filter for the list of accepted values. + * Default 'post_date'. */ public function __construct( $date_query, $default_column = 'post_date' ) { if ( empty( $date_query ) || ! is_array( $date_query ) ) { @@ -494,11 +494,12 @@ public function validate_column( $column ) { * * @since 3.7.0 * @since 4.1.0 Added 'user_registered' to the default recognized columns. + * @since 4.6.0 Added 'registered' and 'last_updated' to the default recognized columns. * * @param string[] $valid_columns An array of valid date query columns. Defaults * are 'post_date', 'post_date_gmt', 'post_modified', * 'post_modified_gmt', 'comment_date', 'comment_date_gmt', - * 'user_registered' + * 'user_registered', 'registered', 'last_updated'. */ if ( ! in_array( $column, apply_filters( 'date_query_valid_columns', $valid_columns ), true ) ) { $column = 'post_date'; diff --git a/src/wp-includes/class-wp-http-cookie.php b/src/wp-includes/class-wp-http-cookie.php index 1e78e3697991c..5fa2de7644082 100644 --- a/src/wp-includes/class-wp-http-cookie.php +++ b/src/wp-includes/class-wp-http-cookie.php @@ -24,6 +24,7 @@ class WP_Http_Cookie { * Cookie name. * * @since 2.8.0 + * * @var string */ public $name; @@ -32,6 +33,7 @@ class WP_Http_Cookie { * Cookie value. * * @since 2.8.0 + * * @var string */ public $value; @@ -40,6 +42,7 @@ class WP_Http_Cookie { * When the cookie expires. Unix timestamp or formatted date. * * @since 2.8.0 + * * @var string|int|null */ public $expires; @@ -48,6 +51,7 @@ class WP_Http_Cookie { * Cookie URL path. * * @since 2.8.0 + * * @var string */ public $path; @@ -56,14 +60,25 @@ class WP_Http_Cookie { * Cookie Domain. * * @since 2.8.0 + * * @var string */ public $domain; + /** + * Cookie port or comma-separated list of ports. + * + * @since 2.8.0 + * + * @var int|string + */ + public $port; + /** * host-only flag. * * @since 5.2.0 + * * @var bool */ public $host_only; @@ -85,7 +100,7 @@ class WP_Http_Cookie { * @type string|int|null $expires Optional. Unix timestamp or formatted date. Default null. * @type string $path Optional. Path. Default '/'. * @type string $domain Optional. Domain. Default host of parsed $requested_url. - * @type int $port Optional. Port. Default null. + * @type int|string $port Optional. Port or comma-separated list of ports. Default null. * @type bool $host_only Optional. host-only storage flag. Default true. * } * @param string $requested_url The URL which the cookie was set on, used for default $domain @@ -93,12 +108,12 @@ class WP_Http_Cookie { */ public function __construct( $data, $requested_url = '' ) { if ( $requested_url ) { - $arrURL = parse_url( $requested_url ); + $parsed_url = parse_url( $requested_url ); } - if ( isset( $arrURL['host'] ) ) { - $this->domain = $arrURL['host']; + if ( isset( $parsed_url['host'] ) ) { + $this->domain = $parsed_url['host']; } - $this->path = isset( $arrURL['path'] ) ? $arrURL['path'] : '/'; + $this->path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '/'; if ( '/' !== substr( $this->path, -1 ) ) { $this->path = dirname( $this->path ) . '/'; } @@ -187,7 +202,7 @@ public function test( $url ) { // Host - very basic check that the request URL ends with the domain restriction (minus leading dot). $domain = ( '.' === substr( $domain, 0, 1 ) ) ? substr( $domain, 1 ) : $domain; - if ( substr( $url['host'], -strlen( $domain ) ) != $domain ) { + if ( substr( $url['host'], -strlen( $domain ) ) !== $domain ) { return false; } @@ -197,7 +212,7 @@ public function test( $url ) { } // Path - request path must start with path restriction. - if ( substr( $url['path'], 0, strlen( $path ) ) != $path ) { + if ( substr( $url['path'], 0, strlen( $path ) ) !== $path ) { return false; } diff --git a/src/wp-includes/class-wp-http-curl.php b/src/wp-includes/class-wp-http-curl.php index 9b6e0eb10bd51..c4505f2e6198e 100644 --- a/src/wp-includes/class-wp-http-curl.php +++ b/src/wp-includes/class-wp-http-curl.php @@ -256,7 +256,8 @@ public function request( $url, $args = array() ) { } curl_exec( $handle ); - $theHeaders = WP_Http::processHeaders( $this->headers, $url ); + + $processed_headers = WP_Http::processHeaders( $this->headers, $url ); $theBody = $this->body; $bytes_written_total = $this->bytes_written_total; @@ -267,7 +268,7 @@ public function request( $url, $args = array() ) { $curl_error = curl_errno( $handle ); // If an error occurred, or, no response. - if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) ) { + if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $processed_headers['headers'] ) ) ) { if ( CURLE_WRITE_ERROR /* 23 */ == $curl_error ) { if ( ! $this->max_body_length || $this->max_body_length != $bytes_written_total ) { if ( $parsed_args['stream'] ) { @@ -299,20 +300,22 @@ public function request( $url, $args = array() ) { } $response = array( - 'headers' => $theHeaders['headers'], + 'headers' => $processed_headers['headers'], 'body' => null, - 'response' => $theHeaders['response'], - 'cookies' => $theHeaders['cookies'], + 'response' => $processed_headers['response'], + 'cookies' => $processed_headers['cookies'], 'filename' => $parsed_args['filename'], ); // Handle redirects. - $redirect_response = WP_HTTP::handle_redirects( $url, $parsed_args, $response ); + $redirect_response = WP_Http::handle_redirects( $url, $parsed_args, $response ); if ( false !== $redirect_response ) { return $redirect_response; } - if ( true === $parsed_args['decompress'] && true === WP_Http_Encoding::should_decode( $theHeaders['headers'] ) ) { + if ( true === $parsed_args['decompress'] + && true === WP_Http_Encoding::should_decode( $processed_headers['headers'] ) + ) { $theBody = WP_Http_Encoding::decompress( $theBody ); } diff --git a/src/wp-includes/class-wp-http-ixr-client.php b/src/wp-includes/class-wp-http-ixr-client.php index 5de31618fa97c..fef16e831d98b 100644 --- a/src/wp-includes/class-wp-http-ixr-client.php +++ b/src/wp-includes/class-wp-http-ixr-client.php @@ -97,7 +97,7 @@ public function query( ...$args ) { return false; } - if ( 200 != wp_remote_retrieve_response_code( $response ) ) { + if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { $this->error = new IXR_Error( -32301, 'transport error - HTTP status code was not 200 (' . wp_remote_retrieve_response_code( $response ) . ')' ); return false; } diff --git a/src/wp-includes/class-wp-http-streams.php b/src/wp-includes/class-wp-http-streams.php index 93933d7be781f..1014460376bda 100644 --- a/src/wp-includes/class-wp-http-streams.php +++ b/src/wp-includes/class-wp-http-streams.php @@ -51,30 +51,30 @@ public function request( $url, $args = array() ) { // Construct Cookie: header if any cookies are set. WP_Http::buildCookieHeader( $parsed_args ); - $arrURL = parse_url( $url ); + $parsed_url = parse_url( $url ); - $connect_host = $arrURL['host']; + $connect_host = $parsed_url['host']; - $secure_transport = ( 'ssl' === $arrURL['scheme'] || 'https' === $arrURL['scheme'] ); - if ( ! isset( $arrURL['port'] ) ) { - if ( 'ssl' === $arrURL['scheme'] || 'https' === $arrURL['scheme'] ) { - $arrURL['port'] = 443; - $secure_transport = true; + $secure_transport = ( 'ssl' === $parsed_url['scheme'] || 'https' === $parsed_url['scheme'] ); + if ( ! isset( $parsed_url['port'] ) ) { + if ( 'ssl' === $parsed_url['scheme'] || 'https' === $parsed_url['scheme'] ) { + $parsed_url['port'] = 443; + $secure_transport = true; } else { - $arrURL['port'] = 80; + $parsed_url['port'] = 80; } } // Always pass a path, defaulting to the root in cases such as http://example.com. - if ( ! isset( $arrURL['path'] ) ) { - $arrURL['path'] = '/'; + if ( ! isset( $parsed_url['path'] ) ) { + $parsed_url['path'] = '/'; } if ( isset( $parsed_args['headers']['Host'] ) || isset( $parsed_args['headers']['host'] ) ) { if ( isset( $parsed_args['headers']['Host'] ) ) { - $arrURL['host'] = $parsed_args['headers']['Host']; + $parsed_url['host'] = $parsed_args['headers']['Host']; } else { - $arrURL['host'] = $parsed_args['headers']['host']; + $parsed_url['host'] = $parsed_args['headers']['host']; } unset( $parsed_args['headers']['Host'], $parsed_args['headers']['host'] ); } @@ -92,6 +92,7 @@ public function request( $url, $args = array() ) { $is_local = isset( $parsed_args['local'] ) && $parsed_args['local']; $ssl_verify = isset( $parsed_args['sslverify'] ) && $parsed_args['sslverify']; + if ( $is_local ) { /** * Filters whether SSL should be verified for local HTTP API requests. @@ -114,7 +115,7 @@ public function request( $url, $args = array() ) { array( 'ssl' => array( 'verify_peer' => $ssl_verify, - // 'CN_match' => $arrURL['host'], // This is handled by self::verify_ssl_certificate(). + // 'CN_match' => $parsed_url['host'], // This is handled by self::verify_ssl_certificate(). 'capture_peer_cert' => $ssl_verify, 'SNI_enabled' => true, 'cafile' => $parsed_args['sslcertificates'], @@ -141,10 +142,24 @@ public function request( $url, $args = array() ) { if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged - $handle = @stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + $handle = @stream_socket_client( + 'tcp://' . $proxy->host() . ':' . $proxy->port(), + $connection_error, + $connection_error_str, + $connect_timeout, + STREAM_CLIENT_CONNECT, + $context + ); } else { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged - $handle = @stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + $handle = @stream_socket_client( + $connect_host . ':' . $parsed_url['port'], + $connection_error, + $connection_error_str, + $connect_timeout, + STREAM_CLIENT_CONNECT, + $context + ); } if ( $secure_transport ) { @@ -152,9 +167,23 @@ public function request( $url, $args = array() ) { } } else { if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { - $handle = stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + $handle = stream_socket_client( + 'tcp://' . $proxy->host() . ':' . $proxy->port(), + $connection_error, + $connection_error_str, + $connect_timeout, + STREAM_CLIENT_CONNECT, + $context + ); } else { - $handle = stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + $handle = stream_socket_client( + $connect_host . ':' . $parsed_url['port'], + $connection_error, + $connection_error_str, + $connect_timeout, + STREAM_CLIENT_CONNECT, + $context + ); } } @@ -169,7 +198,7 @@ public function request( $url, $args = array() ) { // Verify that the SSL certificate is valid for this request. if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) { - if ( ! self::verify_ssl_certificate( $handle, $arrURL['host'] ) ) { + if ( ! self::verify_ssl_certificate( $handle, $parsed_url['host'] ) ) { return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); } } @@ -179,21 +208,21 @@ public function request( $url, $args = array() ) { if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { // Some proxies require full URL in this field. $requestPath = $url; } else { - $requestPath = $arrURL['path'] . ( isset( $arrURL['query'] ) ? '?' . $arrURL['query'] : '' ); + $requestPath = $parsed_url['path'] . ( isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '' ); } $strHeaders = strtoupper( $parsed_args['method'] ) . ' ' . $requestPath . ' HTTP/' . $parsed_args['httpversion'] . "\r\n"; $include_port_in_host_header = ( - ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) || - ( 'http' === $arrURL['scheme'] && 80 != $arrURL['port'] ) || - ( 'https' === $arrURL['scheme'] && 443 != $arrURL['port'] ) + ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) + || ( 'http' === $parsed_url['scheme'] && 80 != $parsed_url['port'] ) + || ( 'https' === $parsed_url['scheme'] && 443 != $parsed_url['port'] ) ); if ( $include_port_in_host_header ) { - $strHeaders .= 'Host: ' . $arrURL['host'] . ':' . $arrURL['port'] . "\r\n"; + $strHeaders .= 'Host: ' . $parsed_url['host'] . ':' . $parsed_url['port'] . "\r\n"; } else { - $strHeaders .= 'Host: ' . $arrURL['host'] . "\r\n"; + $strHeaders .= 'Host: ' . $parsed_url['host'] . "\r\n"; } if ( isset( $parsed_args['user-agent'] ) ) { @@ -238,6 +267,7 @@ public function request( $url, $args = array() ) { $bodyStarted = false; $keep_reading = true; $block_size = 4096; + if ( isset( $parsed_args['limit_response_size'] ) ) { $block_size = min( $block_size, $parsed_args['limit_response_size'] ); } @@ -249,6 +279,7 @@ public function request( $url, $args = array() ) { } else { $stream_handle = fopen( $parsed_args['filename'], 'w+' ); } + if ( ! $stream_handle ) { return new WP_Error( 'http_request_failed', @@ -262,22 +293,25 @@ public function request( $url, $args = array() ) { } $bytes_written = 0; + while ( ! feof( $handle ) && $keep_reading ) { $block = fread( $handle, $block_size ); if ( ! $bodyStarted ) { $strResponse .= $block; if ( strpos( $strResponse, "\r\n\r\n" ) ) { - $process = WP_Http::processResponse( $strResponse ); - $bodyStarted = true; - $block = $process['body']; + $processed_response = WP_Http::processResponse( $strResponse ); + $bodyStarted = true; + $block = $processed_response['body']; unset( $strResponse ); - $process['body'] = ''; + $processed_response['body'] = ''; } } $this_block_size = strlen( $block ); - if ( isset( $parsed_args['limit_response_size'] ) && ( $bytes_written + $this_block_size ) > $parsed_args['limit_response_size'] ) { + if ( isset( $parsed_args['limit_response_size'] ) + && ( $bytes_written + $this_block_size ) > $parsed_args['limit_response_size'] + ) { $this_block_size = ( $parsed_args['limit_response_size'] - $bytes_written ); $block = substr( $block, 0, $this_block_size ); } @@ -292,38 +326,48 @@ public function request( $url, $args = array() ) { $bytes_written += $bytes_written_to_file; - $keep_reading = ! isset( $parsed_args['limit_response_size'] ) || $bytes_written < $parsed_args['limit_response_size']; + $keep_reading = ( + ! isset( $parsed_args['limit_response_size'] ) + || $bytes_written < $parsed_args['limit_response_size'] + ); } fclose( $stream_handle ); } else { $header_length = 0; + while ( ! feof( $handle ) && $keep_reading ) { $block = fread( $handle, $block_size ); $strResponse .= $block; + if ( ! $bodyStarted && strpos( $strResponse, "\r\n\r\n" ) ) { $header_length = strpos( $strResponse, "\r\n\r\n" ) + 4; $bodyStarted = true; } - $keep_reading = ( ! $bodyStarted || ! isset( $parsed_args['limit_response_size'] ) || strlen( $strResponse ) < ( $header_length + $parsed_args['limit_response_size'] ) ); + + $keep_reading = ( + ! $bodyStarted + || ! isset( $parsed_args['limit_response_size'] ) + || strlen( $strResponse ) < ( $header_length + $parsed_args['limit_response_size'] ) + ); } - $process = WP_Http::processResponse( $strResponse ); + $processed_response = WP_Http::processResponse( $strResponse ); unset( $strResponse ); } fclose( $handle ); - $arrHeaders = WP_Http::processHeaders( $process['headers'], $url ); + $processed_headers = WP_Http::processHeaders( $processed_response['headers'], $url ); $response = array( - 'headers' => $arrHeaders['headers'], + 'headers' => $processed_headers['headers'], // Not yet processed. 'body' => null, - 'response' => $arrHeaders['response'], - 'cookies' => $arrHeaders['cookies'], + 'response' => $processed_headers['response'], + 'cookies' => $processed_headers['cookies'], 'filename' => $parsed_args['filename'], ); @@ -334,21 +378,26 @@ public function request( $url, $args = array() ) { } // If the body was chunk encoded, then decode it. - if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) - && 'chunked' === $arrHeaders['headers']['transfer-encoding'] + if ( ! empty( $processed_response['body'] ) + && isset( $processed_headers['headers']['transfer-encoding'] ) + && 'chunked' === $processed_headers['headers']['transfer-encoding'] ) { - $process['body'] = WP_Http::chunkTransferDecode( $process['body'] ); + $processed_response['body'] = WP_Http::chunkTransferDecode( $processed_response['body'] ); } - if ( true === $parsed_args['decompress'] && true === WP_Http_Encoding::should_decode( $arrHeaders['headers'] ) ) { - $process['body'] = WP_Http_Encoding::decompress( $process['body'] ); + if ( true === $parsed_args['decompress'] + && true === WP_Http_Encoding::should_decode( $processed_headers['headers'] ) + ) { + $processed_response['body'] = WP_Http_Encoding::decompress( $processed_response['body'] ); } - if ( isset( $parsed_args['limit_response_size'] ) && strlen( $process['body'] ) > $parsed_args['limit_response_size'] ) { - $process['body'] = substr( $process['body'], 0, $parsed_args['limit_response_size'] ); + if ( isset( $parsed_args['limit_response_size'] ) + && strlen( $processed_response['body'] ) > $parsed_args['limit_response_size'] + ) { + $processed_response['body'] = substr( $processed_response['body'], 0, $parsed_args['limit_response_size'] ); } - $response['body'] = $process['body']; + $response['body'] = $processed_response['body']; return $response; } @@ -470,6 +519,6 @@ public static function test( $args = array() ) { * @since 2.7.0 * @deprecated 3.7.0 Please use WP_HTTP::request() directly */ -class WP_HTTP_Fsockopen extends WP_HTTP_Streams { +class WP_HTTP_Fsockopen extends WP_Http_Streams { // For backward compatibility for users who are using the class directly. } diff --git a/src/wp-includes/class-wp-image-editor-gd.php b/src/wp-includes/class-wp-image-editor-gd.php index c2105169ec5c6..f175b90d2016b 100644 --- a/src/wp-includes/class-wp-image-editor-gd.php +++ b/src/wp-includes/class-wp-image-editor-gd.php @@ -423,13 +423,15 @@ public function flip( $horz, $vert ) { * Saves current in-memory image to file. * * @since 3.5.0 + * @since 5.9.0 Renamed `$filename` to `$destfilename` to match parent class + * for PHP 8 named parameter support. * - * @param string|null $filename - * @param string|null $mime_type + * @param string|null $destfilename Optional. Destination filename. Default null. + * @param string|null $mime_type Optional. The mime-type. Default null. * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} */ - public function save( $filename = null, $mime_type = null ) { - $saved = $this->_save( $this->image, $filename, $mime_type ); + public function save( $destfilename = null, $mime_type = null ) { + $saved = $this->_save( $this->image, $destfilename, $mime_type ); if ( ! is_wp_error( $saved ) ) { $this->file = $saved['path']; diff --git a/src/wp-includes/class-wp-image-editor-imagick.php b/src/wp-includes/class-wp-image-editor-imagick.php index ae91e4697091e..b7336fe5aeb3e 100644 --- a/src/wp-includes/class-wp-image-editor-imagick.php +++ b/src/wp-includes/class-wp-image-editor-imagick.php @@ -662,8 +662,8 @@ public function maybe_exif_rotate() { * * @since 3.5.0 * - * @param string $destfilename - * @param string $mime_type + * @param string $destfilename Optional. Destination filename. Default null. + * @param string $mime_type Optional. The mime-type. Default null. * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} */ public function save( $destfilename = null, $mime_type = null ) { diff --git a/src/wp-includes/class-wp-image-editor.php b/src/wp-includes/class-wp-image-editor.php index 11210180b229d..b9e580c46f3b1 100644 --- a/src/wp-includes/class-wp-image-editor.php +++ b/src/wp-includes/class-wp-image-editor.php @@ -15,9 +15,12 @@ abstract class WP_Image_Editor { protected $file = null; protected $size = null; protected $mime_type = null; + protected $output_mime_type = null; protected $default_mime_type = 'image/jpeg'; protected $quality = false; - protected $default_quality = 82; + + // Deprecated since 5.8.1. See get_default_quality() below. + protected $default_quality = 82; /** * Each instance handles a single file. @@ -74,8 +77,8 @@ abstract public function load(); * @since 3.5.0 * @abstract * - * @param string $destfilename - * @param string $mime_type + * @param string $destfilename Optional. Destination filename. Default null. + * @param string $mime_type Optional. The mime-type. Default null. * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} */ abstract public function save( $destfilename = null, $mime_type = null ); @@ -224,6 +227,11 @@ public function get_quality() { * @return true|WP_Error True if set successfully; WP_Error on failure. */ public function set_quality( $quality = null ) { + // Use the output mime type if present. If not, fall back to the input/initial mime type. + $mime_type = ! empty( $this->output_mime_type ) ? $this->output_mime_type : $this->mime_type; + // Get the default quality setting for the mime type. + $default_quality = $this->get_default_quality( $mime_type ); + if ( null === $quality ) { /** * Filters the default image compression quality setting. @@ -238,9 +246,9 @@ public function set_quality( $quality = null ) { * @param int $quality Quality level between 1 (low) and 100 (high). * @param string $mime_type Image mime type. */ - $quality = apply_filters( 'wp_editor_set_quality', $this->default_quality, $this->mime_type ); + $quality = apply_filters( 'wp_editor_set_quality', $default_quality, $mime_type ); - if ( 'image/jpeg' === $this->mime_type ) { + if ( 'image/jpeg' === $mime_type ) { /** * Filters the JPEG compression quality for backward-compatibility. * @@ -261,7 +269,7 @@ public function set_quality( $quality = null ) { } if ( $quality < 0 || $quality > 100 ) { - $quality = $this->default_quality; + $quality = $default_quality; } } @@ -278,6 +286,27 @@ public function set_quality( $quality = null ) { } } + /** + * Returns the default compression quality setting for the mime type. + * + * @since 5.8.1 + * + * @param string $mime_type + * @return int The default quality setting for the mime type. + */ + protected function get_default_quality( $mime_type ) { + switch ( $mime_type ) { + case 'image/webp': + $quality = 86; + break; + case 'image/jpeg': + default: + $quality = $this->default_quality; + } + + return $quality; + } + /** * Returns preferred mime-type and extension based on provided * file's extension and mime, or current file's extension and mime. @@ -322,19 +351,6 @@ protected function get_output_format( $filename = null, $mime_type = null ) { * Enables filtering the mime type used to save images. By default, * the mapping array is empty, so the mime type matches the source image. * - * This should be considered experimental as there are a few edge cases that - * still need to be solved. - * - * When this filter is used in combination with the {@see 'wp_editor_set_quality'} - * filter, the image quality value used will be that of the original mime type, - * not the mapped one. This could result in unexpected image quality for generated - * images. See https://core.trac.wordpress.org/ticket/53667 for more details. - * - * When a mime type is mapped to another, and two images with the same name are - * uploaded (image.jpg and image.webp, for example), the generated images for one - * will potentially overwrite the other's. - * See https://core.trac.wordpress.org/ticket/53668 for more details. - * * @see WP_Image_Editor::get_output_format() * * @since 5.8.0 @@ -374,13 +390,28 @@ protected function get_output_format( $filename = null, $mime_type = null ) { $new_ext = $this->get_extension( $mime_type ); } - if ( $filename ) { + // Ensure both $filename and $new_ext are not empty. + // $this->get_extension() returns false on error which would effectively remove the extension + // from $filename. That shouldn't happen, files without extensions are not supported. + if ( $filename && $new_ext ) { $dir = pathinfo( $filename, PATHINFO_DIRNAME ); $ext = pathinfo( $filename, PATHINFO_EXTENSION ); $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}"; } + if ( $mime_type && ( $mime_type !== $this->mime_type ) ) { + // The image will be converted when saving. Set the quality for the new mime-type if not already set. + if ( $mime_type !== $this->output_mime_type ) { + $this->output_mime_type = $mime_type; + $this->set_quality(); + } + } elseif ( ! empty( $this->output_mime_type ) ) { + // Reset output_mime_type and quality. + $this->output_mime_type = null; + $this->set_quality(); + } + return array( $filename, $new_ext, $mime_type ); } @@ -591,13 +622,11 @@ protected static function get_mime_type( $extension = null ) { * @return string|false */ protected static function get_extension( $mime_type = null ) { - $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) ); - - if ( empty( $extensions[0] ) ) { + if ( empty( $mime_type ) ) { return false; } - return $extensions[0]; + return wp_get_default_extension_for_mime_type( $mime_type ); } } diff --git a/src/wp-includes/class-wp-meta-query.php b/src/wp-includes/class-wp-meta-query.php index 4ca9e892b0814..0b3ffab033d4d 100644 --- a/src/wp-includes/class-wp-meta-query.php +++ b/src/wp-includes/class-wp-meta-query.php @@ -691,7 +691,7 @@ public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) if ( ! is_array( $meta_value ) ) { $meta_value = preg_split( '/[,\s]+/', $meta_value ); } - } else { + } elseif ( is_string( $meta_value ) ) { $meta_value = trim( $meta_value ); } diff --git a/src/wp-includes/class-wp-oembed.php b/src/wp-includes/class-wp-oembed.php index 4226e8163eaf4..78297780bc154 100644 --- a/src/wp-includes/class-wp-oembed.php +++ b/src/wp-includes/class-wp-oembed.php @@ -102,6 +102,8 @@ public function __construct() { '#https?://www\.someecards\.com/usercards/viewcard/.+#i' => array( 'https://www.someecards.com/v2/oembed/', true ), '#https?://some\.ly\/.+#i' => array( 'https://www.someecards.com/v2/oembed/', true ), '#https?://(www\.)?tiktok\.com/.*/video/.*#i' => array( 'https://www.tiktok.com/oembed', true ), + '#https?://([a-z]{2}|www)\.pinterest\.com(\.(au|mx))?/.*#i' => array( 'https://www.pinterest.com/oembed.json', true ), + '#https?://(www\.)?wolframcloud\.com/obj/.+#i' => array( 'https://www.wolframcloud.com/oembed', true ), ); if ( ! empty( self::$early_providers['add'] ) ) { @@ -179,6 +181,8 @@ public function __construct() { * | Someecards | some.ly | 4.9.0 | * | Crowdsignal | survey.fm | 5.1.0 | * | TikTok | tiktok.com | 5.4.0 | + * | Pinterest | pinterest.com | 5.9.0 | + * | WolframCloud | wolframcloud.com | 5.9.0 | * * No longer supported providers: * diff --git a/src/wp-includes/class-wp-post-type.php b/src/wp-includes/class-wp-post-type.php index 43e8a61514d57..029bd26fe76b4 100644 --- a/src/wp-includes/class-wp-post-type.php +++ b/src/wp-includes/class-wp-post-type.php @@ -358,6 +358,14 @@ final class WP_Post_Type { */ public $rest_base; + /** + * The namespace for this post type's REST API endpoints. + * + * @since 5.9.0 + * @var string|bool $rest_namespace + */ + public $rest_namespace; + /** * The controller for this post type's REST API endpoints. * @@ -452,6 +460,7 @@ public function set_props( $args ) { 'delete_with_user' => null, 'show_in_rest' => false, 'rest_base' => false, + 'rest_namespace' => false, 'rest_controller_class' => false, 'template' => array(), 'template_lock' => false, @@ -473,6 +482,11 @@ public function set_props( $args ) { $args['show_ui'] = $args['public']; } + // If not set, default rest_namespace to wp/v2 if show_in_rest is true. + if ( false === $args['rest_namespace'] && ! empty( $args['show_in_rest'] ) ) { + $args['rest_namespace'] = 'wp/v2'; + } + // If not set, default to the setting for 'show_ui'. if ( null === $args['show_in_menu'] || ! $args['show_ui'] ) { $args['show_in_menu'] = $args['show_ui']; diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 08d0b5cd51267..1f9516eec472e 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -3855,7 +3855,7 @@ public function is_tag( $tag = '' ) { * * @since 3.1.0 * - * @global array $wp_taxonomies + * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies. * * @param string|string[] $taxonomy Optional. Taxonomy slug or slugs to check against. * Default empty. diff --git a/src/wp-includes/class-wp-taxonomy.php b/src/wp-includes/class-wp-taxonomy.php index 9db7403809306..9ef1fdce4a6d3 100644 --- a/src/wp-includes/class-wp-taxonomy.php +++ b/src/wp-includes/class-wp-taxonomy.php @@ -199,6 +199,14 @@ final class WP_Taxonomy { */ public $rest_base; + /** + * The namespace for this taxonomy's REST API endpoints. + * + * @since 5.9.0 + * @var string|bool $rest_namespace + */ + public $rest_namespace; + /** * The controller for this taxonomy's REST API endpoints. * @@ -319,6 +327,7 @@ public function set_props( $object_type, $args ) { 'update_count_callback' => '', 'show_in_rest' => false, 'rest_base' => false, + 'rest_namespace' => false, 'rest_controller_class' => false, 'default_term' => null, 'sort' => null, @@ -384,6 +393,11 @@ public function set_props( $object_type, $args ) { $args['show_in_quick_edit'] = $args['show_ui']; } + // If not set, default rest_namespace to wp/v2 if show_in_rest is true. + if ( false === $args['rest_namespace'] && ! empty( $args['show_in_rest'] ) ) { + $args['rest_namespace'] = 'wp/v2'; + } + $default_caps = array( 'manage_terms' => 'manage_categories', 'edit_terms' => 'manage_categories', diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 0e5a92698a728..47427c27e3297 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -93,7 +93,7 @@ public static function get_fields_to_translate() { */ private static function translate( $theme_json, $domain = 'default' ) { if ( null === self::$i18n_schema ) { - $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); + $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); self::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema; } diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index a35ee1b7958ad..d394bd3301cad 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -636,7 +636,7 @@ private static function to_ruleset( $selector, $declarations ) { $declaration_block = array_reduce( $declarations, - function ( $carry, $element ) { + static function ( $carry, $element ) { return $carry .= $element['name'] . ': ' . $element['value'] . ';'; }, '' ); diff --git a/src/wp-includes/class-wp-user-query.php b/src/wp-includes/class-wp-user-query.php index f760c252886f0..936ffe89bf708 100644 --- a/src/wp-includes/class-wp-user-query.php +++ b/src/wp-includes/class-wp-user-query.php @@ -93,6 +93,9 @@ public static function fill_query_vars( $args ) { 'role' => '', 'role__in' => array(), 'role__not_in' => array(), + 'capability' => '', + 'capability__in' => array(), + 'capability__not_in' => array(), 'meta_key' => '', 'meta_value' => '', 'meta_compare' => '', @@ -133,6 +136,7 @@ public static function fill_query_vars( $args ) { * querying for all users with using -1. * @since 4.7.0 Added 'nicename', 'nicename__in', 'nicename__not_in', 'login', 'login__in', * and 'login__not_in' parameters. + * @since 5.9.0 Added 'capability', 'capability__in', and 'capability__not_in' parameters. * * @global wpdb $wpdb WordPress database abstraction object. * @global int $blog_id @@ -148,6 +152,19 @@ public static function fill_query_vars( $args ) { * roles. Default empty array. * @type string[] $role__not_in An array of role names to exclude. Users matching one or more of these * roles will not be included in results. Default empty array. + * @type string $capability An array or a comma-separated list of capability names that users must match + * to be included in results. Note that this is an inclusive list: users + * must match *each* capability. + * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. + * Default empty. + * @type string[] $capability__in An array of capability names. Matched users must have at least one of these + * capabilities. + * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. + * Default empty array. + * @type string[] $capability__not_in An array of capability names to exclude. Users matching one or more of these + * capabilities will not be included in results. + * Does NOT work for capabilities not in the database or filtered via {@see 'map_meta_cap'}. + * Default empty array. * @type string $meta_key User meta key. Default empty. * @type string $meta_value User meta value. Default empty. * @type string $meta_compare Comparison operator to test the `$meta_value`. Accepts '=', '!=', @@ -320,6 +337,17 @@ public function prepare_query( $query = array() ) { $this->meta_query->parse_query_vars( $qv ); if ( isset( $qv['who'] ) && 'authors' === $qv['who'] && $blog_id ) { + _deprecated_argument( + 'WP_User_Query', + '5.9.0', + sprintf( + /* translators: 1: who, 2: capability */ + __( '%1$s is deprecated. Use %2$s instead.' ), + 'who', + 'capability' + ) + ); + $who_query = array( 'key' => $wpdb->get_blog_prefix( $blog_id ) . 'user_level', 'value' => 0, @@ -343,6 +371,7 @@ public function prepare_query( $query = array() ) { $this->meta_query->parse_query_vars( $this->meta_query->queries ); } + // Roles. $roles = array(); if ( isset( $qv['role'] ) ) { if ( is_array( $qv['role'] ) ) { @@ -362,6 +391,111 @@ public function prepare_query( $query = array() ) { $role__not_in = (array) $qv['role__not_in']; } + // Capabilities. + $available_roles = array(); + + if ( ! empty( $qv['capability'] ) || ! empty( $qv['capability__in'] ) || ! empty( $qv['capability__not_in'] ) ) { + global $wp_roles; + + $wp_roles->for_site( $blog_id ); + $available_roles = $wp_roles->roles; + } + + $capabilities = array(); + if ( ! empty( $qv['capability'] ) ) { + if ( is_array( $qv['capability'] ) ) { + $capabilities = $qv['capability']; + } elseif ( is_string( $qv['capability'] ) ) { + $capabilities = array_map( 'trim', explode( ',', $qv['capability'] ) ); + } + } + + $capability__in = array(); + if ( ! empty( $qv['capability__in'] ) ) { + $capability__in = (array) $qv['capability__in']; + } + + $capability__not_in = array(); + if ( ! empty( $qv['capability__not_in'] ) ) { + $capability__not_in = (array) $qv['capability__not_in']; + } + + // Keep track of all capabilities and the roles they're added on. + $caps_with_roles = array(); + + foreach ( $available_roles as $role => $role_data ) { + $role_caps = array_keys( array_filter( $role_data['capabilities'] ) ); + + foreach ( $capabilities as $cap ) { + if ( in_array( $cap, $role_caps, true ) ) { + $caps_with_roles[ $cap ][] = $role; + break; + } + } + + foreach ( $capability__in as $cap ) { + if ( in_array( $cap, $role_caps, true ) ) { + $role__in[] = $role; + break; + } + } + + foreach ( $capability__not_in as $cap ) { + if ( in_array( $cap, $role_caps, true ) ) { + $role__not_in[] = $role; + break; + } + } + } + + $role__in = array_merge( $role__in, $capability__in ); + $role__not_in = array_merge( $role__not_in, $capability__not_in ); + + $roles = array_unique( $roles ); + $role__in = array_unique( $role__in ); + $role__not_in = array_unique( $role__not_in ); + + // Support querying by capabilities added directly to users. + if ( $blog_id && ! empty( $capabilities ) ) { + $capabilities_clauses = array( 'relation' => 'AND' ); + + foreach ( $capabilities as $cap ) { + $clause = array( 'relation' => 'OR' ); + + $clause[] = array( + 'key' => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities', + 'value' => '"' . $cap . '"', + 'compare' => 'LIKE', + ); + + if ( ! empty( $caps_with_roles[ $cap ] ) ) { + foreach ( $caps_with_roles[ $cap ] as $role ) { + $clause[] = array( + 'key' => $wpdb->get_blog_prefix( $blog_id ) . 'capabilities', + 'value' => '"' . $role . '"', + 'compare' => 'LIKE', + ); + } + } + + $capabilities_clauses[] = $clause; + } + + $role_queries[] = $capabilities_clauses; + + if ( empty( $this->meta_query->queries ) ) { + $this->meta_query->queries[] = $capabilities_clauses; + } else { + // Append the cap query to the original queries and reparse the query. + $this->meta_query->queries = array( + 'relation' => 'AND', + array( $this->meta_query->queries, array( $capabilities_clauses ) ), + ); + } + + $this->meta_query->parse_query_vars( $this->meta_query->queries ); + } + if ( $blog_id && ( ! empty( $roles ) || ! empty( $role__in ) || ! empty( $role__not_in ) || is_multisite() ) ) { $role_queries = array(); diff --git a/src/wp-includes/class-wp-user.php b/src/wp-includes/class-wp-user.php index 195bc24341a98..b2f8687828abf 100644 --- a/src/wp-includes/class-wp-user.php +++ b/src/wp-includes/class-wp-user.php @@ -34,6 +34,7 @@ * @property string $locale * @property string $rich_editing * @property string $syntax_highlighting + * @property string $use_ssl */ class WP_User { /** diff --git a/src/wp-includes/class-wp-walker.php b/src/wp-includes/class-wp-walker.php index c76451cd9453f..b50c2d7505204 100644 --- a/src/wp-includes/class-wp-walker.php +++ b/src/wp-includes/class-wp-walker.php @@ -83,15 +83,16 @@ public function end_lvl( &$output, $depth = 0, $args = array() ) {} * class methods. Includes the element output also. * * @since 2.1.0 + * @since 5.9.0 Renamed `$object` (a PHP reserved keyword) to `$data_object` for PHP 8 named parameter support. * @abstract * * @param string $output Used to append additional content (passed by reference). - * @param object $object The data object. + * @param object $data_object The data object. * @param int $depth Depth of the item. * @param array $args An array of additional arguments. - * @param int $current_object_id ID of the current item. + * @param int $current_object_id Optional. ID of the current item. Default 0. */ - public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {} + public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {} /** * Ends the element output, if needed. @@ -99,14 +100,15 @@ public function start_el( &$output, $object, $depth = 0, $args = array(), $curre * The $args parameter holds additional values that may be used with the child class methods. * * @since 2.1.0 + * @since 5.9.0 Renamed `$object` (a PHP reserved keyword) to `$data_object` for PHP 8 named parameter support. * @abstract * - * @param string $output Used to append additional content (passed by reference). - * @param object $object The data object. - * @param int $depth Depth of the item. - * @param array $args An array of additional arguments. + * @param string $output Used to append additional content (passed by reference). + * @param object $data_object The data object. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. */ - public function end_el( &$output, $object, $depth = 0, $args = array() ) {} + public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {} /** * Traverse elements to create list from elements. diff --git a/src/wp-includes/class-wp.php b/src/wp-includes/class-wp.php index 8c7c48b3b24c3..770df083e70ea 100644 --- a/src/wp-includes/class-wp.php +++ b/src/wp-includes/class-wp.php @@ -170,8 +170,13 @@ public function parse_request( $extra_query_vars = '' ) { list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] ); $self = $_SERVER['PHP_SELF']; - $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' ); - $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) ); + + $home_path = parse_url( home_url(), PHP_URL_PATH ); + $home_path_regex = ''; + if ( is_string( $home_path ) && '' !== $home_path ) { + $home_path = trim( $home_path, '/' ); + $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) ); + } /* * Trim path info from the end and the leading home path from the front. @@ -180,14 +185,17 @@ public function parse_request( $extra_query_vars = '' ) { */ $req_uri = str_replace( $pathinfo, '', $req_uri ); $req_uri = trim( $req_uri, '/' ); - $req_uri = preg_replace( $home_path_regex, '', $req_uri ); - $req_uri = trim( $req_uri, '/' ); - $pathinfo = trim( $pathinfo, '/' ); - $pathinfo = preg_replace( $home_path_regex, '', $pathinfo ); $pathinfo = trim( $pathinfo, '/' ); $self = trim( $self, '/' ); - $self = preg_replace( $home_path_regex, '', $self ); - $self = trim( $self, '/' ); + + if ( ! empty( $home_path_regex ) ) { + $req_uri = preg_replace( $home_path_regex, '', $req_uri ); + $req_uri = trim( $req_uri, '/' ); + $pathinfo = preg_replace( $home_path_regex, '', $pathinfo ); + $pathinfo = trim( $pathinfo, '/' ); + $self = preg_replace( $home_path_regex, '', $self ); + $self = trim( $self, '/' ); + } // The requested permalink is in $pathinfo for path info requests and // $req_uri for other requests. diff --git a/src/wp-includes/class.wp-dependencies.php b/src/wp-includes/class.wp-dependencies.php index 9ed26568edfb0..e9f701b727bc6 100644 --- a/src/wp-includes/class.wp-dependencies.php +++ b/src/wp-includes/class.wp-dependencies.php @@ -17,33 +17,37 @@ */ class WP_Dependencies { /** - * An array of registered handle objects. + * An array of all registered dependencies keyed by handle. * * @since 2.6.8 - * @var array + * + * @var _WP_Dependency[] */ public $registered = array(); /** - * An array of handles of queued objects. + * An array of handles of queued dependencies. * * @since 2.6.8 + * * @var string[] */ public $queue = array(); /** - * An array of handles of objects to queue. + * An array of handles of dependencies to queue. * * @since 2.6.0 + * * @var string[] */ public $to_do = array(); /** - * An array of handles of objects already queued. + * An array of handles of dependencies already queued. * * @since 2.6.0 + * * @var string[] */ public $done = array(); @@ -54,15 +58,20 @@ class WP_Dependencies { * Arguments are appended to the item query string. * * @since 2.6.0 + * * @var array */ public $args = array(); /** - * An array of handle groups to enqueue. + * An array of dependency groups to enqueue. + * + * Each entry is keyed by handle and represents the integer group level or boolean + * false if the handle has no group. * * @since 2.8.0 - * @var array + * + * @var (int|false)[] */ public $groups = array(); @@ -70,6 +79,7 @@ class WP_Dependencies { * A handle group to enqueue. * * @since 2.8.0 + * * @deprecated 4.5.0 * @var int */ @@ -79,6 +89,7 @@ class WP_Dependencies { * Cached lookup array of flattened queued items and dependencies. * * @since 5.4.0 + * * @var array */ private $all_queued_deps; @@ -94,7 +105,7 @@ class WP_Dependencies { * @param string|string[]|false $handles Optional. Items to be processed: queue (false), * single item (string), or multiple items (array of strings). * Default false. - * @param int|false $group Optional. Group level: level (int), no groups (false). + * @param int|false $group Optional. Group level: level (int), no group (false). * @return string[] Array of handles of items that have been processed. */ public function do_items( $handles = false, $group = false ) { @@ -131,7 +142,7 @@ public function do_items( $handles = false, $group = false ) { * @since 5.5.0 Added the `$group` parameter. * * @param string $handle Name of the item. Should be unique. - * @param int|false $group Optional. Group level: level (int), no groups (false). + * @param int|false $group Optional. Group level: level (int), no group (false). * Default false. * @return bool True on success, false if not set. */ @@ -152,7 +163,7 @@ public function do_item( $handle, $group = false ) { * @param string|string[] $handles Item handle (string) or item handles (array of strings). * @param bool $recursion Optional. Internal flag that function is calling itself. * Default false. - * @param int|false $group Optional. Group level: level (int), no groups (false). + * @param int|false $group Optional. Group level: level (int), no group (false). * Default false. * @return bool True on success, false on failure. */ @@ -354,7 +365,7 @@ public function dequeue( $handles ) { } /** - * Recursively search the passed dependency tree for $handle. + * Recursively search the passed dependency tree for a handle. * * @since 4.0.0 * @@ -434,7 +445,7 @@ public function query( $handle, $list = 'registered' ) { * * @param string $handle Name of the item. Should be unique. * @param bool $recursion Internal flag that calling function was called recursively. - * @param int|false $group Group level: level (int), no groups (false). + * @param int|false $group Group level: level (int), no group (false). * @return bool Not already in the group or a lower group. */ public function set_group( $handle, $recursion, $group ) { diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php index a40a98d1706ce..e45088729f557 100644 --- a/src/wp-includes/comment-template.php +++ b/src/wp-includes/comment-template.php @@ -2646,7 +2646,7 @@ function comment_form( $args = array(), $post_id = null ) { /** * Filters a comment form field for display. * - * The dynamic portion of the filter hook, `$name`, refers to the name + * The dynamic portion of the hook name, `$name`, refers to the name * of the comment form field. * * Possible hook names include: diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 5c4f2b5f3e8f9..113bb2e719008 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -1826,6 +1826,15 @@ function wp_transition_comment_status( $new_status, $old_status, $comment ) { * The dynamic portions of the hook name, `$old_status`, and `$new_status`, * refer to the old and new comment statuses, respectively. * + * Possible hook names include: + * + * - `comment_unapproved_to_approved` + * - `comment_spam_to_approved` + * - `comment_approved_to_unapproved` + * - `comment_spam_to_unapproved` + * - `comment_unapproved_to_spam` + * - `comment_approved_to_spam` + * * @since 2.7.0 * * @param WP_Comment $comment Comment object. @@ -1838,8 +1847,19 @@ function wp_transition_comment_status( $new_status, $old_status, $comment ) { * The dynamic portions of the hook name, `$new_status`, and `$comment->comment_type`, * refer to the new comment status, and the type of comment, respectively. * - * Typical comment types include an empty string (standard comment), 'pingback', - * or 'trackback'. + * Typical comment types include 'comment', 'pingback', or 'trackback'. + * + * Possible hook names include: + * + * - `comment_approved_comment` + * - `comment_approved_pingback` + * - `comment_approved_trackback` + * - `comment_unapproved_comment` + * - `comment_unapproved_pingback` + * - `comment_unapproved_trackback` + * - `comment_spam_comment` + * - `comment_spam_pingback` + * - `comment_spam_trackback` * * @since 2.7.0 * diff --git a/src/wp-includes/compat.php b/src/wp-includes/compat.php index 6fe5ab37e17d8..b95275455ceae 100644 --- a/src/wp-includes/compat.php +++ b/src/wp-includes/compat.php @@ -79,6 +79,10 @@ function mb_substr( $str, $start, $length = null, $encoding = null ) { * @return string Extracted substring. */ function _mb_substr( $str, $start, $length = null, $encoding = null ) { + if ( null === $str ) { + return ''; + } + if ( null === $encoding ) { $encoding = get_option( 'blog_charset' ); } diff --git a/src/wp-includes/cron.php b/src/wp-includes/cron.php index 18fe14196e9c1..8e50349f5d652 100644 --- a/src/wp-includes/cron.php +++ b/src/wp-includes/cron.php @@ -118,7 +118,11 @@ function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error * current time) all events scheduled within the next ten minutes * are considered duplicates. */ - $crons = (array) _get_cron_array(); + $crons = _get_cron_array(); + if ( ! is_array( $crons ) ) { + $crons = array(); + } + $key = md5( serialize( $event->args ) ); $duplicate = false; @@ -1036,7 +1040,7 @@ function _wp_cron() { * @since 2.1.0 * @since 5.4.0 The 'weekly' schedule was added. * - * @return array + * @return array[] */ function wp_get_schedules() { $schedules = array( @@ -1063,7 +1067,7 @@ function wp_get_schedules() { * * @since 2.1.0 * - * @param array $new_schedules An array of non-default cron schedules. Default empty. + * @param array[] $new_schedules An array of non-default cron schedule arrays. Default empty. */ return array_merge( apply_filters( 'cron_schedules', array() ), $schedules ); } @@ -1191,6 +1195,10 @@ function _get_cron_array() { * @return bool|WP_Error True if cron array updated. False or WP_Error on failure. */ function _set_cron_array( $cron, $wp_error = false ) { + if ( ! is_array( $cron ) ) { + $cron = array(); + } + $cron['version'] = 2; $result = update_option( 'cron', $cron ); diff --git a/src/wp-includes/css/admin-bar.css b/src/wp-includes/css/admin-bar.css index cfbf442a9d8a4..5720af7b415a8 100644 --- a/src/wp-includes/css/admin-bar.css +++ b/src/wp-includes/css/admin-bar.css @@ -1,3 +1,7 @@ +html { + --wp-admin--admin-bar--height: 32px; +} + #wpadminbar * { height: auto; width: auto; @@ -248,7 +252,7 @@ html:lang(he-il) .rtl #wpadminbar * { #wpadminbar .ab-item:before, #wpadminbar #adminbarsearch:before { position: relative; - transition: all .1s ease-in-out; + transition: color .1s ease-in-out; } #wpadminbar .ab-label { @@ -729,6 +733,10 @@ html:lang(he-il) .rtl #wpadminbar * { } @media screen and (max-width: 782px) { + html { + --wp-admin--admin-bar--height: 46px; + } + /* Toolbar Touchification*/ html #wpadminbar { height: 46px; diff --git a/src/wp-includes/css/editor.css b/src/wp-includes/css/editor.css index e75e9b7b4db0c..fac059c7874ef 100644 --- a/src/wp-includes/css/editor.css +++ b/src/wp-includes/css/editor.css @@ -623,7 +623,7 @@ div.mce-path { div.mce-menubar { border-color: #dcdcde; background: #fff; - border-width: 0px 0px 1px; + border-width: 0 0 1px; } .mce-menubar .mce-menubtn:hover, @@ -643,7 +643,7 @@ div.mce-menubar { div.mce-menu .mce-menu-item-sep, .mce-menu-item-sep:hover { border-bottom: 1px solid #dcdcde; - height: 0px; + height: 0; margin: 5px 0; } diff --git a/src/wp-includes/css/media-views.css b/src/wp-includes/css/media-views.css index 784903db6d745..02c32c4998cb8 100644 --- a/src/wp-includes/css/media-views.css +++ b/src/wp-includes/css/media-views.css @@ -370,7 +370,7 @@ } .media-sidebar h2, -.image-details h2 { +.image-details h2:not(.media-attachments-filter-heading) { position: relative; font-weight: 600; text-transform: uppercase; @@ -1394,7 +1394,7 @@ top: 50%; left: 15%; width: 70%; - margin: -5px 0 0 0; + margin: -5px 0 0; } .media-uploader-status { @@ -1976,7 +1976,7 @@ } .media-modal .imgedit-wrap .imgedit-panel-content { - padding: 16px 16px 0 16px; + padding: 16px 16px 0; position: absolute; top: 0; right: 282px; @@ -2289,7 +2289,7 @@ .image-details .custom-size .sep { float: left; - margin: 26px 6px 0 6px; + margin: 26px 6px 0; } .image-details .custom-size .description { @@ -2428,7 +2428,7 @@ float: left; width: 25%; text-align: right; - margin: 8px 1% 0 1%; + margin: 8px 1% 0; line-height: 1.1; } @@ -2617,13 +2617,15 @@ .attachments-browser .attachments, .attachments-browser .uploader-inline, - .attachments-browser .media-toolbar { + .attachments-browser .media-toolbar, + .attachments-browser .attachments-wrapper, + .attachments-browser.has-load-more .attachments-wrapper { right: 262px; } .media-sidebar .setting, .attachment-details .setting { - margin: 6px 0px; + margin: 6px 0; } .media-sidebar .setting input, @@ -2884,10 +2886,15 @@ .attachments-browser .attachments, .attachments-browser .uploader-inline, - .attachments-browser .media-toolbar { + .attachments-browser .media-toolbar, + .media-frame-content .attachments-browser .attachments-wrapper { right: 0; } + .attachments-browser .attachments-wrapper { + padding-top: 12px; + } + .image-details .media-frame-title { display: block; top: 0; @@ -2912,7 +2919,7 @@ /* Change margin direction on load more button in responsive views. */ .load-more-wrapper .load-more-jump { - margin: 12px 0 0 0; + margin: 12px 0 0; } } @@ -2926,7 +2933,7 @@ /* Change margin direction on load more button in responsive views. */ .load-more-wrapper .load-more-jump { - margin: 12px 0 0 0; + margin: 12px 0 0; } } diff --git a/src/wp-includes/css/wp-embed-template.css b/src/wp-includes/css/wp-embed-template.css index 2c1e294643116..c1f1cc5c847b9 100644 --- a/src/wp-includes/css/wp-embed-template.css +++ b/src/wp-includes/css/wp-embed-template.css @@ -301,7 +301,7 @@ p.wp-embed-share-description { width: 100%; border: none; height: 28px; - margin: 0 0 10px 0; + margin: 0 0 10px; padding: 0 5px; font-size: 14px; font-weight: 400; diff --git a/src/wp-includes/css/wp-pointer.css b/src/wp-includes/css/wp-pointer.css index 9263346e06eb2..a1c085cbcfaa0 100644 --- a/src/wp-includes/css/wp-pointer.css +++ b/src/wp-includes/css/wp-pointer.css @@ -140,7 +140,7 @@ .wp-pointer-top .wp-pointer-arrow, .wp-pointer-undefined .wp-pointer-arrow { top: 0; - border-width: 0 13px 13px 13px; + border-width: 0 13px 13px; border-bottom-color: #2271b1; } @@ -157,7 +157,7 @@ .wp-pointer-bottom .wp-pointer-arrow { bottom: 0; - border-width: 13px 13px 0 13px; + border-width: 13px 13px 0; border-top-color: #c3c4c7; } diff --git a/src/wp-includes/customize/class-wp-customize-background-image-setting.php b/src/wp-includes/customize/class-wp-customize-background-image-setting.php index 96b69a022df32..b8b1a06a9d8c7 100644 --- a/src/wp-includes/customize/class-wp-customize-background-image-setting.php +++ b/src/wp-includes/customize/class-wp-customize-background-image-setting.php @@ -20,7 +20,7 @@ final class WP_Customize_Background_Image_Setting extends WP_Customize_Setting { /** * @since 3.4.0 * - * @param mixed $value + * @param mixed $value The value to update. Not used. */ public function update( $value ) { remove_theme_mod( 'background_image_thumb' ); diff --git a/src/wp-includes/customize/class-wp-customize-background-position-control.php b/src/wp-includes/customize/class-wp-customize-background-position-control.php index bb35b052d0c2c..410a0bf59782b 100644 --- a/src/wp-includes/customize/class-wp-customize-background-position-control.php +++ b/src/wp-includes/customize/class-wp-customize-background-position-control.php @@ -96,7 +96,7 @@ public function content_template() {
$input ) : ?> diff --git a/src/wp-includes/customize/class-wp-customize-custom-css-setting.php b/src/wp-includes/customize/class-wp-customize-custom-css-setting.php index 39750f864c3a3..0e6132f3397db 100644 --- a/src/wp-includes/customize/class-wp-customize-custom-css-setting.php +++ b/src/wp-includes/customize/class-wp-customize-custom-css-setting.php @@ -145,18 +145,22 @@ public function value() { } /** - * Validate CSS. + * Validate a received value for being valid CSS. * * Checks for imbalanced braces, brackets, and comments. * Notifications are rendered when the customizer state is saved. * * @since 4.7.0 * @since 4.9.0 Checking for balanced characters has been moved client-side via linting in code editor. + * @since 5.9.0 Renamed `$css` to `$value` for PHP 8 named parameter support. * - * @param string $css The input string. + * @param string $value CSS to validate. * @return true|WP_Error True if the input was validated, otherwise WP_Error. */ - public function validate( $css ) { + public function validate( $value ) { + // Restores the more descriptive, specific name for use within this method. + $css = $value; + $validity = new WP_Error(); if ( preg_match( '#|i', - function( $matches ) { + static function( $matches ) { return wp_rel_callback( $matches, 'nofollow' ); }, $text @@ -3147,7 +3147,7 @@ function wp_rel_ugc( $text ) { $text = stripslashes( $text ); $text = preg_replace_callback( '||i', - function( $matches ) { + static function( $matches ) { return wp_rel_callback( $matches, 'nofollow ugc' ); }, $text @@ -3539,8 +3539,8 @@ function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { /** * Given a date in UTC or GMT timezone, returns that date in the timezone of the site. * - * Requires and returns a date in the Y-m-d H:i:s format. - * Return format can be overridden using the $format parameter. + * Requires a date in the Y-m-d H:i:s format. + * Default return format of 'Y-m-d H:i:s' can be overridden using the `$format` parameter. * * @since 1.2.0 * @@ -4964,7 +4964,7 @@ function map_deep( $value, $callback ) { * @param array $array Variables will be stored in this array. */ function wp_parse_str( $string, &$array ) { - parse_str( $string, $array ); + parse_str( (string) $string, $array ); /** * Filters the array of variables derived from a parsed string. @@ -5650,7 +5650,7 @@ function print_emoji_styles() { box-shadow: none !important; height: 1em !important; width: 1em !important; - margin: 0 .07em !important; + margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 33344f31532d3..0950f794659c4 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -10,9 +10,9 @@ /** * Convert given MySQL date string into a different format. * - * `$format` should be a PHP date format string. - * 'U' and 'G' formats will return a sum of timestamp with timezone offset. - * `$date` is expected to be local time in MySQL format (`Y-m-d H:i:s`). + * - `$format` should be a PHP date format string. + * - 'U' and 'G' formats will return an integer sum of timestamp with timezone offset. + * - `$date` is expected to be local time in MySQL format (`Y-m-d H:i:s`). * * Historically UTC time could be passed to the function to produce Unix timestamp. * @@ -24,7 +24,7 @@ * @param string $format Format of the date to return. * @param string $date Date string to convert. * @param bool $translate Whether the return date should be translated. Default true. - * @return string|int|false Formatted date string or sum of Unix timestamp and timezone offset. + * @return string|int|false Integer if `$format` is 'U' or 'G', string otherwise. * False on failure. */ function mysql2date( $format, $date, $translate = true ) { @@ -53,20 +53,21 @@ function mysql2date( $format, $date, $translate = true ) { /** * Retrieves the current time based on specified type. * - * The 'mysql' type will return the time in the format for MySQL DATETIME field. - * The 'timestamp' type will return the current timestamp or a sum of timestamp - * and timezone offset, depending on `$gmt`. - * Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d'). + * - The 'mysql' type will return the time in the format for MySQL DATETIME field. + * - The 'timestamp' or 'U' types will return the current timestamp or a sum of timestamp + * and timezone offset, depending on `$gmt`. + * - Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d'). * - * If $gmt is set to either '1' or 'true', then both types will use GMT time. - * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option. + * If `$gmt` is a truthy value then both types will use GMT time, otherwise the + * output is adjusted with the GMT offset for the site. * * @since 1.0.0 + * @since 5.3.0 Now returns an integer if `$type` is 'U'. Previously a string was returned. * - * @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp', + * @param string $type Type of time to retrieve. Accepts 'mysql', 'timestamp', 'U', * or PHP date format string (e.g. 'Y-m-d'). * @param int|bool $gmt Optional. Whether to use GMT timezone. Default false. - * @return int|string Integer if $type is 'timestamp', string otherwise. + * @return int|string Integer if `$type` is 'timestamp' or 'U', string otherwise. */ function current_time( $type, $gmt = 0 ) { // Don't use non-GMT timestamp, unless you know the difference and really need to. @@ -85,7 +86,7 @@ function current_time( $type, $gmt = 0 ) { } /** - * Retrieves the current time as an object with the timezone from settings. + * Retrieves the current time as an object using the site's timezone. * * @since 5.3.0 * @@ -96,14 +97,23 @@ function current_datetime() { } /** - * Retrieves the timezone from site settings as a string. + * Retrieves the timezone of the site as a string. * - * Uses the `timezone_string` option to get a proper timezone if available, - * otherwise falls back to an offset. + * Uses the `timezone_string` option to get a proper timezone name if available, + * otherwise falls back to a manual UTC ± offset. + * + * Example return values: + * + * - 'Europe/Rome' + * - 'America/North_Dakota/New_Salem' + * - 'UTC' + * - '-06:30' + * - '+00:00' + * - '+08:45' * * @since 5.3.0 * - * @return string PHP timezone string or a ±HH:MM offset. + * @return string PHP timezone name or a ±HH:MM offset. */ function wp_timezone_string() { $timezone_string = get_option( 'timezone_string' ); @@ -125,7 +135,7 @@ function wp_timezone_string() { } /** - * Retrieves the timezone from site settings as a `DateTimeZone` object. + * Retrieves the timezone of the site as a `DateTimeZone` object. * * Timezone can be based on a PHP timezone string or a ±HH:MM offset. * @@ -555,7 +565,12 @@ function human_readable_duration( $duration = '' ) { * * @param string $mysqlstring Date or datetime field type from MySQL. * @param int|string $start_of_week Optional. Start of the week as an integer. Default empty string. - * @return array Keys are 'start' and 'end'. + * @return int[] { + * Week start and end dates as Unix timestamps. + * + * @type int $start The week start date as a Unix timestamp. + * @type int $end The week end date as a Unix timestamp. + * } */ function get_weekstartend( $mysqlstring, $start_of_week = '' ) { // MySQL string year. @@ -1533,7 +1548,7 @@ function get_num_queries() { * @since 1.0.0 * * @param string $yn Character string containing either 'y' (yes) or 'n' (no). - * @return bool True if yes, false on anything else. + * @return bool True if 'y', false on anything else. */ function bool_from_yn( $yn ) { return ( 'y' === strtolower( $yn ) ); @@ -2488,6 +2503,10 @@ function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) $filename = sanitize_file_name( $filename ); $ext2 = null; + // Initialize vars used in the wp_unique_filename filter. + $number = ''; + $alt_filenames = array(); + // Separate the filename into a name and extension. $ext = pathinfo( $filename, PATHINFO_EXTENSION ); $name = pathinfo( $filename, PATHINFO_BASENAME ); @@ -2508,8 +2527,7 @@ function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) { $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext ); } else { - $number = ''; - $fname = pathinfo( $filename, PATHINFO_FILENAME ); + $fname = pathinfo( $filename, PATHINFO_FILENAME ); // Always append a number to file names that can potentially match image sub-size file names. if ( $fname && preg_match( '/-(?:\d+x\d+|scaled|rotated)$/', $fname ) ) { @@ -2519,37 +2537,54 @@ function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) $filename = str_replace( "{$fname}{$ext}", "{$fname}-{$number}{$ext}", $filename ); } - // Change '.ext' to lower case. - if ( $ext && strtolower( $ext ) != $ext ) { - $ext2 = strtolower( $ext ); - $filename2 = preg_replace( '|' . preg_quote( $ext ) . '$|', $ext2, $filename ); + // Get the mime type. Uploaded files were already checked with wp_check_filetype_and_ext() + // in _wp_handle_upload(). Using wp_check_filetype() would be sufficient here. + $file_type = wp_check_filetype( $filename ); + $mime_type = $file_type['type']; - // Check for both lower and upper case extension or image sub-sizes may be overwritten. - while ( file_exists( $dir . "/{$filename}" ) || file_exists( $dir . "/{$filename2}" ) ) { - $new_number = (int) $number + 1; - $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); - $filename2 = str_replace( array( "-{$number}{$ext2}", "{$number}{$ext2}" ), "-{$new_number}{$ext2}", $filename2 ); - $number = $new_number; - } + $is_image = ( ! empty( $mime_type ) && 0 === strpos( $mime_type, 'image/' ) ); + $upload_dir = wp_get_upload_dir(); + $lc_filename = null; - $filename = $filename2; - } else { - while ( file_exists( $dir . "/{$filename}" ) ) { - $new_number = (int) $number + 1; + $lc_ext = strtolower( $ext ); + $_dir = trailingslashit( $dir ); - if ( '' === "{$number}{$ext}" ) { - $filename = "{$filename}-{$new_number}"; - } else { - $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); - } + // If the extension is uppercase add an alternate file name with lowercase extension. Both need to be tested + // for uniqueness as the extension will be changed to lowercase for better compatibility with different filesystems. + // Fixes an inconsistency in WP < 2.9 where uppercase extensions were allowed but image sub-sizes were created with + // lowercase extensions. + if ( $ext && $lc_ext !== $ext ) { + $lc_filename = preg_replace( '|' . preg_quote( $ext ) . '$|', $lc_ext, $filename ); + } + + // Increment the number added to the file name if there are any files in $dir whose names match one of the + // possible name variations. + while ( file_exists( $_dir . $filename ) || ( $lc_filename && file_exists( $_dir . $lc_filename ) ) ) { + $new_number = (int) $number + 1; + + if ( $lc_filename ) { + $lc_filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $lc_filename ); + } - $number = $new_number; + if ( '' === "{$number}{$ext}" ) { + $filename = "{$filename}-{$new_number}"; + } else { + $filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename ); } + + $number = $new_number; + } + + // Change the extension to lowercase if needed. + if ( $lc_filename ) { + $filename = $lc_filename; } // Prevent collisions with existing file names that contain dimension-like strings // (whether they are subsizes or originals uploaded prior to #42437). - $upload_dir = wp_get_upload_dir(); + + $files = array(); + $count = 10000; // The (resized) image files would have name and extension, and will be in the uploads dir. if ( $name && $ext && @is_dir( $dir ) && false !== strpos( $dir, $upload_dir['basedir'] ) ) { @@ -2579,18 +2614,77 @@ function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) } if ( ! empty( $files ) ) { - // The extension case may have changed above. - $new_ext = ! empty( $ext2 ) ? $ext2 : $ext; + $count = count( $files ); // Ensure this never goes into infinite loop // as it uses pathinfo() and regex in the check, but string replacement for the changes. - $count = count( $files ); - $i = 0; + $i = 0; while ( $i <= $count && _wp_check_existing_file_names( $filename, $files ) ) { $new_number = (int) $number + 1; - $filename = str_replace( array( "-{$number}{$new_ext}", "{$number}{$new_ext}" ), "-{$new_number}{$new_ext}", $filename ); - $number = $new_number; + + // If $ext is uppercase it was replaced with the lowercase version after the previous loop. + $filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename ); + + $number = $new_number; + $i++; + } + } + } + + // Check if an image will be converted after uploading or some existing images sub-sizes file names may conflict + // when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes. + if ( $is_image ) { + $output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type ); + $alt_types = array(); + + if ( ! empty( $output_formats[ $mime_type ] ) ) { + // The image will be converted to this format/mime type. + $alt_mime_type = $output_formats[ $mime_type ]; + + // Other types of images whose names may conflict if their sub-sizes are regenerated. + $alt_types = array_keys( array_intersect( $output_formats, array( $mime_type, $alt_mime_type ) ) ); + $alt_types[] = $alt_mime_type; + } elseif ( ! empty( $output_formats ) ) { + $alt_types = array_keys( array_intersect( $output_formats, array( $mime_type ) ) ); + } + + // Remove duplicates and the original mime type. It will be added later if needed. + $alt_types = array_unique( array_diff( $alt_types, array( $mime_type ) ) ); + + foreach ( $alt_types as $alt_type ) { + $alt_ext = wp_get_default_extension_for_mime_type( $alt_type ); + + if ( ! $alt_ext ) { + continue; + } + + $alt_ext = ".{$alt_ext}"; + $alt_filename = preg_replace( '|' . preg_quote( $lc_ext ) . '$|', $alt_ext, $filename ); + + $alt_filenames[ $alt_ext ] = $alt_filename; + } + + if ( ! empty( $alt_filenames ) ) { + // Add the original filename. It needs to be checked again together with the alternate filenames + // when $number is incremented. + $alt_filenames[ $lc_ext ] = $filename; + + // Ensure no infinite loop. + $i = 0; + + while ( $i <= $count && _wp_check_alternate_file_names( $alt_filenames, $_dir, $files ) ) { + $new_number = (int) $number + 1; + + foreach ( $alt_filenames as $alt_ext => $alt_filename ) { + $alt_filenames[ $alt_ext ] = str_replace( array( "-{$number}{$alt_ext}", "{$number}{$alt_ext}" ), "-{$new_number}{$alt_ext}", $alt_filename ); + } + + // Also update the $number in (the output) $filename. + // If the extension was uppercase it was already replaced with the lowercase version. + $filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename ); + + $number = $new_number; $i++; } } @@ -2601,13 +2695,42 @@ function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) * Filters the result when generating a unique file name. * * @since 4.5.0 + * @since 5.8.1 The `$alt_filenames` and `$number` parameters were added. * * @param string $filename Unique file name. * @param string $ext File extension, eg. ".png". * @param string $dir Directory path. * @param callable|null $unique_filename_callback Callback function that generates the unique file name. + * @param string[] $alt_filenames Array of alternate file names that were checked for collisions. + * @param int|string $number The highest number that was used to make the file name unique + * or an empty string if unused. */ - return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback ); + return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback, $alt_filenames, $number ); +} + +/** + * Helper function to test if each of an array of file names could conflict with existing files. + * + * @since 5.8.1 + * @access private + * + * @param string[] $filenames Array of file names to check. + * @param string $dir The directory containing the files. + * @param array $files An array of existing files in the directory. May be empty. + * @return bool True if the tested file name could match an existing file, false otherwise. + */ +function _wp_check_alternate_file_names( $filenames, $dir, $files ) { + foreach ( $filenames as $filename ) { + if ( file_exists( $dir . $filename ) ) { + return true; + } + + if ( ! empty( $files ) && _wp_check_existing_file_names( $filename, $files ) ) { + return true; + } + } + + return false; } /** @@ -2793,6 +2916,26 @@ function wp_ext2type( $ext ) { } } +/** + * Returns first matched extension for the mime-type, + * as mapped from wp_get_mime_types(). + * + * @since 5.8.1 + * + * @param string $mime_type + * + * @return string|false + */ +function wp_get_default_extension_for_mime_type( $mime_type ) { + $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) ); + + if ( empty( $extensions[0] ) ) { + return false; + } + + return $extensions[0]; +} + /** * Retrieve the file type from the file name. * @@ -3429,9 +3572,9 @@ function wp_die( $message = '', $title = '', $args = array() ) { * @param callable $function Callback function name. */ $function = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' ); - } elseif ( wp_is_jsonp_request() ) { + } elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST && wp_is_jsonp_request() ) { /** - * Filters the callback for killing WordPress execution for JSONP requests. + * Filters the callback for killing WordPress execution for JSONP REST requests. * * @since 5.2.0 * @@ -5709,6 +5852,10 @@ function iis7_supports_permalinks() { * @return int 0 means nothing is wrong, greater than 0 means something was wrong. */ function validate_file( $file, $allowed_files = array() ) { + if ( ! is_scalar( $file ) || '' === $file ) { + return 0; + } + // `../` on its own is not allowed: if ( '../' === $file ) { return 1; @@ -7486,6 +7633,10 @@ function wp_site_admin_email_change_notification( $old_email, $new_email, $optio * @return string The anonymized IP address. */ function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) { + if ( empty( $ip_addr ) ) { + return '0.0.0.0'; + } + // Detect what kind of IP address this is. $ip_prefix = ''; $is_ipv6 = substr_count( $ip_addr, ':' ) > 1; @@ -7984,8 +8135,9 @@ function get_dirsize( $directory, $max_execution_time = null ) { * @param string $directory Full path of a directory. * @param string|array $exclude Optional. Full path of a subdirectory to exclude from the total, * or array of paths. Expected without trailing slash(es). - * @param int $max_execution_time Maximum time to run before giving up. In seconds. The timeout is global - * and is measured from the moment WordPress started to load. + * @param int $max_execution_time Optional. Maximum time to run before giving up. In seconds. + * The timeout is global and is measured from the moment + * WordPress started to load. * @param array $directory_cache Optional. Array of cached directory paths. * * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout. @@ -8058,7 +8210,9 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul } } - if ( $max_execution_time > 0 && microtime( true ) - WP_START_TIMESTAMP > $max_execution_time ) { + if ( $max_execution_time > 0 && + ( microtime( true ) - WP_START_TIMESTAMP ) > $max_execution_time + ) { // Time exceeded. Give up instead of risking a fatal timeout. $size = null; break; @@ -8069,6 +8223,10 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul } } + if ( ! is_array( $directory_cache ) ) { + $directory_cache = array(); + } + $directory_cache[ $directory ] = $size; // Only write the transient on the top level call and not on recursive calls. @@ -8085,21 +8243,50 @@ function recurse_dirsize( $directory, $exclude = null, $max_execution_time = nul * Removes the current directory and all parent directories from the `dirsize_cache` transient. * * @since 5.6.0 + * @since 5.9.0 Added input validation with a notice for invalid input. * * @param string $path Full path of a directory or file. */ function clean_dirsize_cache( $path ) { + if ( ! is_string( $path ) || empty( $path ) ) { + trigger_error( + sprintf( + /* translators: 1: Function name, 2: A variable type, like "boolean" or "integer". */ + __( '%1$s only accepts a non-empty path string, received %2$s.' ), + 'clean_dirsize_cache()', + '' . gettype( $path ) . '' + ) + ); + return; + } + $directory_cache = get_transient( 'dirsize_cache' ); if ( empty( $directory_cache ) ) { return; } - $path = untrailingslashit( $path ); + if ( + strpos( $path, '/' ) === false && + strpos( $path, '\\' ) === false + ) { + unset( $directory_cache[ $path ] ); + set_transient( 'dirsize_cache', $directory_cache ); + return; + } + + $last_path = null; + $path = untrailingslashit( $path ); unset( $directory_cache[ $path ] ); - while ( DIRECTORY_SEPARATOR !== $path && '.' !== $path && '..' !== $path ) { - $path = dirname( $path ); + while ( + $last_path !== $path && + DIRECTORY_SEPARATOR !== $path && + '.' !== $path && + '..' !== $path + ) { + $last_path = $path; + $path = dirname( $path ); unset( $directory_cache[ $path ] ); } diff --git a/src/wp-includes/functions.wp-scripts.php b/src/wp-includes/functions.wp-scripts.php index abe930758dc18..82d36856724ac 100644 --- a/src/wp-includes/functions.wp-scripts.php +++ b/src/wp-includes/functions.wp-scripts.php @@ -186,7 +186,7 @@ function wp_register_script( $handle, $src, $deps = array(), $ver = false, $in_f /** * Localize a script. * - * Works only if the script has already been added. + * Works only if the script has already been registered. * * Accepts an associative array $l10n and creates a JavaScript object: * @@ -224,7 +224,7 @@ function wp_localize_script( $handle, $object_name, $l10n ) { /** * Sets translated strings for a script. * - * Works only if the script has already been added. + * Works only if the script has already been registered. * * @see WP_Scripts::set_translations() * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. @@ -402,7 +402,7 @@ function wp_script_is( $handle, $list = 'enqueued' ) { /** * Add metadata to a script. * - * Works only if the script has already been added. + * Works only if the script has already been registered. * * Possible values for $key and $value: * 'conditional' string Comments for IE 6, lte IE 7, etc. diff --git a/src/wp-includes/functions.wp-styles.php b/src/wp-includes/functions.wp-styles.php index e1749477cae82..d82bb559250d0 100644 --- a/src/wp-includes/functions.wp-styles.php +++ b/src/wp-includes/functions.wp-styles.php @@ -217,7 +217,7 @@ function wp_style_is( $handle, $list = 'enqueued' ) { /** * Add metadata to a CSS stylesheet. * - * Works only if the stylesheet has already been added. + * Works only if the stylesheet has already been registered. * * Possible values for $key and $value: * 'conditional' string Comments for IE 6, lte IE 7 etc. diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 41b0a174c03fa..4a9835a478f75 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -189,7 +189,7 @@ function get_template_part( $slug, $name = null, $args = array() ) { $templates[] = "{$slug}.php"; /** - * Fires before a template part is loaded. + * Fires before an attempt is made to locate and load a template part. * * @since 5.2.0 * @since 5.5.0 The `$args` parameter was added. @@ -576,25 +576,50 @@ function wp_login_form( $args = array() ) { */ $login_form_bottom = apply_filters( 'login_form_bottom', '', $args ); - $form = ' - - ' . $login_form_top . ' -

- - -

-

- - -

- ' . $login_form_middle . ' - ' . ( $args['remember'] ? '

' : '' ) . ' -

- - -

- ' . $login_form_bottom . ' - '; + $form = + sprintf( + '
', + esc_attr( $args['form_id'] ), + esc_url( site_url( 'wp-login.php', 'login_post' ) ) + ) . + $login_form_top . + sprintf( + '

+ + +

', + esc_attr( $args['id_username'] ), + esc_html( $args['label_username'] ), + esc_attr( $args['value_username'] ) + ) . + sprintf( + '

+ + +

', + esc_attr( $args['id_password'] ), + esc_html( $args['label_password'] ) + ) . + $login_form_middle . + ( $args['remember'] ? + sprintf( + '

', + esc_attr( $args['id_remember'] ), + ( $args['value_remember'] ? ' checked="checked"' : '' ), + esc_html( $args['label_remember'] ) + ) : '' + ) . + sprintf( + '

+ + +

', + esc_attr( $args['id_submit'] ), + esc_attr( $args['label_log_in'] ), + esc_url( $args['redirect'] ) + ) . + $login_form_bottom . + '
'; if ( $args['echo'] ) { echo $form; diff --git a/src/wp-includes/kses.php b/src/wp-includes/kses.php index 527d374c9cdeb..3a7f99dd1a998 100644 --- a/src/wp-includes/kses.php +++ b/src/wp-includes/kses.php @@ -271,6 +271,13 @@ 'lang' => true, 'xml:lang' => true, ), + 'object' => array( + 'data' => true, + 'type' => array( + 'required' => true, + 'values' => array( 'application/pdf' ), + ), + ), 'p' => array( 'align' => true, 'dir' => true, @@ -846,22 +853,26 @@ function wp_kses_one_attr( $string, $element ) { * * @param string|array $context The context for which to retrieve tags. Allowed values are 'post', * 'strip', 'data', 'entities', or the name of a field filter such as - * 'pre_user_description'. + * 'pre_user_description', or an array of allowed HTML elements and attributes. * @return array Array of allowed HTML tags and their allowed attributes. */ function wp_kses_allowed_html( $context = '' ) { global $allowedposttags, $allowedtags, $allowedentitynames; if ( is_array( $context ) ) { + // When `$context` is an array it's actually an array of allowed HTML elements and attributes. + $html = $context; + $context = 'explicit'; + /** * Filters the HTML tags that are allowed for a given context. * * @since 3.5.0 * - * @param array[]|string $context Context to judge allowed tags by. - * @param string $context_type Context name. + * @param array[] $html Allowed HTML tags. + * @param string $context Context name. */ - return apply_filters( 'wp_kses_allowed_html', $context, 'explicit' ); + return apply_filters( 'wp_kses_allowed_html', $html, $context ); } switch ( $context ) { @@ -1161,15 +1172,47 @@ function wp_kses_attr( $element, $attr, $allowed_html, $allowed_protocols ) { // Split it. $attrarr = wp_kses_hair( $attr, $allowed_protocols ); + // Check if there are attributes that are required. + $required_attrs = array_filter( + $allowed_html[ $element_low ], + function( $required_attr_limits ) { + return isset( $required_attr_limits['required'] ) && true === $required_attr_limits['required']; + } + ); + + // If a required attribute check fails, we can return nothing for a self-closing tag, + // but for a non-self-closing tag the best option is to return the element with attributes, + // as KSES doesn't handle matching the relevant closing tag. + $stripped_tag = ''; + if ( empty( $xhtml_slash ) ) { + $stripped_tag = "<$element>"; + } + // Go through $attrarr, and save the allowed attributes for this element // in $attr2. $attr2 = ''; foreach ( $attrarr as $arreach ) { + // Check if this attribute is required. + $required = isset( $required_attrs[ strtolower( $arreach['name'] ) ] ); + if ( wp_kses_attr_check( $arreach['name'], $arreach['value'], $arreach['whole'], $arreach['vless'], $element, $allowed_html ) ) { $attr2 .= ' ' . $arreach['whole']; + + // If this was a required attribute, we can mark it as found. + if ( $required ) { + unset( $required_attrs[ strtolower( $arreach['name'] ) ] ); + } + } elseif ( $required ) { + // This attribute was required, but didn't pass the check. The entire tag is not allowed. + return $stripped_tag; } } + // If some required attributes weren't set, the entire tag is not allowed. + if ( ! empty( $required_attrs ) ) { + return $stripped_tag; + } + // Remove any "<" or ">" characters. $attr2 = preg_replace( '/[<>]/', '', $attr2 ); @@ -1596,6 +1639,17 @@ function wp_kses_check_attr_val( $value, $vless, $checkname, $checkvalue ) { $ok = false; } break; + + case 'values': + /* + * The values check is used when you want to make sure that the attribute + * has one of the given values. + */ + + if ( false === array_search( strtolower( $value ), $checkvalue, true ) ) { + $ok = false; + } + break; } // End switch. return $ok; @@ -2148,6 +2202,16 @@ function kses_init() { * Filters an inline style attribute and removes disallowed rules. * * @since 2.8.1 + * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`. + * @since 4.6.0 Added support for `list-style-type`. + * @since 5.0.0 Added support for `background-image`. + * @since 5.1.0 Added support for `text-transform`. + * @since 5.2.0 Added support for `background-position` and `grid-template-columns`. + * @since 5.3.0 Added support for `grid`, `flex` and `column` layout properties. + * Extend `background-*` support of individual properties. + * @since 5.3.1 Added support for gradient backgrounds. + * @since 5.7.1 Added support for `object-position`. + * @since 5.8.0 Added support for `calc()` and `var()` values. * * @param string $css A string of CSS rules. * @param string $deprecated Not used. @@ -2166,19 +2230,9 @@ function safecss_filter_attr( $css, $deprecated = '' ) { $css_array = explode( ';', trim( $css ) ); /** - * Filters list of allowed CSS attributes. + * Filters the list of allowed CSS attributes. * * @since 2.8.1 - * @since 4.4.0 Added support for `min-height`, `max-height`, `min-width`, and `max-width`. - * @since 4.6.0 Added support for `list-style-type`. - * @since 5.0.0 Added support for `background-image`. - * @since 5.1.0 Added support for `text-transform`. - * @since 5.2.0 Added support for `background-position` and `grid-template-columns`. - * @since 5.3.0 Added support for `grid`, `flex` and `column` layout properties. - * Extend `background-*` support of individual properties. - * @since 5.3.1 Added support for gradient backgrounds. - * @since 5.7.1 Added support for `object-position`. - * @since 5.8.0 Added support for `calc()` and `var()` values. * * @param string[] $attr Array of allowed CSS attributes. */ diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php index 7699d92b1efc9..8347c226faa5c 100644 --- a/src/wp-includes/l10n.php +++ b/src/wp-includes/l10n.php @@ -191,7 +191,7 @@ function translate( $text, $domain = 'default' ) { /** * Filters text with its translation for a domain. * - * The dynamic portion of the hook, `$domain`, refers to the text domain. + * The dynamic portion of the hook name, `$domain`, refers to the text domain. * * @since 5.5.0 * @@ -259,7 +259,7 @@ function translate_with_gettext_context( $text, $context, $domain = 'default' ) /** * Filters text with its translation based on context information for a domain. * - * The dynamic portion of the hook, `$domain`, refers to the text domain. + * The dynamic portion of the hook name, `$domain`, refers to the text domain. * * @since 5.5.0 * @@ -482,7 +482,7 @@ function _n( $single, $plural, $number, $domain = 'default' ) { /** * Filters the singular or plural form of a string for a domain. * - * The dynamic portion of the hook, `$domain`, refers to the text domain. + * The dynamic portion of the hook name, `$domain`, refers to the text domain. * * @since 5.5.0 * @@ -542,7 +542,7 @@ function _nx( $single, $plural, $number, $context, $domain = 'default' ) { /** * Filters the singular or plural form of a string with gettext context for a domain. * - * The dynamic portion of the hook, `$domain`, refers to the text domain. + * The dynamic portion of the hook name, `$domain`, refers to the text domain. * * @since 5.5.0 * diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 340ddc3bb4883..6e7f66760f608 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -2085,6 +2085,7 @@ function _wp_post_thumbnail_class_filter_remove( $attr ) { * @since 2.6.0 * @since 3.9.0 The `class` attribute was added. * @since 5.1.0 The `caption_id` attribute was added. + * @since 5.9.0 The `$content` parameter default value changed from `null` to `''`. * * @param array $attr { * Attributes of the caption shortcode. @@ -2097,10 +2098,10 @@ function _wp_post_thumbnail_class_filter_remove( $attr ) { * @type string $caption The caption text. * @type string $class Additional class name(s) added to the caption container. * } - * @param string $content Shortcode content. + * @param string $content Optional. Shortcode content. Default empty string. * @return string HTML content to display the caption. */ -function img_caption_shortcode( $attr, $content = null ) { +function img_caption_shortcode( $attr, $content = '' ) { // New-style shortcode with the caption inside the shortcode with the link and image tags. if ( ! isset( $attr['caption'] ) ) { if ( preg_match( '#((?:
]+>\s*)?]+>(?:\s*)?)(.*)#is', $content, $matches ) ) { @@ -4455,7 +4456,7 @@ function wp_enqueue_media( $args = array() ) { 'allDates' => __( 'All dates' ), 'noItemsFound' => __( 'No items found.' ), 'insertIntoPost' => $post_type_object->labels->insert_into_item, - 'unattached' => __( 'Unattached' ), + 'unattached' => _x( 'Unattached', 'media items' ), 'mine' => _x( 'Mine', 'media items' ), 'trash' => _x( 'Trash', 'noun' ), 'uploadedToThisPost' => $post_type_object->labels->uploaded_to_this_item, diff --git a/src/wp-includes/meta.php b/src/wp-includes/meta.php index fc7d125fceab2..310b10f933250 100644 --- a/src/wp-includes/meta.php +++ b/src/wp-includes/meta.php @@ -56,7 +56,7 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = /** * Short-circuits adding metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -96,7 +96,7 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = /** * Fires immediately before meta of a specific type is added. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: @@ -134,7 +134,7 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = /** * Fires immediately after meta of a specific type is added. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: @@ -209,7 +209,7 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_ /** * Short-circuits updating metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -268,7 +268,7 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_ /** * Fires immediately before updating metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: @@ -314,7 +314,7 @@ function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_ /** * Fires immediately after updating metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: @@ -401,7 +401,7 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $ /** * Short-circuits deleting metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -456,7 +456,7 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $ /** * Fires immediately before deleting metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: @@ -506,7 +506,7 @@ function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $ /** * Fires immediately after deleting metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: @@ -608,7 +608,7 @@ function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal /** * Short-circuits the return value of a meta field. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -692,7 +692,7 @@ function get_metadata_default( $meta_type, $object_id, $meta_key, $single = fals /** * Filters the default metadata value for a specified meta key and object. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible filter names include: @@ -805,7 +805,7 @@ function get_metadata_by_mid( $meta_type, $meta_id ) { /** * Short-circuits the return value when fetching a meta field by meta ID. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -879,7 +879,7 @@ function update_metadata_by_mid( $meta_type, $meta_id, $meta_value, $meta_key = /** * Short-circuits updating metadata of a specific type by meta ID. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -1002,7 +1002,7 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) { /** * Short-circuits deleting metadata of a specific type by meta ID. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -1036,7 +1036,7 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) { /** * Fires immediately before deleting post or comment metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta + * The dynamic portion of the hook name, `$meta_type`, refers to the meta * object type (post or comment). * * Possible hook names include: @@ -1067,7 +1067,7 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) { /** * Fires immediately after deleting post or comment metadata of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta + * The dynamic portion of the hook name, `$meta_type`, refers to the meta * object type (post or comment). * * Possible hook names include: @@ -1128,7 +1128,7 @@ function update_meta_cache( $meta_type, $object_ids ) { /** * Short-circuits updating the metadata cache of a specific type. * - * The dynamic portion of the hook, `$meta_type`, refers to the meta object type + * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * Returning a non-null value will effectively short-circuit the function. * @@ -1774,7 +1774,7 @@ function get_object_subtype( $object_type, $object_id ) { /** * Filters the object subtype identifier for a non-standard object type. * - * The dynamic portion of the hook, `$object_type`, refers to the meta object type + * The dynamic portion of the hook name, `$object_type`, refers to the meta object type * (post, comment, term, user, or any other type with an associated meta table). * * Possible hook names include: diff --git a/src/wp-includes/ms-default-constants.php b/src/wp-includes/ms-default-constants.php index 7d794e32e6523..016ed437b7146 100644 --- a/src/wp-includes/ms-default-constants.php +++ b/src/wp-includes/ms-default-constants.php @@ -68,7 +68,8 @@ function ms_cookie_constants() { * @since 2.6.0 */ if ( ! defined( 'ADMIN_COOKIE_PATH' ) ) { - if ( ! is_subdomain_install() || trim( parse_url( get_option( 'siteurl' ), PHP_URL_PATH ), '/' ) ) { + $site_path = parse_url( get_option( 'siteurl' ), PHP_URL_PATH ); + if ( ! is_subdomain_install() || is_string( $site_path ) && trim( $site_path, '/' ) ) { define( 'ADMIN_COOKIE_PATH', SITECOOKIEPATH ); } else { define( 'ADMIN_COOKIE_PATH', SITECOOKIEPATH . 'wp-admin' ); diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index ec41b060ae6cf..6cc4e00b1ac7b 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -77,7 +77,10 @@ function get_option( $option, $default = false ) { global $wpdb; - $option = trim( $option ); + if ( is_scalar( $option ) ) { + $option = trim( $option ); + } + if ( empty( $option ) ) { return false; } @@ -378,7 +381,10 @@ function wp_load_core_site_options( $network_id = null ) { function update_option( $option, $value, $autoload = null ) { global $wpdb; - $option = trim( $option ); + if ( is_scalar( $option ) ) { + $option = trim( $option ); + } + if ( empty( $option ) ) { return false; } @@ -565,7 +571,10 @@ function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) _deprecated_argument( __FUNCTION__, '2.3.0' ); } - $option = trim( $option ); + if ( is_scalar( $option ) ) { + $option = trim( $option ); + } + if ( empty( $option ) ) { return false; } @@ -687,7 +696,10 @@ function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) function delete_option( $option ) { global $wpdb; - $option = trim( $option ); + if ( is_scalar( $option ) ) { + $option = trim( $option ); + } + if ( empty( $option ) ) { return false; } @@ -2238,6 +2250,8 @@ function register_initial_settings() { * Registers a setting and its data. * * @since 2.7.0 + * @since 3.0.0 The `misc` option group was deprecated. + * @since 3.5.0 The `privacy` option group was deprecated. * @since 4.7.0 `$args` can be passed to set flags on the setting, similar to `register_meta()`. * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`. * Please consider writing more inclusive code. @@ -2247,7 +2261,7 @@ function register_initial_settings() { * * @param string $option_group A settings group name. Should correspond to an allowed option key name. * Default allowed option key names include 'general', 'discussion', 'media', - * 'reading', 'writing', 'misc', 'options', and 'privacy'. + * 'reading', 'writing', and 'options'. * @param string $option_name The name of an option to sanitize and save. * @param array $args { * Data used to describe the setting when registered. diff --git a/src/wp-includes/pomo/entry.php b/src/wp-includes/pomo/entry.php index f0226dbc54a48..d30a4bda13e73 100644 --- a/src/wp-includes/pomo/entry.php +++ b/src/wp-includes/pomo/entry.php @@ -40,7 +40,7 @@ class Translation_Entry { * - references (array) -- places in the code this strings is used, in relative_to_root_path/file.php:linenum form * - flags (array) -- flags like php-format */ - function __construct( $args = array() ) { + public function __construct( $args = array() ) { // If no singular -- empty object. if ( ! isset( $args['singular'] ) ) { return; @@ -80,7 +80,7 @@ public function Translation_Entry( $args = array() ) { * * @return string|bool the key or false if the entry is empty */ - function key() { + public function key() { if ( null === $this->singular || '' === $this->singular ) { return false; } @@ -96,7 +96,7 @@ function key() { /** * @param object $other */ - function merge_with( &$other ) { + public function merge_with( &$other ) { $this->flags = array_unique( array_merge( $this->flags, $other->flags ) ); $this->references = array_unique( array_merge( $this->references, $other->references ) ); if ( $this->extracted_comments != $other->extracted_comments ) { diff --git a/src/wp-includes/pomo/mo.php b/src/wp-includes/pomo/mo.php index dce70c0f0fdc4..dcac16c6b34a3 100644 --- a/src/wp-includes/pomo/mo.php +++ b/src/wp-includes/pomo/mo.php @@ -37,7 +37,7 @@ public function get_filename() { * @param string $filename MO file to load * @return bool True if the import from file was successful, otherwise false. */ - function import_from_file( $filename ) { + public function import_from_file( $filename ) { $reader = new POMO_FileReader( $filename ); if ( ! $reader->is_resource() ) { @@ -53,7 +53,7 @@ function import_from_file( $filename ) { * @param string $filename * @return bool */ - function export_to_file( $filename ) { + public function export_to_file( $filename ) { $fh = fopen( $filename, 'wb' ); if ( ! $fh ) { return false; @@ -66,7 +66,7 @@ function export_to_file( $filename ) { /** * @return string|false */ - function export() { + public function export() { $tmp_fh = fopen( 'php://temp', 'r+' ); if ( ! $tmp_fh ) { return false; @@ -80,7 +80,7 @@ function export() { * @param Translation_Entry $entry * @return bool */ - function is_entry_good_for_export( $entry ) { + public function is_entry_good_for_export( $entry ) { if ( empty( $entry->translations ) ) { return false; } @@ -96,7 +96,7 @@ function is_entry_good_for_export( $entry ) { * @param resource $fh * @return true */ - function export_to_file_handle( $fh ) { + public function export_to_file_handle( $fh ) { $entries = array_filter( $this->entries, array( $this, 'is_entry_good_for_export' ) ); ksort( $entries ); $magic = 0x950412de; @@ -157,7 +157,7 @@ function export_to_file_handle( $fh ) { * @param Translation_Entry $entry * @return string */ - function export_original( $entry ) { + public function export_original( $entry ) { // TODO: Warnings for control characters. $exported = $entry->singular; if ( $entry->is_plural ) { @@ -173,7 +173,7 @@ function export_original( $entry ) { * @param Translation_Entry $entry * @return string */ - function export_translations( $entry ) { + public function export_translations( $entry ) { // TODO: Warnings for control characters. return $entry->is_plural ? implode( "\0", $entry->translations ) : $entry->translations[0]; } @@ -181,7 +181,7 @@ function export_translations( $entry ) { /** * @return string */ - function export_headers() { + public function export_headers() { $exported = ''; foreach ( $this->headers as $header => $value ) { $exported .= "$header: $value\n"; @@ -193,7 +193,7 @@ function export_headers() { * @param int $magic * @return string|false */ - function get_byteorder( $magic ) { + public function get_byteorder( $magic ) { // The magic is 0x950412de. // bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565 @@ -214,7 +214,7 @@ function get_byteorder( $magic ) { * @param POMO_FileReader $reader * @return bool True if the import was successful, otherwise false. */ - function import_from_reader( $reader ) { + public function import_from_reader( $reader ) { $endian_string = MO::get_byteorder( $reader->readint32() ); if ( false === $endian_string ) { return false; @@ -311,7 +311,7 @@ function import_from_reader( $reader ) { * 0x00 as a plural translations separator * @return Translation_Entry Entry instance. */ - function &make_entry( $original, $translation ) { + public function &make_entry( $original, $translation ) { $entry = new Translation_Entry(); // Look for context, separated by \4. $parts = explode( "\4", $original ); @@ -335,14 +335,14 @@ function &make_entry( $original, $translation ) { * @param int $count * @return string */ - function select_plural_form( $count ) { + public function select_plural_form( $count ) { return $this->gettext_select_plural_form( $count ); } /** * @return int */ - function get_plural_forms_count() { + public function get_plural_forms_count() { return $this->_nplurals; } } diff --git a/src/wp-includes/pomo/po.php b/src/wp-includes/pomo/po.php index 99bb6891b1040..667ff65567135 100644 --- a/src/wp-includes/pomo/po.php +++ b/src/wp-includes/pomo/po.php @@ -13,7 +13,15 @@ define( 'PO_MAX_LINE_LEN', 79 ); } -ini_set( 'auto_detect_line_endings', 1 ); +/* + * The `auto_detect_line_endings` setting has been deprecated in PHP 8.1, + * but will continue to work until PHP 9.0. + * For now, we're silencing the deprecation notice as there may still be + * translation files around which haven't been updated in a long time and + * which still use the old MacOS standalone `\r` as a line ending. + * This fix should be revisited when PHP 9.0 is in alpha/beta. + */ +@ini_set( 'auto_detect_line_endings', 1 ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged /** * Routines for working with PO files @@ -28,7 +36,7 @@ class PO extends Gettext_Translations { * * @return string msgid/msgstr PO entry for this PO file headers, doesn't contain newline at the end */ - function export_headers() { + public function export_headers() { $header_string = ''; foreach ( $this->headers as $header => $value ) { $header_string .= "$header: $value\n"; @@ -47,7 +55,7 @@ function export_headers() { * * @return string sequence of mgsgid/msgstr PO strings, doesn't containt newline at the end */ - function export_entries() { + public function export_entries() { // TODO: Sorting. return implode( "\n\n", array_map( array( 'PO', 'export_entry' ), $this->entries ) ); } @@ -58,7 +66,7 @@ function export_entries() { * @param bool $include_headers whether to include the headers in the export * @return string ready for inclusion in PO file string for headers and all the enrtries */ - function export( $include_headers = true ) { + public function export( $include_headers = true ) { $res = ''; if ( $include_headers ) { $res .= $this->export_headers(); @@ -75,7 +83,7 @@ function export( $include_headers = true ) { * @param bool $include_headers Whether to include the headers in the export. * @return bool true on success, false on error */ - function export_to_file( $filename, $include_headers = true ) { + public function export_to_file( $filename, $include_headers = true ) { $fh = fopen( $filename, 'w' ); if ( false === $fh ) { return false; @@ -95,7 +103,7 @@ function export_to_file( $filename, $include_headers = true ) { * * @param string $text Text to include as a comment. */ - function set_comment_before_headers( $text ) { + public function set_comment_before_headers( $text ) { $this->comments_before_headers = $text; } @@ -285,7 +293,7 @@ public static function match_begin_and_end_newlines( $translation, $original ) { * @param string $filename * @return bool */ - function import_from_file( $filename ) { + public function import_from_file( $filename ) { $f = fopen( $filename, 'r' ); if ( ! $f ) { return false; @@ -327,7 +335,7 @@ protected static function is_final( $context ) { * @param int $lineno * @return null|false|array */ - function read_entry( $f, $lineno = 0 ) { + public function read_entry( $f, $lineno = 0 ) { $entry = new Translation_Entry(); // Where were we in the last step. // Can be: comment, msgctxt, msgid, msgid_plural, msgstr, msgstr_plural. @@ -456,7 +464,7 @@ function read_entry( $f, $lineno = 0 ) { * @param string $action * @return bool */ - function read_line( $f, $action = 'read' ) { + public function read_line( $f, $action = 'read' ) { static $last_line = ''; static $use_last_line = false; if ( 'clear' === $action ) { @@ -478,7 +486,7 @@ function read_line( $f, $action = 'read' ) { * @param Translation_Entry $entry * @param string $po_comment_line */ - function add_comment_to_entry( &$entry, $po_comment_line ) { + public function add_comment_to_entry( &$entry, $po_comment_line ) { $first_two = substr( $po_comment_line, 0, 2 ); $comment = trim( substr( $po_comment_line, 2 ) ); if ( '#:' === $first_two ) { diff --git a/src/wp-includes/pomo/streams.php b/src/wp-includes/pomo/streams.php index a8a3755681640..e95dc1707670f 100644 --- a/src/wp-includes/pomo/streams.php +++ b/src/wp-includes/pomo/streams.php @@ -17,7 +17,7 @@ class POMO_Reader { /** * PHP5 constructor. */ - function __construct() { + public function __construct() { if ( function_exists( 'mb_substr' ) && ( (int) ini_get( 'mbstring.func_overload' ) & 2 ) // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated ) { @@ -46,7 +46,7 @@ public function POMO_Reader() { * * @param string $endian Set the endianness of the file. Accepts 'big', or 'little'. */ - function setEndian( $endian ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid + public function setEndian( $endian ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid $this->endian = $endian; } @@ -56,7 +56,7 @@ function setEndian( $endian ) { // phpcs:ignore WordPress.NamingConventions.Vali * @return mixed The integer, corresponding to the next 32 bits from * the stream of false if there are not enough bytes or on error */ - function readint32() { + public function readint32() { $bytes = $this->read( 4 ); if ( 4 != $this->strlen( $bytes ) ) { return false; @@ -73,7 +73,7 @@ function readint32() { * @return mixed Array of integers or false if there isn't * enough data or on error */ - function readint32array( $count ) { + public function readint32array( $count ) { $bytes = $this->read( 4 * $count ); if ( 4 * $count != $this->strlen( $bytes ) ) { return false; @@ -88,7 +88,7 @@ function readint32array( $count ) { * @param int $length * @return string */ - function substr( $string, $start, $length ) { + public function substr( $string, $start, $length ) { if ( $this->is_overloaded ) { return mb_substr( $string, $start, $length, 'ascii' ); } else { @@ -100,7 +100,7 @@ function substr( $string, $start, $length ) { * @param string $string * @return int */ - function strlen( $string ) { + public function strlen( $string ) { if ( $this->is_overloaded ) { return mb_strlen( $string, 'ascii' ); } else { @@ -113,7 +113,7 @@ function strlen( $string ) { * @param int $chunk_size * @return array */ - function str_split( $string, $chunk_size ) { + public function str_split( $string, $chunk_size ) { if ( ! function_exists( 'str_split' ) ) { $length = $this->strlen( $string ); $out = array(); @@ -129,21 +129,21 @@ function str_split( $string, $chunk_size ) { /** * @return int */ - function pos() { + public function pos() { return $this->_pos; } /** * @return true */ - function is_resource() { + public function is_resource() { return true; } /** * @return true */ - function close() { + public function close() { return true; } } @@ -155,7 +155,7 @@ class POMO_FileReader extends POMO_Reader { /** * @param string $filename */ - function __construct( $filename ) { + public function __construct( $filename ) { parent::__construct(); $this->_f = fopen( $filename, 'rb' ); } @@ -176,7 +176,7 @@ public function POMO_FileReader( $filename ) { * @param int $bytes * @return string|false Returns read string, otherwise false. */ - function read( $bytes ) { + public function read( $bytes ) { return fread( $this->_f, $bytes ); } @@ -184,7 +184,7 @@ function read( $bytes ) { * @param int $pos * @return bool */ - function seekto( $pos ) { + public function seekto( $pos ) { if ( -1 == fseek( $this->_f, $pos, SEEK_SET ) ) { return false; } @@ -195,28 +195,28 @@ function seekto( $pos ) { /** * @return bool */ - function is_resource() { + public function is_resource() { return is_resource( $this->_f ); } /** * @return bool */ - function feof() { + public function feof() { return feof( $this->_f ); } /** * @return bool */ - function close() { + public function close() { return fclose( $this->_f ); } /** * @return string */ - function read_all() { + public function read_all() { $all = ''; while ( ! $this->feof() ) { $all .= $this->read( 4096 ); @@ -238,7 +238,7 @@ class POMO_StringReader extends POMO_Reader { /** * PHP5 constructor. */ - function __construct( $str = '' ) { + public function __construct( $str = '' ) { parent::__construct(); $this->_str = $str; $this->_pos = 0; @@ -260,7 +260,7 @@ public function POMO_StringReader( $str = '' ) { * @param string $bytes * @return string */ - function read( $bytes ) { + public function read( $bytes ) { $data = $this->substr( $this->_str, $this->_pos, $bytes ); $this->_pos += $bytes; if ( $this->strlen( $this->_str ) < $this->_pos ) { @@ -273,7 +273,7 @@ function read( $bytes ) { * @param int $pos * @return int */ - function seekto( $pos ) { + public function seekto( $pos ) { $this->_pos = $pos; if ( $this->strlen( $this->_str ) < $this->_pos ) { $this->_pos = $this->strlen( $this->_str ); @@ -284,14 +284,14 @@ function seekto( $pos ) { /** * @return int */ - function length() { + public function length() { return $this->strlen( $this->_str ); } /** * @return string */ - function read_all() { + public function read_all() { return $this->substr( $this->_str, $this->_pos, $this->strlen( $this->_str ) ); } @@ -306,7 +306,7 @@ class POMO_CachedFileReader extends POMO_StringReader { /** * PHP5 constructor. */ - function __construct( $filename ) { + public function __construct( $filename ) { parent::__construct(); $this->_str = file_get_contents( $filename ); if ( false === $this->_str ) { @@ -348,7 +348,7 @@ public function __construct( $filename ) { * * @see POMO_CachedIntFileReader::__construct() */ - function POMO_CachedIntFileReader( $filename ) { + public function POMO_CachedIntFileReader( $filename ) { _deprecated_constructor( self::class, '5.4.0', static::class ); self::__construct( $filename ); } diff --git a/src/wp-includes/pomo/translations.php b/src/wp-includes/pomo/translations.php index d93c6528f441e..0df56ad4fee8e 100644 --- a/src/wp-includes/pomo/translations.php +++ b/src/wp-includes/pomo/translations.php @@ -21,7 +21,7 @@ class Translations { * @param array|Translation_Entry $entry * @return bool true on success, false if the entry doesn't have a key */ - function add_entry( $entry ) { + public function add_entry( $entry ) { if ( is_array( $entry ) ) { $entry = new Translation_Entry( $entry ); } @@ -37,7 +37,7 @@ function add_entry( $entry ) { * @param array|Translation_Entry $entry * @return bool */ - function add_entry_or_merge( $entry ) { + public function add_entry_or_merge( $entry ) { if ( is_array( $entry ) ) { $entry = new Translation_Entry( $entry ); } @@ -63,14 +63,14 @@ function add_entry_or_merge( $entry ) { * @param string $header header name, without trailing : * @param string $value header value, without trailing \n */ - function set_header( $header, $value ) { + public function set_header( $header, $value ) { $this->headers[ $header ] = $value; } /** * @param array $headers */ - function set_headers( $headers ) { + public function set_headers( $headers ) { foreach ( $headers as $header => $value ) { $this->set_header( $header, $value ); } @@ -79,14 +79,14 @@ function set_headers( $headers ) { /** * @param string $header */ - function get_header( $header ) { + public function get_header( $header ) { return isset( $this->headers[ $header ] ) ? $this->headers[ $header ] : false; } /** * @param Translation_Entry $entry */ - function translate_entry( &$entry ) { + public function translate_entry( &$entry ) { $key = $entry->key(); return isset( $this->entries[ $key ] ) ? $this->entries[ $key ] : false; } @@ -96,7 +96,7 @@ function translate_entry( &$entry ) { * @param string $context * @return string */ - function translate( $singular, $context = null ) { + public function translate( $singular, $context = null ) { $entry = new Translation_Entry( array( 'singular' => $singular, @@ -118,14 +118,14 @@ function translate( $singular, $context = null ) { * * @param int $count number of items */ - function select_plural_form( $count ) { + public function select_plural_form( $count ) { return 1 == $count ? 0 : 1; } /** * @return int */ - function get_plural_forms_count() { + public function get_plural_forms_count() { return 2; } @@ -135,7 +135,7 @@ function get_plural_forms_count() { * @param int $count * @param string $context */ - function translate_plural( $singular, $plural, $count, $context = null ) { + public function translate_plural( $singular, $plural, $count, $context = null ) { $entry = new Translation_Entry( array( 'singular' => $singular, @@ -161,7 +161,7 @@ function translate_plural( $singular, $plural, $count, $context = null ) { * @param Object $other Another Translation object, whose translations will be merged in this one (passed by reference). * @return void */ - function merge_with( &$other ) { + public function merge_with( &$other ) { foreach ( $other->entries as $entry ) { $this->entries[ $entry->key() ] = $entry; } @@ -170,7 +170,7 @@ function merge_with( &$other ) { /** * @param object $other */ - function merge_originals_with( &$other ) { + public function merge_originals_with( &$other ) { foreach ( $other->entries as $entry ) { if ( ! isset( $this->entries[ $entry->key() ] ) ) { $this->entries[ $entry->key() ] = $entry; @@ -190,7 +190,7 @@ class Gettext_Translations extends Translations { * * @param int $count */ - function gettext_select_plural_form( $count ) { + public function gettext_select_plural_form( $count ) { if ( ! isset( $this->_gettext_select_plural_form ) || is_null( $this->_gettext_select_plural_form ) ) { list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header( $this->get_header( 'Plural-Forms' ) ); $this->_nplurals = $nplurals; @@ -203,7 +203,7 @@ function gettext_select_plural_form( $count ) { * @param string $header * @return array */ - function nplurals_and_expression_from_header( $header ) { + public function nplurals_and_expression_from_header( $header ) { if ( preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches ) ) { $nplurals = (int) $matches[1]; $expression = trim( $matches[2] ); @@ -220,7 +220,7 @@ function nplurals_and_expression_from_header( $header ) { * @param int $nplurals * @param string $expression */ - function make_plural_form_function( $nplurals, $expression ) { + public function make_plural_form_function( $nplurals, $expression ) { try { $handler = new Plural_Forms( rtrim( $expression, ';' ) ); return array( $handler, 'get' ); @@ -237,7 +237,7 @@ function make_plural_form_function( $nplurals, $expression ) { * @param string $expression the expression without parentheses * @return string the expression with parentheses added */ - function parenthesize_plural_exression( $expression ) { + public function parenthesize_plural_exression( $expression ) { $expression .= ';'; $res = ''; $depth = 0; @@ -266,7 +266,7 @@ function parenthesize_plural_exression( $expression ) { * @param string $translation * @return array */ - function make_headers( $translation ) { + public function make_headers( $translation ) { $headers = array(); // Sometimes \n's are used instead of real new lines. $translation = str_replace( '\n', "\n", $translation ); @@ -285,7 +285,7 @@ function make_headers( $translation ) { * @param string $header * @param string $value */ - function set_header( $header, $value ) { + public function set_header( $header, $value ) { parent::set_header( $header, $value ); if ( 'Plural-Forms' === $header ) { list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header( $this->get_header( 'Plural-Forms' ) ); @@ -304,7 +304,7 @@ class NOOP_Translations { public $entries = array(); public $headers = array(); - function add_entry( $entry ) { + public function add_entry( $entry ) { return true; } @@ -312,20 +312,20 @@ function add_entry( $entry ) { * @param string $header * @param string $value */ - function set_header( $header, $value ) { + public function set_header( $header, $value ) { } /** * @param array $headers */ - function set_headers( $headers ) { + public function set_headers( $headers ) { } /** * @param string $header * @return false */ - function get_header( $header ) { + public function get_header( $header ) { return false; } @@ -333,7 +333,7 @@ function get_header( $header ) { * @param Translation_Entry $entry * @return false */ - function translate_entry( &$entry ) { + public function translate_entry( &$entry ) { return false; } @@ -341,7 +341,7 @@ function translate_entry( &$entry ) { * @param string $singular * @param string $context */ - function translate( $singular, $context = null ) { + public function translate( $singular, $context = null ) { return $singular; } @@ -349,14 +349,14 @@ function translate( $singular, $context = null ) { * @param int $count * @return bool */ - function select_plural_form( $count ) { + public function select_plural_form( $count ) { return 1 == $count ? 0 : 1; } /** * @return int */ - function get_plural_forms_count() { + public function get_plural_forms_count() { return 2; } @@ -366,14 +366,14 @@ function get_plural_forms_count() { * @param int $count * @param string $context */ - function translate_plural( $singular, $plural, $count, $context = null ) { + public function translate_plural( $singular, $plural, $count, $context = null ) { return 1 == $count ? $singular : $plural; } /** * @param object $other */ - function merge_with( &$other ) { + public function merge_with( &$other ) { } } endif; diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 3ec68625a5f08..0f75bf537e246 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -949,7 +949,7 @@ function get_post_mime_type( $post = null ) { * * @since 2.0.0 * - * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post.. + * @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post. * @return string|false Post status on success, false on failure. */ function get_post_status( $post = null ) { @@ -1077,7 +1077,7 @@ function _wp_privacy_statuses() { * * @since 3.0.0 * - * @global array $wp_post_statuses Inserts new post status object into the list + * @global stdClass[] $wp_post_statuses Inserts new post status object into the list * * @param string $post_status Name of the post status. * @param array|string $args { @@ -1201,12 +1201,12 @@ function register_post_status( $post_status, $args = array() ) { * * @since 3.0.0 * - * @global array $wp_post_statuses List of post statuses. + * @global stdClass[] $wp_post_statuses List of post statuses. * * @see register_post_status() * * @param string $post_status The name of a registered post status. - * @return object|null A post status object. + * @return stdClass|null A post status object. */ function get_post_status_object( $post_status ) { global $wp_post_statuses; @@ -1223,7 +1223,7 @@ function get_post_status_object( $post_status ) { * * @since 3.0.0 * - * @global array $wp_post_statuses List of post statuses. + * @global stdClass[] $wp_post_statuses List of post statuses. * * @see register_post_status() * @@ -1371,6 +1371,7 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) * arguments to register the post type in REST API. * @since 5.0.0 The `template` and `template_lock` arguments were added. * @since 5.3.0 The `supports` argument will now accept an array of arguments for a feature. + * @since 5.9.0 The `rest_namespace` argument was added. * * @global array $wp_post_types List of post types. * @@ -1418,6 +1419,7 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) * @type bool $show_in_rest Whether to include the post type in the REST API. Set this to true * for the post type to be available in the block editor. * @type string $rest_base To change the base URL of REST API route. Default is $post_type. + * @type string $rest_namespace To change the namespace URL of REST API route. Default is wp/v2. * @type string $rest_controller_class REST API controller class name. Default is 'WP_REST_Posts_Controller'. * @type int $menu_position The position in the menu order the post type should appear. To work, * $show_in_menu must be true. Default null (at the bottom). @@ -2817,7 +2819,7 @@ function _count_posts_cache_key( $type = 'post', $perm = '' ) { * * @param string $type Optional. Post type to retrieve count. Default 'post'. * @param string $perm Optional. 'readable' or empty. Default empty. - * @return object Number of posts for each status. + * @return stdClass Number of posts for each status. */ function wp_count_posts( $type = 'post', $perm = '' ) { global $wpdb; @@ -2870,11 +2872,11 @@ function wp_count_posts( $type = 'post', $perm = '' ) { * * @since 3.7.0 * - * @param object $counts An object containing the current post_type's post - * counts by status. - * @param string $type Post type. - * @param string $perm The permission to determine if the posts are 'readable' - * by the current user. + * @param stdClass $counts An object containing the current post_type's post + * counts by status. + * @param string $type Post type. + * @param string $perm The permission to determine if the posts are 'readable' + * by the current user. */ return apply_filters( 'wp_count_posts', $counts, $type, $perm ); } @@ -2893,7 +2895,7 @@ function wp_count_posts( $type = 'post', $perm = '' ) { * * @param string|string[] $mime_type Optional. Array or comma-separated list of * MIME patterns. Default empty. - * @return object An object containing the attachment counts by mime type. + * @return stdClass An object containing the attachment counts by mime type. */ function wp_count_attachments( $mime_type = '' ) { global $wpdb; @@ -2912,7 +2914,7 @@ function wp_count_attachments( $mime_type = '' ) { * * @since 3.7.0 * - * @param object $counts An object containing the attachment counts by + * @param stdClass $counts An object containing the attachment counts by * mime type. * @param string|string[] $mime_type Array or comma-separated list of MIME patterns. */ @@ -2939,7 +2941,7 @@ function get_post_mime_types() { ), ), 'audio' => array( - __( 'Audio' ), + _x( 'Audio', 'file type group' ), __( 'Manage Audio' ), /* translators: %s: Number of audio files. */ _n_noop( @@ -2948,7 +2950,7 @@ function get_post_mime_types() { ), ), 'video' => array( - __( 'Video' ), + _x( 'Video', 'file type group' ), __( 'Manage Video' ), /* translators: %s: Number of video files. */ _n_noop( @@ -3823,7 +3825,14 @@ function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) { * @type int[] $post_category Array of category IDs. * Defaults to value of the 'default_category' option. * @type array $tags_input Array of tag names, slugs, or IDs. Default empty. - * @type array $tax_input Array of taxonomy terms keyed by their taxonomy name. Default empty. + * @type array $tax_input An array of taxonomy terms keyed by their taxonomy name. + * If the taxonomy is hierarchical, the term list needs to be + * either an array of term IDs or a comma-separated string of IDs. + * If the taxonomy is non-hierarchical, the term list can be an array + * that contains term names or slugs, or a comma-separated string + * of names or slugs. This is because, in hierarchical taxonomy, + * child terms can have the same names with different parent terms, + * so the only way to connect them is using ID. Default empty. * @type array $meta_input Array of post meta values keyed by their post meta key. Default empty. * } * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. @@ -5112,6 +5121,12 @@ function wp_transition_post_status( $new_status, $old_status, $post ) { * The dynamic portions of the hook name, `$new_status` and `$old_status`, * refer to the old and new post statuses, respectively. * + * Possible hook names include: + * + * - `draft_to_publish` + * - `publish_to_trash` + * - `pending_to_draft` + * * @since 2.3.0 * * @param WP_Post $post Post object. @@ -5500,6 +5515,8 @@ function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) { if ( $foundid ) { return get_post( $foundid, $output ); } + + return null; } /** @@ -5557,6 +5574,8 @@ function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) if ( $page ) { return get_post( $page, $output ); } + + return null; } /** @@ -6152,7 +6171,7 @@ function wp_delete_attachment( $post_id, $force_delete = false ) { $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true ); $file = get_attached_file( $post_id ); - if ( is_multisite() ) { + if ( is_multisite() && is_string( $file ) && ! empty( $file ) ) { clean_dirsize_cache( $file ); } diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index 7480fd5c648aa..03860a915cef8 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -1091,7 +1091,7 @@ function rest_application_password_collect_status( $user_or_error, $app_password * * @global string|null $wp_rest_application_password_uuid * - * @return string|null The App Password UUID, or null if Application Passwords was not used. + * @return string|null The Application Password UUID, or null if Application Passwords was not used. */ function rest_get_authenticated_app_password() { global $wp_rest_application_password_uuid; @@ -2635,6 +2635,7 @@ function rest_validate_integer_value_from_schema( $value, $args, $param ) { * @since 4.7.0 * @since 5.5.0 Added the `$param` parameter. * @since 5.6.0 Support the "anyOf" and "oneOf" keywords. + * @since 5.9.0 Added `text-field` and `textarea-field` formats. * * @param mixed $value The value to sanitize. * @param array $args Schema array to use for sanitization. @@ -2777,6 +2778,12 @@ function rest_sanitize_value_from_schema( $value, $args, $param = '' ) { case 'uuid': return sanitize_text_field( $value ); + + case 'text-field': + return sanitize_text_field( $value ); + + case 'textarea-field': + return sanitize_textarea_field( $value ); } } @@ -2818,6 +2825,11 @@ function rest_preload_api_request( $memo, $path ) { } } + $path = untrailingslashit( $path ); + if ( empty( $path ) ) { + $path = '/'; + } + $path_parts = parse_url( $path ); if ( false === $path_parts ) { return $memo; @@ -3037,24 +3049,12 @@ function rest_get_route_for_post( $post ) { return ''; } - $post_type = get_post_type_object( $post->post_type ); - if ( ! $post_type ) { - return ''; - } - - $controller = $post_type->get_rest_controller(); - if ( ! $controller ) { + $post_type_route = rest_get_route_for_post_type_items( $post->post_type ); + if ( ! $post_type_route ) { return ''; } - $route = ''; - - // The only two controllers that we can detect are the Attachments and Posts controllers. - if ( in_array( get_class( $controller ), array( 'WP_REST_Attachments_Controller', 'WP_REST_Posts_Controller' ), true ) ) { - $namespace = 'wp/v2'; - $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; - $route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $post->ID ); - } + $route = sprintf( '%s/%d', $post_type_route, $post->ID ); /** * Filters the REST API route for a post. @@ -3067,6 +3067,39 @@ function rest_get_route_for_post( $post ) { return apply_filters( 'rest_route_for_post', $route, $post ); } +/** + * Gets the REST API route for a post type. + * + * @since 5.9.0 + * + * @param string $post_type The name of a registered post type. + * @return string The route path with a leading slash for the given post type, or an empty string if there is not a route. + */ +function rest_get_route_for_post_type_items( $post_type ) { + $post_type = get_post_type_object( $post_type ); + if ( ! $post_type ) { + return ''; + } + + if ( ! $post_type->show_in_rest ) { + return ''; + } + + $namespace = ! empty( $post_type->rest_namespace ) ? $post_type->rest_namespace : 'wp/v2'; + $rest_base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; + $route = sprintf( '/%s/%s', $namespace, $rest_base ); + + /** + * Filters the REST API route for a post type. + * + * @since 5.9.0 + * + * @param string $route The route path. + * @param WP_Post_Type $post_type The post type object. + */ + return apply_filters( 'rest_route_for_post_type_items', $route, $post_type ); +} + /** * Gets the REST API route for a term. * @@ -3082,24 +3115,12 @@ function rest_get_route_for_term( $term ) { return ''; } - $taxonomy = get_taxonomy( $term->taxonomy ); - if ( ! $taxonomy ) { - return ''; - } - - $controller = $taxonomy->get_rest_controller(); - if ( ! $controller ) { + $taxonomy_route = rest_get_route_for_taxonomy_items( $term->taxonomy ); + if ( ! $taxonomy_route ) { return ''; } - $route = ''; - - // The only controller that works is the Terms controller. - if ( $controller instanceof WP_REST_Terms_Controller ) { - $namespace = 'wp/v2'; - $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; - $route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $term->term_id ); - } + $route = sprintf( '%s/%d', $taxonomy_route, $term->term_id ); /** * Filters the REST API route for a term. @@ -3112,6 +3133,39 @@ function rest_get_route_for_term( $term ) { return apply_filters( 'rest_route_for_term', $route, $term ); } +/** + * Gets the REST API route for a taxonomy. + * + * @since 5.9.0 + * + * @param string $taxonomy Name of taxonomy. + * @return string The route path with a leading slash for the given taxonomy. + */ +function rest_get_route_for_taxonomy_items( $taxonomy ) { + $taxonomy = get_taxonomy( $taxonomy ); + if ( ! $taxonomy ) { + return ''; + } + + if ( ! $taxonomy->show_in_rest ) { + return ''; + } + + $namespace = ! empty( $taxonomy->rest_namespace ) ? $taxonomy->rest_namespace : 'wp/v2'; + $rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; + $route = sprintf( '/%s/%s', $namespace, $rest_base ); + + /** + * Filters the REST API route for a taxonomy. + * + * @since 5.9.0 + * + * @param string $route The route path. + * @param WP_Taxonomy $taxonomy The taxonomy object. + */ + return apply_filters( 'rest_route_for_taxonomy_items', $route, $taxonomy ); +} + /** * Gets the REST route for the currently queried object. * @@ -3222,7 +3276,7 @@ function rest_get_endpoint_args_for_schema( $schema, $method = WP_REST_Server::C function rest_convert_error_to_response( $error ) { $status = array_reduce( $error->get_all_error_data(), - function ( $status, $error_data ) { + static function ( $status, $error_data ) { return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status; }, 500 diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index 490b057c24c75..3585aa7656b5e 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -497,6 +497,7 @@ public function serve_request( $path = null ) { $json_error_message = $this->get_json_last_error(); if ( $json_error_message ) { + $this->set_status( 500 ); $json_error_obj = new WP_Error( 'rest_encode_error', $json_error_message, @@ -1077,8 +1078,8 @@ protected function match_request_to_handler( $request ) { * @since 5.6.0 * * @param WP_REST_Request $request The request object. - * @param array $handler The matched route handler. * @param string $route The matched route regex. + * @param array $handler The matched route handler. * @param WP_Error|null $response The current error object if any. * @return WP_REST_Response */ @@ -1287,7 +1288,7 @@ protected function add_site_logo_to_index( WP_REST_Response $response ) { if ( $site_logo_id ) { $response->add_link( 'https://api.w.org/featuredmedia', - rest_url( 'wp/v2/media/' . $site_logo_id ), + rest_url( rest_get_route_for_post( $site_logo_id ) ), array( 'embeddable' => true, ) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php index ecdc221b5fcbc..bdf1959c623b3 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-application-passwords-controller.php @@ -356,7 +356,7 @@ public function update_item( $request ) { } /** - * Checks if a given request has access to delete all application passwords. + * Checks if a given request has access to delete all application passwords for a user. * * @since 5.6.0 * @@ -382,7 +382,7 @@ public function delete_items_permissions_check( $request ) { } /** - * Deletes all application passwords. + * Deletes all application passwords for a user. * * @since 5.6.0 * @@ -411,7 +411,7 @@ public function delete_items( $request ) { } /** - * Checks if a given request has access to delete a specific application password. + * Checks if a given request has access to delete a specific application password for a user. * * @since 5.6.0 * @@ -437,7 +437,7 @@ public function delete_item_permissions_check( $request ) { } /** - * Deletes one application password. + * Deletes an application password for a user. * * @since 5.6.0 * @@ -474,7 +474,7 @@ public function delete_item( $request ) { } /** - * Checks if a given request has access to get the currently used application password. + * Checks if a given request has access to get the currently used application password for a user. * * @since 5.7.0 * @@ -500,7 +500,7 @@ public function get_current_item_permissions_check( $request ) { } /** - * Retrieves the application password being currently used for authentication. + * Retrieves the application password being currently used for authentication of a user. * * @since 5.7.0 * @@ -723,7 +723,7 @@ protected function get_user( $request ) { } /** - * Gets the requested application password. + * Gets the requested application password for a user. * * @since 5.6.0 * diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index 3519b0ad2b50a..ad6a89b234c8f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -707,12 +707,15 @@ protected function prepare_item_for_database( $request ) { * Prepares a single attachment output for response. * * @since 4.7.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post Attachment object. + * @param WP_Post $item Attachment object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $post, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $post = $item; $response = parent::prepare_item_for_response( $post, $request ); $fields = $this->get_fields_for_response( $request ); $data = $response->get_data(); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php index 5f90b4640168d..0a2cf5d49b4b1 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php @@ -67,8 +67,8 @@ public function __construct( $parent_post_type ) { $this->parent_controller = $parent_controller; $this->revisions_controller = new WP_REST_Revisions_Controller( $parent_post_type ); - $this->namespace = 'wp/v2'; $this->rest_base = 'autosaves'; + $this->namespace = ! empty( $post_type_object->rest_namespace ) ? $post_type_object->rest_namespace : 'wp/v2'; $this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; } @@ -396,13 +396,15 @@ public function create_post_autosave( $post_data ) { * Prepares the revision for the REST response. * * @since 5.0.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post Post revision object. + * @param WP_Post $item Post revision object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $post, $request ) { - + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $post = $item; $response = $this->revisions_controller->prepare_item_for_response( $post, $request ); $fields = $this->get_fields_for_response( $request ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php index 2f275072ed6a3..d054a814d4a9f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-directory-controller.php @@ -109,12 +109,16 @@ public function get_items( $request ) { * Parse block metadata for a block, and prepare it for an API repsonse. * * @since 5.5.0 + * @since 5.9.0 Renamed `$plugin` to `$item` to match parent class for PHP 8 named parameter support. * - * @param array $plugin The plugin metadata. + * @param array $item The plugin metadata. * @param WP_REST_Request $request Request object. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ - public function prepare_item_for_response( $plugin, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $plugin = $item; + // There might be multiple blocks in a plugin. Only the first block is mapped. $block_data = reset( $plugin['blocks'] ); @@ -270,7 +274,7 @@ public function get_item_schema() { 'context' => array( 'view' ), ), 'last_updated' => array( - 'description' => __( 'The date when the block was last updated, in fuzzy human readable format.' ), + 'description' => __( 'The date when the block was last updated.' ), 'type' => 'string', 'format' => 'date-time', 'context' => array( 'view' ), diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php index 4a1c07764bb1e..c546a3082a3d4 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php @@ -236,15 +236,17 @@ public function get_item( $request ) { * Prepares a block type object for serialization. * * @since 5.5.0 + * @since 5.9.0 Renamed `$block_type` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Block_Type $block_type Block type data. - * @param WP_REST_Request $request Full details about the request. + * @param WP_Block_Type $item Block type data. + * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Block type data. */ - public function prepare_item_for_response( $block_type, $request ) { - - $fields = $this->get_fields_for_response( $request ); - $data = array(); + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $block_type = $item; + $fields = $this->get_fields_for_response( $request ); + $data = array(); if ( rest_is_field_included( 'attributes', $fields ) ) { $data['attributes'] = $block_type->get_attributes(); @@ -524,7 +526,7 @@ public function get_item_schema() { 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), - 'view_script' => array( + 'view_script' => array( 'description' => __( 'Public facing script handle.' ), 'type' => array( 'string', 'null' ), 'default' => null, diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index 1845e7bd94b77..6e2daa829a508 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -1028,15 +1028,17 @@ public function delete_item( $request ) { * Prepares a single comment output for response. * * @since 4.7.0 + * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Comment $comment Comment object. + * @param WP_Comment $item Comment object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $comment, $request ) { - - $fields = $this->get_fields_for_response( $request ); - $data = array(); + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $comment = $item; + $fields = $this->get_fields_for_response( $request ); + $data = array(); if ( in_array( 'id', $fields, true ) ) { $data['id'] = (int) $comment->comment_ID; diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php index b1cb4be457456..b3f41c6a6a039 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php @@ -597,7 +597,7 @@ public function get_fields_for_response( $request ) { // Return the list of all requested fields which appear in the schema. return array_reduce( $requested_fields, - function( $response_fields, $field ) use ( $fields ) { + static function( $response_fields, $field ) use ( $fields ) { if ( in_array( $field, $fields, true ) ) { $response_fields[] = $field; return $response_fields; diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php index e79a1615eafc1..0c26c20ae0c53 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php @@ -199,12 +199,15 @@ public function get_items( $request ) { * Prepare a raw pattern before it's output in an API response. * * @since 5.8.0 + * @since 5.9.0 Renamed `$raw_pattern` to `$item` to match parent class for PHP 8 named parameter support. * - * @param object $raw_pattern A pattern from api.wordpress.org, before any changes. - * @param WP_REST_Request $request Request object. + * @param object $item Raw pattern from api.wordpress.org, before any changes. + * @param WP_REST_Request $request Request object. * @return WP_REST_Response */ - public function prepare_item_for_response( $raw_pattern, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $raw_pattern = $item; $prepared_pattern = array( 'id' => absint( $raw_pattern->id ), 'title' => sanitize_text_field( $raw_pattern->title->rendered ), diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php index 3a7bf0ff95b32..4da8e7aa18d9a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php @@ -381,7 +381,7 @@ public function create_item( $request ) { $installed_locales = apply_filters( 'plugins_update_check_locales', $installed_locales ); $language_packs = array_map( - function( $item ) { + static function( $item ) { return (object) $item; }, $api->language_packs @@ -389,7 +389,7 @@ function( $item ) { $language_packs = array_filter( $language_packs, - function( $pack ) use ( $installed_locales ) { + static function( $pack ) use ( $installed_locales ) { return in_array( $pack->language, $installed_locales, true ); } ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php index 588bfcaf4158f..4801d7943d576 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php @@ -213,13 +213,15 @@ public function get_item( $request ) { * Prepares a post status object for serialization. * * @since 4.7.0 + * @since 5.9.0 Renamed `$status` to `$item` to match parent class for PHP 8 named parameter support. * - * @param stdClass $status Post status data. + * @param stdClass $item Post status data. * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Post status data. */ - public function prepare_item_for_response( $status, $request ) { - + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $status = $item; $fields = $this->get_fields_for_response( $request ); $data = array(); @@ -261,10 +263,11 @@ public function prepare_item_for_response( $status, $request ) { $response = rest_ensure_response( $data ); + $rest_url = rest_url( rest_get_route_for_post_type_items( 'post' ) ); if ( 'publish' === $status->name ) { - $response->add_link( 'archives', rest_url( 'wp/v2/posts' ) ); + $response->add_link( 'archives', $rest_url ); } else { - $response->add_link( 'archives', add_query_arg( 'status', $status->name, rest_url( 'wp/v2/posts' ) ) ); + $response->add_link( 'archives', add_query_arg( 'status', $status->name, $rest_url ) ); } /** diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php index 5d1d327f4f4e4..088d238883cd0 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php @@ -168,15 +168,19 @@ public function get_item( $request ) { * Prepares a post type object for serialization. * * @since 4.7.0 + * @since 5.9.0 Renamed `$post_type` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post_Type $post_type Post type object. - * @param WP_REST_Request $request Full details about the request. + * @param WP_Post_Type $item Post type object. + * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $post_type, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $post_type = $item; $taxonomies = wp_list_filter( get_object_taxonomies( $post_type->name, 'objects' ), array( 'show_in_rest' => true ) ); $taxonomies = wp_list_pluck( $taxonomies, 'name' ); $base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; + $namespace = ! empty( $post_type->rest_namespace ) ? $post_type->rest_namespace : 'wp/v2'; $supports = get_all_post_type_supports( $post_type->name ); $fields = $this->get_fields_for_response( $request ); @@ -194,6 +198,13 @@ public function prepare_item_for_response( $post_type, $request ) { $data['hierarchical'] = $post_type->hierarchical; } + if ( in_array( 'visibility', $fields, true ) ) { + $data['visibility'] = array( + 'show_in_nav_menus' => (bool) $post_type->show_in_nav_menus, + 'show_ui' => (bool) $post_type->show_ui, + ); + } + if ( in_array( 'viewable', $fields, true ) ) { $data['viewable'] = is_post_type_viewable( $post_type ); } @@ -222,6 +233,10 @@ public function prepare_item_for_response( $post_type, $request ) { $data['rest_base'] = $base; } + if ( in_array( 'rest_namespace', $fields, true ) ) { + $data['rest_namespace'] = $namespace; + } + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); @@ -235,7 +250,7 @@ public function prepare_item_for_response( $post_type, $request ) { 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), ), 'https://api.w.org/items' => array( - 'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ), + 'href' => rest_url( rest_get_route_for_post_type_items( $post_type->name ) ), ), ) ); @@ -258,6 +273,8 @@ public function prepare_item_for_response( $post_type, $request ) { * Retrieves the post type's schema, conforming to JSON Schema. * * @since 4.7.0 + * @since 4.8.0 The `supports` property was added. + * @since 5.9.0 The `visibility` and `rest_namespace` properties were added. * * @return array Item schema data. */ @@ -271,55 +288,55 @@ public function get_item_schema() { 'title' => 'type', 'type' => 'object', 'properties' => array( - 'capabilities' => array( + 'capabilities' => array( 'description' => __( 'All capabilities used by the post type.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), - 'description' => array( + 'description' => array( 'description' => __( 'A human-readable description of the post type.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'hierarchical' => array( + 'hierarchical' => array( 'description' => __( 'Whether or not the post type should have children.' ), 'type' => 'boolean', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'viewable' => array( + 'viewable' => array( 'description' => __( 'Whether or not the post type can be viewed.' ), 'type' => 'boolean', 'context' => array( 'edit' ), 'readonly' => true, ), - 'labels' => array( + 'labels' => array( 'description' => __( 'Human-readable labels for the post type for various contexts.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), - 'name' => array( + 'name' => array( 'description' => __( 'The title for the post type.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), - 'slug' => array( + 'slug' => array( 'description' => __( 'An alphanumeric identifier for the post type.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), - 'supports' => array( + 'supports' => array( 'description' => __( 'All features, supported by the post type.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), - 'taxonomies' => array( + 'taxonomies' => array( 'description' => __( 'Taxonomies associated with post type.' ), 'type' => 'array', 'items' => array( @@ -328,12 +345,34 @@ public function get_item_schema() { 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'rest_base' => array( + 'rest_base' => array( 'description' => __( 'REST base route for the post type.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), + 'rest_namespace' => array( + 'description' => __( 'REST route\'s namespace for the post type.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, + ), + 'visibility' => array( + 'description' => __( 'The visibility settings for the post type.' ), + 'type' => 'object', + 'context' => array( 'edit' ), + 'readonly' => true, + 'properties' => array( + 'show_ui' => array( + 'description' => __( 'Whether to generate a default UI for managing this post type.' ), + 'type' => 'boolean', + ), + 'show_in_nav_menus' => array( + 'description' => __( 'Whether to make the post type is available for selection in navigation menus.' ), + 'type' => 'boolean', + ), + ), + ), ), ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index b534cec5fbdb0..ffb4466892340 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -48,9 +48,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { */ public function __construct( $post_type ) { $this->post_type = $post_type; - $this->namespace = 'wp/v2'; $obj = get_post_type_object( $post_type ); $this->rest_base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name; + $this->namespace = ! empty( $obj->rest_namespace ) ? $obj->rest_namespace : 'wp/v2'; $this->meta = new WP_REST_Post_Meta_Fields( $this->post_type ); } @@ -1679,12 +1679,15 @@ protected function check_delete_permission( $post ) { * Prepares a single post output for response. * * @since 4.7.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post Post object. + * @param WP_Post $item Post object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $post, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $post = $item; $GLOBALS['post'] = $post; setup_postdata( $post ); @@ -2034,7 +2037,7 @@ protected function prepare_links( $post ) { // If we have a featured media, add that. $featured_media = get_post_thumbnail_id( $post->ID ); if ( $featured_media ) { - $image_url = rest_url( 'wp/v2/media/' . $featured_media ); + $image_url = rest_url( rest_get_route_for_post( $featured_media ) ); $links['https://api.w.org/featuredmedia'] = array( 'href' => $image_url, @@ -2043,7 +2046,7 @@ protected function prepare_links( $post ) { } if ( ! in_array( $post->post_type, array( 'attachment', 'nav_menu_item', 'revision' ), true ) ) { - $attachments_url = rest_url( 'wp/v2/media' ); + $attachments_url = rest_url( rest_get_route_for_post_type_items( 'attachment' ) ); $attachments_url = add_query_arg( 'parent', $post->ID, $attachments_url ); $links['https://api.w.org/attachment'] = array( @@ -2057,19 +2060,16 @@ protected function prepare_links( $post ) { $links['https://api.w.org/term'] = array(); foreach ( $taxonomies as $tax ) { - $taxonomy_obj = get_taxonomy( $tax ); + $taxonomy_route = rest_get_route_for_taxonomy_items( $tax ); // Skip taxonomies that are not public. - if ( empty( $taxonomy_obj->show_in_rest ) ) { + if ( empty( $taxonomy_route ) ) { continue; } - - $tax_base = ! empty( $taxonomy_obj->rest_base ) ? $taxonomy_obj->rest_base : $tax; - $terms_url = add_query_arg( 'post', $post->ID, - rest_url( 'wp/v2/' . $tax_base ) + rest_url( $taxonomy_route ) ); $links['https://api.w.org/term'][] = array( diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php index 09f9981d2b3d5..bea3ddac789c6 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php @@ -49,10 +49,10 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller { */ public function __construct( $parent_post_type ) { $this->parent_post_type = $parent_post_type; - $this->namespace = 'wp/v2'; $this->rest_base = 'revisions'; $post_type_object = get_post_type_object( $parent_post_type ); $this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; + $this->namespace = ! empty( $post_type_object->rest_namespace ) ? $post_type_object->rest_namespace : 'wp/v2'; $this->parent_controller = $post_type_object->get_rest_controller(); if ( ! $this->parent_controller ) { @@ -535,12 +535,15 @@ protected function prepare_items_query( $prepared_args = array(), $request = nul * Prepares the revision for the REST response. * * @since 4.7.0 + * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Post $post Post revision object. + * @param WP_Post $item Post revision object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $post, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $post = $item; $GLOBALS['post'] = $post; setup_postdata( $post ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php index a0f2e17520259..b87973c9d606a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php @@ -186,12 +186,15 @@ public function get_items( $request ) { * * @since 5.0.0 * @since 5.6.0 The `$id` parameter can accept a string. + * @since 5.9.0 Renamed `$id` to `$item` to match parent class for PHP 8 named parameter support. * - * @param int|string $id ID of the item to prepare. + * @param int|string $item ID of the item to prepare. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $id, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $item_id = $item; $handler = $this->get_search_handler( $request ); if ( is_wp_error( $handler ) ) { return new WP_REST_Response(); @@ -199,7 +202,7 @@ public function prepare_item_for_response( $id, $request ) { $fields = $this->get_fields_for_response( $request ); - $data = $handler->prepare_item( $id, $fields ); + $data = $handler->prepare_item( $item_id, $fields ); $data = $this->add_additional_fields_to_object( $data, $request ); $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; @@ -207,7 +210,7 @@ public function prepare_item_for_response( $id, $request ) { $response = rest_ensure_response( $data ); - $links = $handler->prepare_item_links( $id ); + $links = $handler->prepare_item_links( $item_id ); $links['collection'] = array( 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php index 18dcc4e9c0488..2aad57ad5425a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php @@ -262,19 +262,22 @@ protected function get_sidebar( $id ) { * Prepares a single sidebar output for response. * * @since 5.8.0 + * @since 5.9.0 Renamed `$raw_sidebar` to `$item` to match parent class for PHP 8 named parameter support. * * @global array $wp_registered_sidebars The registered sidebars. * @global array $wp_registered_widgets The registered widgets. * - * @param array $raw_sidebar Sidebar instance. - * @param WP_REST_Request $request Full details about the request. + * @param array $item Sidebar instance. + * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Prepared response object. */ - public function prepare_item_for_response( $raw_sidebar, $request ) { + public function prepare_item_for_response( $item, $request ) { global $wp_registered_sidebars, $wp_registered_widgets; - $id = $raw_sidebar['id']; - $sidebar = array( 'id' => $id ); + // Restores the more descriptive, specific name for use within this method. + $raw_sidebar = $item; + $id = $raw_sidebar['id']; + $sidebar = array( 'id' => $id ); if ( isset( $wp_registered_sidebars[ $id ] ) ) { $registered_sidebar = $wp_registered_sidebars[ $id ]; diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php index 0089afbfb1fac..ede47585b10ea 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php @@ -200,13 +200,16 @@ public function get_item( $request ) { * Prepares a taxonomy object for serialization. * * @since 4.7.0 + * @since 5.9.0 Renamed `$taxonomy` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Taxonomy $taxonomy Taxonomy data. - * @param WP_REST_Request $request Full details about the request. + * @param WP_Taxonomy $item Taxonomy data. + * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $taxonomy, $request ) { - $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $taxonomy = $item; + $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; $fields = $this->get_fields_for_response( $request ); $data = array(); @@ -247,6 +250,10 @@ public function prepare_item_for_response( $taxonomy, $request ) { $data['rest_base'] = $base; } + if ( in_array( 'rest_namespace', $fields, true ) ) { + $data['rest_namespace'] = $taxonomy->rest_namespace; + } + if ( in_array( 'visibility', $fields, true ) ) { $data['visibility'] = array( 'public' => (bool) $taxonomy->public, @@ -271,7 +278,7 @@ public function prepare_item_for_response( $taxonomy, $request ) { 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), ), 'https://api.w.org/items' => array( - 'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ), + 'href' => rest_url( rest_get_route_for_taxonomy_items( $taxonomy->name ) ), ), ) ); @@ -294,6 +301,8 @@ public function prepare_item_for_response( $taxonomy, $request ) { * Retrieves the taxonomy's schema, conforming to JSON Schema. * * @since 4.7.0 + * @since 5.0.0 The `visibility` property was added. + * @since 5.9.0 The `rest_namespace` property was added. * * @return array Item schema data. */ @@ -307,49 +316,49 @@ public function get_item_schema() { 'title' => 'taxonomy', 'type' => 'object', 'properties' => array( - 'capabilities' => array( + 'capabilities' => array( 'description' => __( 'All capabilities used by the taxonomy.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), - 'description' => array( + 'description' => array( 'description' => __( 'A human-readable description of the taxonomy.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'hierarchical' => array( + 'hierarchical' => array( 'description' => __( 'Whether or not the taxonomy should have children.' ), 'type' => 'boolean', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'labels' => array( + 'labels' => array( 'description' => __( 'Human-readable labels for the taxonomy for various contexts.' ), 'type' => 'object', 'context' => array( 'edit' ), 'readonly' => true, ), - 'name' => array( + 'name' => array( 'description' => __( 'The title for the taxonomy.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), - 'slug' => array( + 'slug' => array( 'description' => __( 'An alphanumeric identifier for the taxonomy.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), - 'show_cloud' => array( + 'show_cloud' => array( 'description' => __( 'Whether or not the term cloud should be displayed.' ), 'type' => 'boolean', 'context' => array( 'edit' ), 'readonly' => true, ), - 'types' => array( + 'types' => array( 'description' => __( 'Types associated with the taxonomy.' ), 'type' => 'array', 'items' => array( @@ -358,13 +367,19 @@ public function get_item_schema() { 'context' => array( 'view', 'edit' ), 'readonly' => true, ), - 'rest_base' => array( + 'rest_base' => array( 'description' => __( 'REST base route for the taxonomy.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), - 'visibility' => array( + 'rest_namespace' => array( + 'description' => __( 'REST namespace route for the taxonomy.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, + ), + 'visibility' => array( 'description' => __( 'The visibility settings for the taxonomy.' ), 'type' => 'object', 'context' => array( 'edit' ), diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php index 48b6d71be0f10..e7712363f7f33 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php @@ -33,9 +33,9 @@ class WP_REST_Templates_Controller extends WP_REST_Controller { */ public function __construct( $post_type ) { $this->post_type = $post_type; - $this->namespace = 'wp/v2'; $obj = get_post_type_object( $post_type ); $this->rest_base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name; + $this->namespace = ! empty( $obj->rest_namespace ) ? $obj->rest_namespace : 'wp/v2'; } /** @@ -402,13 +402,16 @@ protected function prepare_item_for_database( $request ) { * Prepare a single template output for response * * @since 5.8.0 + * @since 5.9.0 Renamed `$template` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Block_Template $template Template instance. + * @param WP_Block_Template $item Template instance. * @param WP_REST_Request $request Request object. * @return WP_REST_Response $data */ - public function prepare_item_for_response( $template, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable - $result = array( + public function prepare_item_for_response( $item, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + // Restores the more descriptive, specific name for use within this method. + $template = $item; + $result = array( 'id' => $template->id, 'theme' => $template->theme, 'content' => array( 'raw' => $template->content ), diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php index 093b98a4911ad..3a92b774f0fd2 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php @@ -57,9 +57,9 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { */ public function __construct( $taxonomy ) { $this->taxonomy = $taxonomy; - $this->namespace = 'wp/v2'; $tax_obj = get_taxonomy( $taxonomy ); $this->rest_base = ! empty( $tax_obj->rest_base ) ? $tax_obj->rest_base : $tax_obj->name; + $this->namespace = ! empty( $tax_obj->rest_namespace ) ? $tax_obj->rest_namespace : 'wp/v2'; $this->meta = new WP_REST_Term_Meta_Fields( $taxonomy ); } @@ -914,15 +914,14 @@ protected function prepare_links( $term ) { $post_type_links = array(); foreach ( $taxonomy_obj->object_type as $type ) { - $post_type_object = get_post_type_object( $type ); + $rest_path = rest_get_route_for_post_type_items( $type ); - if ( empty( $post_type_object->show_in_rest ) ) { + if ( empty( $rest_path ) ) { continue; } - $rest_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name; $post_type_links[] = array( - 'href' => add_query_arg( $this->rest_base, $term->term_id, rest_url( sprintf( 'wp/v2/%s', $rest_base ) ) ), + 'href' => add_query_arg( $this->rest_base, $term->term_id, rest_url( $rest_path ) ), ); } diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php index 021f6adfafcd3..10b5c29a33e76 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php @@ -204,12 +204,15 @@ public function get_items( $request ) { * Prepares a single theme output for response. * * @since 5.0.0 + * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_Theme $theme Theme object. + * @param WP_Theme $item Theme object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $theme, $request ) { + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $theme = $item; $data = array(); $fields = $this->get_fields_for_response( $request ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php index 63ad45b8ecab8..e3e5d935d7a1a 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php @@ -198,6 +198,15 @@ public function get_items_permissions_check( $request ) { ); } + // Check if capabilities is specified in GET request and if user can list users. + if ( ! empty( $request['capabilities'] ) && ! current_user_can( 'list_users' ) ) { + return new WP_Error( + 'rest_user_cannot_view', + __( 'Sorry, you are not allowed to filter users by capability.' ), + array( 'status' => rest_authorization_required_code() ) + ); + } + if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) { return new WP_Error( 'rest_forbidden_context', @@ -254,13 +263,14 @@ public function get_items( $request ) { * present in $registered will be set. */ $parameter_mappings = array( - 'exclude' => 'exclude', - 'include' => 'include', - 'order' => 'order', - 'per_page' => 'number', - 'search' => 'search', - 'roles' => 'role__in', - 'slug' => 'nicename__in', + 'exclude' => 'exclude', + 'include' => 'include', + 'order' => 'order', + 'per_page' => 'number', + 'search' => 'search', + 'roles' => 'role__in', + 'capabilities' => 'capability__in', + 'slug' => 'nicename__in', ); $prepared_args = array(); @@ -963,13 +973,15 @@ public function delete_current_item( $request ) { * Prepares a single user output for response. * * @since 4.7.0 + * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support. * - * @param WP_User $user User object. + * @param WP_User $item User object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ - public function prepare_item_for_response( $user, $request ) { - + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $user = $item; $data = array(); $fields = $this->get_fields_for_response( $request ); @@ -1552,6 +1564,14 @@ public function get_collection_params() { ), ); + $query_params['capabilities'] = array( + 'description' => __( 'Limit result set to users matching at least one specific capability provided. Accepts csv list or single capability.' ), + 'type' => 'array', + 'items' => array( + 'type' => 'string', + ), + ); + $query_params['who'] = array( 'description' => __( 'Limit result set to users who are considered authors.' ), 'type' => 'string', diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php index db88950faa481..82c3a5255ee84 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php @@ -85,7 +85,7 @@ public function register_routes() { 'form_data' => array( 'description' => __( 'Serialized widget form data to encode into instance settings.' ), 'type' => 'string', - 'sanitize_callback' => function( $string ) { + 'sanitize_callback' => static function( $string ) { $array = array(); wp_parse_str( $string, $array ); return $array; @@ -237,6 +237,8 @@ protected function get_widgets() { $widgets[ $widget['id'] ] = $widget; } + ksort( $widgets ); + return $widgets; } @@ -263,14 +265,17 @@ public function get_item( $request ) { * Prepares a widget type object for serialization. * * @since 5.8.0 + * @since 5.9.0 Renamed `$widget_type` to `$item` to match parent class for PHP 8 named parameter support. * - * @param array $widget_type Widget type data. - * @param WP_REST_Request $request Full details about the request. + * @param array $item Widget type data. + * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response Widget type data. */ - public function prepare_item_for_response( $widget_type, $request ) { - $fields = $this->get_fields_for_response( $request ); - $data = array( + public function prepare_item_for_response( $item, $request ) { + // Restores the more descriptive, specific name for use within this method. + $widget_type = $item; + $fields = $this->get_fields_for_response( $request ); + $data = array( 'id' => $widget_type['id'], ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php index 3b425a6b8b640..4c54620f509fa 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php @@ -792,7 +792,7 @@ public function get_item_schema() { 'type' => 'string', 'context' => array(), 'arg_options' => array( - 'sanitize_callback' => function( $string ) { + 'sanitize_callback' => static function( $string ) { $array = array(); wp_parse_str( $string, $array ); return $array; diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 1e2f1d5faeaa7..7b66e1befa031 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -39,11 +39,16 @@ * * @since 5.0.0 * + * @global string $tinymce_version + * @global bool $concatenate_scripts + * @global bool $compress_scripts + * * @param WP_Scripts $scripts WP_Scripts object. * @param bool $force_uncompressed Whether to forcibly prevent gzip compression. Default false. */ function wp_register_tinymce_scripts( $scripts, $force_uncompressed = false ) { global $tinymce_version, $concatenate_scripts, $compress_scripts; + $suffix = wp_scripts_get_suffix(); $dev_suffix = wp_scripts_get_suffix( 'dev' ); @@ -72,6 +77,8 @@ function wp_register_tinymce_scripts( $scripts, $force_uncompressed = false ) { * * @since 5.0.0 * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * * @param WP_Scripts $scripts WP_Scripts object. */ function wp_default_packages_vendor( $scripts ) { @@ -101,7 +108,7 @@ function wp_default_packages_vendor( $scripts ) { 'regenerator-runtime' => '0.13.7', 'moment' => '2.29.1', 'lodash' => '4.17.19', - 'wp-polyfill-fetch' => '3.0.0', + 'wp-polyfill-fetch' => '3.6.2', 'wp-polyfill-formdata' => '4.0.0', 'wp-polyfill-node-contains' => '3.105.0', 'wp-polyfill-url' => '3.6.4', @@ -277,6 +284,8 @@ function wp_default_packages_scripts( $scripts ) { * * @since 5.0.0 * + * @global WP_Locale $wp_locale WordPress date and time locale object. + * * @param WP_Scripts $scripts WP_Scripts object. */ function wp_default_packages_inline_scripts( $scripts ) { @@ -756,55 +765,55 @@ function wp_default_scripts( $scripts ) { // In order to keep backwards compatibility, and to keep the optimized loading, // the source files were flattened and included with some modifications for AMD loading. // A notable change is that 'jquery-ui-core' now contains 'jquery-ui-position' and 'jquery-ui-widget'. - $scripts->add( 'jquery-ui-core', "/wp-includes/js/jquery/ui/core$suffix.js", array( 'jquery' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-core', "/wp-includes/js/jquery/ui/effect$suffix.js", array( 'jquery' ), '1.12.1', 1 ); - - $scripts->add( 'jquery-effects-blind', "/wp-includes/js/jquery/ui/effect-blind$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-bounce', "/wp-includes/js/jquery/ui/effect-bounce$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-clip', "/wp-includes/js/jquery/ui/effect-clip$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-drop', "/wp-includes/js/jquery/ui/effect-drop$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-explode', "/wp-includes/js/jquery/ui/effect-explode$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-fade', "/wp-includes/js/jquery/ui/effect-fade$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-fold', "/wp-includes/js/jquery/ui/effect-fold$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-highlight', "/wp-includes/js/jquery/ui/effect-highlight$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-puff', "/wp-includes/js/jquery/ui/effect-puff$suffix.js", array( 'jquery-effects-core', 'jquery-effects-scale' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-pulsate', "/wp-includes/js/jquery/ui/effect-pulsate$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-scale', "/wp-includes/js/jquery/ui/effect-scale$suffix.js", array( 'jquery-effects-core', 'jquery-effects-size' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-shake', "/wp-includes/js/jquery/ui/effect-shake$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-size', "/wp-includes/js/jquery/ui/effect-size$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-slide', "/wp-includes/js/jquery/ui/effect-slide$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-effects-transfer', "/wp-includes/js/jquery/ui/effect-transfer$suffix.js", array( 'jquery-effects-core' ), '1.12.1', 1 ); + $scripts->add( 'jquery-ui-core', "/wp-includes/js/jquery/ui/core$suffix.js", array( 'jquery' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-core', "/wp-includes/js/jquery/ui/effect$suffix.js", array( 'jquery' ), '1.13.0', 1 ); + + $scripts->add( 'jquery-effects-blind', "/wp-includes/js/jquery/ui/effect-blind$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-bounce', "/wp-includes/js/jquery/ui/effect-bounce$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-clip', "/wp-includes/js/jquery/ui/effect-clip$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-drop', "/wp-includes/js/jquery/ui/effect-drop$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-explode', "/wp-includes/js/jquery/ui/effect-explode$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-fade', "/wp-includes/js/jquery/ui/effect-fade$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-fold', "/wp-includes/js/jquery/ui/effect-fold$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-highlight', "/wp-includes/js/jquery/ui/effect-highlight$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-puff', "/wp-includes/js/jquery/ui/effect-puff$suffix.js", array( 'jquery-effects-core', 'jquery-effects-scale' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-pulsate', "/wp-includes/js/jquery/ui/effect-pulsate$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-scale', "/wp-includes/js/jquery/ui/effect-scale$suffix.js", array( 'jquery-effects-core', 'jquery-effects-size' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-shake', "/wp-includes/js/jquery/ui/effect-shake$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-size', "/wp-includes/js/jquery/ui/effect-size$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-slide', "/wp-includes/js/jquery/ui/effect-slide$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-effects-transfer', "/wp-includes/js/jquery/ui/effect-transfer$suffix.js", array( 'jquery-effects-core' ), '1.13.0', 1 ); // Widgets - $scripts->add( 'jquery-ui-accordion', "/wp-includes/js/jquery/ui/accordion$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-autocomplete', "/wp-includes/js/jquery/ui/autocomplete$suffix.js", array( 'jquery-ui-menu', 'wp-a11y' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-button', "/wp-includes/js/jquery/ui/button$suffix.js", array( 'jquery-ui-core', 'jquery-ui-controlgroup', 'jquery-ui-checkboxradio' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-datepicker', "/wp-includes/js/jquery/ui/datepicker$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-dialog', "/wp-includes/js/jquery/ui/dialog$suffix.js", array( 'jquery-ui-resizable', 'jquery-ui-draggable', 'jquery-ui-button' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-menu', "/wp-includes/js/jquery/ui/menu$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-mouse', "/wp-includes/js/jquery/ui/mouse$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-progressbar', "/wp-includes/js/jquery/ui/progressbar$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-selectmenu', "/wp-includes/js/jquery/ui/selectmenu$suffix.js", array( 'jquery-ui-menu' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-slider', "/wp-includes/js/jquery/ui/slider$suffix.js", array( 'jquery-ui-mouse' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-spinner', "/wp-includes/js/jquery/ui/spinner$suffix.js", array( 'jquery-ui-button' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-tabs', "/wp-includes/js/jquery/ui/tabs$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-tooltip', "/wp-includes/js/jquery/ui/tooltip$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); + $scripts->add( 'jquery-ui-accordion', "/wp-includes/js/jquery/ui/accordion$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-autocomplete', "/wp-includes/js/jquery/ui/autocomplete$suffix.js", array( 'jquery-ui-menu', 'wp-a11y' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-button', "/wp-includes/js/jquery/ui/button$suffix.js", array( 'jquery-ui-core', 'jquery-ui-controlgroup', 'jquery-ui-checkboxradio' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-datepicker', "/wp-includes/js/jquery/ui/datepicker$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-dialog', "/wp-includes/js/jquery/ui/dialog$suffix.js", array( 'jquery-ui-resizable', 'jquery-ui-draggable', 'jquery-ui-button' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-menu', "/wp-includes/js/jquery/ui/menu$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-mouse', "/wp-includes/js/jquery/ui/mouse$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-progressbar', "/wp-includes/js/jquery/ui/progressbar$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-selectmenu', "/wp-includes/js/jquery/ui/selectmenu$suffix.js", array( 'jquery-ui-menu' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-slider', "/wp-includes/js/jquery/ui/slider$suffix.js", array( 'jquery-ui-mouse' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-spinner', "/wp-includes/js/jquery/ui/spinner$suffix.js", array( 'jquery-ui-button' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-tabs', "/wp-includes/js/jquery/ui/tabs$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-tooltip', "/wp-includes/js/jquery/ui/tooltip$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); // New in 1.12.1 - $scripts->add( 'jquery-ui-checkboxradio', "/wp-includes/js/jquery/ui/checkboxradio$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-controlgroup', "/wp-includes/js/jquery/ui/controlgroup$suffix.js", array( 'jquery-ui-core' ), '1.12.1', 1 ); + $scripts->add( 'jquery-ui-checkboxradio', "/wp-includes/js/jquery/ui/checkboxradio$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-controlgroup', "/wp-includes/js/jquery/ui/controlgroup$suffix.js", array( 'jquery-ui-core' ), '1.13.0', 1 ); // Interactions - $scripts->add( 'jquery-ui-draggable', "/wp-includes/js/jquery/ui/draggable$suffix.js", array( 'jquery-ui-mouse' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-droppable', "/wp-includes/js/jquery/ui/droppable$suffix.js", array( 'jquery-ui-draggable' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-resizable', "/wp-includes/js/jquery/ui/resizable$suffix.js", array( 'jquery-ui-mouse' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-selectable', "/wp-includes/js/jquery/ui/selectable$suffix.js", array( 'jquery-ui-mouse' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-sortable', "/wp-includes/js/jquery/ui/sortable$suffix.js", array( 'jquery-ui-mouse' ), '1.12.1', 1 ); + $scripts->add( 'jquery-ui-draggable', "/wp-includes/js/jquery/ui/draggable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-droppable', "/wp-includes/js/jquery/ui/droppable$suffix.js", array( 'jquery-ui-draggable' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-resizable', "/wp-includes/js/jquery/ui/resizable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-selectable', "/wp-includes/js/jquery/ui/selectable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-sortable', "/wp-includes/js/jquery/ui/sortable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.0', 1 ); // As of 1.12.1 `jquery-ui-position` and `jquery-ui-widget` are part of `jquery-ui-core`. // Listed here for back-compat. - $scripts->add( 'jquery-ui-position', false, array( 'jquery-ui-core' ), '1.12.1', 1 ); - $scripts->add( 'jquery-ui-widget', false, array( 'jquery-ui-core' ), '1.12.1', 1 ); + $scripts->add( 'jquery-ui-position', false, array( 'jquery-ui-core' ), '1.13.0', 1 ); + $scripts->add( 'jquery-ui-widget', false, array( 'jquery-ui-core' ), '1.13.0', 1 ); // Strings for 'jquery-ui-autocomplete' live region messages. did_action( 'init' ) && $scripts->localize( @@ -1379,9 +1388,13 @@ function wp_default_scripts( $scripts ) { * * @since 2.6.0 * + * @global array $editor_styles + * * @param WP_Styles $styles */ function wp_default_styles( $styles ) { + global $editor_styles; + // Include an unmodified $wp_version. require ABSPATH . WPINC . '/version.php'; @@ -1534,7 +1547,6 @@ function wp_default_styles( $styles ) { $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles'; } - global $editor_styles; if ( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 ) { // Include opinionated block styles if no $editor_styles are declared, so the editor never appears broken. $wp_edit_blocks_dependencies[] = 'wp-block-library-theme'; @@ -2032,16 +2044,17 @@ function _print_scripts() { * @return array */ function wp_print_head_scripts() { + global $wp_scripts; + if ( ! did_action( 'wp_print_scripts' ) ) { /** This action is documented in wp-includes/functions.wp-scripts.php */ do_action( 'wp_print_scripts' ); } - global $wp_scripts; - if ( ! ( $wp_scripts instanceof WP_Scripts ) ) { return array(); // No need to run if nothing is queued. } + return print_head_scripts(); } @@ -2243,8 +2256,6 @@ function script_concat_settings() { * the editor and the front-end. * * @since 5.0.0 - * - * @global WP_Screen $current_screen WordPress current screen object. */ function wp_common_block_scripts_and_styles() { if ( is_admin() && ! wp_should_load_block_editor_scripts_and_styles() ) { @@ -2299,9 +2310,11 @@ function wp_enqueue_global_styles() { ! is_admin() ); - $stylesheet = null; + $stylesheet = null; + $transient_name = 'global_styles_' . get_stylesheet(); + if ( $can_use_cache ) { - $cache = get_transient( 'global_styles' ); + $cache = get_transient( $transient_name ); if ( $cache ) { $stylesheet = $cache; } @@ -2313,7 +2326,7 @@ function wp_enqueue_global_styles() { $stylesheet = $theme_json->get_stylesheet(); if ( $can_use_cache ) { - set_transient( 'global_styles', $stylesheet, MINUTE_IN_SECONDS ); + set_transient( $transient_name, $stylesheet, MINUTE_IN_SECONDS ); } } @@ -2332,6 +2345,8 @@ function wp_enqueue_global_styles() { * * @since 5.6.0 * + * @global WP_Screen $current_screen WordPress current screen object. + * * @return bool Whether scripts and styles should be enqueued. */ function wp_should_load_block_editor_scripts_and_styles() { @@ -2435,8 +2450,12 @@ function wp_enqueue_registered_block_scripts_and_styles() { * Function responsible for enqueuing the styles required for block styles functionality on the editor and on the frontend. * * @since 5.3.0 + * + * @global WP_Styles $wp_styles */ function enqueue_block_styles_assets() { + global $wp_styles; + $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); foreach ( $block_styles as $block_name => $styles ) { @@ -2447,7 +2466,7 @@ function enqueue_block_styles_assets() { if ( wp_should_load_separate_core_block_assets() ) { add_filter( 'render_block', - function( $html, $block ) use ( $style_properties ) { + function( $html ) use ( $style_properties ) { wp_enqueue_style( $style_properties['style_handle'] ); return $html; } @@ -2464,7 +2483,7 @@ function( $html, $block ) use ( $style_properties ) { // If the site loads separate styles per-block, check if the block has a stylesheet registered. if ( wp_should_load_separate_core_block_assets() ) { $block_stylesheet_handle = generate_block_asset_handle( $block_name, 'style' ); - global $wp_styles; + if ( isset( $wp_styles->registered[ $block_stylesheet_handle ] ) ) { $handle = $block_stylesheet_handle; } @@ -2692,7 +2711,7 @@ function wp_maybe_inline_styles() { // Reorder styles array based on size. usort( $styles, - function( $a, $b ) { + static function( $a, $b ) { return ( $a['size'] <= $b['size'] ) ? -1 : 1; } ); diff --git a/src/wp-includes/sitemaps/class-wp-sitemaps-provider.php b/src/wp-includes/sitemaps/class-wp-sitemaps-provider.php index 3440f62b34a4c..e77681d7215d3 100644 --- a/src/wp-includes/sitemaps/class-wp-sitemaps-provider.php +++ b/src/wp-includes/sitemaps/class-wp-sitemaps-provider.php @@ -160,7 +160,7 @@ public function get_sitemap_url( $name, $page ) { ); if ( ! $wp_rewrite->using_permalinks() ) { - $basename = '/?' . http_build_query( $params, null, '&' ); + $basename = '/?' . http_build_query( $params, '', '&' ); } return home_url( $basename ); diff --git a/src/wp-includes/sitemaps/providers/class-wp-sitemaps-posts.php b/src/wp-includes/sitemaps/providers/class-wp-sitemaps-posts.php index 56acfb7697c20..701d170a6ad72 100644 --- a/src/wp-includes/sitemaps/providers/class-wp-sitemaps-posts.php +++ b/src/wp-includes/sitemaps/providers/class-wp-sitemaps-posts.php @@ -53,12 +53,18 @@ public function get_object_subtypes() { * Gets a URL list for a post type sitemap. * * @since 5.5.0 + * @since 5.9.0 Renamed `$post_type` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. + * + * @param int $page_num Page of results. + * @param string $object_subtype Optional. Post type name. Default empty. * - * @param int $page_num Page of results. - * @param string $post_type Optional. Post type name. Default empty. * @return array Array of URLs for a sitemap. */ - public function get_url_list( $page_num, $post_type = '' ) { + public function get_url_list( $page_num, $object_subtype = '' ) { + // Restores the more descriptive, specific name for use within this method. + $post_type = $object_subtype; + // Bail early if the queried post type is not supported. $supported_types = $this->get_object_subtypes(); @@ -142,15 +148,20 @@ public function get_url_list( $page_num, $post_type = '' ) { * Gets the max number of pages available for the object type. * * @since 5.5.0 + * @since 5.9.0 Renamed `$post_type` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. * - * @param string $post_type Optional. Post type name. Default empty. + * @param string $object_subtype Optional. Post type name. Default empty. * @return int Total number of pages. */ - public function get_max_num_pages( $post_type = '' ) { - if ( empty( $post_type ) ) { + public function get_max_num_pages( $object_subtype = '' ) { + if ( empty( $object_subtype ) ) { return 0; } + // Restores the more descriptive, specific name for use within this method. + $post_type = $object_subtype; + /** * Filters the max number of pages before it is generated. * diff --git a/src/wp-includes/sitemaps/providers/class-wp-sitemaps-taxonomies.php b/src/wp-includes/sitemaps/providers/class-wp-sitemaps-taxonomies.php index e8fcc6d5ab222..636815397e181 100644 --- a/src/wp-includes/sitemaps/providers/class-wp-sitemaps-taxonomies.php +++ b/src/wp-includes/sitemaps/providers/class-wp-sitemaps-taxonomies.php @@ -51,12 +51,16 @@ public function get_object_subtypes() { * Gets a URL list for a taxonomy sitemap. * * @since 5.5.0 + * @since 5.9.0 Renamed `$taxonomy` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. * - * @param int $page_num Page of results. - * @param string $taxonomy Optional. Taxonomy name. Default empty. + * @param int $page_num Page of results. + * @param string $object_subtype Optional. Taxonomy name. Default empty. * @return array Array of URLs for a sitemap. */ - public function get_url_list( $page_num, $taxonomy = '' ) { + public function get_url_list( $page_num, $object_subtype = '' ) { + // Restores the more descriptive, specific name for use within this method. + $taxonomy = $object_subtype; $supported_types = $this->get_object_subtypes(); // Bail early if the queried taxonomy is not supported. @@ -130,15 +134,20 @@ public function get_url_list( $page_num, $taxonomy = '' ) { * Gets the max number of pages available for the object type. * * @since 5.5.0 + * @since 5.9.0 Renamed `$taxonomy` to `$object_subtype` to match parent class + * for PHP 8 named parameter support. * - * @param string $taxonomy Taxonomy name. + * @param string $object_subtype Optional. Taxonomy name. Default empty. * @return int Total number of pages. */ - public function get_max_num_pages( $taxonomy = '' ) { - if ( empty( $taxonomy ) ) { + public function get_max_num_pages( $object_subtype = '' ) { + if ( empty( $object_subtype ) ) { return 0; } + // Restores the more descriptive, specific name for use within this method. + $taxonomy = $object_subtype; + /** * Filters the max number of pages before it is generated. * diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 5d9cf1ad2c8d1..5b1acb4fc6eeb 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -198,7 +198,7 @@ function create_initial_taxonomies() { * * @since 3.0.0 * - * @global array $wp_taxonomies The registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. * * @param array $args Optional. An array of `key => value` arguments to match against the taxonomy objects. * Default empty array. @@ -231,7 +231,7 @@ function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) * * @since 2.3.0 * - * @global array $wp_taxonomies The registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. * * @param string|string[]|WP_Post $object Name of the type of taxonomy object, or an object (row from posts) * @param string $output Optional. The type of output to return in the array. Accepts either @@ -272,7 +272,7 @@ function get_object_taxonomies( $object, $output = 'names' ) { * * @since 2.3.0 * - * @global array $wp_taxonomies The registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. * * @param string $taxonomy Name of taxonomy object to return. * @return WP_Taxonomy|false The Taxonomy Object or false if $taxonomy doesn't exist. @@ -298,7 +298,7 @@ function get_taxonomy( $taxonomy ) { * * @since 3.0.0 * - * @global array $wp_taxonomies The registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. * * @param string $taxonomy Name of taxonomy object. * @return bool Whether the taxonomy exists. @@ -355,8 +355,9 @@ function is_taxonomy_hierarchical( $taxonomy ) { * @since 5.1.0 Introduced `meta_box_sanitize_cb` argument. * @since 5.4.0 Added the registered taxonomy object as a return value. * @since 5.5.0 Introduced `default_term` argument. + * @since 5.9.0 Introduced `rest_namespace` argument. * - * @global array $wp_taxonomies Registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies Registered taxonomies. * * @param string $taxonomy Taxonomy key, must not exceed 32 characters. * @param array|string $object_type Object type or array of object types with which the taxonomy should be associated. @@ -387,6 +388,7 @@ function is_taxonomy_hierarchical( $taxonomy ) { * @type bool $show_in_rest Whether to include the taxonomy in the REST API. Set this to true * for the taxonomy to be available in the block editor. * @type string $rest_base To change the base url of REST API route. Default is $taxonomy. + * @type string $rest_namespace To change the namespace URL of REST API route. Default is wp/v2. * @type string $rest_controller_class REST API Controller class name. Default is 'WP_REST_Terms_Controller'. * @type bool $show_tagcloud Whether to list the taxonomy in the Tag Cloud Widget controls. If not set, * the default is inherited from `$show_ui` (default true). @@ -507,7 +509,7 @@ function register_taxonomy( $taxonomy, $object_type, $args = array() ) { * @since 4.5.0 * * @global WP $wp Current WordPress environment instance. - * @global array $wp_taxonomies List of taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies List of taxonomies. * * @param string $taxonomy Taxonomy name. * @return true|WP_Error True on success, WP_Error on failure or if the taxonomy doesn't exist. @@ -684,7 +686,7 @@ function get_taxonomy_labels( $tax ) { * * @since 3.0.0 * - * @global array $wp_taxonomies The registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. * * @param string $taxonomy Name of taxonomy object. * @param string $object_type Name of the object type. @@ -726,7 +728,7 @@ function register_taxonomy_for_object_type( $taxonomy, $object_type ) { * * @since 3.7.0 * - * @global array $wp_taxonomies The registered taxonomies. + * @global WP_Taxonomy[] $wp_taxonomies The registered taxonomies. * * @param string $taxonomy Name of taxonomy object. * @param string $object_type Name of the object type. @@ -945,7 +947,7 @@ function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { /** * Filters a taxonomy term object. * - * The dynamic portion of the filter name, `$taxonomy`, refers + * The dynamic portion of the hook name, `$taxonomy`, refers * to the slug of the term's taxonomy. * * Possible hook names include: @@ -1006,7 +1008,7 @@ function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { * * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. * - * @param string $field Either 'slug', 'name', 'id' or 'ID' (term_id), or 'term_taxonomy_id'. + * @param string $field Either 'slug', 'name', 'term_id' (or 'id', 'ID'), or 'term_taxonomy_id'. * @param string|int $value Search for this term value. * @param string $taxonomy Taxonomy name. Optional, if `$field` is 'term_taxonomy_id'. * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which @@ -1480,6 +1482,10 @@ function unregister_term_meta( $taxonomy, $meta_key ) { function term_exists( $term, $taxonomy = '', $parent = null ) { global $wpdb; + if ( null === $term ) { + return null; + } + $select = "SELECT term_id FROM $wpdb->terms as t WHERE "; $tax_select = "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE "; @@ -1655,7 +1661,7 @@ function sanitize_term_field( $field, $value, $term_id, $taxonomy, $context ) { /** * Filters a term field to edit before it is sanitized. * - * The dynamic portion of the filter name, `$field`, refers to the term field. + * The dynamic portion of the hook name, `$field`, refers to the term field. * * @since 2.3.0 * @@ -1688,7 +1694,7 @@ function sanitize_term_field( $field, $value, $term_id, $taxonomy, $context ) { /** * Filters a term field value before it is sanitized. * - * The dynamic portion of the filter name, `$field`, refers to the term field. + * The dynamic portion of the hook name, `$field`, refers to the term field. * * @since 2.3.0 * @@ -1727,7 +1733,7 @@ function sanitize_term_field( $field, $value, $term_id, $taxonomy, $context ) { /** * Filters the term field for use in RSS. * - * The dynamic portion of the filter name, `$field`, refers to the term field. + * The dynamic portion of the hook name, `$field`, refers to the term field. * * @since 2.3.0 * @@ -1753,7 +1759,7 @@ function sanitize_term_field( $field, $value, $term_id, $taxonomy, $context ) { /** * Filters the term field sanitized for display. * - * The dynamic portion of the filter name, `$field`, refers to the term field name. + * The dynamic portion of the hook name, `$field`, refers to the term field name. * * @since 2.3.0 * diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index 384c056404b2a..e233b4127a7da 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -3073,7 +3073,7 @@ function require_if_theme_supports( $feature, $include ) { * @type string $type The type of data associated with this feature. * Valid values are 'string', 'boolean', 'integer', * 'number', 'array', and 'object'. Defaults to 'boolean'. - * @type boolean $variadic Does this feature utilize the variadic support + * @type bool $variadic Does this feature utilize the variadic support * of add_theme_support(), or are all arguments specified * as the second parameter. Must be used with the "array" type. * @type string $description A short description of the feature. Included in diff --git a/src/wp-includes/update.php b/src/wp-includes/update.php index 79e3b3ea33d5b..85d0d4c9a86d0 100644 --- a/src/wp-includes/update.php +++ b/src/wp-includes/update.php @@ -517,7 +517,7 @@ function wp_update_plugins( $extra_stats = array() ) { } } - $sanitize_plugin_update_payload = function( &$item ) { + $sanitize_plugin_update_payload = static function( &$item ) { $item = (object) $item; unset( $item->translations, $item->compatibility ); diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 7c1c2c1f5534c..018c960c031b1 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -1320,13 +1320,32 @@ function wp_dropdown_users( $args = '' ) { 'role' => '', 'role__in' => array(), 'role__not_in' => array(), + 'capability' => '', + 'capability__in' => array(), + 'capability__not_in' => array(), ); $defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0; $parsed_args = wp_parse_args( $args, $defaults ); - $query_args = wp_array_slice_assoc( $parsed_args, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who', 'role', 'role__in', 'role__not_in' ) ); + $query_args = wp_array_slice_assoc( + $parsed_args, + array( + 'blog_id', + 'include', + 'exclude', + 'orderby', + 'order', + 'who', + 'role', + 'role__in', + 'role__not_in', + 'capability', + 'capability__in', + 'capability__not_in', + ) + ); $fields = array( 'ID', 'user_login' ); @@ -1711,9 +1730,10 @@ function validate_username( $username ) { * @since 2.0.0 * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact * methods for new installations. See wp_get_user_contact_methods(). - * @since 4.7.0 The user's locale can be passed to `$userdata`. + * @since 4.7.0 The `locale` field can be passed to `$userdata`. * @since 5.3.0 The `user_activation_key` field can be passed to `$userdata`. * @since 5.3.0 The `spam` field can be passed to `$userdata` (Multisite only). + * @since 5.9.0 The `meta_input` field can be passed to `$userdata` to allow addition of user meta data. * * @global wpdb $wpdb WordPress database abstraction object. * @@ -1758,6 +1778,8 @@ function validate_username( $username ) { * as a string literal, not boolean. Default 'true'. * @type string $role User's role. * @type string $locale User's locale. Default empty. + * @type array $meta_input Array of custom user meta values keyed by meta key. + * Default empty. * } * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not * be created. @@ -2058,6 +2080,8 @@ function wp_insert_user( $userdata ) { * * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`. * + * For custom meta fields, see the {@see 'insert_custom_user_meta'} filter. + * * @since 4.4.0 * @since 5.8.0 The $userdata parameter was added. * @@ -2084,6 +2108,28 @@ function wp_insert_user( $userdata ) { */ $meta = apply_filters( 'insert_user_meta', $meta, $user, $update, $userdata ); + $custom_meta = array(); + if ( array_key_exists( 'meta_input', $userdata ) && is_array( $userdata['meta_input'] ) && ! empty( $userdata['meta_input'] ) ) { + $custom_meta = $userdata['meta_input']; + } + + /** + * Filters a user's custom meta values and keys immediately after the user is created or updated + * and before any user meta is inserted or updated. + * + * For non-custom meta fields, see the {@see 'insert_user_meta'} filter. + * + * @since 5.9.0 + * + * @param array $custom_meta Array of custom user meta values keyed by meta key. + * @param WP_User $user User object. + * @param bool $update Whether the user is being updated rather than created. + * @param array $userdata The raw array of data passed to wp_insert_user(). + */ + $custom_meta = apply_filters( 'insert_custom_user_meta', $custom_meta, $user, $update, $userdata ); + + $meta = array_merge( $meta, $custom_meta ); + // Update user meta. foreach ( $meta as $key => $value ) { update_user_meta( $user_id, $key, $value ); @@ -3459,7 +3505,7 @@ function wp_user_personal_data_exporter( $email_address ) { // Remove items that use reserved names. $extra_data = array_filter( $_extra_data, - function( $item ) use ( $reserved_names ) { + static function( $item ) use ( $reserved_names ) { return ! in_array( $item['name'], $reserved_names, true ); } ); diff --git a/src/wp-includes/version.php b/src/wp-includes/version.php index 9965b10a7220f..87b8638c0aa42 100644 --- a/src/wp-includes/version.php +++ b/src/wp-includes/version.php @@ -11,6 +11,9 @@ /** * The WordPress version string. * + * Holds the current version number for WordPress core. Used to bust caches + * and to enable development mode for scripts when running from the /src directory. + * * @global string $wp_version */ $wp_version = '5.9-alpha-51272-src'; @@ -20,7 +23,7 @@ * * @global int $wp_db_version */ -$wp_db_version = 49752; +$wp_db_version = 51917; /** * Holds the TinyMCE version. diff --git a/src/wp-includes/widgets.php b/src/wp-includes/widgets.php index 61caf6af56d6a..de15317d1b7d0 100644 --- a/src/wp-includes/widgets.php +++ b/src/wp-includes/widgets.php @@ -1255,7 +1255,17 @@ function _wp_sidebars_changed() { } /** - * Look for "lost" widgets, this has to run at least on each theme change. + * Validates and remaps any "orphaned" widgets to wp_inactive_widgets sidebar, + * and saves the widget settings. This has to run at least on each theme change. + * + * For example, let's say theme A has a "footer" sidebar, and theme B doesn't have one. + * After switching from theme A to theme B, all the widgets previously assigned + * to the footer would be inaccessible. This function detects this scenario, and + * moves all the widgets previously assigned to the footer under wp_inactive_widgets. + * + * Despite the word "retrieve" in the name, this function actually updates the database + * and the global `$sidebars_widgets`. For that reason it should not be run on front end, + * unless the `$theme_changed` value is 'customize' (to bypass the database write). * * @since 2.8.0 * @@ -1310,6 +1320,7 @@ function retrieve_widgets( $theme_changed = false ) { $sidebars_widgets['wp_inactive_widgets'] = array_merge( $lost_widgets, (array) $sidebars_widgets['wp_inactive_widgets'] ); if ( 'customize' !== $theme_changed ) { + // Update the widgets settings in the database. wp_set_sidebars_widgets( $sidebars_widgets ); } @@ -1728,11 +1739,12 @@ function wp_widget_rss_process( $widget_rss, $check_feed = true ) { $show_summary = isset( $widget_rss['show_summary'] ) ? (int) $widget_rss['show_summary'] : 0; $show_author = isset( $widget_rss['show_author'] ) ? (int) $widget_rss['show_author'] : 0; $show_date = isset( $widget_rss['show_date'] ) ? (int) $widget_rss['show_date'] : 0; + $error = false; + $link = ''; if ( $check_feed ) { - $rss = fetch_feed( $url ); - $error = false; - $link = ''; + $rss = fetch_feed( $url ); + if ( is_wp_error( $rss ) ) { $error = $rss->get_error_message(); } else { diff --git a/src/wp-includes/widgets/class-wp-widget-block.php b/src/wp-includes/widgets/class-wp-widget-block.php index bf63359e2152b..44534c7fa88ea 100644 --- a/src/wp-includes/widgets/class-wp-widget-block.php +++ b/src/wp-includes/widgets/class-wp-widget-block.php @@ -202,7 +202,12 @@ public function form( $instance ) { $instance = wp_parse_args( (array) $instance, $this->default_instance ); ?>

- +

get_instance_schema(); foreach ( $schema as $field => $field_schema ) { @@ -303,10 +305,10 @@ public function update( $new_instance, $instance ) { if ( is_wp_error( $value ) ) { continue; } - $instance[ $field ] = $value; + $old_instance[ $field ] = $value; } - return $instance; + return $old_instance; } /** @@ -315,7 +317,6 @@ public function update( $new_instance, $instance ) { * @since 4.8.0 * * @param array $instance Widget instance props. - * @return string */ abstract public function render_media( $instance ); diff --git a/src/wp-includes/widgets/class-wp-widget-tag-cloud.php b/src/wp-includes/widgets/class-wp-widget-tag-cloud.php index fb17e69a1679f..52b06d9b60026 100644 --- a/src/wp-includes/widgets/class-wp-widget-tag-cloud.php +++ b/src/wp-includes/widgets/class-wp-widget-tag-cloud.php @@ -53,6 +53,8 @@ public function widget( $args, $instance ) { } } + $default_title = $title; + $show_count = ! empty( $instance['count'] ); $tag_cloud = wp_tag_cloud( diff --git a/src/wp-includes/wp-db.php b/src/wp-includes/wp-db.php index 04fa15c1ee6a9..53ba207203944 100644 --- a/src/wp-includes/wp-db.php +++ b/src/wp-includes/wp-db.php @@ -59,6 +59,7 @@ class wpdb { * Default is to show errors if both WP_DEBUG and WP_DEBUG_DISPLAY evaluate to true. * * @since 0.71 + * * @var bool */ public $show_errors = false; @@ -67,6 +68,7 @@ class wpdb { * Whether to suppress errors during the DB bootstrapping. Default false. * * @since 2.5.0 + * * @var bool */ public $suppress_errors = false; @@ -75,6 +77,7 @@ class wpdb { * The error encountered during the last query. * * @since 2.5.0 + * * @var string */ public $last_error = ''; @@ -83,6 +86,7 @@ class wpdb { * The number of queries made. * * @since 1.2.0 + * * @var int */ public $num_queries = 0; @@ -91,6 +95,7 @@ class wpdb { * Count of rows returned by the last query. * * @since 0.71 + * * @var int */ public $num_rows = 0; @@ -99,6 +104,7 @@ class wpdb { * Count of rows affected by the last query. * * @since 0.71 + * * @var int */ public $rows_affected = 0; @@ -107,6 +113,7 @@ class wpdb { * The ID generated for an AUTO_INCREMENT column by the last query (usually INSERT). * * @since 0.71 + * * @var int */ public $insert_id = 0; @@ -115,6 +122,7 @@ class wpdb { * The last query made. * * @since 0.71 + * * @var string */ public $last_query; @@ -123,6 +131,7 @@ class wpdb { * Results of the last query. * * @since 0.71 + * * @var array|null */ public $last_result; @@ -131,6 +140,7 @@ class wpdb { * MySQL result, which is either a resource or boolean. * * @since 0.71 + * * @var mixed */ protected $result; @@ -139,6 +149,7 @@ class wpdb { * Cached column info, for sanity checking data before inserting. * * @since 4.2.0 + * * @var array */ protected $col_meta = array(); @@ -147,6 +158,7 @@ class wpdb { * Calculated character sets on tables. * * @since 4.2.0 + * * @var array */ protected $table_charset = array(); @@ -155,6 +167,7 @@ class wpdb { * Whether text fields in the current query need to be sanity checked. Default false. * * @since 4.2.0 + * * @var bool */ protected $check_current_query = true; @@ -163,6 +176,7 @@ class wpdb { * Flag to ensure we don't run into recursion problems when checking the collation. * * @since 4.2.0 + * * @see wpdb::check_safe_collation() * @var bool */ @@ -172,6 +186,7 @@ class wpdb { * Saved info on the table column. * * @since 0.71 + * * @var array */ protected $col_info; @@ -204,6 +219,7 @@ class wpdb { * The number of times to retry reconnecting before dying. Default 5. * * @since 3.9.0 + * * @see wpdb::check_connection() * @var int */ @@ -216,6 +232,7 @@ class wpdb { * The second reason is for possible security precautions. * * @since 2.5.0 + * * @var string */ public $prefix = ''; @@ -224,6 +241,7 @@ class wpdb { * WordPress base table prefix. * * @since 3.0.0 + * * @var string */ public $base_prefix; @@ -232,6 +250,7 @@ class wpdb { * Whether the database queries are ready to start executing. * * @since 2.3.2 + * * @var bool */ public $ready = false; @@ -240,6 +259,7 @@ class wpdb { * Blog ID. * * @since 3.0.0 + * * @var int */ public $blogid = 0; @@ -248,6 +268,7 @@ class wpdb { * Site ID. * * @since 3.0.0 + * * @var int */ public $siteid = 0; @@ -256,6 +277,7 @@ class wpdb { * List of WordPress per-blog tables. * * @since 2.5.0 + * * @see wpdb::tables() * @var array */ @@ -278,6 +300,7 @@ class wpdb { * 'categories', 'post2cat', and 'link2cat' were deprecated in 2.3.0, db version 5539. * * @since 2.9.0 + * * @see wpdb::tables() * @var array */ @@ -287,6 +310,7 @@ class wpdb { * List of WordPress global tables. * * @since 3.0.0 + * * @see wpdb::tables() * @var array */ @@ -296,6 +320,7 @@ class wpdb { * List of Multisite global tables. * * @since 3.0.0 + * * @see wpdb::tables() * @var array */ @@ -313,6 +338,7 @@ class wpdb { * WordPress Comments table. * * @since 1.5.0 + * * @var string */ public $comments; @@ -321,6 +347,7 @@ class wpdb { * WordPress Comment Metadata table. * * @since 2.9.0 + * * @var string */ public $commentmeta; @@ -329,6 +356,7 @@ class wpdb { * WordPress Links table. * * @since 1.5.0 + * * @var string */ public $links; @@ -337,6 +365,7 @@ class wpdb { * WordPress Options table. * * @since 1.5.0 + * * @var string */ public $options; @@ -345,6 +374,7 @@ class wpdb { * WordPress Post Metadata table. * * @since 1.5.0 + * * @var string */ public $postmeta; @@ -353,6 +383,7 @@ class wpdb { * WordPress Posts table. * * @since 1.5.0 + * * @var string */ public $posts; @@ -361,6 +392,7 @@ class wpdb { * WordPress Terms table. * * @since 2.3.0 + * * @var string */ public $terms; @@ -369,6 +401,7 @@ class wpdb { * WordPress Term Relationships table. * * @since 2.3.0 + * * @var string */ public $term_relationships; @@ -377,6 +410,7 @@ class wpdb { * WordPress Term Taxonomy table. * * @since 2.3.0 + * * @var string */ public $term_taxonomy; @@ -385,6 +419,7 @@ class wpdb { * WordPress Term Meta table. * * @since 4.4.0 + * * @var string */ public $termmeta; @@ -397,6 +432,7 @@ class wpdb { * WordPress User Metadata table. * * @since 2.3.0 + * * @var string */ public $usermeta; @@ -405,6 +441,7 @@ class wpdb { * WordPress Users table. * * @since 1.5.0 + * * @var string */ public $users; @@ -413,6 +450,7 @@ class wpdb { * Multisite Blogs table. * * @since 3.0.0 + * * @var string */ public $blogs; @@ -421,6 +459,7 @@ class wpdb { * Multisite Blog Metadata table. * * @since 5.1.0 + * * @var string */ public $blogmeta; @@ -429,6 +468,7 @@ class wpdb { * Multisite Registration Log table. * * @since 3.0.0 + * * @var string */ public $registration_log; @@ -437,6 +477,7 @@ class wpdb { * Multisite Signups table. * * @since 3.0.0 + * * @var string */ public $signups; @@ -445,6 +486,7 @@ class wpdb { * Multisite Sites table. * * @since 3.0.0 + * * @var string */ public $site; @@ -453,6 +495,7 @@ class wpdb { * Multisite Sitewide Terms table. * * @since 3.0.0 + * * @var string */ public $sitecategories; @@ -461,6 +504,7 @@ class wpdb { * Multisite Site Metadata table. * * @since 3.0.0 + * * @var string */ public $sitemeta; @@ -472,6 +516,7 @@ class wpdb { * Keys are column names, values are format types: 'ID' => '%d'. * * @since 2.8.0 + * * @see wpdb::prepare() * @see wpdb::insert() * @see wpdb::update() @@ -485,6 +530,7 @@ class wpdb { * Database table columns charset. * * @since 2.2.0 + * * @var string */ public $charset; @@ -493,6 +539,7 @@ class wpdb { * Database table columns collate. * * @since 2.2.0 + * * @var string */ public $collate; @@ -501,6 +548,7 @@ class wpdb { * Database Username. * * @since 2.9.0 + * * @var string */ protected $dbuser; @@ -509,6 +557,7 @@ class wpdb { * Database Password. * * @since 3.1.0 + * * @var string */ protected $dbpassword; @@ -517,6 +566,7 @@ class wpdb { * Database Name. * * @since 3.1.0 + * * @var string */ protected $dbname; @@ -525,6 +575,7 @@ class wpdb { * Database Host. * * @since 3.1.0 + * * @var string */ protected $dbhost; @@ -533,6 +584,7 @@ class wpdb { * Database Handle. * * @since 0.71 + * * @var string */ protected $dbh; @@ -541,6 +593,7 @@ class wpdb { * A textual description of the last query/get_row/get_var call. * * @since 3.0.0 + * * @var string */ public $func_call; @@ -554,6 +607,7 @@ class wpdb { * will force the checks to occur. * * @since 3.3.0 + * * @var bool */ public $is_mysql = null; @@ -562,6 +616,7 @@ class wpdb { * A list of incompatible SQL modes. * * @since 3.9.0 + * * @var array */ protected $incompatible_modes = array( @@ -577,6 +632,7 @@ class wpdb { * Whether to use mysqli over mysql. Default false. * * @since 3.9.0 + * * @var bool */ private $use_mysqli = false; @@ -585,10 +641,31 @@ class wpdb { * Whether we've managed to successfully connect at some point. * * @since 3.9.0 + * * @var bool */ private $has_connected = false; + /** + * Time when the last query was performed. + * + * Only set when `SAVEQUERIES` is defined and truthy. + * + * @since 1.5.0 + * + * @var float + */ + public $time_start = null; + + /** + * The last SQL error that was encountered. + * + * @since 2.5.0 + * + * @var WP_Error|string + */ + public $error = null; + /** * Connects to the database server and selects a database. * @@ -1139,7 +1216,7 @@ public function select( $db, $dbh = null ) { * @param string $string * @return string */ - function _weak_escape( $string ) { + public function _weak_escape( $string ) { if ( func_num_args() === 1 && function_exists( '_deprecated_function' ) ) { _deprecated_function( __METHOD__, '3.6.0', 'wpdb::prepare() or esc_sql()' ); } @@ -1157,8 +1234,8 @@ function _weak_escape( $string ) { * @param string $string String to escape. * @return string Escaped string. */ - function _real_escape( $string ) { - if ( ! is_scalar( $string ) && ! is_null( $string ) ) { + public function _real_escape( $string ) { + if ( ! is_scalar( $string ) ) { return ''; } @@ -2254,7 +2331,7 @@ public function replace( $table, $data, $format = null ) { * Default 'INSERT'. * @return int|false The number of rows affected, or false on error. */ - function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { + public function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT' ) { $this->insert_id = 0; if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ), true ) ) { diff --git a/src/wp-login.php b/src/wp-login.php index 11517dac21a67..b7c14b4c83f60 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -434,18 +434,18 @@ function wp_login_viewport_meta() { * * Possible hook names include: * - * - 'login_form_checkemail' - * - 'login_form_confirm_admin_email' - * - 'login_form_confirmaction' - * - 'login_form_entered_recovery_mode' - * - 'login_form_login' - * - 'login_form_logout' - * - 'login_form_lostpassword' - * - 'login_form_postpass' - * - 'login_form_register' - * - 'login_form_resetpass' - * - 'login_form_retrievepassword' - * - 'login_form_rp' + * - `login_form_checkemail` + * - `login_form_confirm_admin_email` + * - `login_form_confirmaction` + * - `login_form_entered_recovery_mode` + * - `login_form_login` + * - `login_form_logout` + * - `login_form_lostpassword` + * - `login_form_postpass` + * - `login_form_register` + * - `login_form_resetpass` + * - `login_form_retrievepassword` + * - `login_form_rp` * * @since 2.8.0 */ @@ -1267,7 +1267,10 @@ function wp_login_viewport_meta() { $errors->add( 'enter_recovery_mode', __( 'Recovery Mode Initialized. Please log in to continue.' ), 'message' ); } elseif ( isset( $_GET['redirect_to'] ) && false !== strpos( $_GET['redirect_to'], 'wp-admin/authorize-application.php' ) ) { $query_component = wp_parse_url( $_GET['redirect_to'], PHP_URL_QUERY ); - parse_str( $query_component, $query ); + $query = array(); + if ( $query_component ) { + parse_str( $query_component, $query ); + } if ( ! empty( $query['app_name'] ) ) { /* translators: 1: Website name, 2: Application name. */ diff --git a/src/wp-mail.php b/src/wp-mail.php index 1d5fbedf03987..c3f921ad69c6e 100644 --- a/src/wp-mail.php +++ b/src/wp-mail.php @@ -77,6 +77,9 @@ $content_transfer_encoding = ''; $post_author = 1; $author_found = false; + $post_date = null; + $post_date_gmt = null; + foreach ( $message as $line ) { // Body signal. if ( strlen( $line ) < 3 ) { diff --git a/src/wp-signup.php b/src/wp-signup.php index cbc4ddb4020df..375dad9517c56 100644 --- a/src/wp-signup.php +++ b/src/wp-signup.php @@ -15,7 +15,7 @@ } /** - * Prints signup_header via wp_head + * Prints signup_header via wp_head. * * @since MU (3.0.0) */ @@ -43,14 +43,14 @@ function do_signup_header() { $wp_query->is_404 = false; /** - * Fires before the Site Signup page is loaded. + * Fires before the Site Sign-up page is loaded. * * @since 4.4.0 */ do_action( 'before_signup_header' ); /** - * Prints styles for front-end Multisite signup pages + * Prints styles for front-end Multisite Sign-up pages. * * @since MU (3.0.0) */ @@ -79,7 +79,7 @@ function wpmu_signup_stylesheet() { get_header( 'wp-signup' ); /** - * Fires before the site sign-up form. + * Fires before the site Sign-up form. * * @since 3.0.0 */ @@ -89,7 +89,7 @@ function wpmu_signup_stylesheet() {
@@ -744,17 +747,17 @@ function signup_blog( $user_name = '', $user_email = '', $blogname = '', $blog_t do_action( 'signup_hidden_fields', 'validate-site' ); ?> -

+

assertIsObject( $object, $message . ' Passed $object is not an object.' ); + $this->assertIsArray( $fields, $message . ' Passed $fields is not an array.' ); + $this->assertNotEmpty( $fields, $message . ' Fields array is empty.' ); + foreach ( $fields as $field_name => $field_value ) { $this->assertObjectHasAttribute( $field_name, $object, $message . " Property $field_name does not exist on the object." ); $this->assertSame( $field_value, $object->$field_name, $message . " Value of property $field_name is not $field_value." ); @@ -697,12 +703,20 @@ public function assertEqualFields( $object, $fields, $message = '' ) { * @since UT (3.7.0) * @since 5.9.0 Added the `$message` parameter. * - * @param string $expected The expected value. - * @param string $actual The actual value. + * @param mixed $expected The expected value. + * @param mixed $actual The actual value. * @param string $message Optional. Message to display when the assertion fails. */ public function assertDiscardWhitespace( $expected, $actual, $message = '' ) { - $this->assertEquals( preg_replace( '/\s*/', '', $expected ), preg_replace( '/\s*/', '', $actual ), $message ); + if ( is_string( $expected ) ) { + $expected = preg_replace( '/\s*/', '', $expected ); + } + + if ( is_string( $actual ) ) { + $actual = preg_replace( '/\s*/', '', $actual ); + } + + $this->assertEquals( $expected, $actual, $message ); } /** @@ -712,24 +726,36 @@ public function assertDiscardWhitespace( $expected, $actual, $message = '' ) { * @since 5.8.0 Added support for nested arrays. * @since 5.9.0 Added the `$message` parameter. * - * @param string|array $expected The expected value. - * @param string|array $actual The actual value. - * @param string $message Optional. Message to display when the assertion fails. + * @param mixed $expected The expected value. + * @param mixed $actual The actual value. + * @param string $message Optional. Message to display when the assertion fails. */ public function assertSameIgnoreEOL( $expected, $actual, $message = '' ) { - $expected = map_deep( - $expected, - function ( $value ) { - return str_replace( "\r\n", "\n", $value ); - } - ); + if ( null !== $expected ) { + $expected = map_deep( + $expected, + static function ( $value ) { + if ( is_string( $value ) ) { + return str_replace( "\r\n", "\n", $value ); + } + + return $value; + } + ); + } - $actual = map_deep( - $actual, - function ( $value ) { - return str_replace( "\r\n", "\n", $value ); - } - ); + if ( null !== $actual ) { + $actual = map_deep( + $actual, + static function ( $value ) { + if ( is_string( $value ) ) { + return str_replace( "\r\n", "\n", $value ); + } + + return $value; + } + ); + } $this->assertSame( $expected, $actual, $message ); } @@ -741,8 +767,8 @@ function ( $value ) { * @since 5.6.0 Turned into an alias for `::assertSameIgnoreEOL()`. * @since 5.9.0 Added the `$message` parameter. * - * @param string $expected The expected value. - * @param string $actual The actual value. + * @param mixed $expected The expected value. + * @param mixed $actual The actual value. * @param string $message Optional. Message to display when the assertion fails. */ public function assertEqualsIgnoreEOL( $expected, $actual, $message = '' ) { @@ -760,6 +786,9 @@ public function assertEqualsIgnoreEOL( $expected, $actual, $message = '' ) { * @param string $message Optional. Message to display when the assertion fails. */ public function assertSameSets( $expected, $actual, $message = '' ) { + $this->assertIsArray( $expected, $message . ' Expected value must be an array.' ); + $this->assertIsArray( $actual, $message . ' Value under test is not an array.' ); + sort( $expected ); sort( $actual ); $this->assertSame( $expected, $actual, $message ); @@ -776,6 +805,9 @@ public function assertSameSets( $expected, $actual, $message = '' ) { * @param string $message Optional. Message to display when the assertion fails. */ public function assertEqualSets( $expected, $actual, $message = '' ) { + $this->assertIsArray( $expected, $message . ' Expected value must be an array.' ); + $this->assertIsArray( $actual, $message . ' Value under test is not an array.' ); + sort( $expected ); sort( $actual ); $this->assertEquals( $expected, $actual, $message ); @@ -792,6 +824,9 @@ public function assertEqualSets( $expected, $actual, $message = '' ) { * @param string $message Optional. Message to display when the assertion fails. */ public function assertSameSetsWithIndex( $expected, $actual, $message = '' ) { + $this->assertIsArray( $expected, $message . ' Expected value must be an array.' ); + $this->assertIsArray( $actual, $message . ' Value under test is not an array.' ); + ksort( $expected ); ksort( $actual ); $this->assertSame( $expected, $actual, $message ); @@ -808,6 +843,9 @@ public function assertSameSetsWithIndex( $expected, $actual, $message = '' ) { * @param string $message Optional. Message to display when the assertion fails. */ public function assertEqualSetsWithIndex( $expected, $actual, $message = '' ) { + $this->assertIsArray( $expected, $message . ' Expected value must be an array.' ); + $this->assertIsArray( $actual, $message . ' Value under test is not an array.' ); + ksort( $expected ); ksort( $actual ); $this->assertEquals( $expected, $actual, $message ); diff --git a/tests/phpunit/includes/bootstrap.php b/tests/phpunit/includes/bootstrap.php index 9a4e5fc160748..f366c8ce0379a 100644 --- a/tests/phpunit/includes/bootstrap.php +++ b/tests/phpunit/includes/bootstrap.php @@ -31,8 +31,18 @@ require_once __DIR__ . '/functions.php'; if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS && ! is_dir( ABSPATH ) ) { - echo 'Error: The /build/ directory is missing! Please run `npm run build` prior to running PHPUnit.' . PHP_EOL; - exit( 1 ); + if ( substr( ABSPATH, -7 ) !== '/build/' ) { + printf( + 'Error: The ABSPATH constant in the `wp-tests-config.php` file is set to a non-existent path "%s". Please verify.' . PHP_EOL, + ABSPATH + ); + exit( 1 ); + } else { + echo 'Error: The PHPUnit tests should be run on the /src/ directory, not the /build/ directory.' + . ' Please update the ABSPATH constant in your `wp-tests-config.php` file to `dirname( __FILE__ ) . \'/src/\'`' + . ' or run `npm run build` prior to running PHPUnit.' . PHP_EOL; + exit( 1 ); + } } $phpunit_version = tests_get_phpunit_version(); @@ -51,22 +61,25 @@ * * The PHPUnit Polyfills are a requirement for the WP test suite. * + * For running the Core tests, the Make WordPress Core handbook contains step-by-step instructions + * on how to get up and running for a variety of supported workflows: + * {@link https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/#test-running-workflow-options} + * * Plugin/theme integration tests can handle this in any of the following ways: - * - When using a full WP install: run `composer update` for the WP install prior to running the tests. + * - When using a full WP install: run `composer update -W` for the WP install prior to running the tests. * - When using a partial WP test suite install: - * - Add a `yoast/phpunit-polyfills` (dev) requirement to their own `composer.json` file. + * - Add a `yoast/phpunit-polyfills` (dev) requirement to the plugin/theme's own `composer.json` file. * - And then: * - Either load the PHPUnit Polyfills autoload file prior to running the WP core bootstrap file. - * - Or declare a `WP_TESTS_PHPUNIT_POLYFILLS_PATH` constant pointing to the root directory - * of the PHPUnit Polyfills installation. - * This constant can be declared in the `phpunit.xml[.dist]` file like this: - * ` - * or can be declared as a PHP constant in the `wp-tests-config.php` file or the plugin/theme - * test bootstrap file. + * - Or declare a `WP_TESTS_PHPUNIT_POLYFILLS_PATH` constant containing the absolute path to the + * root directory of the PHPUnit Polyfills installation. + * If the constant is used, it is strongly recommended to declare this constant in the plugin/theme's + * own test bootstrap file. + * The constant MUST be declared prior to calling this file. */ if ( ! class_exists( 'Yoast\PHPUnitPolyfills\Autoload' ) ) { // Default location of the autoloader for WP core test runs. - $phpunit_polyfills_autoloader = __DIR__ . '/../../../vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php'; + $phpunit_polyfills_autoloader = dirname( dirname( dirname( __DIR__ ) ) ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php'; $phpunit_polyfills_error = false; // Allow for a custom installation location to be provided for plugin/theme integration tests. @@ -76,13 +89,13 @@ if ( is_string( WP_TESTS_PHPUNIT_POLYFILLS_PATH ) && '' !== WP_TESTS_PHPUNIT_POLYFILLS_PATH ) { - $phpunit_polyfills_path = rtrim( $phpunit_polyfills_path, '/\\' ); - $phpunit_polyfills_path = realpath( $phpunit_polyfills_path . '/phpunitpolyfills-autoload.php' ); - if ( false !== $phpunit_polyfills_path ) { - $phpunit_polyfills_autoloader = $phpunit_polyfills_path; - } else { - $phpunit_polyfills_error = true; + // Be tolerant to the path being provided including the filename. + if ( substr( $phpunit_polyfills_path, -29 ) !== 'phpunitpolyfills-autoload.php' ) { + $phpunit_polyfills_path = rtrim( $phpunit_polyfills_path, '/\\' ); + $phpunit_polyfills_path = $phpunit_polyfills_path . '/phpunitpolyfills-autoload.php'; } + + $phpunit_polyfills_autoloader = $phpunit_polyfills_path; } else { $phpunit_polyfills_error = true; } @@ -90,15 +103,30 @@ if ( $phpunit_polyfills_error || ! file_exists( $phpunit_polyfills_autoloader ) ) { echo 'Error: The PHPUnit Polyfills library is a requirement for running the WP test suite.' . PHP_EOL; - if ( isset( $phpunit_polyfills_path ) ) { + if ( defined( 'WP_TESTS_PHPUNIT_POLYFILLS_PATH' ) ) { printf( 'The PHPUnit Polyfills autoload file was not found in "%s"' . PHP_EOL, WP_TESTS_PHPUNIT_POLYFILLS_PATH ); echo 'Please verify that the file path provided in the WP_TESTS_PHPUNIT_POLYFILLS_PATH constant is correct.' . PHP_EOL; + echo 'The WP_TESTS_PHPUNIT_POLYFILLS_PATH constant should contain an absolute path to the root directory' + . ' of the PHPUnit Polyfills library.' . PHP_EOL; + } elseif ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) { + echo 'You need to run `composer update -W` before running the tests.' . PHP_EOL; + echo 'Once the dependencies are installed, you can run the tests using the Composer-installed version' + . ' of PHPUnit or using a PHPUnit phar file, but the dependencies do need to be installed' + . ' whichever way the tests are run.' . PHP_EOL; } else { - echo 'You need to run `composer update` before running the tests.' . PHP_EOL; - echo 'Once the dependencies are installed, you can run the tests using the Composer-installed version of PHPUnit or using a PHPUnit phar file, but the dependencies do need to be installed whichever way the tests are run.' . PHP_EOL; + echo 'If you are trying to run plugin/theme integration tests, make sure the PHPUnit Polyfills library' + . ' (https://github.com/Yoast/PHPUnit-Polyfills) is available and either load the autoload file' + . ' of this library in your own test bootstrap before calling the WP Core test bootstrap file;' + . ' or set the absolute path to the PHPUnit Polyfills library in a "WP_TESTS_PHPUNIT_POLYFILLS_PATH"' + . ' constant to allow the WP Core bootstrap to load the Polyfills.' . PHP_EOL . PHP_EOL; + echo 'If you are trying to run the WP Core tests, make sure to set the "WP_RUN_CORE_TESTS" constant' + . ' to 1 and run `composer update -W` before running the tests.' . PHP_EOL; + echo 'Once the dependencies are installed, you can run the tests using the Composer-installed' + . ' version of PHPUnit or using a PHPUnit phar file, but the dependencies do need to be' + . ' installed whichever way the tests are run.' . PHP_EOL; } exit( 1 ); } @@ -114,14 +142,22 @@ $phpunit_polyfills_minimum_version = '1.0.1'; if ( class_exists( '\Yoast\PHPUnitPolyfills\Autoload' ) && ( defined( '\Yoast\PHPUnitPolyfills\Autoload::VERSION' ) === false - || version_compare( \Yoast\PHPUnitPolyfills\Autoload::VERSION, $phpunit_polyfills_minimum_version, '<' ) ) + || version_compare( Yoast\PHPUnitPolyfills\Autoload::VERSION, $phpunit_polyfills_minimum_version, '<' ) ) ) { printf( - 'Error: Version mismatch detected for the PHPUnit Polyfills. Please ensure that PHPUnit Polyfills %s or higher is loaded.' . PHP_EOL, - $phpunit_polyfills_minimum_version + 'Error: Version mismatch detected for the PHPUnit Polyfills.' + . ' Please ensure that PHPUnit Polyfills %s or higher is loaded. Found version: %s' . PHP_EOL, + $phpunit_polyfills_minimum_version, + defined( '\Yoast\PHPUnitPolyfills\Autoload::VERSION' ) ? Yoast\PHPUnitPolyfills\Autoload::VERSION : '1.0.0 or lower' ); - if ( ! defined( 'WP_TESTS_PHPUNIT_POLYFILLS_PATH' ) ) { - echo 'Please run `composer update` to install the latest version.' . PHP_EOL; + if ( defined( 'WP_TESTS_PHPUNIT_POLYFILLS_PATH' ) ) { + printf( + 'Please ensure that the PHPUnit Polyfill installation in "%s" is updated to version %s or higher.' . PHP_EOL, + WP_TESTS_PHPUNIT_POLYFILLS_PATH, + $phpunit_polyfills_minimum_version + ); + } elseif ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) { + echo 'Please run `composer update -W` to install the latest version.' . PHP_EOL; } exit( 1 ); } diff --git a/tests/phpunit/includes/mock-image-editor.php b/tests/phpunit/includes/mock-image-editor.php index 4cd252b1c3459..bc08fbb2907be 100644 --- a/tests/phpunit/includes/mock-image-editor.php +++ b/tests/phpunit/includes/mock-image-editor.php @@ -56,6 +56,8 @@ public function flip( $horz, $vert ) { } } public function save( $destfilename = null, $mime_type = null ) { + // Set new mime-type and quality if converting the image. + $this->get_output_format( $destfilename, $mime_type ); return self::$save_return; } public function stream( $mime_type = null ) { diff --git a/tests/phpunit/includes/plural-form-function.php b/tests/phpunit/includes/plural-form-function.php index 714381339d15d..a5cdf703e3b91 100644 --- a/tests/phpunit/includes/plural-form-function.php +++ b/tests/phpunit/includes/plural-form-function.php @@ -7,7 +7,7 @@ * @param string $expression */ function tests_make_plural_form_function( $nplurals, $expression ) { - $closure = function ( $n ) use ( $nplurals, $expression ) { + $closure = static function ( $n ) use ( $nplurals, $expression ) { $expression = str_replace( 'n', $n, $expression ); // phpcs:ignore Squiz.PHP.Eval -- This is test code, not production. diff --git a/tests/phpunit/includes/spy-rest-server.php b/tests/phpunit/includes/spy-rest-server.php index 596117347ce00..5bfd1d2dba306 100644 --- a/tests/phpunit/includes/spy-rest-server.php +++ b/tests/phpunit/includes/spy-rest-server.php @@ -6,6 +6,7 @@ class Spy_REST_Server extends WP_REST_Server { public $sent_body = ''; public $last_request = null; public $override_by_default = false; + public $status = null; /** * Gets the raw $endpoints data from the server. @@ -37,6 +38,14 @@ public function send_header( $header, $value ) { $this->sent_headers[ $header ] = $value; } + /** + * Stores last set status. + * @param int $code HTTP status. + */ + public function set_status( $status ) { + $this->status = $status; + } + /** * Removes a header from the list of sent headers. * diff --git a/tests/phpunit/multisite.xml b/tests/phpunit/multisite.xml index ea9fa9d203bfe..5bb20a759da27 100644 --- a/tests/phpunit/multisite.xml +++ b/tests/phpunit/multisite.xml @@ -6,6 +6,10 @@ colors="true" beStrictAboutTestsThatDoNotTestAnything="true" beStrictAboutOutputDuringTests="true" + convertErrorsToExceptions="true" + convertWarningsToExceptions="true" + convertNoticesToExceptions="true" + convertDeprecationsToExceptions="true" > diff --git a/tests/phpunit/tests/actions.php b/tests/phpunit/tests/actions.php index a511890bb7c5e..ceacc72d7c9b9 100644 --- a/tests/phpunit/tests/actions.php +++ b/tests/phpunit/tests/actions.php @@ -7,6 +7,9 @@ */ class Tests_Actions extends WP_UnitTestCase { + /** + * @covers ::do_action + */ function test_simple_action() { $a = new MockAction(); $tag = __FUNCTION__; @@ -24,6 +27,9 @@ function test_simple_action() { $this->assertSame( array( '' ), $args ); } + /** + * @covers ::remove_action + */ function test_remove_action() { $a = new MockAction(); $tag = __FUNCTION__; @@ -43,6 +49,9 @@ function test_remove_action() { } + /** + * @covers ::has_action + */ function test_has_action() { $tag = __FUNCTION__; $func = __FUNCTION__ . '_func'; @@ -57,7 +66,11 @@ function test_has_action() { $this->assertFalse( has_action( $tag ) ); } - // One tag with multiple actions. + /** + * One tag with multiple actions. + * + * @covers ::do_action + */ function test_multiple_actions() { $a1 = new MockAction(); $a2 = new MockAction(); @@ -74,6 +87,11 @@ function test_multiple_actions() { $this->assertSame( 1, $a2->get_call_count() ); } + /** + * One tag with multiple actions. + * + * @covers ::do_action + */ function test_action_args_1() { $a = new MockAction(); $tag = __FUNCTION__; @@ -89,6 +107,11 @@ function test_action_args_1() { $this->assertSame( array( $val ), array_pop( $argsvar ) ); } + /** + * One tag with multiple actions. + * + * @covers ::do_action + */ function test_action_args_2() { $a1 = new MockAction(); $a2 = new MockAction(); @@ -120,6 +143,8 @@ function test_action_args_2() { * * @see https://core.trac.wordpress.org/ticket/17817#comment:72 * @ticket 17817 + * + * @covers ::do_action */ function test_action_args_3() { $a1 = new MockAction(); @@ -157,6 +182,8 @@ function test_action_args_3() { * Tests PHP 4 notation for calling actions while passing in an object by reference. * * @ticket 48312 + * + * @covers ::do_action */ function test_action_args_with_php4_syntax() { $a = new MockAction(); @@ -201,6 +228,9 @@ function test_action_priority() { $this->assertSame( $expected, $a->get_events() ); } + /** + * @covers ::did_action + */ function test_did_action() { $tag1 = 'action1'; $tag2 = 'action2'; @@ -222,6 +252,9 @@ function test_did_action() { } + /** + * @covers ::do_action + */ function test_all_action() { $a = new MockAction(); $tag1 = __FUNCTION__ . '_1'; @@ -246,6 +279,9 @@ function test_all_action() { } + /** + * @covers ::remove_action + */ function test_remove_all_action() { $a = new MockAction(); $tag = __FUNCTION__; @@ -266,6 +302,9 @@ function test_remove_all_action() { $this->assertSame( array( $tag ), $a->get_tags() ); } + /** + * @covers ::do_action_ref_array + */ function test_action_ref_array() { $obj = new stdClass(); $a = new MockAction(); @@ -284,6 +323,8 @@ function test_action_ref_array() { /** * @ticket 11241 + * + * @covers ::do_action */ function test_action_keyed_array() { $a = new MockAction(); @@ -309,6 +350,9 @@ function test_action_keyed_array() { } + /** + * @covers ::remove_action + */ function test_action_self_removal() { add_action( 'test_action_self_removal', array( $this, 'action_self_removal' ) ); do_action( 'test_action_self_removal' ); @@ -321,6 +365,8 @@ function action_self_removal() { /** * @ticket 17817 + * + * @covers ::do_action */ function test_action_recursion() { $tag = __FUNCTION__; @@ -336,6 +382,9 @@ function test_action_recursion() { $this->assertSame( 2, $b->get_call_count(), 'recursive actions should call callbacks with later priority' ); } + /** + * @covers ::do_action + */ function action_that_causes_recursion( $tag ) { static $recursing = false; if ( ! $recursing ) { @@ -348,6 +397,9 @@ function action_that_causes_recursion( $tag ) { /** * @ticket 9968 * @ticket 17817 + * + * @covers ::remove_action + * @covers ::add_action */ function test_action_callback_manipulation_while_running() { $tag = __FUNCTION__; @@ -383,6 +435,8 @@ function action_that_manipulates_a_running_hook( $tag, $mocks ) { * * This specificaly addresses the concern raised at * https://core.trac.wordpress.org/ticket/17817#comment:52 + * + * @covers ::remove_filter */ function test_remove_anonymous_callback() { $tag = __FUNCTION__; @@ -416,6 +470,10 @@ function test_remove_anonymous_callback() { * Test the ArrayAccess methods of WP_Hook * * @ticket 17817 + * + * @covers WP_Hook::offsetGet + * @covers WP_Hook::offsetSet + * @covers WP_Hook::offsetUnset */ function test_array_access_of_wp_filter_global() { global $wp_filter; @@ -442,6 +500,8 @@ function test_array_access_of_wp_filter_global() { * Make sure current_action() behaves as current_filter() * * @ticket 14994 + * + * @covers ::current_action */ function test_current_action() { global $wp_current_filter; @@ -453,6 +513,8 @@ function test_current_action() { /** * @ticket 14994 + * + * @covers ::doing_filter */ function test_doing_filter() { global $wp_current_filter; @@ -472,6 +534,8 @@ function test_doing_filter() { /** * @ticket 14994 + * + * @covers ::doing_filter */ function test_doing_action() { global $wp_current_filter; @@ -491,6 +555,8 @@ function test_doing_action() { /** * @ticket 14994 + * + * @covers ::doing_filter */ function test_doing_filter_real() { $this->assertFalse( doing_filter() ); // No filter is passed in, and no filter is being processed. @@ -541,6 +607,8 @@ function apply_testing_nested_filter() { /** * @ticket 10441 * @expectedDeprecated tests_do_action_deprecated + * + * @covers ::do_action_deprecated */ public function test_do_action_deprecated() { $p = new WP_Post( (object) array( 'post_title' => 'Foo' ) ); @@ -559,6 +627,8 @@ public static function deprecated_action_callback( $p ) { /** * @ticket 10441 * @expectedDeprecated tests_do_action_deprecated + * + * @covers ::do_action_deprecated */ public function test_do_action_deprecated_with_multiple_params() { $p1 = new WP_Post( (object) array( 'post_title' => 'Foo1' ) ); diff --git a/tests/phpunit/tests/actions/callbacks.php b/tests/phpunit/tests/actions/callbacks.php index fc58c3390670e..32d1c733d97e6 100644 --- a/tests/phpunit/tests/actions/callbacks.php +++ b/tests/phpunit/tests/actions/callbacks.php @@ -7,6 +7,8 @@ class Tests_Actions_Callbacks extends WP_UnitTestCase { /** * @ticket 23265 + * + * @covers ::add_action */ function test_callback_representations() { $tag = __FUNCTION__; diff --git a/tests/phpunit/tests/actions/closures.php b/tests/phpunit/tests/actions/closures.php index d1a458e273005..833367714b908 100644 --- a/tests/phpunit/tests/actions/closures.php +++ b/tests/phpunit/tests/actions/closures.php @@ -9,10 +9,14 @@ class Tests_Actions_Closures extends WP_UnitTestCase { /** * @ticket 10493 + * + * @covers ::add_action + * @covers ::has_action + * @covers ::do_action */ function test_action_closure() { $tag = 'test_action_closure'; - $closure = function( $a, $b ) { + $closure = static function( $a, $b ) { $GLOBALS[ $a ] = $b; }; add_action( $tag, $closure, 10, 2 ); @@ -25,7 +29,7 @@ function test_action_closure() { $this->assertSame( $GLOBALS[ $context[0] ], $context[1] ); $tag2 = 'test_action_closure_2'; - $closure2 = function() { + $closure2 = static function() { $GLOBALS['closure_no_args'] = true; }; add_action( $tag2, $closure2 ); diff --git a/tests/phpunit/tests/admin/includesComment.php b/tests/phpunit/tests/admin/includesComment.php index 79f96afe24f16..1e0aba2108fd2 100644 --- a/tests/phpunit/tests/admin/includesComment.php +++ b/tests/phpunit/tests/admin/includesComment.php @@ -47,6 +47,8 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { /** * Verify that both the comment date and author must match for a comment to exist. + * + * @covers ::comment_exists */ public function test_must_match_date_and_author() { $this->assertNull( comment_exists( 1, '2004-01-02 12:00:00' ) ); @@ -55,6 +57,8 @@ public function test_must_match_date_and_author() { /** * @ticket 33871 + * + * @covers ::comment_exists */ public function test_default_value_of_timezone_should_be_blog() { $this->assertEquals( self::$post_id, comment_exists( 1, '2014-05-06 12:00:00' ) ); @@ -62,6 +66,8 @@ public function test_default_value_of_timezone_should_be_blog() { /** * @ticket 33871 + * + * @covers ::comment_exists */ public function test_should_respect_timezone_blog() { $this->assertEquals( self::$post_id, comment_exists( 1, '2014-05-06 12:00:00', 'blog' ) ); @@ -69,6 +75,8 @@ public function test_should_respect_timezone_blog() { /** * @ticket 33871 + * + * @covers ::comment_exists */ public function test_should_respect_timezone_gmt() { $this->assertEquals( self::$post_id, comment_exists( 1, '2014-05-06 07:00:00', 'gmt' ) ); @@ -76,6 +84,8 @@ public function test_should_respect_timezone_gmt() { /** * @ticket 33871 + * + * @covers ::comment_exists */ public function test_invalid_timezone_should_fall_back_on_blog() { $this->assertEquals( self::$post_id, comment_exists( 1, '2014-05-06 12:00:00', 'not_a_valid_value' ) ); diff --git a/tests/phpunit/tests/admin/includesFile.php b/tests/phpunit/tests/admin/includesFile.php index a3af5da2d1c9c..db17f834b55ea 100644 --- a/tests/phpunit/tests/admin/includesFile.php +++ b/tests/phpunit/tests/admin/includesFile.php @@ -4,7 +4,7 @@ * @group file * @group admin */ -class Tests_Admin_includesFile extends WP_UnitTestCase { +class Tests_Admin_IncludesFile extends WP_UnitTestCase { /** * @ticket 20449 @@ -77,4 +77,249 @@ public function _fake_download_url_non_200_response_code( $response, $args, $url public function __return_5() { return 5; } + + /** + * @ticket 38231 + * @dataProvider data_download_url_should_respect_filename_from_content_disposition_header + * + * @covers ::download_url + * + * @param $filter A callback containing a fake Content-Disposition header. + */ + public function test_download_url_should_respect_filename_from_content_disposition_header( $filter ) { + add_filter( 'pre_http_request', array( $this, $filter ), 10, 3 ); + + $filename = download_url( 'url_with_content_disposition_header' ); + $this->assertStringContainsString( 'filename-from-content-disposition-header', $filename ); + $this->assertFileExists( $filename ); + $this->unlink( $filename ); + + remove_filter( 'pre_http_request', array( $this, $filter ) ); + } + + /** + * Data provider for test_download_url_should_respect_filename_from_content_disposition_header. + * + * @return array + */ + public function data_download_url_should_respect_filename_from_content_disposition_header() { + return array( + 'valid parameters' => array( 'filter_content_disposition_header_with_filename' ), + 'path traversal' => array( 'filter_content_disposition_header_with_filename_with_path_traversal' ), + 'no quotes' => array( 'filter_content_disposition_header_with_filename_without_quotes' ), + ); + } + + /** + * Filter callback for data_download_url_should_respect_filename_from_content_disposition_header. + * + * @since 5.9.0 + * + * @return array + */ + public function filter_content_disposition_header_with_filename( $response, $args, $url ) { + return array( + 'response' => array( + 'code' => 200, + ), + 'headers' => array( + 'content-disposition' => 'attachment; filename="filename-from-content-disposition-header.txt"', + ), + ); + } + + /** + * Filter callback for data_download_url_should_respect_filename_from_content_disposition_header. + * + * @since 5.9.0 + * + * @return array + */ + public function filter_content_disposition_header_with_filename_with_path_traversal( $response, $args, $url ) { + return array( + 'response' => array( + 'code' => 200, + ), + 'headers' => array( + 'content-disposition' => 'attachment; filename="../../filename-from-content-disposition-header.txt"', + ), + ); + } + + /** + * Filter callback for data_download_url_should_respect_filename_from_content_disposition_header. + * + * @since 5.9.0 + * + * @return array + */ + public function filter_content_disposition_header_with_filename_without_quotes( $response, $args, $url ) { + return array( + 'response' => array( + 'code' => 200, + ), + 'headers' => array( + 'content-disposition' => 'attachment; filename=filename-from-content-disposition-header.txt', + ), + ); + } + + /** + * @ticket 38231 + * @dataProvider data_download_url_should_reject_filename_from_invalid_content_disposition_header + * + * @covers ::download_url + * + * @param $filter A callback containing a fake Content-Disposition header. + */ + public function test_download_url_should_reject_filename_from_invalid_content_disposition_header( $filter ) { + add_filter( 'pre_http_request', array( $this, $filter ), 10, 3 ); + + $filename = download_url( 'url_with_content_disposition_header' ); + $this->assertStringContainsString( 'url_with_content_disposition_header', $filename ); + $this->unlink( $filename ); + + remove_filter( 'pre_http_request', array( $this, $filter ) ); + } + + /** + * Data provider for test_download_url_should_reject_filename_from_invalid_content_disposition_header. + * + * @return array + */ + public function data_download_url_should_reject_filename_from_invalid_content_disposition_header() { + return array( + 'no context' => array( 'filter_content_disposition_header_with_filename_without_context' ), + 'inline context' => array( 'filter_content_disposition_header_with_filename_with_inline_context' ), + 'form-data context' => array( 'filter_content_disposition_header_with_filename_with_form_data_context' ), + ); + } + + /** + * Filter callback for data_download_url_should_reject_filename_from_invalid_content_disposition_header. + * + * @since 5.9.0 + * + * @return array + */ + public function filter_content_disposition_header_with_filename_without_context( $response, $args, $url ) { + return array( + 'response' => array( + 'code' => 200, + ), + 'headers' => array( + 'content-disposition' => 'filename="filename-from-content-disposition-header.txt"', + ), + ); + } + + /** + * Filter callback for data_download_url_should_reject_filename_from_invalid_content_disposition_header. + * + * @since 5.9.0 + * + * @return array + */ + public function filter_content_disposition_header_with_filename_with_inline_context( $response, $args, $url ) { + return array( + 'response' => array( + 'code' => 200, + ), + 'headers' => array( + 'content-disposition' => 'inline; filename="filename-from-content-disposition-header.txt"', + ), + ); + } + + /** + * Filter callback for data_download_url_should_reject_filename_from_invalid_content_disposition_header. + * + * @since 5.9.0 + * + * @return array + */ + public function filter_content_disposition_header_with_filename_with_form_data_context( $response, $args, $url ) { + return array( + 'response' => array( + 'code' => 200, + ), + 'headers' => array( + 'content-disposition' => 'form-data; name="file"; filename="filename-from-content-disposition-header.txt"', + ), + ); + } + + /** + * Verify that a WP_Error object is returned when invalid input is passed as the `$url` parameter. + * + * @covers ::download_url + * @dataProvider data_download_url_empty_url + * + * @param mixed $url Input URL. + */ + public function test_download_url_empty_url( $url ) { + $error = download_url( $url ); + $this->assertWPError( $error ); + $this->assertSame( 'http_no_url', $error->get_error_code() ); + $this->assertSame( 'Invalid URL Provided.', $error->get_error_message() ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_download_url_empty_url() { + return array( + 'null' => array( null ), + 'false' => array( false ), + 'integer 0' => array( 0 ), + 'empty string' => array( '' ), + 'string 0' => array( '0' ), + ); + } + + /** + * Test that PHP 8.1 "passing null to non-nullable" deprecation notice + * is not thrown when the `$url` does not have a path component. + * + * @ticket 53635 + * @covers ::download_url + */ + public function test_download_url_no_warning_for_url_without_path() { + $result = download_url( 'https://example.com' ); + + $this->assertIsString( $result ); + $this->assertNotEmpty( $result ); // File path will be generated, but will never be empty. + } + + /** + * Test that PHP 8.1 "passing null to non-nullable" deprecation notice + * is not thrown when the `$url` does not have a path component, + * and signature verification via a local file is requested. + * + * @ticket 53635 + * @covers ::download_url + */ + public function test_download_url_no_warning_for_url_without_path_with_signature_verification() { + add_filter( + 'wp_signature_hosts', + static function( $urls ) { + $urls[] = 'example.com'; + return $urls; + } + ); + $error = download_url( 'https://example.com', 300, true ); + + /* + * Note: This test is not testing the signature verification itself. + * There is no signature available for the domain used in the test, + * which is why an error is expected and that's fine. + * The point of the test is to verify that the call to `verify_file_signature()` + * is actually reached and that no PHP deprecation notice is thrown + * before this point. + */ + $this->assertWPError( $error ); + $this->assertSame( 'signature_verification_no_signature', $error->get_error_code() ); + } } diff --git a/tests/phpunit/tests/admin/includesListTable.php b/tests/phpunit/tests/admin/includesListTable.php index b15d6d5c153e9..ac2e153e2fb1c 100644 --- a/tests/phpunit/tests/admin/includesListTable.php +++ b/tests/phpunit/tests/admin/includesListTable.php @@ -3,7 +3,7 @@ /** * @group admin */ -class Tests_Admin_includesListTable extends WP_UnitTestCase { +class Tests_Admin_IncludesListTable extends WP_UnitTestCase { protected static $top = array(); protected static $children = array(); protected static $grandchildren = array(); @@ -360,7 +360,7 @@ public function test_bulk_action_menu_supports_options_and_optgroups() { add_filter( 'bulk_actions-edit-comments', - function() { + static function() { return array( 'delete' => 'Delete', 'Change State' => array( diff --git a/tests/phpunit/tests/admin/includesMisc.php b/tests/phpunit/tests/admin/includesMisc.php index 93951af4e5205..6b267335c42a6 100644 --- a/tests/phpunit/tests/admin/includesMisc.php +++ b/tests/phpunit/tests/admin/includesMisc.php @@ -3,7 +3,7 @@ /** * @group admin */ -class Tests_Admin_includesMisc extends WP_UnitTestCase { +class Tests_Admin_IncludesMisc extends WP_UnitTestCase { function test_shorten_url() { $tests = array( 'wordpress\.org/about/philosophy' diff --git a/tests/phpunit/tests/admin/includesPlugin.php b/tests/phpunit/tests/admin/includesPlugin.php index ebba733f23b9e..7542db6b59b36 100644 --- a/tests/phpunit/tests/admin/includesPlugin.php +++ b/tests/phpunit/tests/admin/includesPlugin.php @@ -3,7 +3,7 @@ * @group plugins * @group admin */ -class Tests_Admin_includesPlugin extends WP_UnitTestCase { +class Tests_Admin_IncludesPlugin extends WP_UnitTestCase { public static function wpSetUpBeforeClass( $factory ) { self::_back_up_mu_plugins(); } @@ -366,7 +366,7 @@ public function test_get_plugin_files_single() { public function test_get_plugin_files_folder() { $plugin_dir = WP_PLUGIN_DIR . '/list_files_test_plugin'; @mkdir( $plugin_dir ); - $plugin = $this->_create_plugin( null, 'list_files_test_plugin.php', $plugin_dir ); + $plugin = $this->_create_plugin( '', 'list_files_test_plugin.php', $plugin_dir ); $sub_dir = trailingslashit( dirname( $plugin[1] ) ) . 'subdir'; mkdir( $sub_dir ); diff --git a/tests/phpunit/tests/admin/includesPost.php b/tests/phpunit/tests/admin/includesPost.php index 1b33aff87cd63..8c5013279ed84 100644 --- a/tests/phpunit/tests/admin/includesPost.php +++ b/tests/phpunit/tests/admin/includesPost.php @@ -3,7 +3,7 @@ /** * @group admin */ -class Tests_Admin_Includes_Post extends WP_UnitTestCase { +class Tests_Admin_IncludesPost extends WP_UnitTestCase { protected static $contributor_id; protected static $author_ids; protected static $editor_id; diff --git a/tests/phpunit/tests/admin/includesSchema.php b/tests/phpunit/tests/admin/includesSchema.php index 1ce0a95b2e537..fb19c716b495e 100644 --- a/tests/phpunit/tests/admin/includesSchema.php +++ b/tests/phpunit/tests/admin/includesSchema.php @@ -3,7 +3,7 @@ /** * @group admin */ -class Tests_Admin_Includes_Schema extends WP_UnitTestCase { +class Tests_Admin_IncludesSchema extends WP_UnitTestCase { private static $options; private static $blogmeta; diff --git a/tests/phpunit/tests/admin/includesScreen.php b/tests/phpunit/tests/admin/includesScreen.php index a93803e57ea87..c52e6f1597536 100644 --- a/tests/phpunit/tests/admin/includesScreen.php +++ b/tests/phpunit/tests/admin/includesScreen.php @@ -4,7 +4,7 @@ * @group admin * @group adminScreen */ -class Tests_Admin_includesScreen extends WP_UnitTestCase { +class Tests_Admin_IncludesScreen extends WP_UnitTestCase { public $core_screens = array( 'index.php' => array( 'base' => 'dashboard', diff --git a/tests/phpunit/tests/admin/includesTemplate.php b/tests/phpunit/tests/admin/includesTemplate.php index 7a7b5ccd405d9..c5e73d59e3ad0 100644 --- a/tests/phpunit/tests/admin/includesTemplate.php +++ b/tests/phpunit/tests/admin/includesTemplate.php @@ -2,10 +2,10 @@ /** * @group admin */ -class Tests_Admin_includesTemplate extends WP_UnitTestCase { +class Tests_Admin_IncludesTemplate extends WP_UnitTestCase { /** - * @ticket 51147 + * @ticket 51137 * @dataProvider data_wp_terms_checklist_with_selected_cats */ public function test_wp_terms_checklist_with_selected_cats( $term_id ) { @@ -21,7 +21,7 @@ public function test_wp_terms_checklist_with_selected_cats( $term_id ) { } /** - * @ticket 51147 + * @ticket 51137 * @dataProvider data_wp_terms_checklist_with_selected_cats */ public function test_wp_terms_checklist_with_popular_cats( $term_id ) { diff --git a/tests/phpunit/tests/admin/includesTheme.php b/tests/phpunit/tests/admin/includesTheme.php index 58b7ff5391ab6..1cb39e6832082 100644 --- a/tests/phpunit/tests/admin/includesTheme.php +++ b/tests/phpunit/tests/admin/includesTheme.php @@ -2,7 +2,7 @@ /** * @group themes */ -class Tests_Admin_includesTheme extends WP_UnitTestCase { +class Tests_Admin_IncludesTheme extends WP_UnitTestCase { function set_up() { parent::set_up(); diff --git a/tests/phpunit/tests/admin/includesCommunityEvents.php b/tests/phpunit/tests/admin/wpCommunityEvents.php similarity index 96% rename from tests/phpunit/tests/admin/includesCommunityEvents.php rename to tests/phpunit/tests/admin/wpCommunityEvents.php index 4ca5a64360fba..631d8fdfeb80f 100644 --- a/tests/phpunit/tests/admin/includesCommunityEvents.php +++ b/tests/phpunit/tests/admin/wpCommunityEvents.php @@ -8,14 +8,14 @@ */ /** - * Class Test_WP_Community_Events. + * Class Tests_Admin_wpCommunityEvents. * * @group admin * @group community-events * * @since 4.8.0 */ -class Test_WP_Community_Events extends WP_UnitTestCase { +class Tests_Admin_wpCommunityEvents extends WP_UnitTestCase { /** * An instance of the class to test. * @@ -26,6 +26,17 @@ class Test_WP_Community_Events extends WP_UnitTestCase { */ private $instance; + /** + * Performs setup tasks before the first test is run. + * + * @since 5.9.0 + */ + public static function set_up_before_class() { + parent::set_up_before_class(); + + require_once ABSPATH . 'wp-admin/includes/class-wp-community-events.php'; + } + /** * Performs setup tasks for every test. * @@ -34,8 +45,6 @@ class Test_WP_Community_Events extends WP_UnitTestCase { public function set_up() { parent::set_up(); - require_once ABSPATH . 'wp-admin/includes/class-wp-community-events.php'; - $this->instance = new WP_Community_Events( 1, $this->get_user_location() ); } @@ -60,6 +69,8 @@ private function get_user_location() { * Test: get_events() should return an instance of WP_Error if the response code is not 200. * * @since 4.8.0 + * + * @covers WP_Community_Events::get_events */ public function test_get_events_bad_response_code() { add_filter( 'pre_http_request', array( $this, '_http_request_bad_response_code' ) ); @@ -73,6 +84,8 @@ public function test_get_events_bad_response_code() { * Test: The response body should not be cached if the response code is not 200. * * @since 4.8.0 + * + * @covers WP_Community_Events::get_cached_events */ public function test_get_cached_events_bad_response_code() { add_filter( 'pre_http_request', array( $this, '_http_request_bad_response_code' ) ); @@ -108,6 +121,8 @@ public function _http_request_bad_response_code() { * the required properties. * * @since 4.8.0 + * + * @covers WP_Community_Events::get_events */ public function test_get_events_invalid_response() { add_filter( 'pre_http_request', array( $this, '_http_request_invalid_response' ) ); @@ -121,6 +136,8 @@ public function test_get_events_invalid_response() { * Test: The response body should not be cached if it does not have the required properties. * * @since 4.8.0 + * + * @covers WP_Community_Events::get_cached_events */ public function test_get_cached_events_invalid_response() { add_filter( 'pre_http_request', array( $this, '_http_request_invalid_response' ) ); @@ -156,6 +173,8 @@ public function _http_request_invalid_response() { * an events array with individual events that have Unix start/end timestamps. * * @since 4.8.0 + * + * @covers WP_Community_Events::get_events */ public function test_get_events_valid_response() { add_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) ); @@ -175,6 +194,8 @@ public function test_get_events_valid_response() { * timestamps for each event. * * @since 4.8.0 + * + * @covers WP_Community_Events::get_cached_events */ public function test_get_cached_events_valid_response() { add_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) ); @@ -278,9 +299,9 @@ protected function get_valid_events() { /** * Test: `trim_events()` should immediately remove expired events. * - * @covers WP_Community_Events::trim_events - * * @since 5.5.2 + * + * @covers WP_Community_Events::trim_events */ public function test_trim_expired_events() { $trim_events = new ReflectionMethod( $this->instance, 'trim_events' ); @@ -306,10 +327,10 @@ public function test_trim_expired_events() { /** * Test: get_events() should return the events with the WordCamp pinned in the prepared list. * - * @covers WP_Community_Events::trim_events - * * @since 4.9.7 * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`. + * + * @covers WP_Community_Events::trim_events */ public function test_trim_events_pin_wordcamp() { $trim_events = new ReflectionMethod( $this->instance, 'trim_events' ); @@ -411,10 +432,10 @@ public function _events_with_unpinned_wordcamp() { * Test: get_events() shouldn't stick an extra WordCamp when there's already one that naturally * falls into the list. * - * @covers WP_Community_Events::trim_events - * * @since 4.9.7 * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`. + * + * @covers WP_Community_Events::trim_events */ public function test_trim_events_dont_pin_multiple_wordcamps() { $trim_events = new ReflectionMethod( $this->instance, 'trim_events' ); @@ -536,6 +557,8 @@ public function _events_with_multiple_wordcamps() { * @dataProvider data_get_unsafe_client_ip * * @ticket 41083 + * + * @covers WP_Community_Events::get_unsafe_client_ip */ public function test_get_unsafe_client_ip( $raw_ip, $expected_result ) { $_SERVER['REMOTE_ADDR'] = 'this should not be used'; diff --git a/tests/phpunit/tests/admin/wpMediaListTable.php b/tests/phpunit/tests/admin/wpMediaListTable.php new file mode 100644 index 0000000000000..6a2b2d64fa8a7 --- /dev/null +++ b/tests/phpunit/tests/admin/wpMediaListTable.php @@ -0,0 +1,50 @@ +getMockBuilder( WP_Media_List_Table::class ) + ->disableOriginalConstructor() + ->disallowMockingUnknownTypes() + ->setMethods( array( 'set_pagination_args' ) ) + ->getMock(); + + $mock->expects( $this->once() ) + ->method( 'set_pagination_args' ); + + $wp_query->query_vars['posts_per_page'] = 10; + delete_option( 'cron' ); + + // Verify that the cause of the error is in place. + $this->assertFalse( _get_cron_array(), '_get_cron_array() does not return false' ); + + // If this test does not error out due to the PHP warning, we're good. + $mock->prepare_items(); + } +} diff --git a/tests/phpunit/tests/ajax/Attachments.php b/tests/phpunit/tests/ajax/Attachments.php index 0b2cb09451f29..657213d27841d 100644 --- a/tests/phpunit/tests/ajax/Attachments.php +++ b/tests/phpunit/tests/ajax/Attachments.php @@ -63,10 +63,9 @@ public function test_wp_ajax_send_attachment_to_editor_should_return_an_image() /** * @ticket 36578 + * @group ms-excluded */ public function test_wp_ajax_send_attachment_to_editor_should_return_a_link() { - $this->skipWithMultisite(); - // Become an administrator. $post = $_POST; $user_id = self::factory()->user->create( diff --git a/tests/phpunit/tests/ajax/DeletePlugin.php b/tests/phpunit/tests/ajax/DeletePlugin.php index d84f401a17ffa..c42e238499327 100644 --- a/tests/phpunit/tests/ajax/DeletePlugin.php +++ b/tests/phpunit/tests/ajax/DeletePlugin.php @@ -125,8 +125,10 @@ public function test_invalid_file() { $this->assertSameSets( $expected, $response ); } + /** + * @group ms-excluded + */ public function test_delete_plugin() { - $this->skipWithMultisite(); $this->_setRole( 'administrator' ); $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' ); diff --git a/tests/phpunit/tests/ajax/ManageThemes.php b/tests/phpunit/tests/ajax/ManageThemes.php index 8d0f9c5b7f401..89f2a9f9783cb 100644 --- a/tests/phpunit/tests/ajax/ManageThemes.php +++ b/tests/phpunit/tests/ajax/ManageThemes.php @@ -101,8 +101,10 @@ public function test_missing_capability() { $this->assertSameSets( $expected, $response ); } + /** + * @group ms-excluded + */ public function test_update_theme() { - $this->skipWithMultisite(); $this->_setRole( 'administrator' ); $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' ); @@ -139,8 +141,10 @@ public function test_update_theme() { $this->assertSameSets( $expected, $response ); } + /** + * @group ms-excluded + */ function test_uppercase_theme_slug() { - $this->skipWithMultisite(); $this->_setRole( 'administrator' ); $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' ); diff --git a/tests/phpunit/tests/ajax/UpdatePlugin.php b/tests/phpunit/tests/ajax/UpdatePlugin.php index ceab32bfeb451..44ce630633a41 100644 --- a/tests/phpunit/tests/ajax/UpdatePlugin.php +++ b/tests/phpunit/tests/ajax/UpdatePlugin.php @@ -129,8 +129,10 @@ public function test_invalid_file() { $this->assertSameSets( $expected, $response ); } + /** + * @group ms-excluded + */ public function test_update_plugin() { - $this->skipWithMultisite(); $this->_setRole( 'administrator' ); $_POST['_ajax_nonce'] = wp_create_nonce( 'updates' ); diff --git a/tests/phpunit/tests/block-template-utils.php b/tests/phpunit/tests/block-template-utils.php index b528067dc4adc..c52c25a99fe78 100644 --- a/tests/phpunit/tests/block-template-utils.php +++ b/tests/phpunit/tests/block-template-utils.php @@ -70,7 +70,7 @@ function test_get_block_template_from_post() { function test_get_block_templates() { function get_template_ids( $templates ) { return array_map( - function( $template ) { + static function( $template ) { return $template->id; }, $templates diff --git a/tests/phpunit/tests/blocks/context.php b/tests/phpunit/tests/blocks/context.php index b23b8da3ae66a..f39b378c65aa9 100644 --- a/tests/phpunit/tests/blocks/context.php +++ b/tests/phpunit/tests/blocks/context.php @@ -115,7 +115,7 @@ function test_provides_block_context() { 'gutenberg/contextWithAssigned', 'gutenberg/contextWithoutDefault', ), - 'render_callback' => function( $attributes, $content, $block ) use ( &$provided_context ) { + 'render_callback' => static function( $attributes, $content, $block ) use ( &$provided_context ) { $provided_context[] = $block->context; return ''; @@ -155,7 +155,7 @@ function test_provides_default_context() { 'gutenberg/test-context-consumer', array( 'uses_context' => array( 'postId', 'postType' ), - 'render_callback' => function( $attributes, $content, $block ) use ( &$provided_context ) { + 'render_callback' => static function( $attributes, $content, $block ) use ( &$provided_context ) { $provided_context[] = $block->context; return ''; @@ -188,7 +188,7 @@ function test_default_context_is_filterable() { 'gutenberg/test-context-consumer', array( 'uses_context' => array( 'example' ), - 'render_callback' => function( $attributes, $content, $block ) use ( &$provided_context ) { + 'render_callback' => static function( $attributes, $content, $block ) use ( &$provided_context ) { $provided_context[] = $block->context; return ''; @@ -196,7 +196,7 @@ function test_default_context_is_filterable() { ) ); - $filter_block_context = function( $context ) { + $filter_block_context = static function( $context ) { $context['example'] = 'ok'; return $context; }; diff --git a/tests/phpunit/tests/blocks/register.php b/tests/phpunit/tests/blocks/register.php index 1f3104d09b3a6..ee98bca81b727 100644 --- a/tests/phpunit/tests/blocks/register.php +++ b/tests/phpunit/tests/blocks/register.php @@ -510,7 +510,7 @@ function test_has_blocks() { * @ticket 49615 */ public function test_filter_block_registration() { - $filter_registration = function( $args, $name ) { + $filter_registration = static function( $args, $name ) { $args['attributes'] = array( $name => array( 'type' => 'boolean' ) ); return $args; }; @@ -528,7 +528,7 @@ public function test_filter_block_registration() { * @ticket 52138 */ public function test_filter_block_registration_metadata() { - $filter_metadata_registration = function( $metadata ) { + $filter_metadata_registration = static function( $metadata ) { $metadata['apiVersion'] = 3; return $metadata; }; @@ -546,7 +546,7 @@ public function test_filter_block_registration_metadata() { * @ticket 52138 */ public function test_filter_block_registration_metadata_settings() { - $filter_metadata_registration = function( $settings, $metadata ) { + $filter_metadata_registration = static function( $settings, $metadata ) { $settings['api_version'] = $metadata['apiVersion'] + 1; return $settings; }; diff --git a/tests/phpunit/tests/blocks/serialize.php b/tests/phpunit/tests/blocks/serialize.php index 199a72007ecd0..f7077b7c28c7e 100644 --- a/tests/phpunit/tests/blocks/serialize.php +++ b/tests/phpunit/tests/blocks/serialize.php @@ -47,6 +47,9 @@ function data_serialize_identity_from_parsed() { // Block with attribute values that may conflict with HTML comment. array( '' ), + + // Block with attribute values that should not be escaped. + array( '' ), ); } diff --git a/tests/phpunit/tests/blocks/supportedStyles.php b/tests/phpunit/tests/blocks/supportedStyles.php index b3e50800dd6c3..bdbf91aa2eb13 100644 --- a/tests/phpunit/tests/blocks/supportedStyles.php +++ b/tests/phpunit/tests/blocks/supportedStyles.php @@ -712,7 +712,7 @@ public function test_render_block_suppresses_warnings_without_at_suppression() { // Custom error handler's see Warnings even if they are suppressed by the @ symbol. $errors = array(); set_error_handler( - function ( $errno = 0, $errstr = '' ) use ( &$errors ) { + static function ( $errno = 0, $errstr = '' ) use ( &$errors ) { $errors[] = $errstr; return false; } diff --git a/tests/phpunit/tests/blocks/wpBlock.php b/tests/phpunit/tests/blocks/wpBlock.php index a50fc7e878f94..0545babd6ab09 100644 --- a/tests/phpunit/tests/blocks/wpBlock.php +++ b/tests/phpunit/tests/blocks/wpBlock.php @@ -275,7 +275,7 @@ function test_render_static_block_type_returns_own_content() { $this->registry->register( 'core/dynamic', array( - 'render_callback' => function() { + 'render_callback' => static function() { return 'b'; }, ) @@ -296,7 +296,7 @@ function test_render_passes_block_for_render_callback() { $this->registry->register( 'core/greeting', array( - 'render_callback' => function( $attributes, $content, $block ) { + 'render_callback' => static function( $attributes, $content, $block ) { return sprintf( 'Hello from %s', $block->name ); }, ) @@ -366,7 +366,7 @@ function test_passes_attributes_to_render_callback() { 'default' => '!', ), ), - 'render_callback' => function( $block_attributes ) { + 'render_callback' => static function( $block_attributes ) { return sprintf( 'Hello %s%s', $block_attributes['toWhom'], @@ -391,7 +391,7 @@ function test_passes_content_to_render_callback() { $this->registry->register( 'core/outer', array( - 'render_callback' => function( $block_attributes, $content ) { + 'render_callback' => static function( $block_attributes, $content ) { return $content; }, ) @@ -399,7 +399,7 @@ function test_passes_content_to_render_callback() { $this->registry->register( 'core/inner', array( - 'render_callback' => function() { + 'render_callback' => static function() { return 'b'; }, ) @@ -628,4 +628,44 @@ public function test_block_has_support_provided_defaults() { $gradient_support = block_has_support( $block_type, array( 'color', 'gradient' ), true ); $this->assertFalse( $gradient_support ); } + + /** + * @ticket 51612 + */ + public function test_block_filters_for_inner_blocks() { + $pre_render_callback = new MockAction(); + $render_block_data_callback = new MockAction(); + $render_block_context_callback = new MockAction(); + + $this->registry->register( + 'core/outer', + array( + 'render_callback' => function( $block_attributes, $content ) { + return $content; + }, + ) + ); + + $this->registry->register( + 'core/inner', + array( + 'render_callback' => function() { + return 'b'; + }, + ) + ); + + $parsed_blocks = parse_blocks( 'ac' ); + $parsed_block = $parsed_blocks[0]; + + add_filter( 'pre_render_block', array( $pre_render_callback, 'filter' ) ); + add_filter( 'render_block_data', array( $render_block_data_callback, 'filter' ) ); + add_filter( 'render_block_context', array( $render_block_context_callback, 'filter' ) ); + + render_block( $parsed_block ); + + $this->assertSame( 2, $pre_render_callback->get_call_count() ); + $this->assertSame( 2, $render_block_data_callback->get_call_count() ); + $this->assertSame( 2, $render_block_context_callback->get_call_count() ); + } } diff --git a/tests/phpunit/tests/canonical.php b/tests/phpunit/tests/canonical.php index 3069ba840027d..d5198ee558d42 100644 --- a/tests/phpunit/tests/canonical.php +++ b/tests/phpunit/tests/canonical.php @@ -247,7 +247,7 @@ public function test_pre_redirect_guess_404_permalink() { // Test short-circuit filter. add_filter( 'pre_redirect_guess_404_permalink', - function() { + static function() { return 'wp'; } ); diff --git a/tests/phpunit/tests/canonical/pageOnFront.php b/tests/phpunit/tests/canonical/pageOnFront.php index 8f6488a9ab2f2..64058ab4fe664 100644 --- a/tests/phpunit/tests/canonical/pageOnFront.php +++ b/tests/phpunit/tests/canonical/pageOnFront.php @@ -51,21 +51,21 @@ function data() { */ return array( // Check against an odd redirect. - array( '/page/2/', '/page/2/' ), - array( '/?page=2', '/page/2/' ), - array( '/page/1/', '/' ), - array( '/?page=1', '/' ), + array( '/page/2/', '/page/2/', 20385 ), + array( '/?page=2', '/page/2/', 35344 ), + array( '/page/1/', '/', 35344 ), + array( '/?page=1', '/', 35344 ), // The page designated as the front page should redirect to the front of the site. - array( '/front-page/', '/' ), + array( '/front-page/', '/', 20385 ), // The front page supports the pagination. - array( '/front-page/2/', '/page/2/' ), - array( '/front-page/?page=2', '/page/2/' ), + array( '/front-page/2/', '/page/2/', 35344 ), + array( '/front-page/?page=2', '/page/2/', 35344 ), // The posts page does not support the pagination. - array( '/blog-page/2/', '/blog-page/' ), - array( '/blog-page/?page=2', '/blog-page/' ), + array( '/blog-page/2/', '/blog-page/', 45337 ), + array( '/blog-page/?page=2', '/blog-page/', 45337 ), // The posts page supports regular pagination. - array( '/blog-page/?paged=2', '/blog-page/page/2/' ), + array( '/blog-page/?paged=2', '/blog-page/page/2/', 20385 ), ); } } diff --git a/tests/phpunit/tests/category/walkerCategory.php b/tests/phpunit/tests/category/walkerCategory.php index ac49a30216431..92d5c3f309136 100644 --- a/tests/phpunit/tests/category/walkerCategory.php +++ b/tests/phpunit/tests/category/walkerCategory.php @@ -38,7 +38,7 @@ public function test_start_el_with_empty_attributes( $value, $expected ) { add_filter( 'category_list_link_attributes', - function( $atts ) use ( $value ) { + static function( $atts ) use ( $value ) { $atts['data-test'] = $value; return $atts; } diff --git a/tests/phpunit/tests/comment/commentsTemplate.php b/tests/phpunit/tests/comment/commentsTemplate.php index c0cee5dc743db..7135118485a8a 100644 --- a/tests/phpunit/tests/comment/commentsTemplate.php +++ b/tests/phpunit/tests/comment/commentsTemplate.php @@ -993,7 +993,7 @@ public function test_comments_template_top_level_query_args( $expected, $query_a add_filter( 'comments_template_query_args', - function ( $args ) use ( &$offset, $query_args ) { + static function ( $args ) use ( &$offset, $query_args ) { $offset = $args['offset']; return array_merge( $args, $query_args ); @@ -1003,7 +1003,7 @@ function ( $args ) use ( &$offset, $query_args ) { if ( ! empty( $top_level_query_args ) ) { add_filter( 'comments_template_top_level_query_args', - function ( $args ) use ( $top_level_query_args ) { + static function ( $args ) use ( $top_level_query_args ) { return array_merge( $args, $top_level_query_args ); } ); diff --git a/tests/phpunit/tests/compat.php b/tests/phpunit/tests/compat.php deleted file mode 100644 index ab75d6256ba37..0000000000000 --- a/tests/phpunit/tests/compat.php +++ /dev/null @@ -1,325 +0,0 @@ -assertSame( $expected_character_length, _mb_strlen( $string, 'UTF-8' ) ); - } - - /** - * @dataProvider utf8_string_lengths - */ - function test_mb_strlen_via_regex( $string, $expected_character_length ) { - _wp_can_use_pcre_u( false ); - $this->assertSame( $expected_character_length, _mb_strlen( $string, 'UTF-8' ) ); - _wp_can_use_pcre_u( 'reset' ); - } - - /** - * @dataProvider utf8_string_lengths - */ - function test_8bit_mb_strlen( $string, $expected_character_length, $expected_byte_length ) { - $this->assertSame( $expected_byte_length, _mb_strlen( $string, '8bit' ) ); - } - - /** - * @dataProvider utf8_substrings - */ - function test_mb_substr( $string, $start, $length, $expected_character_substring ) { - $this->assertSame( $expected_character_substring, _mb_substr( $string, $start, $length, 'UTF-8' ) ); - } - - /** - * @dataProvider utf8_substrings - */ - function test_mb_substr_via_regex( $string, $start, $length, $expected_character_substring ) { - _wp_can_use_pcre_u( false ); - $this->assertSame( $expected_character_substring, _mb_substr( $string, $start, $length, 'UTF-8' ) ); - _wp_can_use_pcre_u( 'reset' ); - } - - /** - * @dataProvider utf8_substrings - */ - function test_8bit_mb_substr( $string, $start, $length, $expected_character_substring, $expected_byte_substring ) { - $this->assertSame( $expected_byte_substring, _mb_substr( $string, $start, $length, '8bit' ) ); - } - - function test_mb_substr_phpcore() { - /* https://github.com/php/php-src/blob/php-5.6.8/ext/mbstring/tests/mb_substr_basic.phpt */ - $string_ascii = 'ABCDEF'; - $string_mb = base64_decode( '5pel5pys6Kqe44OG44Kt44K544OI44Gn44GZ44CCMDEyMzTvvJXvvJbvvJfvvJjvvJnjgII=' ); - - $this->assertSame( 'DEF', _mb_substr( $string_ascii, 3 ) ); - $this->assertSame( 'DEF', _mb_substr( $string_ascii, 3, 5, 'ISO-8859-1' ) ); - - // Specific latin-1 as that is the default the core PHP test operates under. - $this->assertSame( 'peacrOiqng==', base64_encode( _mb_substr( $string_mb, 2, 7, 'latin-1' ) ) ); - $this->assertSame( '6Kqe44OG44Kt44K544OI44Gn44GZ', base64_encode( _mb_substr( $string_mb, 2, 7, 'utf-8' ) ) ); - - /* https://github.com/php/php-src/blob/php-5.6.8/ext/mbstring/tests/mb_substr_variation1.phpt */ - $start = 0; - $length = 5; - $unset_var = 10; - unset( $unset_var ); - $heredoc = <<assertSame( $outputs[ $iterator ], _mb_substr( $input, $start, $length ) ); - $iterator++; - } - - } - - function test_hash_hmac_simple() { - $this->assertSame( '140d1cb79fa12e2a31f32d35ad0a2723', _hash_hmac( 'md5', 'simple', 'key' ) ); - $this->assertSame( '993003b95758e0ac2eba451a4c5877eb1bb7b92a', _hash_hmac( 'sha1', 'simple', 'key' ) ); - } - - function test_hash_hmac_padding() { - $this->assertSame( '3c1399103807cf12ec38228614416a8c', _hash_hmac( 'md5', 'simple', '65 character key 65 character key 65 character key 65 character k' ) ); - $this->assertSame( '4428826d20003e309d6c2a6515891370daf184ea', _hash_hmac( 'sha1', 'simple', '65 character key 65 character key 65 character key 65 character k' ) ); - } - - function test_hash_hmac_output() { - $this->assertSame( array( 1 => '140d1cb79fa12e2a31f32d35ad0a2723' ), unpack( 'H32', _hash_hmac( 'md5', 'simple', 'key', true ) ) ); - $this->assertSame( array( 1 => '993003b95758e0ac2eba451a4c5877eb1bb7b92a' ), unpack( 'H40', _hash_hmac( 'sha1', 'simple', 'key', true ) ) ); - } - - function test_json_encode_decode() { - $this->expectDeprecation(); - - require_once ABSPATH . WPINC . '/class-json.php'; - $json = new Services_JSON(); - // Super basic test to verify Services_JSON is intact and working. - $this->assertSame( '["foo"]', $json->encodeUnsafe( array( 'foo' ) ) ); - $this->assertSame( array( 'foo' ), $json->decode( '["foo"]' ) ); - } - - /** - * Test that is_countable() is always available (either from PHP or WP). - * - * @ticket 43583 - */ - function test_is_countable_availability() { - $this->assertTrue( function_exists( 'is_countable' ) ); - } - - /** - * Test is_countable() polyfill. - * - * @ticket 43583 - * - * @dataProvider countable_variable_test_data - * - * @param mixed $variable Variable to check. - * @param bool $is_countable The expected return value of PHP 7.3 is_countable() function. - */ - function test_is_countable_functionality( $variable, $is_countable ) { - $this->assertSame( is_countable( $variable ), $is_countable ); - } - - /** - * Data provider for test_is_countable_functionality(). - * - * @ticket 43583 - * - * @return array { - * @type array { - * @type mixed $variable Variable to check. - * @type bool $is_countable The expected return value of PHP 7.3 is_countable() function. - * } - * } - */ - public function countable_variable_test_data() { - return array( - array( true, false ), - array( new stdClass(), false ), - array( new ArrayIteratorFake(), true ), - array( new CountableFake(), true ), - array( 16, false ), - array( null, false ), - array( array( 1, 2, 3 ), true ), - array( (array) 1, true ), - array( (object) array( 'foo', 'bar', 'baz' ), false ), - ); - } - - /** - * Test is_countable() polyfill for ResourceBundle. - * - * @ticket 43583 - * - * @requires extension intl - */ - function test_is_countable_ResourceBundle() { - $this->assertTrue( is_countable( new ResourceBundle( 'en', null ) ) ); - } - - /** - * Test is_countable() polyfill for SimpleXMLElement. - * - * @ticket 43583 - * - * @requires extension simplexml - */ - function test_is_countable_SimpleXMLElement() { - $this->assertTrue( is_countable( new SimpleXMLElement( '12' ) ) ); - } - - /** - * Test that is_iterable() is always available (either from PHP or WP). - * - * @ticket 43619 - */ - function test_is_iterable_availability() { - $this->assertTrue( function_exists( 'is_iterable' ) ); - } - - /** - * Test is_iterable() polyfill. - * - * @ticket 43619 - * - * @dataProvider iterable_variable_test_data - * - * @param mixed $variable Variable to check. - * @param bool $is_iterable The expected return value of PHP 7.1 is_iterable() function. - */ - function test_is_iterable_functionality( $variable, $is_iterable ) { - $this->assertSame( is_iterable( $variable ), $is_iterable ); - } - - /** - * Data provider for test_is_iterable_functionality(). - * - * @ticket 43619 - * - * @return array { - * @type array { - * @type mixed $variable Variable to check. - * @type bool $is_iterable The expected return value of PHP 7.1 is_iterable() function. - * } - * } - */ - public function iterable_variable_test_data() { - return array( - array( array(), true ), - array( array( 1, 2, 3 ), true ), - array( new ArrayIterator( array( 1, 2, 3 ) ), true ), - array( 1, false ), - array( 3.14, false ), - array( new stdClass(), false ), - ); - } -} - -/* used in test_mb_substr_phpcore */ -class ClassA { - public function __toString() { - return 'Class A object'; - } -} - -class ArrayIteratorFake extends ArrayIterator { -} - -class CountableFake implements Countable { - #[ReturnTypeWillChange] - public function count() { - return 16; - } -} diff --git a/tests/phpunit/tests/compat/hashHmac.php b/tests/phpunit/tests/compat/hashHmac.php new file mode 100644 index 0000000000000..f9a61d5faca63 --- /dev/null +++ b/tests/phpunit/tests/compat/hashHmac.php @@ -0,0 +1,65 @@ +assertTrue( function_exists( 'hash_hmac' ) ); + } + + public function test_hash_hmac_simple() { + $data = 'simple'; + $key = 'key'; + + $this->assertSame( + '140d1cb79fa12e2a31f32d35ad0a2723', + _hash_hmac( 'md5', $data, $key ), + 'MD5 hash does not match' + ); + $this->assertSame( + '993003b95758e0ac2eba451a4c5877eb1bb7b92a', + _hash_hmac( 'sha1', $data, $key ), + 'sha1 hash does not match' + ); + } + + public function test_hash_hmac_padding() { + $data = 'simple'; + $key = '65 character key 65 character key 65 character key 65 character k'; + + $this->assertSame( + '3c1399103807cf12ec38228614416a8c', + _hash_hmac( 'md5', $data, $key ), + 'MD5 hash does not match' + ); + $this->assertSame( + '4428826d20003e309d6c2a6515891370daf184ea', + _hash_hmac( 'sha1', $data, $key ), + 'sha1 hash does not match' + ); + } + + public function test_hash_hmac_output() { + $data = 'simple'; + $key = 'key'; + + $this->assertSame( + array( 1 => '140d1cb79fa12e2a31f32d35ad0a2723' ), + unpack( 'H32', _hash_hmac( 'md5', $data, $key, true ) ), + 'unpacked MD5 hash does not match' + ); + $this->assertSame( + array( 1 => '993003b95758e0ac2eba451a4c5877eb1bb7b92a' ), + unpack( 'H40', _hash_hmac( 'sha1', $data, $key, true ) ), + 'unpacked sha1 hash does not match' + ); + } +} diff --git a/tests/phpunit/tests/compat/isCountable.php b/tests/phpunit/tests/compat/isCountable.php new file mode 100644 index 0000000000000..66bf3c8c6c09f --- /dev/null +++ b/tests/phpunit/tests/compat/isCountable.php @@ -0,0 +1,117 @@ +assertTrue( function_exists( 'is_countable' ) ); + } + + /** + * Test is_countable() polyfill. + * + * @ticket 43583 + * + * @dataProvider data_is_countable_functionality + * + * @param mixed $variable Variable to check. + * @param bool $is_countable The expected return value of PHP 7.3 is_countable() function. + */ + public function test_is_countable_functionality( $variable, $is_countable ) { + $this->assertSame( $is_countable, is_countable( $variable ) ); + } + + /** + * Data provider for test_is_countable_functionality(). + * + * @ticket 43583 + * + * @return array { + * @type array { + * @type mixed $variable Variable to check. + * @type bool $is_countable The expected return value of PHP 7.3 is_countable() function. + * } + * } + */ + public function data_is_countable_functionality() { + return array( + 'boolean true' => array( + 'variable' => true, + 'is_countable' => false, + ), + 'plain stdClass object' => array( + 'variable' => new stdClass(), + 'is_countable' => false, + ), + 'Array iterator object' => array( + 'variable' => new ArrayIteratorFakeForIsCountable(), + 'is_countable' => true, + ), + 'Countable object' => array( + 'variable' => new CountableFakeForIsCountable(), + 'is_countable' => true, + ), + 'integer 16' => array( + 'variable' => 16, + 'is_countable' => false, + ), + 'null' => array( + 'variable' => null, + 'is_countable' => false, + ), + 'non-empty array, 3 items' => array( + 'variable' => array( 1, 2, 3 ), + 'is_countable' => true, + ), + 'non-empty array, 1 item via cast' => array( + 'variable' => (array) 1, + 'is_countable' => true, + ), + 'array cast to object' => array( + 'variable' => (object) array( 'foo', 'bar', 'baz' ), + 'is_countable' => false, + ), + ); + } + + /** + * Test is_countable() polyfill for ResourceBundle. + * + * @ticket 43583 + * + * @requires extension intl + */ + public function test_is_countable_ResourceBundle() { + $this->assertTrue( is_countable( new ResourceBundle( 'en', null ) ) ); + } + + /** + * Test is_countable() polyfill for SimpleXMLElement. + * + * @ticket 43583 + * + * @requires extension simplexml + */ + public function test_is_countable_SimpleXMLElement() { + $this->assertTrue( is_countable( new SimpleXMLElement( '12' ) ) ); + } +} + +class ArrayIteratorFakeForIsCountable extends ArrayIterator { +} + +class CountableFakeForIsCountable implements Countable { + #[ReturnTypeWillChange] + public function count() { + return 16; + } +} diff --git a/tests/phpunit/tests/compat/isIterable.php b/tests/phpunit/tests/compat/isIterable.php new file mode 100644 index 0000000000000..e09bb18278ccb --- /dev/null +++ b/tests/phpunit/tests/compat/isIterable.php @@ -0,0 +1,77 @@ +assertTrue( function_exists( 'is_iterable' ) ); + } + + /** + * Test is_iterable() polyfill. + * + * @ticket 43619 + * + * @dataProvider data_is_iterable_functionality + * + * @param mixed $variable Variable to check. + * @param bool $is_iterable The expected return value of PHP 7.1 is_iterable() function. + */ + public function test_is_iterable_functionality( $variable, $is_iterable ) { + $this->assertSame( $is_iterable, is_iterable( $variable ) ); + } + + /** + * Data provider for test_is_iterable_functionality(). + * + * @ticket 43619 + * + * @return array { + * @type array { + * @type mixed $variable Variable to check. + * @type bool $is_iterable The expected return value of PHP 7.1 is_iterable() function. + * } + * } + */ + public function data_is_iterable_functionality() { + return array( + 'empty array' => array( + 'variable' => array(), + 'is_iterable' => true, + ), + 'non-empty array' => array( + 'variable' => array( 1, 2, 3 ), + 'is_iterable' => true, + ), + 'Iterator object' => array( + 'variable' => new ArrayIterator( array( 1, 2, 3 ) ), + 'is_iterable' => true, + ), + 'null' => array( + 'variable' => null, + 'is_iterable' => false, + ), + 'integer 1' => array( + 'variable' => 1, + 'is_iterable' => false, + ), + 'float 3.14' => array( + 'variable' => 3.14, + 'is_iterable' => false, + ), + 'plain stdClass object' => array( + 'variable' => new stdClass(), + 'is_iterable' => false, + ), + ); + } +} diff --git a/tests/phpunit/tests/compat/jsonEncodeDecode.php b/tests/phpunit/tests/compat/jsonEncodeDecode.php new file mode 100644 index 0000000000000..be51c6022b193 --- /dev/null +++ b/tests/phpunit/tests/compat/jsonEncodeDecode.php @@ -0,0 +1,36 @@ +setExpectedDeprecated( 'class-json.php' ); + $this->setExpectedDeprecated( 'Services_JSON::__construct' ); + $this->setExpectedDeprecated( 'Services_JSON::encodeUnsafe' ); + $this->setExpectedDeprecated( 'Services_JSON::_encode' ); + $this->setExpectedDeprecated( 'Services_JSON::reduce_string' ); + $this->setExpectedDeprecated( 'Services_JSON::decode' ); + $this->setExpectedDeprecated( 'Services_JSON::isError' ); + $this->setExpectedDeprecated( 'Services_JSON::strlen8' ); + $this->setExpectedDeprecated( 'Services_JSON::substr8' ); + + require_once ABSPATH . WPINC . '/class-json.php'; + $json = new Services_JSON(); + + // Super basic test to verify Services_JSON is intact and working. + $this->assertSame( + '["foo"]', + $json->encodeUnsafe( array( 'foo' ) ), + 'encodeUnsafe() did not return expected output' + ); + $this->assertSame( + array( 'foo' ), + $json->decode( '["foo"]' ), + 'decode() did not return expected output' + ); + } +} diff --git a/tests/phpunit/tests/compat/mbStrlen.php b/tests/phpunit/tests/compat/mbStrlen.php new file mode 100644 index 0000000000000..e34b44534b1e4 --- /dev/null +++ b/tests/phpunit/tests/compat/mbStrlen.php @@ -0,0 +1,91 @@ +assertTrue( function_exists( 'mb_strlen' ) ); + } + + /** + * @dataProvider utf8_string_lengths + */ + public function test_mb_strlen( $string, $expected_character_length ) { + $this->assertSame( $expected_character_length, _mb_strlen( $string, 'UTF-8' ) ); + } + + /** + * @dataProvider utf8_string_lengths + */ + public function test_mb_strlen_via_regex( $string, $expected_character_length ) { + _wp_can_use_pcre_u( false ); + $this->assertSame( $expected_character_length, _mb_strlen( $string, 'UTF-8' ) ); + _wp_can_use_pcre_u( 'reset' ); + } + + /** + * @dataProvider utf8_string_lengths + */ + public function test_8bit_mb_strlen( $string, $expected_character_length, $expected_byte_length ) { + $this->assertSame( $expected_byte_length, _mb_strlen( $string, '8bit' ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function utf8_string_lengths() { + return array( + array( + 'string' => 'баба', + 'expected_character_length' => 4, + 'expected_byte_length' => 8, + ), + array( + 'string' => 'баб', + 'expected_character_length' => 3, + 'expected_byte_length' => 6, + ), + array( + 'string' => 'I am your б', + 'expected_character_length' => 11, + 'expected_byte_length' => 12, + ), + array( + 'string' => '1111111111', + 'expected_character_length' => 10, + 'expected_byte_length' => 10, + ), + array( + 'string' => '²²²²²²²²²²', + 'expected_character_length' => 10, + 'expected_byte_length' => 20, + ), + array( + 'string' => '3333333333', + 'expected_character_length' => 10, + 'expected_byte_length' => 30, + ), + array( + 'string' => '𝟜𝟜𝟜𝟜𝟜𝟜𝟜𝟜𝟜𝟜', + 'expected_character_length' => 10, + 'expected_byte_length' => 40, + ), + array( + 'string' => '1²3𝟜1²3𝟜1²3𝟜', + 'expected_character_length' => 12, + 'expected_byte_length' => 30, + ), + ); + } +} diff --git a/tests/phpunit/tests/compat/mbSubstr.php b/tests/phpunit/tests/compat/mbSubstr.php new file mode 100644 index 0000000000000..f03f5f0f193bf --- /dev/null +++ b/tests/phpunit/tests/compat/mbSubstr.php @@ -0,0 +1,241 @@ +assertTrue( function_exists( 'mb_substr' ) ); + } + + /** + * @dataProvider utf8_substrings + */ + public function test_mb_substr( $string, $start, $length, $expected_character_substring ) { + $this->assertSame( $expected_character_substring, _mb_substr( $string, $start, $length, 'UTF-8' ) ); + } + + /** + * @dataProvider utf8_substrings + */ + public function test_mb_substr_via_regex( $string, $start, $length, $expected_character_substring ) { + _wp_can_use_pcre_u( false ); + $this->assertSame( $expected_character_substring, _mb_substr( $string, $start, $length, 'UTF-8' ) ); + _wp_can_use_pcre_u( 'reset' ); + } + + /** + * @dataProvider utf8_substrings + */ + public function test_8bit_mb_substr( $string, $start, $length, $expected_character_substring, $expected_byte_substring ) { + $this->assertSame( $expected_byte_substring, _mb_substr( $string, $start, $length, '8bit' ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function utf8_substrings() { + return array( + array( + 'string' => 'баба', + 'start' => 0, + 'length' => 3, + 'expected_character_substring' => 'баб', + 'expected_byte_substring' => "б\xD0", + ), + array( + 'string' => 'баба', + 'start' => 0, + 'length' => -1, + 'expected_character_substring' => 'баб', + 'expected_byte_substring' => "баб\xD0", + ), + array( + 'string' => 'баба', + 'start' => 1, + 'length' => null, + 'expected_character_substring' => 'аба', + 'expected_byte_substring' => "\xB1аба", + ), + array( + 'string' => 'баба', + 'start' => -3, + 'length' => null, + 'expected_character_substring' => 'аба', + 'expected_byte_substring' => "\xB1а", + ), + array( + 'string' => 'баба', + 'start' => -3, + 'length' => 2, + 'expected_character_substring' => 'аб', + 'expected_byte_substring' => "\xB1\xD0", + ), + array( + 'string' => 'баба', + 'start' => -1, + 'length' => 2, + 'expected_character_substring' => 'а', + 'expected_byte_substring' => "\xB0", + ), + array( + 'string' => 'I am your баба', + 'start' => 0, + 'length' => 11, + 'expected_character_substring' => 'I am your б', + 'expected_byte_substring' => "I am your \xD0", + ), + ); + } + + /** + * @link https://github.com/php/php-src/blob/php-5.6.8/ext/mbstring/tests/mb_substr_basic.phpt + */ + public function test_mb_substr_phpcore_basic() { + $string_ascii = 'ABCDEF'; + $string_mb = base64_decode( '5pel5pys6Kqe44OG44Kt44K544OI44Gn44GZ44CCMDEyMzTvvJXvvJbvvJfvvJjvvJnjgII=' ); + + $this->assertSame( + 'DEF', + _mb_substr( $string_ascii, 3 ), + 'Substring does not match expected for offset 3' + ); + $this->assertSame( + 'DEF', + _mb_substr( $string_ascii, 3, 5, 'ISO-8859-1' ), + 'Substring does not match expected for offset 3, length 5, with iso charset' + ); + + // Specific latin-1 as that is the default the core PHP test operates under. + $this->assertSame( + 'peacrOiqng==', + base64_encode( _mb_substr( $string_mb, 2, 7, 'latin-1' ) ), + 'Substring does not match expected for offset 2, length 7, with latin-1 charset' + ); + $this->assertSame( + '6Kqe44OG44Kt44K544OI44Gn44GZ', + base64_encode( _mb_substr( $string_mb, 2, 7, 'utf-8' ) ), + 'Substring does not match expected for offset 2, length 7, with utf-8 charset' + ); + } + + /** + * @link https://github.com/php/php-src/blob/php-5.6.8/ext/mbstring/tests/mb_substr_variation1.phpt + * + * @dataProvider data_mb_substr_phpcore_input_type_handling + * + * @param mixed $input Input to pass to the function. + * @param string $expected Expected function output. + */ + public function test_mb_substr_phpcore_input_type_handling( $input, $expected ) { + $start = 0; + $length = 5; + + $this->assertSame( $expected, _mb_substr( $input, $start, $length ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_mb_substr_phpcore_input_type_handling() { + $heredoc = << array( + 'input' => 0, + 'expected' => '0', + ), + 'integer 1' => array( + 'input' => 1, + 'expected' => '1', + ), + 'positive integer' => array( + 'input' => 12345, + 'expected' => '12345', + ), + 'negative integer' => array( + 'input' => -2345, + 'expected' => '-2345', + ), + // Float data. + 'positive float with fraction' => array( + 'input' => 10.5, + 'expected' => '10.5', + ), + 'negative float with fraction' => array( + 'input' => -10.5, + 'expected' => '-10.5', + ), + 'float scientific whole number' => array( + 'input' => 12.3456789000e10, + 'expected' => '12345', + ), + 'float scientific with fraction' => array( + 'input' => 12.3456789000E-10, + 'expected' => '1.234', + ), + 'float, fraction only' => array( + 'input' => .5, + 'expected' => '0.5', + ), + // Null data. + 'null' => array( + 'input' => null, + 'expected' => '', + ), + // Boolean data. + 'boolean true' => array( + 'input' => true, + 'expected' => '1', + ), + 'boolean false' => array( + 'input' => false, + 'expected' => '', + ), + // Empty data. + 'empty string' => array( + 'input' => '', + 'expected' => '', + ), + // String data. + 'double quoted string' => array( + 'input' => "string'", + 'expected' => 'strin', + ), + 'single quoted string' => array( + 'input' => 'string', + 'expected' => 'strin', + ), + 'heredoc string' => array( + 'input' => $heredoc, + 'expected' => 'hello', + ), + // Object data. + 'object with __toString method' => array( + 'input' => new ClassWithToStringForMbSubstr(), + 'expected' => 'Class', + ), + ); + } +} + +/* used in data_mb_substr_phpcore_input_type_handling() */ +class ClassWithToStringForMbSubstr { + public function __toString() { + return 'Class object'; + } +} diff --git a/tests/phpunit/tests/cron.php b/tests/phpunit/tests/cron.php index 9b9c475954caf..2940c1708a56f 100644 --- a/tests/phpunit/tests/cron.php +++ b/tests/phpunit/tests/cron.php @@ -100,7 +100,6 @@ function test_schedule_event_args() { $this->assertSame( $recur, wp_get_schedule( $hook, $args ) ); } - /** * Tests that a call to wp_schedule_event() on a site without any scheduled events * does not result in a PHP deprecation warning on PHP 8.1 or higher. @@ -125,6 +124,30 @@ function test_wp_schedule_event_without_cron_option_does_not_throw_warning() { $this->assertTrue( wp_schedule_event( $timestamp, 'daily', $hook ) ); } + /** + * Tests that a call to wp_schedule_single_event() on a site without any scheduled events + * does not result in the value "false" being added into the cron array. + * + * @ticket 53950 + * + * @covers ::wp_schedule_single_event + */ + function test_wp_schedule_single_event_without_cron_option() { + delete_option( 'cron' ); + + // Verify that the cause of the error is in place. + $this->assertFalse( _get_cron_array(), '_get_cron_array() does not return false' ); + + $hook = __FUNCTION__; + $timestamp = strtotime( '+10 minutes' ); + + // Add an event. + $this->assertTrue( wp_schedule_single_event( $timestamp, $hook ), 'Scheduling single event failed' ); + + // Verify that "false" is not a value in the final cron array. + $this->assertNotContains( false, get_option( 'cron' ), 'Resulting cron array contains the value "false"' ); + } + function test_unschedule_event() { // Schedule an event and make sure it's returned by wp_next_scheduled(). $hook = __FUNCTION__; @@ -1055,7 +1078,7 @@ public function test_cron_array_error_is_returned_when_scheduling_single_event() // Force update_option() to fail by setting the new value to match the existing: add_filter( 'pre_update_option_cron', - function() { + static function() { return get_option( 'cron' ); } ); @@ -1075,7 +1098,7 @@ public function test_cron_array_error_is_returned_when_scheduling_event() { // Force update_option() to fail by setting the new value to match the existing: add_filter( 'pre_update_option_cron', - function() { + static function() { return get_option( 'cron' ); } ); @@ -1098,7 +1121,7 @@ public function test_cron_array_error_is_returned_when_unscheduling_hook() { // Force update_option() to fail by setting the new value to match the existing: add_filter( 'pre_update_option_cron', - function() { + static function() { return get_option( 'cron' ); } ); @@ -1122,7 +1145,7 @@ public function test_cron_array_error_is_returned_when_unscheduling_event() { // Force update_option() to fail by setting the new value to match the existing: add_filter( 'pre_update_option_cron', - function() { + static function() { return get_option( 'cron' ); } ); diff --git a/tests/phpunit/tests/cron/setCronArray.php b/tests/phpunit/tests/cron/setCronArray.php new file mode 100644 index 0000000000000..30e7eddec3e43 --- /dev/null +++ b/tests/phpunit/tests/cron/setCronArray.php @@ -0,0 +1,175 @@ +assertTrue( _set_cron_array( $input ) ); + + $crons = get_option( 'cron' ); + $this->assertIsArray( $crons, 'Cron option is not an array.' ); + $this->assertArrayHasKey( 'version', $crons, 'Cron option does not have a "version" key.' ); + $this->assertCount( $expected, $crons, 'Cron option does not contain the expected nr of entries.' ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_set_cron_array_input_validation() { + return array( + 'null' => array( + 'input' => null, + 'expected' => 1, + ), + // Function _get_cron_array() may return `false`, so this is the PHP 8.1 "problem" test. + 'false' => array( + 'input' => false, + 'expected' => 1, + ), + 'empty array' => array( + 'input' => array(), + 'expected' => 1, + ), + 'cron array' => array( + 'input' => array( + 'version' => 2, + time() => array( + 'hookname' => array( + 'event key' => array( + 'schedule' => 'schedule', + 'args' => 'args', + 'interval' => 'interval', + ), + ), + ), + ), + 'expected' => 2, + ), + ); + } + + /** + * Tests that `_set_cron_array()` returns `false` when the cron option was not updated. + * + * @dataProvider data_set_cron_array_returns_false_when_not_updated + * + * @param array $input Cron array. + * @param mixed $wp_error Value to use for $wp_error. + */ + public function test_set_cron_array_returns_false_when_not_updated( $input, $wp_error ) { + $this->assertFalse( _set_cron_array( $input ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_set_cron_array_returns_false_when_not_updated() { + return array( + 'empty array' => array( + 'input' => array(), + 'wp_error' => false, + ), + 'cron array' => array( + 'input' => array( + 'version' => 2, + ), + 'wp_error' => 0, + ), + ); + } + + /** + * Tests that `_set_cron_array()` returns a WP_Error object when the cron option was not updated and `$wp_error` is truthy. + * + * @dataProvider data_set_cron_array_returns_WP_Error_when_not_updated + * + * @param array $input Cron array. + * @param mixed $wp_error Value to use for $wp_error. + */ + public function test_set_cron_array_returns_WP_Error_when_not_updated( $input, $wp_error ) { + $result = _set_cron_array( $input, $wp_error ); + $this->assertWPError( $result, 'Return value is not an instance of WP_Error.' ); + $this->assertSame( 'could_not_set', $result->get_error_code(), 'WP_Error error code does not match expected code.' ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_set_cron_array_returns_WP_Error_when_not_updated() { + return array( + 'empty array' => array( + 'input' => array(), + 'wp_error' => true, + ), + 'cron array' => array( + 'input' => array( + 'version' => 2, + ), + 'wp_error' => 1, + ), + ); + } + + /** + * Tests that `_set_cron_array()` returns true when the cron option was updated and `$wp_error` is truthy. + */ + public function test_set_cron_array_does_not_return_WP_Error_when_updated() { + $result = _set_cron_array( + array( + 'version' => 2, + time() => array( + 'hookname' => array( + 'event key' => array( + 'schedule' => 'schedule', + 'args' => 'args', + 'interval' => 'interval', + ), + ), + ), + ), + true + ); + + $this->assertTrue( $result ); + } +} diff --git a/tests/phpunit/tests/db/realEscape.php b/tests/phpunit/tests/db/realEscape.php new file mode 100644 index 0000000000000..393b9515c9137 --- /dev/null +++ b/tests/phpunit/tests/db/realEscape.php @@ -0,0 +1,87 @@ +assertSame( $expected, $wpdb->_real_escape( $input ) ); + } + + /** + * Data provider. + * + * @var array + */ + public function data_real_escape_input_type_handling() { + return array( + 'null' => array( + 'input' => null, + 'expected' => '', + ), + 'boolean false' => array( + 'input' => false, + 'expected' => '', + ), + 'boolean true' => array( + 'input' => true, + 'expected' => '1', + ), + 'integer zero' => array( + 'input' => 0, + 'expected' => '0', + ), + 'negative integer' => array( + 'input' => -1327, + 'expected' => '-1327', + ), + 'positive integer' => array( + 'input' => 47896, + 'expected' => '47896', + ), + 'float zero' => array( + 'input' => 0.0, + 'expected' => '0', + ), + 'positive float' => array( + 'input' => 25.52, + 'expected' => '25.52', + ), + 'simple string' => array( + 'input' => 'foobar', + 'expected' => 'foobar', + ), + 'empty array' => array( + 'input' => array(), + 'expected' => '', + ), + 'non-empty array' => array( + 'input' => array( 1, 2, 3 ), + 'expected' => '', + ), + 'simple object' => array( + 'input' => new stdClass(), + 'expected' => '', + ), + ); + } +} diff --git a/tests/phpunit/tests/dependencies/wpInlineScriptTag.php b/tests/phpunit/tests/dependencies/wpInlineScriptTag.php index d2c2185d48470..1e517b637ddaf 100644 --- a/tests/phpunit/tests/dependencies/wpInlineScriptTag.php +++ b/tests/phpunit/tests/dependencies/wpInlineScriptTag.php @@ -80,7 +80,7 @@ public function test_get_inline_script_tag_unescaped_src() { public function test_print_script_tag_prints_get_inline_script_tag() { add_filter( 'wp_inline_script_attributes', - function ( $attributes ) { + static function ( $attributes ) { if ( isset( $attributes['id'] ) && 'utils-js-extra' === $attributes['id'] ) { $attributes['async'] = true; } diff --git a/tests/phpunit/tests/dependencies/wpScriptTag.php b/tests/phpunit/tests/dependencies/wpScriptTag.php index ba80c8cabfbbc..f009bb5790c55 100644 --- a/tests/phpunit/tests/dependencies/wpScriptTag.php +++ b/tests/phpunit/tests/dependencies/wpScriptTag.php @@ -64,7 +64,7 @@ function test_get_script_tag_type_not_set() { function test_print_script_tag_prints_get_script_tag() { add_filter( 'wp_script_attributes', - function ( $attributes ) { + static function ( $attributes ) { if ( isset( $attributes['id'] ) && 'utils-js-extra' === $attributes['id'] ) { $attributes['async'] = true; } diff --git a/tests/phpunit/tests/editor/wpEditors.php b/tests/phpunit/tests/editor/wpEditors.php index 2370b34a93fc1..c4e9e50515fda 100644 --- a/tests/phpunit/tests/editor/wpEditors.php +++ b/tests/phpunit/tests/editor/wpEditors.php @@ -9,7 +9,7 @@ * * @coversDefaultClass _WP_Editors */ -class Tests_WP_Editors extends WP_UnitTestCase { +class Tests_Editor_wpEditors extends WP_UnitTestCase { /** * @covers ::wp_link_query diff --git a/tests/phpunit/tests/error-protection/recovery-mode-cookie-service.php b/tests/phpunit/tests/error-protection/wpRecoveryModeCookieService.php similarity index 97% rename from tests/phpunit/tests/error-protection/recovery-mode-cookie-service.php rename to tests/phpunit/tests/error-protection/wpRecoveryModeCookieService.php index e261645d0aa06..122a9193f2883 100644 --- a/tests/phpunit/tests/error-protection/recovery-mode-cookie-service.php +++ b/tests/phpunit/tests/error-protection/wpRecoveryModeCookieService.php @@ -3,7 +3,7 @@ /** * @group error-protection */ -class Tests_Recovery_Mode_Cookie_Service extends WP_UnitTestCase { +class Tests_Error_Protection_wpRecoveryModeCookieService extends WP_UnitTestCase { /** * @ticket 46130 diff --git a/tests/phpunit/tests/error-protection/recovery-mode-key-service.php b/tests/phpunit/tests/error-protection/wpRecoveryModeKeyService.php similarity index 98% rename from tests/phpunit/tests/error-protection/recovery-mode-key-service.php rename to tests/phpunit/tests/error-protection/wpRecoveryModeKeyService.php index 66f15e6c1ecc4..316655d7a36c7 100644 --- a/tests/phpunit/tests/error-protection/recovery-mode-key-service.php +++ b/tests/phpunit/tests/error-protection/wpRecoveryModeKeyService.php @@ -3,7 +3,7 @@ /** * @group error-protection */ -class Tests_Recovery_Mode_Key_Service extends WP_UnitTestCase { +class Tests_Error_Protection_wpRecoveryModeKeyService extends WP_UnitTestCase { /** * @ticket 46130 diff --git a/tests/phpunit/tests/feed/atom.php b/tests/phpunit/tests/feed/atom.php index b54c3ae8f4209..3b2c82774965f 100644 --- a/tests/phpunit/tests/feed/atom.php +++ b/tests/phpunit/tests/feed/atom.php @@ -8,7 +8,7 @@ * * @group feed */ -class Tests_Feeds_Atom extends WP_UnitTestCase { +class Tests_Feed_Atom extends WP_UnitTestCase { public static $user_id; public static $posts; public static $category; diff --git a/tests/phpunit/tests/feed/rss2.php b/tests/phpunit/tests/feed/rss2.php index d2eea6bc6296e..50138cf255f39 100644 --- a/tests/phpunit/tests/feed/rss2.php +++ b/tests/phpunit/tests/feed/rss2.php @@ -8,7 +8,7 @@ * * @group feed */ -class Tests_Feeds_RSS2 extends WP_UnitTestCase { +class Tests_Feed_RSS2 extends WP_UnitTestCase { public static $user_id; public static $posts; public static $category; diff --git a/tests/phpunit/tests/feed/wp-simplepie-file.php b/tests/phpunit/tests/feed/wpSimplePieFile.php similarity index 98% rename from tests/phpunit/tests/feed/wp-simplepie-file.php rename to tests/phpunit/tests/feed/wpSimplePieFile.php index ada28f6451836..f9748e3a7bcac 100644 --- a/tests/phpunit/tests/feed/wp-simplepie-file.php +++ b/tests/phpunit/tests/feed/wpSimplePieFile.php @@ -15,7 +15,7 @@ * * @since 5.6.1 */ -class Tests_WP_SimplePie_File extends WP_UnitTestCase { +class Tests_Feed_wpSimplePieFile extends WP_UnitTestCase { public static function set_up_before_class() { parent::set_up_before_class(); diff --git a/tests/phpunit/tests/formatting/CapitalPDangit.php b/tests/phpunit/tests/formatting/capitalPDangit.php similarity index 100% rename from tests/phpunit/tests/formatting/CapitalPDangit.php rename to tests/phpunit/tests/formatting/capitalPDangit.php diff --git a/tests/phpunit/tests/formatting/CleanPre.php b/tests/phpunit/tests/formatting/cleanPre.php similarity index 100% rename from tests/phpunit/tests/formatting/CleanPre.php rename to tests/phpunit/tests/formatting/cleanPre.php diff --git a/tests/phpunit/tests/formatting/ConvertInvalidEntries.php b/tests/phpunit/tests/formatting/convertInvalidEntries.php similarity index 100% rename from tests/phpunit/tests/formatting/ConvertInvalidEntries.php rename to tests/phpunit/tests/formatting/convertInvalidEntries.php diff --git a/tests/phpunit/tests/formatting/Smilies.php b/tests/phpunit/tests/formatting/convertSmilies.php similarity index 99% rename from tests/phpunit/tests/formatting/Smilies.php rename to tests/phpunit/tests/formatting/convertSmilies.php index f5394d4268e67..63d95aa07169b 100644 --- a/tests/phpunit/tests/formatting/Smilies.php +++ b/tests/phpunit/tests/formatting/convertSmilies.php @@ -4,7 +4,7 @@ * @group formatting * @group emoji */ -class Tests_Formatting_Smilies extends WP_UnitTestCase { +class Tests_Formatting_ConvertSmilies extends WP_UnitTestCase { /** * Basic Test Content DataProvider diff --git a/tests/phpunit/tests/formatting/Emoji.php b/tests/phpunit/tests/formatting/emoji.php similarity index 100% rename from tests/phpunit/tests/formatting/Emoji.php rename to tests/phpunit/tests/formatting/emoji.php diff --git a/tests/phpunit/tests/formatting/ent2ncr.php b/tests/phpunit/tests/formatting/ent2ncr.php index ba84e6d2e0692..64571580e4d94 100644 --- a/tests/phpunit/tests/formatting/ent2ncr.php +++ b/tests/phpunit/tests/formatting/ent2ncr.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_Ent2NCR extends WP_UnitTestCase { +class Tests_Formatting_Ent2ncr extends WP_UnitTestCase { /** * @dataProvider entities */ diff --git a/tests/phpunit/tests/formatting/EscAttr.php b/tests/phpunit/tests/formatting/escAttr.php similarity index 100% rename from tests/phpunit/tests/formatting/EscAttr.php rename to tests/phpunit/tests/formatting/escAttr.php diff --git a/tests/phpunit/tests/formatting/EscHtml.php b/tests/phpunit/tests/formatting/escHtml.php similarity index 100% rename from tests/phpunit/tests/formatting/EscHtml.php rename to tests/phpunit/tests/formatting/escHtml.php diff --git a/tests/phpunit/tests/formatting/JSEscape.php b/tests/phpunit/tests/formatting/escJs.php similarity index 95% rename from tests/phpunit/tests/formatting/JSEscape.php rename to tests/phpunit/tests/formatting/escJs.php index 4dcb06481940f..bd6407518b3bd 100644 --- a/tests/phpunit/tests/formatting/JSEscape.php +++ b/tests/phpunit/tests/formatting/escJs.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_JSEscape extends WP_UnitTestCase { +class Tests_Formatting_EscJs extends WP_UnitTestCase { function test_js_escape_simple() { $out = esc_js( 'foo bar baz();' ); $this->assertSame( 'foo bar baz();', $out ); diff --git a/tests/phpunit/tests/formatting/EscTextarea.php b/tests/phpunit/tests/formatting/escTextarea.php similarity index 100% rename from tests/phpunit/tests/formatting/EscTextarea.php rename to tests/phpunit/tests/formatting/escTextarea.php diff --git a/tests/phpunit/tests/formatting/EscUrl.php b/tests/phpunit/tests/formatting/escUrl.php similarity index 100% rename from tests/phpunit/tests/formatting/EscUrl.php rename to tests/phpunit/tests/formatting/escUrl.php diff --git a/tests/phpunit/tests/formatting/EscXml.php b/tests/phpunit/tests/formatting/escXml.php similarity index 100% rename from tests/phpunit/tests/formatting/EscXml.php rename to tests/phpunit/tests/formatting/escXml.php diff --git a/tests/phpunit/tests/formatting/ExcerptRemoveBlocks.php b/tests/phpunit/tests/formatting/excerptRemoveBlocks.php similarity index 100% rename from tests/phpunit/tests/formatting/ExcerptRemoveBlocks.php rename to tests/phpunit/tests/formatting/excerptRemoveBlocks.php diff --git a/tests/phpunit/tests/formatting/BlogInfo.php b/tests/phpunit/tests/formatting/getBloginfo.php similarity index 96% rename from tests/phpunit/tests/formatting/BlogInfo.php rename to tests/phpunit/tests/formatting/getBloginfo.php index 37ce3450facae..b1f87a0d16e9a 100644 --- a/tests/phpunit/tests/formatting/BlogInfo.php +++ b/tests/phpunit/tests/formatting/getBloginfo.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_BlogInfo extends WP_UnitTestCase { +class Tests_Formatting_GetBloginfo extends WP_UnitTestCase { /** * @dataProvider locales diff --git a/tests/phpunit/tests/formatting/GetUrlInContent.php b/tests/phpunit/tests/formatting/getUrlInContent.php similarity index 100% rename from tests/phpunit/tests/formatting/GetUrlInContent.php rename to tests/phpunit/tests/formatting/getUrlInContent.php diff --git a/tests/phpunit/tests/formatting/HumanTimeDiff.php b/tests/phpunit/tests/formatting/humanTimeDiff.php similarity index 100% rename from tests/phpunit/tests/formatting/HumanTimeDiff.php rename to tests/phpunit/tests/formatting/humanTimeDiff.php diff --git a/tests/phpunit/tests/formatting/IsEmail.php b/tests/phpunit/tests/formatting/isEmail.php similarity index 100% rename from tests/phpunit/tests/formatting/IsEmail.php rename to tests/phpunit/tests/formatting/isEmail.php diff --git a/tests/phpunit/tests/formatting/LikeEscape.php b/tests/phpunit/tests/formatting/likeEscape.php similarity index 100% rename from tests/phpunit/tests/formatting/LikeEscape.php rename to tests/phpunit/tests/formatting/likeEscape.php diff --git a/tests/phpunit/tests/formatting/LinksAddTarget.php b/tests/phpunit/tests/formatting/linksAddTarget.php similarity index 100% rename from tests/phpunit/tests/formatting/LinksAddTarget.php rename to tests/phpunit/tests/formatting/linksAddTarget.php diff --git a/tests/phpunit/tests/formatting/MakeClickable.php b/tests/phpunit/tests/formatting/makeClickable.php similarity index 100% rename from tests/phpunit/tests/formatting/MakeClickable.php rename to tests/phpunit/tests/formatting/makeClickable.php diff --git a/tests/phpunit/tests/formatting/MapDeep.php b/tests/phpunit/tests/formatting/mapDeep.php similarity index 100% rename from tests/phpunit/tests/formatting/MapDeep.php rename to tests/phpunit/tests/formatting/mapDeep.php diff --git a/tests/phpunit/tests/formatting/NormalizeWhitespace.php b/tests/phpunit/tests/formatting/normalizeWhitespace.php similarity index 100% rename from tests/phpunit/tests/formatting/NormalizeWhitespace.php rename to tests/phpunit/tests/formatting/normalizeWhitespace.php diff --git a/tests/phpunit/tests/formatting/RemoveAccents.php b/tests/phpunit/tests/formatting/removeAccents.php similarity index 100% rename from tests/phpunit/tests/formatting/RemoveAccents.php rename to tests/phpunit/tests/formatting/removeAccents.php diff --git a/tests/phpunit/tests/formatting/SanitizeFileName.php b/tests/phpunit/tests/formatting/sanitizeFileName.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeFileName.php rename to tests/phpunit/tests/formatting/sanitizeFileName.php diff --git a/tests/phpunit/tests/formatting/SanitizeMimeType.php b/tests/phpunit/tests/formatting/sanitizeMimeType.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeMimeType.php rename to tests/phpunit/tests/formatting/sanitizeMimeType.php diff --git a/tests/phpunit/tests/formatting/SanitizeOrderby.php b/tests/phpunit/tests/formatting/sanitizeOrderby.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeOrderby.php rename to tests/phpunit/tests/formatting/sanitizeOrderby.php diff --git a/tests/phpunit/tests/formatting/SanitizePost.php b/tests/phpunit/tests/formatting/sanitizePost.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizePost.php rename to tests/phpunit/tests/formatting/sanitizePost.php diff --git a/tests/phpunit/tests/formatting/SanitizeTextField.php b/tests/phpunit/tests/formatting/sanitizeTextField.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeTextField.php rename to tests/phpunit/tests/formatting/sanitizeTextField.php diff --git a/tests/phpunit/tests/formatting/SanitizeTitle.php b/tests/phpunit/tests/formatting/sanitizeTitle.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeTitle.php rename to tests/phpunit/tests/formatting/sanitizeTitle.php diff --git a/tests/phpunit/tests/formatting/SanitizeTitleWithDashes.php b/tests/phpunit/tests/formatting/sanitizeTitleWithDashes.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeTitleWithDashes.php rename to tests/phpunit/tests/formatting/sanitizeTitleWithDashes.php diff --git a/tests/phpunit/tests/formatting/SanitizeTrackbackUrls.php b/tests/phpunit/tests/formatting/sanitizeTrackbackUrls.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeTrackbackUrls.php rename to tests/phpunit/tests/formatting/sanitizeTrackbackUrls.php diff --git a/tests/phpunit/tests/formatting/SanitizeUser.php b/tests/phpunit/tests/formatting/sanitizeUser.php similarity index 100% rename from tests/phpunit/tests/formatting/SanitizeUser.php rename to tests/phpunit/tests/formatting/sanitizeUser.php diff --git a/tests/phpunit/tests/formatting/SeemsUtf8.php b/tests/phpunit/tests/formatting/seemsUtf8.php similarity index 100% rename from tests/phpunit/tests/formatting/SeemsUtf8.php rename to tests/phpunit/tests/formatting/seemsUtf8.php diff --git a/tests/phpunit/tests/formatting/Slashit.php b/tests/phpunit/tests/formatting/slashit.php similarity index 100% rename from tests/phpunit/tests/formatting/Slashit.php rename to tests/phpunit/tests/formatting/slashit.php diff --git a/tests/phpunit/tests/formatting/StripSlashesDeep.php b/tests/phpunit/tests/formatting/stripslashesDeep.php similarity index 96% rename from tests/phpunit/tests/formatting/StripSlashesDeep.php rename to tests/phpunit/tests/formatting/stripslashesDeep.php index a401a99f792c3..a475f9402afdb 100644 --- a/tests/phpunit/tests/formatting/StripSlashesDeep.php +++ b/tests/phpunit/tests/formatting/stripslashesDeep.php @@ -4,7 +4,7 @@ * @group formatting * @group slashes */ -class Tests_Formatting_StripSlashesDeep extends WP_UnitTestCase { +class Tests_Formatting_StripslashesDeep extends WP_UnitTestCase { /** * @ticket 18026 */ diff --git a/tests/phpunit/tests/formatting/URLShorten.php b/tests/phpunit/tests/formatting/urlShorten.php similarity index 91% rename from tests/phpunit/tests/formatting/URLShorten.php rename to tests/phpunit/tests/formatting/urlShorten.php index a1f1942809871..94e2728e6b5ae 100644 --- a/tests/phpunit/tests/formatting/URLShorten.php +++ b/tests/phpunit/tests/formatting/urlShorten.php @@ -3,8 +3,8 @@ /** * @group formatting */ -class Tests_Formatting_URLShorten extends WP_UnitTestCase { - function test_shorten_url() { +class Tests_Formatting_UrlShorten extends WP_UnitTestCase { + function test_url_shorten() { $tests = array( 'wordpress\.org/about/philosophy' => 'wordpress\.org/about/philosophy', // No longer strips slashes. 'wordpress.org/about/philosophy' => 'wordpress.org/about/philosophy', diff --git a/tests/phpunit/tests/formatting/UrlencodeDeep.php b/tests/phpunit/tests/formatting/urlencodeDeep.php similarity index 100% rename from tests/phpunit/tests/formatting/UrlencodeDeep.php rename to tests/phpunit/tests/formatting/urlencodeDeep.php diff --git a/tests/phpunit/tests/formatting/Utf8UriEncode.php b/tests/phpunit/tests/formatting/utf8UriEncode.php similarity index 100% rename from tests/phpunit/tests/formatting/Utf8UriEncode.php rename to tests/phpunit/tests/formatting/utf8UriEncode.php diff --git a/tests/phpunit/tests/formatting/Autop.php b/tests/phpunit/tests/formatting/wpAutop.php similarity index 99% rename from tests/phpunit/tests/formatting/Autop.php rename to tests/phpunit/tests/formatting/wpAutop.php index 8a77c6879ead6..ccb6721073534 100644 --- a/tests/phpunit/tests/formatting/Autop.php +++ b/tests/phpunit/tests/formatting/wpAutop.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_Autop extends WP_UnitTestCase { +class Tests_Formatting_wpAutop extends WP_UnitTestCase { /** * @ticket 11008 diff --git a/tests/phpunit/tests/formatting/WPBasename.php b/tests/phpunit/tests/formatting/wpBasename.php similarity index 91% rename from tests/phpunit/tests/formatting/WPBasename.php rename to tests/phpunit/tests/formatting/wpBasename.php index a664e399c00b4..341a4c8a66e4f 100644 --- a/tests/phpunit/tests/formatting/WPBasename.php +++ b/tests/phpunit/tests/formatting/wpBasename.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WP_Basename extends WP_UnitTestCase { +class Tests_Formatting_wpBasename extends WP_UnitTestCase { function test_wp_basename_unix() { $this->assertSame( diff --git a/tests/phpunit/tests/formatting/HtmlExcerpt.php b/tests/phpunit/tests/formatting/wpHtmlExcerpt.php similarity index 90% rename from tests/phpunit/tests/formatting/HtmlExcerpt.php rename to tests/phpunit/tests/formatting/wpHtmlExcerpt.php index 36315fc541880..bbe89106b3697 100644 --- a/tests/phpunit/tests/formatting/HtmlExcerpt.php +++ b/tests/phpunit/tests/formatting/wpHtmlExcerpt.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_HtmlExcerpt extends WP_UnitTestCase { +class Tests_Formatting_wpHtmlExcerpt extends WP_UnitTestCase { function test_simple() { $this->assertSame( 'Baba', wp_html_excerpt( 'Baba told me not to come', 4 ) ); } diff --git a/tests/phpunit/tests/formatting/WpHtmlSplit.php b/tests/phpunit/tests/formatting/wpHtmlSplit.php similarity index 94% rename from tests/phpunit/tests/formatting/WpHtmlSplit.php rename to tests/phpunit/tests/formatting/wpHtmlSplit.php index a9baa7cb8c1a8..50ebdd70511c8 100644 --- a/tests/phpunit/tests/formatting/WpHtmlSplit.php +++ b/tests/phpunit/tests/formatting/wpHtmlSplit.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WpHtmlSplit extends WP_UnitTestCase { +class Tests_Formatting_wpHtmlSplit extends WP_UnitTestCase { /** * Basic functionality goes here. diff --git a/tests/phpunit/tests/formatting/WpHtmlEditPre.php b/tests/phpunit/tests/formatting/wpHtmleditPre.php similarity index 93% rename from tests/phpunit/tests/formatting/WpHtmlEditPre.php rename to tests/phpunit/tests/formatting/wpHtmleditPre.php index fceabbe8db3b7..f00e917f2ce3e 100644 --- a/tests/phpunit/tests/formatting/WpHtmlEditPre.php +++ b/tests/phpunit/tests/formatting/wpHtmleditPre.php @@ -4,7 +4,7 @@ * @group formatting * @expectedDeprecated wp_htmledit_pre */ -class Tests_Formatting_WpHtmlEditPre extends WP_UnitTestCase { +class Tests_Formatting_wpHtmleditPre extends WP_UnitTestCase { function _charset_iso_8859_1() { return 'iso-8859-1'; diff --git a/tests/phpunit/tests/formatting/isoDescrambler.php b/tests/phpunit/tests/formatting/wpIsoDescrambler.php similarity index 82% rename from tests/phpunit/tests/formatting/isoDescrambler.php rename to tests/phpunit/tests/formatting/wpIsoDescrambler.php index c1133c4bcf896..bb2be63514f71 100644 --- a/tests/phpunit/tests/formatting/isoDescrambler.php +++ b/tests/phpunit/tests/formatting/wpIsoDescrambler.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Test_WP_ISO_Descrambler extends WP_UnitTestCase { +class Tests_Formatting_wpIsoDescrambler extends WP_UnitTestCase { /* * Decodes text in RFC2047 "Q"-encoding, e.g. * =?iso-8859-1?q?this=20is=20some=20text?= diff --git a/tests/phpunit/tests/formatting/WPMakeLinkRelative.php b/tests/phpunit/tests/formatting/wpMakeLinkRelative.php similarity index 95% rename from tests/phpunit/tests/formatting/WPMakeLinkRelative.php rename to tests/phpunit/tests/formatting/wpMakeLinkRelative.php index da6099302b056..2592c2a2d0ac2 100644 --- a/tests/phpunit/tests/formatting/WPMakeLinkRelative.php +++ b/tests/phpunit/tests/formatting/wpMakeLinkRelative.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WPMakeLinkRelative extends WP_UnitTestCase { +class Tests_Formatting_wpMakeLinkRelative extends WP_UnitTestCase { public function test_wp_make_link_relative_with_http_scheme() { $link = 'http://example.com/this-is-a-test-http-url/'; diff --git a/tests/phpunit/tests/formatting/wpParseStr.php b/tests/phpunit/tests/formatting/wpParseStr.php new file mode 100644 index 0000000000000..b8c3d063d2423 --- /dev/null +++ b/tests/phpunit/tests/formatting/wpParseStr.php @@ -0,0 +1,144 @@ +assertSame( $expected, $output ); + } + + /** + * Data Provider. + * + * @return array + */ + public function data_wp_parse_str() { + return array( + 'null' => array( + 'input' => null, + 'expected' => array(), + ), + 'boolean false' => array( + 'input' => false, + 'expected' => array(), + ), + 'boolean true' => array( + 'input' => true, + 'expected' => array( + 1 => '', + ), + ), + 'integer 0' => array( + 'input' => 0, + 'expected' => array( + 0 => '', + ), + ), + 'integer 456' => array( + 'input' => 456, + 'expected' => array( + 456 => '', + ), + ), + 'float 12.53' => array( + 'input' => 12.53, + 'expected' => array( + '12_53' => '', + ), + ), + 'plain string' => array( + 'input' => 'foobar', + 'expected' => array( + 'foobar' => '', + ), + ), + 'query string' => array( + 'input' => 'x=5&_baba=dudu&', + 'expected' => array( + 'x' => '5', + '_baba' => 'dudu', + ), + ), + 'stringable object' => array( + 'input' => new Fixture_Formatting_wpParseStr(), + 'expected' => array( + 'foobar' => '', + ), + ), + ); + } + + /** + * Tests that the result array only contains the result of the string parsing + * when provided with different types of input for the `$output` parameter. + * + * @dataProvider data_wp_parse_str_result_array_is_always_overwritten + * + * @param array|null $output Value for the `$output` parameter. + * @param array $expected Expected function output. + */ + public function test_wp_parse_str_result_array_is_always_overwritten( $output, $expected ) { + wp_parse_str( 'key=25&thing=text', $output ); + $this->assertSame( $expected, $output ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_wp_parse_str_result_array_is_always_overwritten() { + // Standard value for expected output. + $expected = array( + 'key' => '25', + 'thing' => 'text', + ); + + return array( + 'output null' => array( + 'output' => null, + 'expected' => $expected, + ), + 'output empty array' => array( + 'output' => array(), + 'expected' => $expected, + ), + 'output non empty array, no conflicting keys' => array( + 'output' => array( + 'foo' => 'bar', + ), + 'expected' => $expected, + ), + 'output non empty array, conflicting keys' => array( + 'output' => array( + 'key' => 'value', + ), + 'expected' => $expected, + ), + ); + } +} + +/** + * Fixture for use in the tests. + */ +class Fixture_Formatting_wpParseStr { + public function __toString() { + return 'foobar'; + } +} diff --git a/tests/phpunit/tests/formatting/WPRelNoFollow.php b/tests/phpunit/tests/formatting/wpRelNofollow.php similarity index 97% rename from tests/phpunit/tests/formatting/WPRelNoFollow.php rename to tests/phpunit/tests/formatting/wpRelNofollow.php index 10385cade78bd..f66da5db5ed6c 100644 --- a/tests/phpunit/tests/formatting/WPRelNoFollow.php +++ b/tests/phpunit/tests/formatting/wpRelNofollow.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Rel_No_Follow extends WP_UnitTestCase { +class Tests_Formatting_wpRelNofollow extends WP_UnitTestCase { /** * @ticket 9959 diff --git a/tests/phpunit/tests/formatting/WPRelUgc.php b/tests/phpunit/tests/formatting/wpRelUgc.php similarity index 97% rename from tests/phpunit/tests/formatting/WPRelUgc.php rename to tests/phpunit/tests/formatting/wpRelUgc.php index 85470155a1d67..ea0d4dda65adc 100644 --- a/tests/phpunit/tests/formatting/WPRelUgc.php +++ b/tests/phpunit/tests/formatting/wpRelUgc.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Rel_Ugc extends WP_UnitTestCase { +class Tests_Formatting_wpRelUgc extends WP_UnitTestCase { /** * @ticket 48022 diff --git a/tests/phpunit/tests/formatting/WpReplaceInHtmlTags.php b/tests/phpunit/tests/formatting/wpReplaceInHtmlTags.php similarity index 90% rename from tests/phpunit/tests/formatting/WpReplaceInHtmlTags.php rename to tests/phpunit/tests/formatting/wpReplaceInHtmlTags.php index 764a0cc178441..70b6c94e734cc 100644 --- a/tests/phpunit/tests/formatting/WpReplaceInHtmlTags.php +++ b/tests/phpunit/tests/formatting/wpReplaceInHtmlTags.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WpReplaceInTags extends WP_UnitTestCase { +class Tests_Formatting_wpReplaceInHtmlTags extends WP_UnitTestCase { /** * Check for expected behavior of new function wp_replace_in_html_tags(). * diff --git a/tests/phpunit/tests/formatting/WpRichEditPre.php b/tests/phpunit/tests/formatting/wpRicheditPre.php similarity index 94% rename from tests/phpunit/tests/formatting/WpRichEditPre.php rename to tests/phpunit/tests/formatting/wpRicheditPre.php index 79ed8b1bc6d18..553e42049c850 100644 --- a/tests/phpunit/tests/formatting/WpRichEditPre.php +++ b/tests/phpunit/tests/formatting/wpRicheditPre.php @@ -4,7 +4,7 @@ * @group formatting * @expectedDeprecated wp_richedit_pre */ -class Tests_Formatting_WpRichEditPre extends WP_UnitTestCase { +class Tests_Formatting_wpRicheditPre extends WP_UnitTestCase { function _charset_iso_8859_1() { return 'iso-8859-1'; diff --git a/tests/phpunit/tests/formatting/WPSlash.php b/tests/phpunit/tests/formatting/wpSlash.php similarity index 97% rename from tests/phpunit/tests/formatting/WPSlash.php rename to tests/phpunit/tests/formatting/wpSlash.php index 4b0d206c06866..bc31a93987149 100644 --- a/tests/phpunit/tests/formatting/WPSlash.php +++ b/tests/phpunit/tests/formatting/wpSlash.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WPSlash extends WP_UnitTestCase { +class Tests_Formatting_wpSlash extends WP_UnitTestCase { /** * @ticket 42195 diff --git a/tests/phpunit/tests/formatting/WPSpecialchars.php b/tests/phpunit/tests/formatting/wpSpecialchars.php similarity index 98% rename from tests/phpunit/tests/formatting/WPSpecialchars.php rename to tests/phpunit/tests/formatting/wpSpecialchars.php index 7cc131da04ea5..59169cd574ec3 100644 --- a/tests/phpunit/tests/formatting/WPSpecialchars.php +++ b/tests/phpunit/tests/formatting/wpSpecialchars.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WPSpecialchars extends WP_UnitTestCase { +class Tests_Formatting_wpSpecialchars extends WP_UnitTestCase { function test_wp_specialchars_basics() { $html = '&<hello world>'; $this->assertSame( $html, _wp_specialchars( $html ) ); diff --git a/tests/phpunit/tests/formatting/WPStripAllTags.php b/tests/phpunit/tests/formatting/wpStripAllTags.php similarity index 93% rename from tests/phpunit/tests/formatting/WPStripAllTags.php rename to tests/phpunit/tests/formatting/wpStripAllTags.php index 8656af26957df..cbeb3214a7202 100644 --- a/tests/phpunit/tests/formatting/WPStripAllTags.php +++ b/tests/phpunit/tests/formatting/wpStripAllTags.php @@ -4,7 +4,7 @@ * * @group formatting */ -class Tests_Formatting_WPStripAllTags extends WP_UnitTestCase { +class Tests_Formatting_wpStripAllTags extends WP_UnitTestCase { function test_wp_strip_all_tags() { diff --git a/tests/phpunit/tests/formatting/WPTargetedLinkRel.php b/tests/phpunit/tests/formatting/wpTargetedLinkRel.php similarity index 98% rename from tests/phpunit/tests/formatting/WPTargetedLinkRel.php rename to tests/phpunit/tests/formatting/wpTargetedLinkRel.php index 932100c1cdae2..b58f4188b58cb 100644 --- a/tests/phpunit/tests/formatting/WPTargetedLinkRel.php +++ b/tests/phpunit/tests/formatting/wpTargetedLinkRel.php @@ -4,7 +4,7 @@ * @group formatting * @ticket 43187 */ -class Tests_Targeted_Link_Rel extends WP_UnitTestCase { +class Tests_Formatting_wpTargetedLinkRel extends WP_UnitTestCase { public function test_add_to_links_with_target_blank() { $content = '

Links: No rel

'; diff --git a/tests/phpunit/tests/formatting/WPTexturize.php b/tests/phpunit/tests/formatting/wpTexturize.php similarity index 99% rename from tests/phpunit/tests/formatting/WPTexturize.php rename to tests/phpunit/tests/formatting/wpTexturize.php index fda1fa9730c57..bfad5c707ad13 100644 --- a/tests/phpunit/tests/formatting/WPTexturize.php +++ b/tests/phpunit/tests/formatting/wpTexturize.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WPTexturize extends WP_UnitTestCase { +class Tests_Formatting_wpTexturize extends WP_UnitTestCase { function test_dashes() { $this->assertSame( 'Hey — boo?', wptexturize( 'Hey -- boo?' ) ); $this->assertSame( 'Hey — boo?', wptexturize( 'Hey -- boo?' ) ); diff --git a/tests/phpunit/tests/formatting/WpTrimExcerpt.php b/tests/phpunit/tests/formatting/wpTrimExcerpt.php similarity index 96% rename from tests/phpunit/tests/formatting/WpTrimExcerpt.php rename to tests/phpunit/tests/formatting/wpTrimExcerpt.php index 01353c8e22ac9..f05e21fb2a613 100644 --- a/tests/phpunit/tests/formatting/WpTrimExcerpt.php +++ b/tests/phpunit/tests/formatting/wpTrimExcerpt.php @@ -4,7 +4,7 @@ * @group formatting * @covers ::wp_trim_excerpt */ -class Tests_Formatting_WpTrimExcerpt extends WP_UnitTestCase { +class Tests_Formatting_wpTrimExcerpt extends WP_UnitTestCase { /** * @ticket 25349 */ diff --git a/tests/phpunit/tests/formatting/WPTrimWords.php b/tests/phpunit/tests/formatting/wpTrimWords.php similarity index 98% rename from tests/phpunit/tests/formatting/WPTrimWords.php rename to tests/phpunit/tests/formatting/wpTrimWords.php index b7ec436df0f1b..3f18d782a6137 100644 --- a/tests/phpunit/tests/formatting/WPTrimWords.php +++ b/tests/phpunit/tests/formatting/wpTrimWords.php @@ -3,7 +3,7 @@ /** * @group formatting */ -class Tests_Formatting_WPTrimWords extends WP_UnitTestCase { +class Tests_Formatting_wpTrimWords extends WP_UnitTestCase { /** * Long Dummy Text. diff --git a/tests/phpunit/tests/formatting/Zeroise.php b/tests/phpunit/tests/formatting/zeroise.php similarity index 100% rename from tests/phpunit/tests/formatting/Zeroise.php rename to tests/phpunit/tests/formatting/zeroise.php diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index 4ef24d22a1991..cdeb2361a8148 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -168,13 +168,21 @@ function test_wp_unique_filename() { $testdir = DIR_TESTDATA . '/images/'; // Sanity check. - $this->assertSame( 'abcdefg.png', wp_unique_filename( $testdir, 'abcdefg.png' ), 'Sanitiy check failed' ); + $this->assertSame( 'abcdefg.png', wp_unique_filename( $testdir, 'abcdefg.png' ), 'Test non-existing file, file name should be unchanged.' ); - // Check number is appended for file already exists. + // Ensure correct images exist. $this->assertFileExists( $testdir . 'test-image.png', 'Test image does not exist' ); - $this->assertSame( 'test-image-1.png', wp_unique_filename( $testdir, 'test-image.png' ), 'Number not appended correctly' ); $this->assertFileDoesNotExist( $testdir . 'test-image-1.png' ); + // Check number is appended if file already exists. + $this->assertSame( 'test-image-1.png', wp_unique_filename( $testdir, 'test-image.png' ), 'File name not unique, number not appended.' ); + + // Check file with uppercase extension. + $this->assertSame( 'test-image-1.png', wp_unique_filename( $testdir, 'test-image.PNG' ), 'File name with uppercase extension not unique, number not appended.' ); + + // Check file name with already added number. + $this->assertSame( 'test-image-2-1.gif', wp_unique_filename( $testdir, 'test-image-2.gif' ), 'File name not unique, number not appended correctly.' ); + // Check special chars. $this->assertSame( 'testtest-image.png', wp_unique_filename( $testdir, 'testtést-imagé.png' ), 'Filename with special chars failed' ); @@ -221,6 +229,88 @@ function upload_dir_patch_basedir( $upload_dir ) { return $upload_dir; } + /** + * @ticket 53668 + */ + function test_wp_unique_filename_with_additional_image_extension() { + $testdir = DIR_TESTDATA . '/images/'; + + add_filter( 'upload_dir', array( $this, 'upload_dir_patch_basedir' ) ); + + // Set conversions for uploaded images. + add_filter( 'image_editor_output_format', array( $this, 'image_editor_output_format_handler' ) ); + + // Ensure the test images exist. + $this->assertFileExists( $testdir . 'test-image-1-100x100.jpg', 'test-image-1-100x100.jpg does not exist' ); + $this->assertFileExists( $testdir . 'test-image-2.gif', 'test-image-2.gif does not exist' ); + $this->assertFileExists( $testdir . 'test-image-3.jpg', 'test-image-3.jpg does not exist' ); + $this->assertFileExists( $testdir . 'test-image-4.png', 'test-image-4.png does not exist' ); + + // Standard test: file does not exist and there are no possible intersections with other files. + $this->assertSame( + 'abcdef.png', + wp_unique_filename( $testdir, 'abcdef.png' ), + 'The abcdef.png, abcdef.gif, and abcdef.jpg images do not exist. The file name should not be changed.' + ); + + // Actual clash recognized. + $this->assertSame( + 'canola-1.jpg', + wp_unique_filename( $testdir, 'canola.jpg' ), + 'The canola.jpg image exists. The file name should be unique.' + ); + + // Same name with different extension and the image will be converted. + $this->assertSame( + 'canola-1.png', + wp_unique_filename( $testdir, 'canola.png' ), + 'The canola.jpg image exists. Uploading canola.png that will be converted to canola.jpg should produce unique file name.' + ); + + // Same name with different uppercase extension and the image will be converted. + $this->assertSame( + 'canola-1.png', + wp_unique_filename( $testdir, 'canola.PNG' ), + 'The canola.jpg image exists. Uploading canola.PNG that will be converted to canola.jpg should produce unique file name.' + ); + + // Actual clash with several images with different extensions. + $this->assertSame( + 'test-image-5.png', + wp_unique_filename( $testdir, 'test-image.png' ), + 'The test-image.png, test-image-1-100x100.jpg, test-image-2.gif, test-image-3.jpg, and test-image-4.png images exist.' . + 'All of them may clash when creating sub-sizes or regenerating thumbnails in the future. The filename should be unique.' + ); + + // Possible clash with regenerated thumbnails in the future. + $this->assertSame( + 'codeispoetry-1.jpg', + wp_unique_filename( $testdir, 'codeispoetry.jpg' ), + 'The codeispoetry.png image exists. When regenerating thumbnails for it they will be converted to JPG.' . + 'The name of the newly uploaded codeispoetry.jpg should be made unique.' + ); + + remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_format_handler' ) ); + remove_filter( 'upload_dir', array( $this, 'upload_dir_patch_basedir' ) ); + } + + /** + * Changes the output format when editing images. When uploading a PNG file + * it will be converted to JPEG, GIF to JPEG, and PICT to BMP + * (if the image editor in PHP supports it). + * + * @param array $formats + * + * @return array + */ + public function image_editor_output_format_handler( $formats ) { + $formats['image/png'] = 'image/jpeg'; + $formats['image/gif'] = 'image/jpeg'; + $formats['image/pct'] = 'image/bmp'; + + return $formats; + } + /** * @dataProvider data_is_not_serialized */ @@ -1946,4 +2036,18 @@ public function data_test_wp_is_json_media_type() { array( 'application/activity+json, application/nojson', true ), ); } + + /** + * @ticket 53668 + */ + public function test_wp_get_default_extension_for_mime_type() { + $this->assertEquals( 'jpg', wp_get_default_extension_for_mime_type( 'image/jpeg' ), 'jpg not returned as default extension for "image/jpeg"' ); + $this->assertNotEquals( 'jpeg', wp_get_default_extension_for_mime_type( 'image/jpeg' ), 'jpeg should not be returned as default extension for "image/jpeg"' ); + $this->assertEquals( 'png', wp_get_default_extension_for_mime_type( 'image/png' ), 'png not returned as default extension for "image/png"' ); + $this->assertFalse( wp_get_default_extension_for_mime_type( 'wibble/wobble' ), 'false not returned for unrecognized mime type' ); + $this->assertFalse( wp_get_default_extension_for_mime_type( '' ), 'false not returned when empty string as mime type supplied' ); + $this->assertFalse( wp_get_default_extension_for_mime_type( ' ' ), 'false not returned when empty string as mime type supplied' ); + $this->assertFalse( wp_get_default_extension_for_mime_type( 123 ), 'false not returned when int as mime type supplied' ); + $this->assertFalse( wp_get_default_extension_for_mime_type( null ), 'false not returned when null as mime type supplied' ); + } } diff --git a/tests/phpunit/tests/functions/anonymization.php b/tests/phpunit/tests/functions/anonymization.php index 9ca33b441e80b..b0dfafa528a28 100644 --- a/tests/phpunit/tests/functions/anonymization.php +++ b/tests/phpunit/tests/functions/anonymization.php @@ -26,6 +26,8 @@ class Tests_Functions_Anonymization extends WP_UnitTestCase { * @ticket 41083 * @ticket 43545 * + * @covers ::wp_privacy_anonymize_ip + * * @param string $raw_ip Raw IP address. * @param string $expected_result Expected result. */ @@ -56,6 +58,22 @@ public function data_wp_privacy_anonymize_ip() { null, '0.0.0.0', ), + array( + false, + '0.0.0.0', + ), + array( + true, + '0.0.0.0', + ), + array( + 0, + '0.0.0.0', + ), + array( + 1, + '0.0.0.0', + ), array( '', '0.0.0.0', @@ -166,6 +184,8 @@ public function data_wp_privacy_anonymize_ip() { * @requires function inet_ntop * @requires function inet_pton * + * @covers ::wp_privacy_anonymize_ip + * * @param string $raw_ip Raw IP address. * @param string $expected_result Expected result. */ diff --git a/tests/phpunit/tests/functions/cleanDirsizeCache.php b/tests/phpunit/tests/functions/cleanDirsizeCache.php new file mode 100644 index 0000000000000..27aacda62b9b9 --- /dev/null +++ b/tests/phpunit/tests/functions/cleanDirsizeCache.php @@ -0,0 +1,140 @@ +expectNotice(); + $this->expectNoticeMessage( $expected_message ); + + clean_dirsize_cache( $path ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_clean_dirsize_cache_with_invalid_inputs() { + return array( + 'null' => array( + 'path' => null, + 'expected_message' => 'clean_dirsize_cache() only accepts a non-empty path string, received NULL.', + ), + 'bool false' => array( + 'path' => false, + 'expected_message' => 'clean_dirsize_cache() only accepts a non-empty path string, received boolean.', + ), + 'empty string' => array( + 'path' => '', + 'expected_message' => 'clean_dirsize_cache() only accepts a non-empty path string, received string.', + ), + 'array' => array( + 'path' => array( '.', './second/path/' ), + 'expected_message' => 'clean_dirsize_cache() only accepts a non-empty path string, received array.', + ), + ); + } + + /** + * Test the handling of a non-path text string passed as the $path parameter. + * + * @ticket 52241 + * + * @covers ::clean_dirsize_cache + * + * @dataProvider data_clean_dirsize_cache_with_non_path_string + * + * @param string $path Path input to use in the test. + * @param int $expected_count Expected number of paths in the cache after cleaning. + */ + public function test_clean_dirsize_cache_with_non_path_string( $path, $expected_count ) { + // Set the dirsize cache to our mock. + set_transient( 'dirsize_cache', $this->mock_dirsize_cache_with_non_path_string() ); + + clean_dirsize_cache( $path ); + + $cache = get_transient( 'dirsize_cache' ); + $this->assertIsArray( $cache ); + $this->assertCount( $expected_count, $cache ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_clean_dirsize_cache_with_non_path_string() { + return array( + 'single dot' => array( + 'path' => '.', + 'expected_count' => 1, + ), + 'non-path' => array( + 'path' => 'string', + 'expected_count' => 1, + ), + 'non-existant string, but non-path' => array( + 'path' => 'doesnotexist', + 'expected_count' => 2, + ), + ); + } + + private function mock_dirsize_cache_with_non_path_string() { + return array( + '.' => array( 'size' => 50 ), + 'string' => array( 'size' => 42 ), + ); + } + + /** + * Test the behaviour of the function when the transient doesn't exist. + * + * @ticket 52241 + * @ticket 53635 + * + * @covers ::recurse_dirsize + */ + public function test_recurse_dirsize_without_transient() { + delete_transient( 'dirsize_cache' ); + + $size = recurse_dirsize( DIR_TESTDATA . '/functions' ); + + $this->assertGreaterThan( 10, $size ); + } + + /** + * Test the behaviour of the function when the transient does exist, but is not an array. + * + * In particular, this tests that no PHP TypeErrors are being thrown. + * + * @ticket 52241 + * @ticket 53635 + * + * @covers ::recurse_dirsize + */ + public function test_recurse_dirsize_with_invalid_transient() { + set_transient( 'dirsize_cache', 'this is not a valid transient for dirsize cache' ); + + $size = recurse_dirsize( DIR_TESTDATA . '/functions' ); + + $this->assertGreaterThan( 10, $size ); + } +} diff --git a/tests/phpunit/tests/functions/doEnclose.php b/tests/phpunit/tests/functions/doEnclose.php index 30a8e73dac0c2..5c8a42089fba7 100644 --- a/tests/phpunit/tests/functions/doEnclose.php +++ b/tests/phpunit/tests/functions/doEnclose.php @@ -280,7 +280,7 @@ public function fake_http_request( $false, $arguments, $url ) { $path = parse_url( $url, PHP_URL_PATH ); - if ( null !== $path ) { + if ( is_string( $path ) ) { $extension = pathinfo( $path, PATHINFO_EXTENSION ); if ( isset( $fake_headers[ $extension ] ) ) { return $fake_headers[ $extension ]; diff --git a/tests/phpunit/tests/functions/wpFilterObjectList.php b/tests/phpunit/tests/functions/wpFilterObjectList.php new file mode 100644 index 0000000000000..b0c9edc4eda47 --- /dev/null +++ b/tests/phpunit/tests/functions/wpFilterObjectList.php @@ -0,0 +1,204 @@ +array_list['foo'] = array( + 'name' => 'foo', + 'id' => 'f', + 'field1' => true, + 'field2' => true, + 'field3' => true, + 'field4' => array( 'red' ), + ); + $this->array_list['bar'] = array( + 'name' => 'bar', + 'id' => 'b', + 'field1' => true, + 'field2' => true, + 'field3' => false, + 'field4' => array( 'green' ), + ); + $this->array_list['baz'] = array( + 'name' => 'baz', + 'id' => 'z', + 'field1' => true, + 'field2' => false, + 'field3' => false, + 'field4' => array( 'blue' ), + ); + foreach ( $this->array_list as $key => $value ) { + $this->object_list[ $key ] = (object) $value; + } + } + + public function test_filter_object_list_and() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field1' => true, + 'field2' => true, + ), + 'AND' + ); + $this->assertCount( 2, $list ); + $this->assertArrayHasKey( 'foo', $list ); + $this->assertArrayHasKey( 'bar', $list ); + } + + public function test_filter_object_list_or() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field1' => true, + 'field2' => true, + ), + 'OR' + ); + $this->assertCount( 3, $list ); + $this->assertArrayHasKey( 'foo', $list ); + $this->assertArrayHasKey( 'bar', $list ); + $this->assertArrayHasKey( 'baz', $list ); + } + + public function test_filter_object_list_not() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field2' => true, + 'field3' => true, + ), + 'NOT' + ); + $this->assertCount( 1, $list ); + $this->assertArrayHasKey( 'baz', $list ); + } + + public function test_filter_object_list_and_field() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field1' => true, + 'field2' => true, + ), + 'AND', + 'name' + ); + $this->assertSame( + array( + 'foo' => 'foo', + 'bar' => 'bar', + ), + $list + ); + } + + public function test_filter_object_list_or_field() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field2' => true, + 'field3' => true, + ), + 'OR', + 'name' + ); + $this->assertSame( + array( + 'foo' => 'foo', + 'bar' => 'bar', + ), + $list + ); + } + + public function test_filter_object_list_not_field() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field2' => true, + 'field3' => true, + ), + 'NOT', + 'name' + ); + $this->assertSame( array( 'baz' => 'baz' ), $list ); + } + + public function test_filter_object_list_nested_array_and() { + $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'blue' ) ), 'AND' ); + $this->assertCount( 1, $list ); + $this->assertArrayHasKey( 'baz', $list ); + } + + public function test_filter_object_list_nested_array_not() { + $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'red' ) ), 'NOT' ); + $this->assertCount( 2, $list ); + $this->assertArrayHasKey( 'bar', $list ); + $this->assertArrayHasKey( 'baz', $list ); + } + + public function test_filter_object_list_nested_array_or() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field3' => true, + 'field4' => array( 'blue' ), + ), + 'OR' + ); + $this->assertCount( 2, $list ); + $this->assertArrayHasKey( 'foo', $list ); + $this->assertArrayHasKey( 'baz', $list ); + } + + public function test_filter_object_list_nested_array_or_singular() { + $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'blue' ) ), 'OR' ); + $this->assertCount( 1, $list ); + $this->assertArrayHasKey( 'baz', $list ); + } + + public function test_filter_object_list_nested_array_and_field() { + $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'blue' ) ), 'AND', 'name' ); + $this->assertSame( array( 'baz' => 'baz' ), $list ); + } + + public function test_filter_object_list_nested_array_not_field() { + $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'green' ) ), 'NOT', 'name' ); + $this->assertSame( + array( + 'foo' => 'foo', + 'baz' => 'baz', + ), + $list + ); + } + + public function test_filter_object_list_nested_array_or_field() { + $list = wp_filter_object_list( + $this->object_list, + array( + 'field3' => true, + 'field4' => array( 'blue' ), + ), + 'OR', + 'name' + ); + $this->assertSame( + array( + 'foo' => 'foo', + 'baz' => 'baz', + ), + $list + ); + } +} diff --git a/tests/phpunit/tests/functions/wpListFilter.php b/tests/phpunit/tests/functions/wpListFilter.php index b79837bf162bb..45ea4f9601f6e 100644 --- a/tests/phpunit/tests/functions/wpListFilter.php +++ b/tests/phpunit/tests/functions/wpListFilter.php @@ -1,356 +1,215 @@ array_list['foo'] = array( - 'name' => 'foo', - 'id' => 'f', - 'field1' => true, - 'field2' => true, - 'field3' => true, - 'field4' => array( 'red' ), - ); - $this->array_list['bar'] = array( - 'name' => 'bar', - 'id' => 'b', - 'field1' => true, - 'field2' => true, - 'field3' => false, - 'field4' => array( 'green' ), - ); - $this->array_list['baz'] = array( - 'name' => 'baz', - 'id' => 'z', - 'field1' => true, - 'field2' => false, - 'field3' => false, - 'field4' => array( 'blue' ), - ); - foreach ( $this->array_list as $key => $value ) { - $this->object_list[ $key ] = (object) $value; - } - } - - function test_filter_object_list_and() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field1' => true, - 'field2' => true, - ), - 'AND' - ); - $this->assertCount( 2, $list ); - $this->assertArrayHasKey( 'foo', $list ); - $this->assertArrayHasKey( 'bar', $list ); - } - - function test_filter_object_list_or() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field1' => true, - 'field2' => true, - ), - 'OR' - ); - $this->assertCount( 3, $list ); - $this->assertArrayHasKey( 'foo', $list ); - $this->assertArrayHasKey( 'bar', $list ); - $this->assertArrayHasKey( 'baz', $list ); - } - - function test_filter_object_list_not() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field2' => true, - 'field3' => true, - ), - 'NOT' - ); - $this->assertCount( 1, $list ); - $this->assertArrayHasKey( 'baz', $list ); - } - - function test_filter_object_list_and_field() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field1' => true, - 'field2' => true, - ), - 'AND', - 'name' - ); - $this->assertSame( - array( - 'foo' => 'foo', - 'bar' => 'bar', - ), - $list - ); - } - - function test_filter_object_list_or_field() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field2' => true, - 'field3' => true, - ), - 'OR', - 'name' - ); - $this->assertSame( - array( - 'foo' => 'foo', - 'bar' => 'bar', - ), - $list - ); - } - - function test_filter_object_list_not_field() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field2' => true, - 'field3' => true, - ), - 'NOT', - 'name' - ); - $this->assertSame( array( 'baz' => 'baz' ), $list ); - } - - function test_wp_list_pluck() { - $list = wp_list_pluck( $this->object_list, 'name' ); - $this->assertSame( - array( - 'foo' => 'foo', - 'bar' => 'bar', - 'baz' => 'baz', - ), - $list - ); - - $list = wp_list_pluck( $this->array_list, 'name' ); - $this->assertSame( - array( - 'foo' => 'foo', - 'bar' => 'bar', - 'baz' => 'baz', - ), - $list - ); - } - - /** - * @ticket 28666 - */ - function test_wp_list_pluck_index_key() { - $list = wp_list_pluck( $this->array_list, 'name', 'id' ); - $this->assertSame( - array( - 'f' => 'foo', - 'b' => 'bar', - 'z' => 'baz', - ), - $list - ); - } - - /** - * @ticket 28666 - */ - function test_wp_list_pluck_object_index_key() { - $list = wp_list_pluck( $this->object_list, 'name', 'id' ); - $this->assertSame( - array( - 'f' => 'foo', - 'b' => 'bar', - 'z' => 'baz', - ), - $list - ); - } /** - * @ticket 28666 + * @dataProvider data_test_wp_list_filter + * + * @param array $list An array of objects to filter. + * @param array $args An array of key => value arguments to match + * against each object. + * @param string $operator The logical operation to perform. + * @param array $expected Expected result. */ - function test_wp_list_pluck_missing_index_key() { - $list = wp_list_pluck( $this->array_list, 'name', 'nonexistent' ); - $this->assertSame( - array( - 0 => 'foo', - 1 => 'bar', - 2 => 'baz', - ), - $list - ); - } - - /** - * @ticket 28666 - */ - function test_wp_list_pluck_partial_missing_index_key() { - $array_list = $this->array_list; - unset( $array_list['bar']['id'] ); - $list = wp_list_pluck( $array_list, 'name', 'id' ); - $this->assertSame( - array( - 'f' => 'foo', - 0 => 'bar', - 'z' => 'baz', - ), - $list - ); - } - - /** - * @ticket 28666 - */ - function test_wp_list_pluck_mixed_index_key() { - $mixed_list = $this->array_list; - $mixed_list['bar'] = (object) $mixed_list['bar']; - $list = wp_list_pluck( $mixed_list, 'name', 'id' ); - $this->assertSame( - array( - 'f' => 'foo', - 'b' => 'bar', - 'z' => 'baz', - ), - $list - ); + public function test_wp_list_filter( $list, $args, $operator, $expected ) { + $this->assertEqualSetsWithIndex( $expected, wp_list_filter( $list, $args, $operator ) ); } - /** - * @ticket 16895 - */ - function test_wp_list_pluck_containing_references() { - $ref_list = array( - & $this->object_list['foo'], - & $this->object_list['bar'], - ); - - $this->assertInstanceOf( 'stdClass', $ref_list[0] ); - $this->assertInstanceOf( 'stdClass', $ref_list[1] ); - - $list = wp_list_pluck( $ref_list, 'name' ); - $this->assertSame( - array( + public function data_test_wp_list_filter() { + return array( + 'string instead of array' => array( 'foo', - 'bar', - ), - $list - ); - - $this->assertInstanceOf( 'stdClass', $ref_list[0] ); - $this->assertInstanceOf( 'stdClass', $ref_list[1] ); - } - - /** - * @ticket 16895 - */ - function test_wp_list_pluck_containing_references_keys() { - $ref_list = array( - & $this->object_list['foo'], - & $this->object_list['bar'], - ); - - $this->assertInstanceOf( 'stdClass', $ref_list[0] ); - $this->assertInstanceOf( 'stdClass', $ref_list[1] ); - - $list = wp_list_pluck( $ref_list, 'name', 'id' ); - $this->assertSame( - array( - 'f' => 'foo', - 'b' => 'bar', - ), - $list - ); - - $this->assertInstanceOf( 'stdClass', $ref_list[0] ); - $this->assertInstanceOf( 'stdClass', $ref_list[1] ); - } - - function test_filter_object_list_nested_array_and() { - $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'blue' ) ), 'AND' ); - $this->assertCount( 1, $list ); - $this->assertArrayHasKey( 'baz', $list ); - } - - function test_filter_object_list_nested_array_not() { - $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'red' ) ), 'NOT' ); - $this->assertCount( 2, $list ); - $this->assertArrayHasKey( 'bar', $list ); - $this->assertArrayHasKey( 'baz', $list ); - } - - function test_filter_object_list_nested_array_or() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field3' => true, - 'field4' => array( 'blue' ), - ), - 'OR' - ); - $this->assertCount( 2, $list ); - $this->assertArrayHasKey( 'foo', $list ); - $this->assertArrayHasKey( 'baz', $list ); - } - - function test_filter_object_list_nested_array_or_singular() { - $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'blue' ) ), 'OR' ); - $this->assertCount( 1, $list ); - $this->assertArrayHasKey( 'baz', $list ); - } - - function test_filter_object_list_nested_array_and_field() { - $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'blue' ) ), 'AND', 'name' ); - $this->assertSame( array( 'baz' => 'baz' ), $list ); - } - - function test_filter_object_list_nested_array_not_field() { - $list = wp_filter_object_list( $this->object_list, array( 'field4' => array( 'green' ) ), 'NOT', 'name' ); - $this->assertSame( - array( - 'foo' => 'foo', - 'baz' => 'baz', - ), - $list - ); - } - - function test_filter_object_list_nested_array_or_field() { - $list = wp_filter_object_list( - $this->object_list, - array( - 'field3' => true, - 'field4' => array( 'blue' ), - ), - 'OR', - 'name' - ); - $this->assertSame( - array( - 'foo' => 'foo', - 'baz' => 'baz', + array(), + 'AND', + array(), + ), + 'object instead of array' => array( + (object) array( 'foo' ), + array(), + 'AND', + array(), + ), + 'empty args' => array( + array( 'foo', 'bar' ), + array(), + 'AND', + array( 'foo', 'bar' ), + ), + 'invalid operator' => array( + array( + (object) array( 'foo' => 'bar' ), + (object) array( 'foo' => 'baz' ), + ), + array( 'foo' => 'bar' ), + 'XOR', + array(), + ), + 'single argument to match' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + (object) array( + 'foo' => 'baz', + 'key' => 'value', + ), + (object) array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( 'foo' => 'bar' ), + 'AND', + array( + 0 => (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + 3 => (object) array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + ), + 'all must match' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + (object) array( + 'foo' => 'baz', + 'key' => 'value', + 'bar' => 'baz', + ), + (object) array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'foo' => 'bar', + 'bar' => 'baz', + ), + 'AND', + array( + 0 => (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + ), + ), + 'any must match' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + (object) array( + 'foo' => 'baz', + 'key' => 'value', + 'bar' => 'baz', + ), + (object) array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'value', + 'bar' => 'baz', + ), + 'OR', + array( + 0 => (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + 2 => (object) array( + 'foo' => 'baz', + 'key' => 'value', + 'bar' => 'baz', + ), + 3 => (object) array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + ), + 'none must match' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + (object) array( + 'foo' => 'baz', + 'key' => 'value', + ), + (object) array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'value', + 'bar' => 'baz', + ), + 'NOT', + array( + 1 => (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), ), - $list ); } } diff --git a/tests/phpunit/tests/functions/wpListPluck.php b/tests/phpunit/tests/functions/wpListPluck.php new file mode 100644 index 0000000000000..10c78ed9bd3ff --- /dev/null +++ b/tests/phpunit/tests/functions/wpListPluck.php @@ -0,0 +1,353 @@ +array_list['foo'] = array( + 'name' => 'foo', + 'id' => 'f', + 'field1' => true, + 'field2' => true, + 'field3' => true, + 'field4' => array( 'red' ), + ); + $this->array_list['bar'] = array( + 'name' => 'bar', + 'id' => 'b', + 'field1' => true, + 'field2' => true, + 'field3' => false, + 'field4' => array( 'green' ), + ); + $this->array_list['baz'] = array( + 'name' => 'baz', + 'id' => 'z', + 'field1' => true, + 'field2' => false, + 'field3' => false, + 'field4' => array( 'blue' ), + ); + foreach ( $this->array_list as $key => $value ) { + $this->object_list[ $key ] = (object) $value; + } + } + + public function test_wp_list_pluck_array_and_object() { + $list = wp_list_pluck( $this->object_list, 'name' ); + $this->assertSame( + array( + 'foo' => 'foo', + 'bar' => 'bar', + 'baz' => 'baz', + ), + $list + ); + + $list = wp_list_pluck( $this->array_list, 'name' ); + $this->assertSame( + array( + 'foo' => 'foo', + 'bar' => 'bar', + 'baz' => 'baz', + ), + $list + ); + } + + /** + * @ticket 28666 + */ + public function test_wp_list_pluck_index_key() { + $list = wp_list_pluck( $this->array_list, 'name', 'id' ); + $this->assertSame( + array( + 'f' => 'foo', + 'b' => 'bar', + 'z' => 'baz', + ), + $list + ); + } + + /** + * @ticket 28666 + */ + public function test_wp_list_pluck_object_index_key() { + $list = wp_list_pluck( $this->object_list, 'name', 'id' ); + $this->assertSame( + array( + 'f' => 'foo', + 'b' => 'bar', + 'z' => 'baz', + ), + $list + ); + } + + /** + * @ticket 28666 + */ + public function test_wp_list_pluck_missing_index_key() { + $list = wp_list_pluck( $this->array_list, 'name', 'nonexistent' ); + $this->assertSame( + array( + 0 => 'foo', + 1 => 'bar', + 2 => 'baz', + ), + $list + ); + } + + /** + * @ticket 28666 + */ + public function test_wp_list_pluck_partial_missing_index_key() { + $array_list = $this->array_list; + unset( $array_list['bar']['id'] ); + $list = wp_list_pluck( $array_list, 'name', 'id' ); + $this->assertSame( + array( + 'f' => 'foo', + 0 => 'bar', + 'z' => 'baz', + ), + $list + ); + } + + /** + * @ticket 28666 + */ + public function test_wp_list_pluck_mixed_index_key() { + $mixed_list = $this->array_list; + $mixed_list['bar'] = (object) $mixed_list['bar']; + $list = wp_list_pluck( $mixed_list, 'name', 'id' ); + $this->assertSame( + array( + 'f' => 'foo', + 'b' => 'bar', + 'z' => 'baz', + ), + $list + ); + } + + /** + * @ticket 16895 + */ + public function test_wp_list_pluck_containing_references() { + $ref_list = array( + & $this->object_list['foo'], + & $this->object_list['bar'], + ); + + $this->assertInstanceOf( 'stdClass', $ref_list[0] ); + $this->assertInstanceOf( 'stdClass', $ref_list[1] ); + + $list = wp_list_pluck( $ref_list, 'name' ); + $this->assertSame( + array( + 'foo', + 'bar', + ), + $list + ); + + $this->assertInstanceOf( 'stdClass', $ref_list[0] ); + $this->assertInstanceOf( 'stdClass', $ref_list[1] ); + } + + /** + * @ticket 16895 + */ + public function test_wp_list_pluck_containing_references_keys() { + $ref_list = array( + & $this->object_list['foo'], + & $this->object_list['bar'], + ); + + $this->assertInstanceOf( 'stdClass', $ref_list[0] ); + $this->assertInstanceOf( 'stdClass', $ref_list[1] ); + + $list = wp_list_pluck( $ref_list, 'name', 'id' ); + $this->assertSame( + array( + 'f' => 'foo', + 'b' => 'bar', + ), + $list + ); + + $this->assertInstanceOf( 'stdClass', $ref_list[0] ); + $this->assertInstanceOf( 'stdClass', $ref_list[1] ); + } + + /** + * @dataProvider data_test_wp_list_pluck + * + * @param array $list List of objects or arrays. + * @param int|string $field Field from the object to place instead of the entire object + * @param int|string $index_key Field from the object to use as keys for the new array. + * @param array $expected Expected result. + */ + public function test_wp_list_pluck( $list, $field, $index_key, $expected ) { + $this->assertSameSetsWithIndex( $expected, wp_list_pluck( $list, $field, $index_key ) ); + } + + public function data_test_wp_list_pluck() { + return array( + 'arrays' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + ), + array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + ), + array( 'foo' => 'baz' ), + ), + 'foo', + null, + array( 'bar', 'foo', 'baz' ), + ), + 'arrays with index key' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'key', + array( + 'foo' => 'bar', + 'bar' => 'foo', + 'value' => 'baz', + ), + ), + 'arrays with index key missing' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + ), + array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'key', + array( + 'bar', + 'bar' => 'foo', + 'value' => 'baz', + ), + ), + 'objects' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + ), + (object) array( 'foo' => 'baz' ), + ), + 'foo', + null, + array( 'bar', 'foo', 'baz' ), + ), + 'objects with index key' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + 'key' => 'foo', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + (object) array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'key', + array( + 'foo' => 'bar', + 'bar' => 'foo', + 'value' => 'baz', + ), + ), + 'objects with index key missing' => array( + array( + (object) array( + 'foo' => 'bar', + 'bar' => 'baz', + 'abc' => 'xyz', + ), + (object) array( + 'foo' => 'foo', + '123' => '456', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + (object) array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'key', + array( + 'bar', + 'bar' => 'foo', + 'value' => 'baz', + ), + ), + ); + } +} diff --git a/tests/phpunit/tests/functions/wpListSort.php b/tests/phpunit/tests/functions/wpListSort.php new file mode 100644 index 0000000000000..7159af4937687 --- /dev/null +++ b/tests/phpunit/tests/functions/wpListSort.php @@ -0,0 +1,660 @@ + $order. + * @param string $order Either 'ASC' or 'DESC'. + */ + public function test_wp_list_sort( $list, $orderby, $order, $expected ) { + $this->assertSame( $expected, wp_list_sort( $list, $orderby, $order ) ); + } + + public function data_test_wp_list_sort() { + return array( + 'single orderby ascending' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'ASC', + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + 'single orderby descending' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'DESC', + array( + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + ), + ), + 'single orderby array ascending' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + array( 'foo' => 'ASC' ), + 'IGNORED', + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + 'single orderby array descending' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + array( 'foo' => 'DESC' ), + 'IGNORED', + array( + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'baz', + 'key' => 'value', + ), + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + ), + ), + 'multiple orderby ascending' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'foo', + 'key' => 'key', + ), + array( + 'foo' => 'baz', + 'key' => 'key', + ), + array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'ASC', + 'foo' => 'ASC', + ), + 'IGNORED', + array( + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'baz', + 'key' => 'key', + ), + array( + 'foo' => 'foo', + 'key' => 'key', + ), + array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + ), + 'multiple orderby descending' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'foo', + 'key' => 'key', + ), + array( + 'foo' => 'baz', + 'key' => 'key', + ), + array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'DESC', + 'foo' => 'DESC', + ), + 'IGNORED', + array( + array( + 'foo' => 'bar', + 'key' => 'value', + ), + array( + 'foo' => 'foo', + 'key' => 'key', + ), + array( + 'foo' => 'baz', + 'key' => 'key', + ), + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + 'multiple orderby mixed' => array( + array( + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + array( + 'foo' => 'foo', + 'key' => 'key', + ), + array( + 'foo' => 'baz', + 'key' => 'key', + ), + array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'DESC', + 'foo' => 'ASC', + ), + 'IGNORED', + array( + array( + 'foo' => 'bar', + 'key' => 'value', + ), + array( + 'foo' => 'baz', + 'key' => 'key', + ), + array( + 'foo' => 'foo', + 'key' => 'key', + ), + array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + ); + } + + /** + * @dataProvider data_test_wp_list_sort_preserve_keys + * + * @param string|array $orderby Either the field name to order by or an array + * of multiple orderby fields as $orderby => $order. + * @param string $order Either 'ASC' or 'DESC'. + */ + public function test_wp_list_sort_preserve_keys( $list, $orderby, $order, $expected ) { + $this->assertSame( $expected, wp_list_sort( $list, $orderby, $order, true ) ); + } + + public function data_test_wp_list_sort_preserve_keys() { + return array( + 'single orderby ascending' => array( + array( + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'ASC', + array( + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + 'single orderby descending' => array( + array( + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + 'foo', + 'DESC', + array( + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + ), + ), + 'single orderby array ascending' => array( + array( + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + array( 'foo' => 'ASC' ), + 'IGNORED', + array( + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + 'single orderby array descending' => array( + array( + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + ), + array( 'foo' => 'DESC' ), + 'IGNORED', + array( + 'foofoo' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobaz' => array( + 'foo' => 'baz', + 'key' => 'value', + ), + 'foobar' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + ), + ), + 'multiple orderby ascending' => array( + array( + 'foobarfoo' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoobar' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foofookey' => array( + 'foo' => 'foo', + 'key' => 'key', + ), + 'foobazkey' => array( + 'foo' => 'baz', + 'key' => 'key', + ), + 'foobarvalue' => array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'ASC', + 'foo' => 'ASC', + ), + 'IGNORED', + array( + 'foofoobar' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foobarfoo' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foobazkey' => array( + 'foo' => 'baz', + 'key' => 'key', + ), + 'foofookey' => array( + 'foo' => 'foo', + 'key' => 'key', + ), + 'foobarvalue' => array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + ), + 'multiple orderby descending' => array( + array( + 'foobarfoo' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoobar' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foofookey' => array( + 'foo' => 'foo', + 'key' => 'key', + ), + 'foobazkey' => array( + 'foo' => 'baz', + 'key' => 'key', + ), + 'foobarvalue' => array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'DESC', + 'foo' => 'DESC', + ), + 'IGNORED', + array( + 'foobarvalue' => array( + 'foo' => 'bar', + 'key' => 'value', + ), + 'foofookey' => array( + 'foo' => 'foo', + 'key' => 'key', + ), + 'foobazkey' => array( + 'foo' => 'baz', + 'key' => 'key', + ), + 'foobarfoo' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoobar' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + 'multiple orderby mixed' => array( + array( + 'foobarfoo' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoobar' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + 'foofookey' => array( + 'foo' => 'foo', + 'key' => 'key', + ), + 'foobazkey' => array( + 'foo' => 'baz', + 'key' => 'key', + ), + 'foobarvalue' => array( + 'foo' => 'bar', + 'key' => 'value', + ), + ), + array( + 'key' => 'DESC', + 'foo' => 'ASC', + ), + 'IGNORED', + array( + 'foobarvalue' => array( + 'foo' => 'bar', + 'key' => 'value', + ), + 'foobazkey' => array( + 'foo' => 'baz', + 'key' => 'key', + ), + 'foofookey' => array( + 'foo' => 'foo', + 'key' => 'key', + ), + 'foobarfoo' => array( + 'foo' => 'bar', + 'bar' => 'baz', + 'key' => 'foo', + ), + 'foofoobar' => array( + 'foo' => 'foo', + 'lorem' => 'ipsum', + 'key' => 'bar', + ), + ), + ), + ); + } +} diff --git a/tests/phpunit/tests/functions/wpListUtil.php b/tests/phpunit/tests/functions/wpListUtil.php index 69b32d95f42b8..45cad6627aa38 100644 --- a/tests/phpunit/tests/functions/wpListUtil.php +++ b/tests/phpunit/tests/functions/wpListUtil.php @@ -1,1032 +1,12 @@ array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - ), - array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - ), - array( 'foo' => 'baz' ), - ), - 'foo', - null, - array( 'bar', 'foo', 'baz' ), - ), - 'arrays with index key' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'key', - array( - 'foo' => 'bar', - 'bar' => 'foo', - 'value' => 'baz', - ), - ), - 'arrays with index key missing' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - ), - array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'key', - array( - 'bar', - 'bar' => 'foo', - 'value' => 'baz', - ), - ), - 'objects' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - ), - (object) array( 'foo' => 'baz' ), - ), - 'foo', - null, - array( 'bar', 'foo', 'baz' ), - ), - 'objects with index key' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - (object) array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'key', - array( - 'foo' => 'bar', - 'bar' => 'foo', - 'value' => 'baz', - ), - ), - 'objects with index key missing' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - (object) array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'key', - array( - 'bar', - 'bar' => 'foo', - 'value' => 'baz', - ), - ), - ); - } - - /** - * @dataProvider data_test_wp_list_pluck - * - * @covers ::wp_list_pluck - * - * @param array $list List of objects or arrays. - * @param int|string $field Field from the object to place instead of the entire object - * @param int|string $index_key Field from the object to use as keys for the new array. - * @param array $expected Expected result. - */ - public function test_wp_list_pluck( $list, $field, $index_key, $expected ) { - $this->assertSameSetsWithIndex( $expected, wp_list_pluck( $list, $field, $index_key ) ); - } - - public function data_test_wp_list_filter() { - return array( - 'string instead of array' => array( - 'foo', - array(), - 'AND', - array(), - ), - 'object instead of array' => array( - (object) array( 'foo' ), - array(), - 'AND', - array(), - ), - 'empty args' => array( - array( 'foo', 'bar' ), - array(), - 'AND', - array( 'foo', 'bar' ), - ), - 'invalid operator' => array( - array( - (object) array( 'foo' => 'bar' ), - (object) array( 'foo' => 'baz' ), - ), - array( 'foo' => 'bar' ), - 'XOR', - array(), - ), - 'single argument to match' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - (object) array( - 'foo' => 'baz', - 'key' => 'value', - ), - (object) array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( 'foo' => 'bar' ), - 'AND', - array( - 0 => (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - 3 => (object) array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - ), - 'all must match' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - (object) array( - 'foo' => 'baz', - 'key' => 'value', - 'bar' => 'baz', - ), - (object) array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'foo' => 'bar', - 'bar' => 'baz', - ), - 'AND', - array( - 0 => (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - ), - ), - 'any must match' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - (object) array( - 'foo' => 'baz', - 'key' => 'value', - 'bar' => 'baz', - ), - (object) array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'value', - 'bar' => 'baz', - ), - 'OR', - array( - 0 => (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - 2 => (object) array( - 'foo' => 'baz', - 'key' => 'value', - 'bar' => 'baz', - ), - 3 => (object) array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - ), - 'none must match' => array( - array( - (object) array( - 'foo' => 'bar', - 'bar' => 'baz', - 'abc' => 'xyz', - 'key' => 'foo', - ), - (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - (object) array( - 'foo' => 'baz', - 'key' => 'value', - ), - (object) array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'value', - 'bar' => 'baz', - ), - 'NOT', - array( - 1 => (object) array( - 'foo' => 'foo', - '123' => '456', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - ); - } - - /** - * @dataProvider data_test_wp_list_filter - * - * @covers ::wp_list_filter - * - * @param array $list An array of objects to filter. - * @param array $args An array of key => value arguments to match - * against each object. - * @param string $operator The logical operation to perform. - * @param array $expected Expected result. - */ - public function test_wp_list_filter( $list, $args, $operator, $expected ) { - $this->assertEqualSetsWithIndex( $expected, wp_list_filter( $list, $args, $operator ) ); - } - - public function data_test_wp_list_sort() { - return array( - 'single orderby ascending' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'ASC', - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - 'single orderby descending' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'DESC', - array( - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - ), - ), - 'single orderby array ascending' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - array( 'foo' => 'ASC' ), - 'IGNORED', - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - 'single orderby array descending' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - array( 'foo' => 'DESC' ), - 'IGNORED', - array( - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'baz', - 'key' => 'value', - ), - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - ), - ), - 'multiple orderby ascending' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'foo', - 'key' => 'key', - ), - array( - 'foo' => 'baz', - 'key' => 'key', - ), - array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'ASC', - 'foo' => 'ASC', - ), - 'IGNORED', - array( - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'baz', - 'key' => 'key', - ), - array( - 'foo' => 'foo', - 'key' => 'key', - ), - array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - ), - 'multiple orderby descending' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'foo', - 'key' => 'key', - ), - array( - 'foo' => 'baz', - 'key' => 'key', - ), - array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'DESC', - 'foo' => 'DESC', - ), - 'IGNORED', - array( - array( - 'foo' => 'bar', - 'key' => 'value', - ), - array( - 'foo' => 'foo', - 'key' => 'key', - ), - array( - 'foo' => 'baz', - 'key' => 'key', - ), - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - 'multiple orderby mixed' => array( - array( - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - array( - 'foo' => 'foo', - 'key' => 'key', - ), - array( - 'foo' => 'baz', - 'key' => 'key', - ), - array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'DESC', - 'foo' => 'ASC', - ), - 'IGNORED', - array( - array( - 'foo' => 'bar', - 'key' => 'value', - ), - array( - 'foo' => 'baz', - 'key' => 'key', - ), - array( - 'foo' => 'foo', - 'key' => 'key', - ), - array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - ); - } - - /** - * @dataProvider data_test_wp_list_sort - * - * @covers ::wp_list_sort - * - * @param string|array $orderby Either the field name to order by or an array - * of multiple orderby fields as $orderby => $order. - * @param string $order Either 'ASC' or 'DESC'. - */ - public function test_wp_list_sort( $list, $orderby, $order, $expected ) { - $this->assertSame( $expected, wp_list_sort( $list, $orderby, $order ) ); - } - - public function data_test_wp_list_sort_preserve_keys() { - return array( - 'single orderby ascending' => array( - array( - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'ASC', - array( - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - 'single orderby descending' => array( - array( - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - 'foo', - 'DESC', - array( - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - ), - ), - 'single orderby array ascending' => array( - array( - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - array( 'foo' => 'ASC' ), - 'IGNORED', - array( - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - 'single orderby array descending' => array( - array( - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - ), - array( 'foo' => 'DESC' ), - 'IGNORED', - array( - 'foofoo' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobaz' => array( - 'foo' => 'baz', - 'key' => 'value', - ), - 'foobar' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - ), - ), - 'multiple orderby ascending' => array( - array( - 'foobarfoo' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoobar' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foofookey' => array( - 'foo' => 'foo', - 'key' => 'key', - ), - 'foobazkey' => array( - 'foo' => 'baz', - 'key' => 'key', - ), - 'foobarvalue' => array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'ASC', - 'foo' => 'ASC', - ), - 'IGNORED', - array( - 'foofoobar' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foobarfoo' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foobazkey' => array( - 'foo' => 'baz', - 'key' => 'key', - ), - 'foofookey' => array( - 'foo' => 'foo', - 'key' => 'key', - ), - 'foobarvalue' => array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - ), - 'multiple orderby descending' => array( - array( - 'foobarfoo' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoobar' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foofookey' => array( - 'foo' => 'foo', - 'key' => 'key', - ), - 'foobazkey' => array( - 'foo' => 'baz', - 'key' => 'key', - ), - 'foobarvalue' => array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'DESC', - 'foo' => 'DESC', - ), - 'IGNORED', - array( - 'foobarvalue' => array( - 'foo' => 'bar', - 'key' => 'value', - ), - 'foofookey' => array( - 'foo' => 'foo', - 'key' => 'key', - ), - 'foobazkey' => array( - 'foo' => 'baz', - 'key' => 'key', - ), - 'foobarfoo' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoobar' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - 'multiple orderby mixed' => array( - array( - 'foobarfoo' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoobar' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - 'foofookey' => array( - 'foo' => 'foo', - 'key' => 'key', - ), - 'foobazkey' => array( - 'foo' => 'baz', - 'key' => 'key', - ), - 'foobarvalue' => array( - 'foo' => 'bar', - 'key' => 'value', - ), - ), - array( - 'key' => 'DESC', - 'foo' => 'ASC', - ), - 'IGNORED', - array( - 'foobarvalue' => array( - 'foo' => 'bar', - 'key' => 'value', - ), - 'foobazkey' => array( - 'foo' => 'baz', - 'key' => 'key', - ), - 'foofookey' => array( - 'foo' => 'foo', - 'key' => 'key', - ), - 'foobarfoo' => array( - 'foo' => 'bar', - 'bar' => 'baz', - 'key' => 'foo', - ), - 'foofoobar' => array( - 'foo' => 'foo', - 'lorem' => 'ipsum', - 'key' => 'bar', - ), - ), - ), - ); - } - - /** - * @dataProvider data_test_wp_list_sort_preserve_keys - * - * @covers ::wp_list_sort - * - * @param string|array $orderby Either the field name to order by or an array - * of multiple orderby fields as $orderby => $order. - * @param string $order Either 'ASC' or 'DESC'. - */ - public function test_wp_list_sort_preserve_keys( $list, $orderby, $order, $expected ) { - $this->assertSame( $expected, wp_list_sort( $list, $orderby, $order, true ) ); - } - /** * @covers WP_List_Util::get_input */ diff --git a/tests/phpunit/tests/https-detection.php b/tests/phpunit/tests/https-detection.php index 6ed466af6a191..1ae5af13091e1 100644 --- a/tests/phpunit/tests/https-detection.php +++ b/tests/phpunit/tests/https-detection.php @@ -117,7 +117,7 @@ public function test_pre_wp_update_https_detection_errors() { // Override to enforce no errors being detected. add_filter( 'pre_wp_update_https_detection_errors', - function() { + static function() { return new WP_Error(); } ); @@ -127,7 +127,7 @@ function() { // Override to enforce an error being detected. add_filter( 'pre_wp_update_https_detection_errors', - function() { + static function() { return new WP_Error( 'ssl_verification_failed', 'Bad SSL certificate.' @@ -345,7 +345,7 @@ private function get_sample_html_string( $head_tag = '' ) { * @return callable Filter callback. */ private function filter_set_url_scheme( $scheme ) { - return function( $url ) use ( $scheme ) { + return static function( $url ) use ( $scheme ) { return set_url_scheme( $url, $scheme ); }; } diff --git a/tests/phpunit/tests/https-migration.php b/tests/phpunit/tests/https-migration.php index dccf40b602855..d06e1f0fba053 100644 --- a/tests/phpunit/tests/https-migration.php +++ b/tests/phpunit/tests/https-migration.php @@ -161,7 +161,7 @@ public function test_wp_should_replace_insecure_home_url_integration() { private function force_wp_is_using_https( $enabled ) { $scheme = $enabled ? 'https' : 'http'; - $replace_scheme = function( $url ) use ( $scheme ) { + $replace_scheme = static function( $url ) use ( $scheme ) { return str_replace( array( 'http://', 'https://' ), $scheme . '://', $url ); }; @@ -172,7 +172,7 @@ private function force_wp_is_using_https( $enabled ) { private function force_option( $option, $value ) { add_filter( "option_$option", - function() use ( $value ) { + static function() use ( $value ) { return $value; } ); diff --git a/tests/phpunit/tests/image/editor.php b/tests/phpunit/tests/image/editor.php index 7ed30ebdb0410..a35f8af9f2856 100644 --- a/tests/phpunit/tests/image/editor.php +++ b/tests/phpunit/tests/image/editor.php @@ -110,6 +110,92 @@ public function test_set_quality() { remove_filter( 'wp_editor_set_quality', $func_100_percent ); } + /** + * Test test_quality when converting image + * + * @ticket 6821 + */ + public function test_set_quality_with_image_conversion() { + $editor = wp_get_image_editor( DIR_TESTDATA . '/images/test-image.png' ); + $editor->set_mime_type( 'image/png' ); // Ensure mime-specific filters act properly. + + // Set conversions for uploaded images. + add_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) ); + + // Quality setting for the source image. For PNG the fallback default of 82 is used. + $this->assertSame( 82, $editor->get_quality(), 'Default quality setting is 82.' ); + + // Quality should change to the output format's value. + // A PNG image will be converted to WEBP whose quialty should be 86. + $editor->save(); + $this->assertSame( 86, $editor->get_quality(), 'Output image format is WEBP. Quality setting for it should be 86.' ); + + // Removing PNG to WEBP conversion on save. Quality setting should reset to the default. + remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) ); + $editor->save(); + $this->assertSame( 82, $editor->get_quality(), 'After removing image conversion quality setting should reset to the default of 82.' ); + + unset( $editor ); + + // Set conversions for uploaded images. + add_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) ); + // Change the quality values. + add_filter( 'wp_editor_set_quality', array( $this, 'image_editor_change_quality' ), 10, 2 ); + + // Get a new editor to clear quality state. + $editor = wp_get_image_editor( DIR_TESTDATA . '/images/test-image.jpg' ); + $editor->set_mime_type( 'image/jpeg' ); + + $this->assertSame( 56, $editor->get_quality(), 'Filtered default quality for JPEG is 56.' ); + + // Quality should change to the output format's value as filtered above. + // A JPEG image will be converted to WEBP whose quialty should be 42. + $editor->save(); + $this->assertSame( 42, $editor->get_quality(), 'Image conversion from JPEG to WEBP. Filtered WEBP quality shoild be 42.' ); + + // After removing the conversion the quality setting should reset to the filtered value for the original image type, JPEG. + remove_filter( 'image_editor_output_format', array( $this, 'image_editor_output_formats' ) ); + $editor->save(); + $this->assertSame( + 56, + $editor->get_quality(), + 'After removing image conversion the quality setting should reset to the filtered value for JPEG, 56.' + ); + + remove_filter( 'wp_editor_set_quality', array( $this, 'image_editor_change_quality' ) ); + } + + /** + * Changes the output format when editing images. PNG and JPEG files + * will be converted to WEBP (if the image editor in PHP supports it). + * + * @param array $formats + * + * @return array + */ + public function image_editor_output_formats( $formats ) { + $formats['image/png'] = 'image/webp'; + $formats['image/jpeg'] = 'image/webp'; + return $formats; + } + + /** + * Changes the quality according to the mime-type. + * + * @param int $quality Default quality. + * @param string $mime_type Image mime-type. + * @return int The changed quality. + */ + public function image_editor_change_quality( $quality, $mime_type ) { + if ( 'image/jpeg' === $mime_type ) { + return 56; + } elseif ( 'image/webp' === $mime_type ) { + return 42; + } else { + return 30; + } + } + /** * Test generate_filename * diff --git a/tests/phpunit/tests/image/intermediateSize.php b/tests/phpunit/tests/image/intermediateSize.php index d2098c49e12bb..cf5b3888fed93 100644 --- a/tests/phpunit/tests/image/intermediateSize.php +++ b/tests/phpunit/tests/image/intermediateSize.php @@ -69,7 +69,7 @@ function test_make_intermediate_size_successful() { function test_image_editor_output_format_filter() { add_filter( 'image_editor_output_format', - function() { + static function() { return array( 'image/jpeg' => 'image/webp' ); } ); diff --git a/tests/phpunit/tests/kses.php b/tests/phpunit/tests/kses.php index 961ed71b1652d..11434d37e8ab4 100644 --- a/tests/phpunit/tests/kses.php +++ b/tests/phpunit/tests/kses.php @@ -1496,4 +1496,298 @@ function test_wp_kses_main_tag_standard_attributes() { $this->assertSame( $html, wp_kses_post( $html ) ); } + + /** + * Test that object tags are allowed under limited circumstances. + * + * @ticket 54261 + * + * @dataProvider data_wp_kses_object_tag_allowed + * + * @param string $html A string of HTML to test. + * @param string $expected The expected result from KSES. + */ + function test_wp_kses_object_tag_allowed( $html, $expected ) { + $this->assertSame( $expected, wp_kses_post( $html ) ); + } + + /** + * Data provider for test_wp_kses_object_tag_allowed(). + */ + 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( + '', + '', + ), + ); + } + + /** + * Test that object tags will continue to function if they've been added using the + * 'wp_kses_allowed_html' filter. + * + * @ticket 54261 + */ + function test_wp_kses_object_added_in_html_filter() { + $html = << + + + +HTML; + + add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_object_added_in_html_filter' ), 10, 2 ); + + $filtered_html = wp_kses_post( $html ); + + remove_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_object_added_in_html_filter' ) ); + + $this->assertSame( $html, $filtered_html ); + } + + function filter_wp_kses_object_added_in_html_filter( $tags, $context ) { + if ( 'post' === $context ) { + $tags['object'] = array( + 'type' => true, + 'data' => true, + ); + + $tags['param'] = array( + 'name' => true, + 'value' => true, + ); + } + + return $tags; + } + + /** + * Test that attributes with a list of allowed values are filtered correctly. + * + * @ticket 54261 + * + * @dataProvider data_wp_kses_allowed_values_list + * + * @param string $html A string of HTML to test. + * @param string $expected The expected result from KSES. + * @param array $allowed_html The allowed HTML to pass to KSES. + */ + function test_wp_kses_allowed_values_list( $html, $expected, $allowed_html ) { + $this->assertSame( $expected, wp_kses( $html, $allowed_html ) ); + } + + /** + * Data provider for test_wp_kses_allowed_values_list(). + */ + function data_wp_kses_allowed_values_list() { + $data = array( + 'valid dir attribute value' => array( + '

foo

', + '

foo

', + ), + 'valid dir attribute value, upper case' => array( + '

foo

', + '

foo

', + ), + 'invalid dir attribute value' => array( + '

foo

', + '

foo

', + ), + 'dir attribute with empty value' => array( + '

foo

', + '

foo

', + ), + 'dir attribute with no value' => array( + '

foo

', + '

foo

', + ), + ); + + return array_map( + function ( $datum ) { + $datum[] = array( + 'p' => array( + 'dir' => array( + 'values' => array( 'ltr', 'rtl' ), + ), + ), + ); + + return $datum; + }, + $data + ); + } + + /** + * Test that attributes with the required flag are handled correctly. + * + * @ticket 54261 + * + * @dataProvider data_wp_kses_required_attribute + * + * @param string $html A string of HTML to test. + * @param string $expected The expected result from KSES. + * @param array $allowed_html The allowed HTML to pass to KSES. + */ + function test_wp_kses_required_attribute( $html, $expected, $allowed_html ) { + $this->assertSame( $expected, wp_kses( $html, $allowed_html ) ); + } + + /** + * Data provider for test_wp_kses_required_attribute(). + */ + function data_wp_kses_required_attribute() { + $data = array( + 'valid dir attribute value' => array( + '

foo

', // Test HTML. + '

foo

', // Expected result when dir is not required. + '

foo

', // Expected result when dir is required. + '

foo

', // Expected result when dir is required, but has no value filter. + ), + 'valid dir attribute value, upper case' => array( + '

foo

', + '

foo

', + '

foo

', + '

foo

', + ), + 'invalid dir attribute value' => array( + '

foo

', + '

foo

', + '

foo

', + '

foo

', + ), + 'dir attribute with empty value' => array( + '

foo

', + '

foo

', + '

foo

', + '

foo

', + ), + 'dir attribute with no value' => array( + '

foo

', + '

foo

', + '

foo

', + '

foo

', + ), + 'dir attribute not set' => array( + '

foo

', + '

foo

', + '

foo

', + '

foo

', + ), + ); + + $return_data = array(); + + foreach ( $data as $description => $datum ) { + // Test that the required flag defaults to false. + $return_data[ "$description - required flag not set" ] = array( + $datum[0], + $datum[1], + array( + 'p' => array( + 'dir' => array( + 'values' => array( 'ltr', 'rtl' ), + ), + ), + ), + ); + + // Test when the attribute is not required, but has allowed values. + $return_data[ "$description - required flag set to false" ] = array( + $datum[0], + $datum[1], + array( + 'p' => array( + 'dir' => array( + 'required' => false, + 'values' => array( 'ltr', 'rtl' ), + ), + ), + ), + ); + + // Test when the attribute is required, but has allowed values. + $return_data[ "$description - required flag set to true" ] = array( + $datum[0], + $datum[2], + array( + 'p' => array( + 'dir' => array( + 'required' => true, + 'values' => array( 'ltr', 'rtl' ), + ), + ), + ), + ); + + // Test when the attribute is required, but has no allowed values. + $return_data[ "$description - required flag set to true, no allowed values specified" ] = array( + $datum[0], + $datum[3], + array( + 'p' => array( + 'dir' => array( + 'required' => true, + ), + ), + ), + ); + } + + return $return_data; + } } diff --git a/tests/phpunit/tests/l10n/loadScriptTextdomain.php b/tests/phpunit/tests/l10n/loadScriptTextdomain.php index b9b6ef0c3f705..0cce2a1f2e02c 100644 --- a/tests/phpunit/tests/l10n/loadScriptTextdomain.php +++ b/tests/phpunit/tests/l10n/loadScriptTextdomain.php @@ -49,7 +49,7 @@ public function data_test_resolve_relative_path() { 'default', array( 'site_url', - function ( $site_url ) { + static function ( $site_url ) { return $site_url . '/wp'; }, ), @@ -62,7 +62,7 @@ function ( $site_url ) { 'internationalized-plugin', array( 'plugins_url', - function () { + static function () { return 'https://plugins.example.com'; }, ), @@ -75,7 +75,7 @@ function () { 'internationalized-plugin', array( 'content_url', - function () { + static function () { return 'https://content.example.com'; }, ), @@ -88,7 +88,7 @@ function () { 'internationalized-plugin', array( 'content_url', - function () { + static function () { return '/'; }, ), @@ -101,7 +101,7 @@ function () { 'internationalized-plugin', array( 'plugins_url', - function () { + static function () { return '/'; }, ), @@ -114,7 +114,7 @@ function () { 'default', array( 'site_url', - function () { + static function () { return '/wp'; }, ), diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 79cc067712d4d..1be2526ff47d9 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -84,7 +84,7 @@ function test_img_caption_shortcode_added() { function test_img_caption_shortcode_with_empty_params() { $result = img_caption_shortcode( array() ); - $this->assertNull( $result ); + $this->assertSame( '', $result ); } /** @@ -134,7 +134,7 @@ function test_img_caption_shortcode_empty_caption() { 'caption' => '', ) ); - $this->assertNull( $result ); + $this->assertSame( '', $result ); } /** diff --git a/tests/phpunit/tests/menu/walker-nav-menu.php b/tests/phpunit/tests/menu/walker-nav-menu.php index 83523644e5371..1811284b50b7e 100644 --- a/tests/phpunit/tests/menu/walker-nav-menu.php +++ b/tests/phpunit/tests/menu/walker-nav-menu.php @@ -94,7 +94,7 @@ public function test_start_el_with_empty_attributes( $value, $expected ) { add_filter( 'nav_menu_link_attributes', - function( $atts ) use ( $value ) { + static function( $atts ) use ( $value ) { $atts['data-test'] = $value; return $atts; } diff --git a/tests/phpunit/tests/multisite.php b/tests/phpunit/tests/multisite.php index deb45b4fe4e9c..22beb7f53ccbc 100644 --- a/tests/phpunit/tests/multisite.php +++ b/tests/phpunit/tests/multisite.php @@ -8,19 +8,6 @@ * @group multisite */ class Tests_Multisite extends WP_UnitTestCase { - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } function test_wpmu_log_new_registrations() { global $wpdb; diff --git a/tests/phpunit/tests/multisite/avoidBlogPagePermalinkCollision.php b/tests/phpunit/tests/multisite/avoidBlogPagePermalinkCollision.php new file mode 100644 index 0000000000000..137dff5b79394 --- /dev/null +++ b/tests/phpunit/tests/multisite/avoidBlogPagePermalinkCollision.php @@ -0,0 +1,69 @@ +blog->create( + array( + 'path' => '/' . self::$post_and_blog_path, + ) + ); + + self::$root_page = self::factory()->post->create_and_get( + array( + 'post_type' => 'page', + 'post_title' => 'Bar', + 'post_name' => self::$post_and_blog_path, + ) + ); + + self::$child_page = self::factory()->post->create_and_get( + array( + 'post_parent' => self::$root_page->ID, + 'post_type' => 'page', + 'post_title' => 'Bar', + 'post_name' => self::$post_and_blog_path, + ) + ); + } + + /** + * Delete blog and pages we created. + */ + public static function wpTearDownAfterClass() { + wp_delete_site( self::$site_id ); + + wp_delete_post( self::$root_page->ID ); + wp_delete_post( self::$child_page->ID ); + } + + public function test_avoid_blog_page_permalink_collision_renames_post_name() { + $this->assertNotSame( self::$post_and_blog_path, self::$root_page->post_name ); + } + + /** + * Ensure `avoid_blog_page_permalink_collision()` doesn't rename child pages' post_name. + * + * @ticket 51147 + */ + public function test_avoid_blog_page_permalink_collision_doesnt_rename_child_pages() { + $this->assertSame( self::$post_and_blog_path, self::$child_page->post_name ); + } + } + +endif; diff --git a/tests/phpunit/tests/multisite/cleanDirsizeCache.php b/tests/phpunit/tests/multisite/cleanDirsizeCache.php index 8aaa596d39ceb..b190acd2266c0 100644 --- a/tests/phpunit/tests/multisite/cleanDirsizeCache.php +++ b/tests/phpunit/tests/multisite/cleanDirsizeCache.php @@ -8,20 +8,7 @@ * @ticket 19879 * @group multisite */ - class Tests_Multisite_Dirsize_Cache extends WP_UnitTestCase { - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } + class Tests_Multisite_CleanDirsizeCache extends WP_UnitTestCase { /** * Test whether dirsize_cache values are used correctly with a more complex dirsize cache mock. diff --git a/tests/phpunit/tests/multisite/getBlogDetails.php b/tests/phpunit/tests/multisite/getBlogDetails.php index 358499e55a19e..b4c456f082147 100644 --- a/tests/phpunit/tests/multisite/getBlogDetails.php +++ b/tests/phpunit/tests/multisite/getBlogDetails.php @@ -7,7 +7,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Get_Blog_Details extends WP_UnitTestCase { + class Tests_Multisite_GetBlogDetails extends WP_UnitTestCase { protected static $network_ids; protected static $site_ids; diff --git a/tests/phpunit/tests/multisite/getIdFromBlogname.php b/tests/phpunit/tests/multisite/getIdFromBlogname.php index 29d7c8c761122..49b4bf6f85c49 100644 --- a/tests/phpunit/tests/multisite/getIdFromBlogname.php +++ b/tests/phpunit/tests/multisite/getIdFromBlogname.php @@ -8,7 +8,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Get_Id_From_Blogname extends WP_UnitTestCase { + class Tests_Multisite_GetIdFromBlogname extends WP_UnitTestCase { protected static $network_ids; protected static $site_ids; diff --git a/tests/phpunit/tests/multisite/getMainSiteId.php b/tests/phpunit/tests/multisite/getMainSiteId.php index 63e68ef16344d..3a6e9c4d8c0a0 100644 --- a/tests/phpunit/tests/multisite/getMainSiteId.php +++ b/tests/phpunit/tests/multisite/getMainSiteId.php @@ -8,7 +8,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Get_Main_Site_ID extends WP_UnitTestCase { + class Tests_Multisite_GetMainSiteId extends WP_UnitTestCase { protected static $network_ids; protected static $site_ids; diff --git a/tests/phpunit/tests/multisite/getSite.php b/tests/phpunit/tests/multisite/getSite.php index f1c4779d6be9e..46a5121247fd9 100644 --- a/tests/phpunit/tests/multisite/getSite.php +++ b/tests/phpunit/tests/multisite/getSite.php @@ -7,7 +7,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Get_Site extends WP_UnitTestCase { + class Tests_Multisite_GetSite extends WP_UnitTestCase { protected static $site_ids; public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { diff --git a/tests/phpunit/tests/multisite/getSpaceAllowed.php b/tests/phpunit/tests/multisite/getSpaceAllowed.php index 735e4320c257b..5e87fc0087bae 100644 --- a/tests/phpunit/tests/multisite/getSpaceAllowed.php +++ b/tests/phpunit/tests/multisite/getSpaceAllowed.php @@ -7,21 +7,7 @@ * * @group multisite */ - class Tests_Multisite_Get_Space_Allowed extends WP_UnitTestCase { - protected $suppress = false; - - public function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - public function tear_down() { - global $wpdb; - - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } + class Tests_Multisite_GetSpaceAllowed extends WP_UnitTestCase { /** * When no option exists for the site or the network, a fallback of diff --git a/tests/phpunit/tests/multisite/getSpaceUsed.php b/tests/phpunit/tests/multisite/getSpaceUsed.php index b6492d661ec3f..d243fc8efa625 100644 --- a/tests/phpunit/tests/multisite/getSpaceUsed.php +++ b/tests/phpunit/tests/multisite/getSpaceUsed.php @@ -6,20 +6,7 @@ * @group multisite * @covers ::get_space_used */ - class Tests_Multisite_Get_Space_Used extends WP_UnitTestCase { - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } + class Tests_Multisite_GetSpaceUsed extends WP_UnitTestCase { function test_get_space_used_switched_site() { $blog_id = self::factory()->blog->create(); diff --git a/tests/phpunit/tests/multisite/isUploadSpaceAvailable.php b/tests/phpunit/tests/multisite/isUploadSpaceAvailable.php index d520791879e17..bc983d5d464b9 100644 --- a/tests/phpunit/tests/multisite/isUploadSpaceAvailable.php +++ b/tests/phpunit/tests/multisite/isUploadSpaceAvailable.php @@ -10,24 +10,13 @@ * * @group multisite */ - class Tests_Multisite_Is_Upload_Space_Available extends WP_UnitTestCase { - protected $suppress = false; + class Tests_Multisite_IsUploadSpaceAvailable extends WP_UnitTestCase { public function set_up() { - global $wpdb; parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - update_site_option( 'upload_space_check_disabled', false ); } - public function tear_down() { - global $wpdb; - - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } - /** * A default of 100MB is used when no `blog_upload_space` option * exists at the site or network level. diff --git a/tests/phpunit/tests/multisite/ms-files-rewriting.php b/tests/phpunit/tests/multisite/msFilesRewriting.php similarity index 90% rename from tests/phpunit/tests/multisite/ms-files-rewriting.php rename to tests/phpunit/tests/multisite/msFilesRewriting.php index 4288d2ef61104..4964d7ed8a416 100644 --- a/tests/phpunit/tests/multisite/ms-files-rewriting.php +++ b/tests/phpunit/tests/multisite/msFilesRewriting.php @@ -11,26 +11,14 @@ * @group ms-files * @group multisite */ - class Tests_Multisite_MS_Files_Rewriting extends WP_UnitTestCase { - protected $suppress = false; + class Tests_Multisite_msFilesRewriting extends WP_UnitTestCase { function set_up() { - global $wpdb; parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - update_site_option( 'ms_files_rewriting', 1 ); ms_upload_constants(); } - function tear_down() { - global $wpdb; - - $wpdb->suppress_errors( $this->suppress ); - - parent::tear_down(); - } - function test_switch_upload_dir() { $this->assertTrue( is_main_site() ); diff --git a/tests/phpunit/tests/multisite/network.php b/tests/phpunit/tests/multisite/network.php index 656db4fbb15f7..bad6626b56e21 100644 --- a/tests/phpunit/tests/multisite/network.php +++ b/tests/phpunit/tests/multisite/network.php @@ -10,20 +10,12 @@ */ class Tests_Multisite_Network extends WP_UnitTestCase { protected $plugin_hook_count = 0; - protected $suppress = false; protected static $different_network_id; protected static $different_site_ids = array(); - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - function tear_down() { - global $wpdb, $current_site; - $wpdb->suppress_errors( $this->suppress ); + global $current_site; $current_site->id = 1; parent::tear_down(); } @@ -590,9 +582,13 @@ public function filter_wp_is_large_network_on_different_network( $is_large_netwo * @ticket 38699 */ public function test_wpmu_create_blog_updates_correct_network_site_count() { + global $wpdb; + $original_count = get_blog_count( self::$different_network_id ); - $site_id = wpmu_create_blog( 'example.org', '/', '', 1, array(), self::$different_network_id ); + $suppress = $wpdb->suppress_errors(); + $site_id = wpmu_create_blog( 'example.org', '/', '', 1, array(), self::$different_network_id ); + $wpdb->suppress_errors( $suppress ); $result = get_blog_count( self::$different_network_id ); diff --git a/tests/phpunit/tests/multisite/siteDetails.php b/tests/phpunit/tests/multisite/siteDetails.php index 78b392c487426..d8eb84382b6b3 100644 --- a/tests/phpunit/tests/multisite/siteDetails.php +++ b/tests/phpunit/tests/multisite/siteDetails.php @@ -7,7 +7,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Site_Details extends WP_UnitTestCase { + class Tests_Multisite_SiteDetails extends WP_UnitTestCase { /** * @dataProvider data_allowed_options * diff --git a/tests/phpunit/tests/multisite/siteMeta.php b/tests/phpunit/tests/multisite/siteMeta.php index 72d86f6a47247..4a1a30fee2e81 100644 --- a/tests/phpunit/tests/multisite/siteMeta.php +++ b/tests/phpunit/tests/multisite/siteMeta.php @@ -8,7 +8,7 @@ * @group meta * @ticket 37923 */ - class Tests_Multisite_Site_Meta extends WP_UnitTestCase { + class Tests_Multisite_SiteMeta extends WP_UnitTestCase { protected static $site_id; protected static $site_id2; protected static $flag_was_set; diff --git a/tests/phpunit/tests/multisite/updateBlogDetails.php b/tests/phpunit/tests/multisite/updateBlogDetails.php index c3bd0e3cdff51..7a983fc7de154 100644 --- a/tests/phpunit/tests/multisite/updateBlogDetails.php +++ b/tests/phpunit/tests/multisite/updateBlogDetails.php @@ -6,7 +6,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Update_Blog_Details extends WP_UnitTestCase { + class Tests_Multisite_UpdateBlogDetails extends WP_UnitTestCase { /** * If `update_blog_details()` is called with any kind of empty arguments, it * should return false. diff --git a/tests/phpunit/tests/multisite/uploadIsUserOverQuota.php b/tests/phpunit/tests/multisite/uploadIsUserOverQuota.php index 544e632da4d4c..5b08569091cbe 100644 --- a/tests/phpunit/tests/multisite/uploadIsUserOverQuota.php +++ b/tests/phpunit/tests/multisite/uploadIsUserOverQuota.php @@ -10,23 +10,13 @@ * * @group multisite */ - class Tests_Multisite_Upload_Is_User_Over_Quota extends WP_UnitTestCase { - protected $suppress = false; + class Tests_Multisite_UploadIsUserOverQuota extends WP_UnitTestCase { public function set_up() { - global $wpdb; parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - update_site_option( 'upload_space_check_disabled', false ); } - public function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } - public function test_upload_is_user_over_quota_allowed_0_used_5() { add_filter( 'get_space_allowed', '__return_zero' ); add_filter( 'pre_get_space_used', array( $this, '_filter_space_5' ) ); diff --git a/tests/phpunit/tests/multisite/wpGetSites.php b/tests/phpunit/tests/multisite/wpGetSites.php index 163a4714dd283..1abcb595152cb 100644 --- a/tests/phpunit/tests/multisite/wpGetSites.php +++ b/tests/phpunit/tests/multisite/wpGetSites.php @@ -7,7 +7,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_WP_Get_Sites extends WP_UnitTestCase { + class Tests_Multisite_wpGetSites extends WP_UnitTestCase { protected static $site_ids; public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { diff --git a/tests/phpunit/tests/multisite/wpInstallDefaults.php b/tests/phpunit/tests/multisite/wpInstallDefaults.php index 05371f215941b..c48a832a05cdc 100644 --- a/tests/phpunit/tests/multisite/wpInstallDefaults.php +++ b/tests/phpunit/tests/multisite/wpInstallDefaults.php @@ -8,7 +8,7 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Install_Defaults extends WP_UnitTestCase { + class Tests_Multisite_wpInstallDefaults extends WP_UnitTestCase { /** * @ticket 40036 */ diff --git a/tests/phpunit/tests/multisite/wpMSSitesListTable.php b/tests/phpunit/tests/multisite/wpMsSitesListTable.php similarity index 98% rename from tests/phpunit/tests/multisite/wpMSSitesListTable.php rename to tests/phpunit/tests/multisite/wpMsSitesListTable.php index 9b26e35a36d37..a14fcf5dca199 100644 --- a/tests/phpunit/tests/multisite/wpMSSitesListTable.php +++ b/tests/phpunit/tests/multisite/wpMsSitesListTable.php @@ -6,7 +6,7 @@ * @group admin * @group network-admin */ - class Tests_WP_MS_Sites_List_Table extends WP_UnitTestCase { + class Tests_Multisite_wpMsSitesListTable extends WP_UnitTestCase { protected static $site_ids; /** diff --git a/tests/phpunit/tests/multisite/networkQuery.php b/tests/phpunit/tests/multisite/wpNetworkQuery.php similarity index 97% rename from tests/phpunit/tests/multisite/networkQuery.php rename to tests/phpunit/tests/multisite/wpNetworkQuery.php index a69bc2210c7d8..42fcc21f96182 100644 --- a/tests/phpunit/tests/multisite/networkQuery.php +++ b/tests/phpunit/tests/multisite/wpNetworkQuery.php @@ -9,23 +9,9 @@ * @group ms-network-query * @group multisite */ - class Tests_Multisite_Network_Query extends WP_UnitTestCase { + class Tests_Multisite_wpNetworkQuery extends WP_UnitTestCase { protected static $network_ids; - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } - public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { self::$network_ids = array( 'wordpress.org/' => array( diff --git a/tests/phpunit/tests/multisite/siteQuery.php b/tests/phpunit/tests/multisite/wpSiteQuery.php similarity index 98% rename from tests/phpunit/tests/multisite/siteQuery.php rename to tests/phpunit/tests/multisite/wpSiteQuery.php index 1a4108c10d720..f48667f23fc89 100644 --- a/tests/phpunit/tests/multisite/siteQuery.php +++ b/tests/phpunit/tests/multisite/wpSiteQuery.php @@ -8,24 +8,10 @@ * @group ms-site * @group multisite */ - class Tests_Multisite_Site_Query extends WP_UnitTestCase { + class Tests_Multisite_wpSiteQuery extends WP_UnitTestCase { protected static $network_ids; protected static $site_ids; - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } - public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { self::$network_ids = array( 'wordpress.org/' => array( diff --git a/tests/phpunit/tests/multisite/wpmuValidateBlogSignup.php b/tests/phpunit/tests/multisite/wpmuValidateBlogSignup.php index 576822c12f24e..fc5c5fe445cbb 100644 --- a/tests/phpunit/tests/multisite/wpmuValidateBlogSignup.php +++ b/tests/phpunit/tests/multisite/wpmuValidateBlogSignup.php @@ -5,7 +5,7 @@ /** * @group multisite */ - class Tests_Multisite_WpmuValidateBlogSignup extends WP_UnitTestCase { + class Tests_Multisite_wpmuValidateBlogSignup extends WP_UnitTestCase { protected static $super_admin_id; protected static $existing_user_login = 'existinguserfoo'; diff --git a/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php b/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php index 7e0ad2750fbf6..f88ed0ff788ce 100644 --- a/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php +++ b/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php @@ -5,7 +5,7 @@ /** * @group multisite */ - class Tests_Multisite_WpmuValidateUserSignup extends WP_UnitTestCase { + class Tests_Multisite_wpmuValidateUserSignup extends WP_UnitTestCase { /** * @dataProvider data_user_name */ diff --git a/tests/phpunit/tests/option/multisite.php b/tests/phpunit/tests/option/multisite.php index 54388d0144842..4a16bb9748933 100644 --- a/tests/phpunit/tests/option/multisite.php +++ b/tests/phpunit/tests/option/multisite.php @@ -10,19 +10,6 @@ * @group multisite */ class Tests_Multisite_Option extends WP_UnitTestCase { - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } function test_from_same_site() { $key = __FUNCTION__ . '_1'; diff --git a/tests/phpunit/tests/option/option.php b/tests/phpunit/tests/option/option.php index 0f67fa9490f48..a2145f1c1845e 100644 --- a/tests/phpunit/tests/option/option.php +++ b/tests/phpunit/tests/option/option.php @@ -89,14 +89,123 @@ function test_serialized_data() { /** * @ticket 23289 + * + * @dataProvider data_bad_option_names + * + * @param mixed $option_name Option name. + */ + public function test_get_option_bad_option_name( $option_name ) { + $this->assertFalse( get_option( $option_name ) ); + } + + /** + * @ticket 23289 + * + * @dataProvider data_bad_option_names + * + * @param mixed $option_name Option name. + */ + public function test_add_option_bad_option_name( $option_name ) { + $this->assertFalse( add_option( $option_name, '' ) ); + } + + /** + * @ticket 23289 + * + * @dataProvider data_bad_option_names + * + * @param mixed $option_name Option name. */ - function test_bad_option_names() { - foreach ( array( '', '0', ' ', 0, false, null ) as $empty ) { - $this->assertFalse( get_option( $empty ) ); - $this->assertFalse( add_option( $empty, '' ) ); - $this->assertFalse( update_option( $empty, '' ) ); - $this->assertFalse( delete_option( $empty ) ); - } + public function test_update_option_bad_option_name( $option_name ) { + $this->assertFalse( update_option( $option_name, '' ) ); + } + + /** + * @ticket 23289 + * + * @dataProvider data_bad_option_names + * + * @param mixed $option_name Option name. + */ + public function test_delete_option_bad_option_name( $option_name ) { + $this->assertFalse( delete_option( $option_name ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_bad_option_names() { + return array( + 'empty string' => array( '' ), + 'string 0' => array( '0' ), + 'string single space' => array( ' ' ), + 'integer 0' => array( 0 ), + 'float 0.0' => array( 0.0 ), + 'boolean false' => array( false ), + 'null' => array( null ), + ); + } + + /** + * @ticket 53635 + * + * @dataProvider data_valid_but_undesired_option_names + * + * @param mixed $option_name Option name. + */ + public function test_get_option_valid_but_undesired_option_names( $option_name ) { + $this->assertFalse( get_option( $option_name ) ); + } + + /** + * @ticket 53635 + * + * @dataProvider data_valid_but_undesired_option_names + * + * @param mixed $option_name Option name. + */ + public function test_add_option_valid_but_undesired_option_names( $option_name ) { + $this->assertTrue( add_option( $option_name, '' ) ); + } + + /** + * @ticket 53635 + * + * @dataProvider data_valid_but_undesired_option_names + * + * @param mixed $option_name Option name. + */ + public function test_update_option_valid_but_undesired_option_names( $option_name ) { + $this->assertTrue( update_option( $option_name, '' ) ); + } + + /** + * @ticket 53635 + * + * @dataProvider data_valid_but_undesired_option_names + * + * @param mixed $option_name Option name. + */ + public function test_delete_option_valid_but_undesired_option_names( $option_name ) { + $this->assertFalse( delete_option( $option_name ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_valid_but_undesired_option_names() { + return array( + 'string 123' => array( '123' ), + 'integer 123' => array( 123 ), + 'integer -123' => array( -123 ), + 'float 12.3' => array( 12.3 ), + 'float -1.23' => array( -1.23 ), + 'boolean true' => array( true ), + ); } /** diff --git a/tests/phpunit/tests/pomo/po.php b/tests/phpunit/tests/pomo/po.php index c79b37033f77a..9a37b4dd4eabd 100644 --- a/tests/phpunit/tests/pomo/po.php +++ b/tests/phpunit/tests/pomo/po.php @@ -4,9 +4,16 @@ * @group pomo */ class Tests_POMO_PO extends WP_UnitTestCase { - function set_up() { - parent::set_up(); + + public static function set_up_before_class() { + parent::set_up_before_class(); + require_once ABSPATH . '/wp-includes/pomo/po.php'; + } + + public function set_up() { + parent::set_up(); + // Not so random wordpress.pot string -- multiple lines. $this->mail = 'Your new WordPress blog has been successfully set up at: diff --git a/tests/phpunit/tests/post/revisions.php b/tests/phpunit/tests/post/revisions.php index 3e0899ca999d1..840597c4a9abb 100644 --- a/tests/phpunit/tests/post/revisions.php +++ b/tests/phpunit/tests/post/revisions.php @@ -594,7 +594,7 @@ public function test_wp_revisions_to_keep_filter() { add_filter( 'wp_revisions_to_keep', - function () use ( $expected ) { + static function () use ( $expected ) { return $expected; } ); @@ -619,7 +619,7 @@ public function test_wp_post_type_revisions_to_keep_filter() { add_filter( 'wp_revisions_to_keep', - function () use ( $generic ) { + static function () use ( $generic ) { return $generic; } ); @@ -630,7 +630,7 @@ function () use ( $generic ) { add_filter( "wp_{$post->post_type}_revisions_to_keep", - function () use ( $expected ) { + static function () use ( $expected ) { return $expected; } ); diff --git a/tests/phpunit/tests/post/walkerPage.php b/tests/phpunit/tests/post/walkerPage.php index f0ad198d78998..6b71bb021667b 100644 --- a/tests/phpunit/tests/post/walkerPage.php +++ b/tests/phpunit/tests/post/walkerPage.php @@ -33,7 +33,7 @@ public function test_start_el_with_empty_attributes( $value, $expected ) { add_filter( 'page_menu_link_attributes', - function( $atts ) use ( $value ) { + static function( $atts ) use ( $value ) { $atts['data-test'] = $value; return $atts; } diff --git a/tests/phpunit/tests/rest-api.php b/tests/phpunit/tests/rest-api.php index 288c7140e8b8d..34b414903daf4 100644 --- a/tests/phpunit/tests/rest-api.php +++ b/tests/phpunit/tests/rest-api.php @@ -954,6 +954,31 @@ function test_rest_preload_api_request_with_method() { $GLOBALS['wp_rest_server'] = $rest_server; } + /** + * @ticket 51636 + */ + function test_rest_preload_api_request_removes_trailing_slashes() { + $rest_server = $GLOBALS['wp_rest_server']; + $GLOBALS['wp_rest_server'] = null; + + $preload_paths = array( + '/wp/v2/types//', + array( '/wp/v2/media///', 'OPTIONS' ), + '////', + ); + + $preload_data = array_reduce( + $preload_paths, + 'rest_preload_api_request', + array() + ); + + $this->assertSame( array_keys( $preload_data ), array( '/wp/v2/types', 'OPTIONS', '/' ) ); + $this->assertArrayHasKey( '/wp/v2/media', $preload_data['OPTIONS'] ); + + $GLOBALS['wp_rest_server'] = $rest_server; + } + /** * @ticket 40614 */ @@ -1804,6 +1829,48 @@ public function test_rest_get_route_for_post_invalid_post_type() { $this->assertSame( '', rest_get_route_for_post( $post ) ); } + /** + * @ticket 53656 + */ + public function test_rest_get_route_for_post_custom_namespace() { + register_post_type( + 'cpt', + array( + 'show_in_rest' => true, + 'rest_base' => 'cpt', + 'rest_namespace' => 'wordpress/v1', + ) + ); + $post = self::factory()->post->create_and_get( array( 'post_type' => 'cpt' ) ); + + $this->assertSame( '/wordpress/v1/cpt/' . $post->ID, rest_get_route_for_post( $post ) ); + unregister_post_type( 'cpt' ); + } + + /** + * @ticket 53656 + */ + public function test_rest_get_route_for_post_type_items() { + $this->assertSame( '/wp/v2/posts', rest_get_route_for_post_type_items( 'post' ) ); + } + + /** + * @ticket 53656 + */ + public function test_rest_get_route_for_post_type_items_custom_namespace() { + register_post_type( + 'cpt', + array( + 'show_in_rest' => true, + 'rest_base' => 'cpt', + 'rest_namespace' => 'wordpress/v1', + ) + ); + + $this->assertSame( '/wordpress/v1/cpt', rest_get_route_for_post_type_items( 'cpt' ) ); + unregister_post_type( 'cpt' ); + } + /** * @ticket 49116 */ @@ -1814,10 +1881,11 @@ public function test_rest_get_route_for_post_non_rest() { /** * @ticket 49116 + * @ticket 53656 */ public function test_rest_get_route_for_post_custom_controller() { $post = self::factory()->post->create_and_get( array( 'post_type' => 'wp_block' ) ); - $this->assertSame( '', rest_get_route_for_post( $post ) ); + $this->assertSame( '/wp/v2/blocks/' . $post->ID, rest_get_route_for_post( $post ) ); } /** @@ -1894,6 +1962,50 @@ public function test_rest_get_route_for_term_id() { $this->assertSame( '/wp/v2/tags/' . $term->term_id, rest_get_route_for_term( $term->term_id ) ); } + /** + * @ticket 54267 + */ + public function test_rest_get_route_for_taxonomy_custom_namespace() { + register_taxonomy( + 'ct', + 'post', + array( + 'show_in_rest' => true, + 'rest_base' => 'ct', + 'rest_namespace' => 'wordpress/v1', + ) + ); + $term = self::factory()->term->create_and_get( array( 'taxonomy' => 'ct' ) ); + + $this->assertSame( '/wordpress/v1/ct/' . $term->term_id, rest_get_route_for_term( $term ) ); + unregister_taxonomy( 'ct' ); + } + + /** + * @ticket 54267 + */ + public function test_rest_get_route_for_taxonomy_items() { + $this->assertSame( '/wp/v2/categories', rest_get_route_for_taxonomy_items( 'category' ) ); + } + + /** + * @ticket 54267 + */ + public function test_rest_get_route_for_taxonomy_items_custom_namespace() { + register_taxonomy( + 'ct', + 'post', + array( + 'show_in_rest' => true, + 'rest_base' => 'ct', + 'rest_namespace' => 'wordpress/v1', + ) + ); + + $this->assertSame( '/wordpress/v1/ct', rest_get_route_for_taxonomy_items( 'ct' ) ); + unregister_post_type( 'ct' ); + } + /** * @ticket 50300 * diff --git a/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php b/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php index ac07737b4d796..cbfe965fa1a3e 100644 --- a/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php +++ b/tests/phpunit/tests/rest-api/rest-application-passwords-controller.php @@ -937,7 +937,7 @@ public function test_introspect_item_password_invalid() { $this->setup_app_password_authenticated_request(); add_action( 'application_password_did_authenticate', - function() { + static function() { $GLOBALS['wp_rest_application_password_uuid'] = 'invalid_uuid'; } ); diff --git a/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php b/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php index 6d76a2f5d69ba..454bc6da35e13 100644 --- a/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php +++ b/tests/phpunit/tests/rest-api/rest-block-renderer-controller.php @@ -435,7 +435,7 @@ public function test_get_item() { public function test_get_item_with_pre_render_block_filter() { wp_set_current_user( self::$user_id ); - $pre_render_filter = function( $output, $block ) { + $pre_render_filter = static function( $output, $block ) { if ( $block['blockName'] === self::$block_name ) { return '

Alternate content.

'; } diff --git a/tests/phpunit/tests/rest-api/rest-controller.php b/tests/phpunit/tests/rest-api/rest-controller.php index 0af9460aa5d2c..270d1f32d191c 100644 --- a/tests/phpunit/tests/rest-api/rest-controller.php +++ b/tests/phpunit/tests/rest-api/rest-controller.php @@ -23,35 +23,43 @@ public function set_up() { '/wp/v2/testroute', array( 'args' => array( - 'someinteger' => array( + 'someinteger' => array( 'type' => 'integer', ), - 'someboolean' => array( + 'someboolean' => array( 'type' => 'boolean', ), - 'somestring' => array( + 'somestring' => array( 'type' => 'string', ), - 'somehex' => array( + 'somehex' => array( 'type' => 'string', 'format' => 'hex-color', ), - 'someenum' => array( + 'someenum' => array( 'type' => 'string', 'enum' => array( 'a' ), ), - 'somedate' => array( + 'somedate' => array( 'type' => 'string', 'format' => 'date-time', ), - 'someemail' => array( + 'someemail' => array( 'type' => 'string', 'format' => 'email', ), - 'someuuid' => array( + 'someuuid' => array( 'type' => 'string', 'format' => 'uuid', ), + 'sometextfield' => array( + 'type' => 'string', + 'format' => 'text-field', + ), + 'sometextareafield' => array( + 'type' => 'string', + 'format' => 'textarea-field', + ), ), ) ); @@ -219,6 +227,52 @@ public function test_validate_schema_format_uuid() { ); } + /** + * @ticket 49960 + */ + public function test_validate_schema_format_text_field() { + $this->assertTrue( + rest_validate_request_arg( 'Hello World', $this->request, 'sometextfield' ) + ); + + $this->assertErrorResponse( + 'rest_invalid_type', + rest_validate_request_arg( false, $this->request, 'sometextfield' ) + ); + + $this->assertSame( + 'Hello World', + rest_sanitize_request_arg( 'Hello World', $this->request, 'sometextfield' ) + ); + $this->assertSame( + 'Hello World', + rest_sanitize_request_arg( '

Hello World

', $this->request, 'sometextfield' ) + ); + } + + /** + * @ticket 49960 + */ + public function test_validate_schema_format_textarea_field() { + $this->assertTrue( + rest_validate_request_arg( "Hello\nWorld", $this->request, 'sometextareafield' ) + ); + + $this->assertErrorResponse( + 'rest_invalid_type', + rest_validate_request_arg( false, $this->request, 'sometextareafield' ) + ); + + $this->assertSame( + "Hello\nWorld", + rest_sanitize_request_arg( "Hello\nWorld", $this->request, 'sometextareafield' ) + ); + $this->assertSame( + "Hello\nWorld", + rest_sanitize_request_arg( "

Hello\nWorld

", $this->request, 'sometextareafield' ) + ); + } + /** * @ticket 50876 */ @@ -234,6 +288,8 @@ public function test_get_endpoint_args_for_item_schema() { $this->assertArrayHasKey( 'someemail', $args ); $this->assertArrayHasKey( 'somehex', $args ); $this->assertArrayHasKey( 'someuuid', $args ); + $this->assertArrayHasKey( 'sometextfield', $args ); + $this->assertArrayHasKey( 'sometextareafield', $args ); $this->assertArrayHasKey( 'someenum', $args ); $this->assertArrayHasKey( 'someargoptions', $args ); $this->assertArrayHasKey( 'somedefault', $args ); @@ -323,6 +379,8 @@ public function test_get_fields_for_response( $param, $expected ) { 'someemail', 'somehex', 'someuuid', + 'sometextfield', + 'sometextareafield', 'someenum', 'someargoptions', 'somedefault', @@ -356,6 +414,8 @@ public function data_get_fields_for_response() { 'someemail', 'somehex', 'someuuid', + 'sometextfield', + 'sometextareafield', 'someenum', 'someargoptions', 'somedefault', diff --git a/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php b/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php index c21ba712f6310..4a12e663b5392 100644 --- a/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php +++ b/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php @@ -272,7 +272,7 @@ public function test_get_items_prepare_filter() { // Test that filter changes uncached values. add_filter( 'rest_prepare_block_pattern', - function( $response ) { + static function( $response ) { return 'initial value'; } ); @@ -286,7 +286,7 @@ function( $response ) { // Test that filter changes cached values (the previous request primed the cache). add_filter( 'rest_prepare_block_pattern', - function( $response ) { + static function( $response ) { return 'modified the cache'; }, 11 diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 1e506c282aaef..85671eff54981 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -2708,7 +2708,7 @@ public function test_boolean_meta_update_to_false_stores_0() { 'single' => true, 'type' => 'boolean', 'show_in_rest' => true, - 'sanitize_callback' => function( $value ) { + 'sanitize_callback' => static function( $value ) { return $value ? '1' : '0'; }, ) diff --git a/tests/phpunit/tests/rest-api/rest-post-types-controller.php b/tests/phpunit/tests/rest-api/rest-post-types-controller.php index 0e06bf9d15410..22ff225a69a52 100644 --- a/tests/phpunit/tests/rest-api/rest-post-types-controller.php +++ b/tests/phpunit/tests/rest-api/rest-post-types-controller.php @@ -62,6 +62,23 @@ public function test_get_item() { $this->assertSame( array( 'category', 'post_tag' ), $data['taxonomies'] ); } + /** + * @ticket 53656 + */ + public function test_get_item_cpt() { + register_post_type( + 'cpt', + array( + 'show_in_rest' => true, + 'rest_base' => 'cpt', + 'rest_namespace' => 'wordpress/v1', + ) + ); + $request = new WP_REST_Request( 'GET', '/wp/v2/types/cpt' ); + $response = rest_get_server()->dispatch( $request ); + $this->check_post_type_object_response( 'view', $response, 'cpt' ); + } + public function test_get_item_page() { $request = new WP_REST_Request( 'GET', '/wp/v2/types/page' ); $response = rest_get_server()->dispatch( $request ); @@ -144,7 +161,7 @@ public function test_get_item_schema() { $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $properties = $data['schema']['properties']; - $this->assertCount( 10, $properties ); + $this->assertCount( 12, $properties ); $this->assertArrayHasKey( 'capabilities', $properties ); $this->assertArrayHasKey( 'description', $properties ); $this->assertArrayHasKey( 'hierarchical', $properties ); @@ -155,6 +172,8 @@ public function test_get_item_schema() { $this->assertArrayHasKey( 'supports', $properties ); $this->assertArrayHasKey( 'taxonomies', $properties ); $this->assertArrayHasKey( 'rest_base', $properties ); + $this->assertArrayHasKey( 'rest_namespace', $properties ); + $this->assertArrayHasKey( 'visibility', $properties ); } public function test_get_additional_field_registration() { @@ -203,6 +222,7 @@ protected function check_post_type_obj( $context, $post_type_obj, $data, $links $this->assertSame( $post_type_obj->description, $data['description'] ); $this->assertSame( $post_type_obj->hierarchical, $data['hierarchical'] ); $this->assertSame( $post_type_obj->rest_base, $data['rest_base'] ); + $this->assertSame( $post_type_obj->rest_namespace, $data['rest_namespace'] ); $links = test_rest_expand_compact_links( $links ); $this->assertSame( rest_url( 'wp/v2/types' ), $links['collection'][0]['href'] ); @@ -216,6 +236,11 @@ protected function check_post_type_obj( $context, $post_type_obj, $data, $links $viewable = is_post_type_viewable( $post_type_obj ); } $this->assertSame( $viewable, $data['viewable'] ); + $visibility = array( + 'show_in_nav_menus' => (bool) $post_type_obj->show_in_nav_menus, + 'show_ui' => (bool) $post_type_obj->show_ui, + ); + $this->assertSame( $visibility, $data['visibility'] ); $this->assertSame( get_all_post_type_supports( $post_type_obj->name ), $data['supports'] ); } else { $this->assertArrayNotHasKey( 'capabilities', $data ); diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php index ba6dc53c0b2d3..b35921a73db19 100644 --- a/tests/phpunit/tests/rest-api/rest-posts-controller.php +++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php @@ -2137,7 +2137,7 @@ public function test_prepare_item_limit_fields() { */ public function test_prepare_item_filters_content_when_needed() { $filter_count = 0; - $filter_content = function() use ( &$filter_count ) { + $filter_content = static function() use ( &$filter_count ) { $filter_count++; return '

Filtered content.

'; }; @@ -2173,7 +2173,7 @@ public function test_prepare_item_filters_content_when_needed() { */ public function test_prepare_item_skips_content_filter_if_not_needed() { $filter_count = 0; - $filter_content = function() use ( &$filter_count ) { + $filter_content = static function() use ( &$filter_count ) { $filter_count++; return '

Filtered content.

'; }; diff --git a/tests/phpunit/tests/rest-api/rest-request.php b/tests/phpunit/tests/rest-api/rest-request.php index 55b3b188d017c..836cb6159dbfe 100644 --- a/tests/phpunit/tests/rest-api/rest-request.php +++ b/tests/phpunit/tests/rest-api/rest-request.php @@ -475,7 +475,7 @@ public function test_sanitize_params_error_multiple_messages() { array( 'args' => array( 'failparam' => array( - 'sanitize_callback' => function () { + 'sanitize_callback' => static function () { $error = new WP_Error( 'invalid', 'Invalid.' ); $error->add( 'invalid', 'Super Invalid.' ); $error->add( 'broken', 'Broken.' ); @@ -510,7 +510,7 @@ public function test_sanitize_params_provides_detailed_errors() { array( 'args' => array( 'failparam' => array( - 'sanitize_callback' => function () { + 'sanitize_callback' => static function () { return new WP_Error( 'invalid', 'Invalid.', 'mydata' ); }, ), @@ -738,7 +738,7 @@ public function test_invalid_params_error_multiple_messages() { array( 'args' => array( 'failparam' => array( - 'validate_callback' => function () { + 'validate_callback' => static function () { $error = new WP_Error( 'invalid', 'Invalid.' ); $error->add( 'invalid', 'Super Invalid.' ); $error->add( 'broken', 'Broken.' ); @@ -773,7 +773,7 @@ public function test_invalid_params_provides_detailed_errors() { array( 'args' => array( 'failparam' => array( - 'validate_callback' => function () { + 'validate_callback' => static function () { return new WP_Error( 'invalid', 'Invalid.', 'mydata' ); }, ), diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 3c1e4107edb92..30977958fa911 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -1392,7 +1392,7 @@ public function test_does_not_echo_body_for_null_responses() { '/test', array( 'methods' => array( 'GET' ), - 'callback' => function () { + 'callback' => static function () { return new WP_REST_Response(); }, 'permission_callback' => '__return_true', @@ -1414,7 +1414,7 @@ public function test_does_not_echo_body_for_responses_with_204_status() { '/test', array( 'methods' => array( 'GET' ), - 'callback' => function () { + 'callback' => static function () { return new WP_REST_Response( 'data', 204 ); }, 'permission_callback' => '__return_true', @@ -1505,7 +1505,7 @@ public function test_get_routes_no_namespace_overriding() { '/test', array( 'methods' => array( 'GET' ), - 'callback' => function() { + 'callback' => static function() { return new WP_REST_Response( 'data', 204 ); }, 'permission_callback' => '__return_true', @@ -1516,7 +1516,7 @@ public function test_get_routes_no_namespace_overriding() { '/test', array( 'methods' => array( 'GET' ), - 'callback' => function() { + 'callback' => static function() { return new WP_REST_Response( 'data', 204 ); }, 'permission_callback' => '__return_true', @@ -1928,7 +1928,7 @@ static function() { '/test/(?P[\d+])', array( 'methods' => array( 'POST', 'DELETE' ), - 'callback' => function ( WP_REST_Request $request ) { + 'callback' => static function ( WP_REST_Request $request ) { return new WP_REST_Response( 'test' ); }, 'permission_callback' => '__return_true', @@ -2022,6 +2022,28 @@ public function test_index_includes_link_to_active_theme_if_authenticated() { $this->assertArrayHasKey( 'https://api.w.org/active-theme', $index->get_links() ); } + /** + * @ticket 53056 + */ + public function test_json_encode_error_results_in_500_status_code() { + register_rest_route( + 'test-ns/v1', + '/test', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => function() { + return new \WP_REST_Response( INF ); + }, + 'permission_callback' => '__return_true', + 'args' => array(), + ), + ) + ); + rest_get_server()->serve_request( '/test-ns/v1/test' ); + $this->assertSame( 500, rest_get_server()->status ); + } + public function _validate_as_integer_123( $value, $request, $key ) { if ( ! is_int( $value ) ) { return new WP_Error( 'some-error', 'This is not valid!' ); diff --git a/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php b/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php index 357e1c7e17607..17be251c1d352 100644 --- a/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php +++ b/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php @@ -219,7 +219,7 @@ public function test_get_item_schema() { $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $properties = $data['schema']['properties']; - $this->assertCount( 10, $properties ); + $this->assertCount( 11, $properties ); $this->assertArrayHasKey( 'capabilities', $properties ); $this->assertArrayHasKey( 'description', $properties ); $this->assertArrayHasKey( 'hierarchical', $properties ); @@ -230,6 +230,7 @@ public function test_get_item_schema() { $this->assertArrayHasKey( 'types', $properties ); $this->assertArrayHasKey( 'visibility', $properties ); $this->assertArrayHasKey( 'rest_base', $properties ); + $this->assertArrayHasKey( 'rest_namespace', $properties ); } /** @@ -252,6 +253,7 @@ protected function check_taxonomy_object( $context, $tax_obj, $data, $links ) { $this->assertSame( $tax_obj->description, $data['description'] ); $this->assertSame( $tax_obj->hierarchical, $data['hierarchical'] ); $this->assertSame( $tax_obj->rest_base, $data['rest_base'] ); + $this->assertSame( $tax_obj->rest_namespace, $data['rest_namespace'] ); $this->assertSame( rest_url( 'wp/v2/taxonomies' ), $links['collection'][0]['href'] ); $this->assertArrayHasKey( 'https://api.w.org/items', $links ); if ( 'edit' === $context ) { diff --git a/tests/phpunit/tests/rest-api/rest-test-controller.php b/tests/phpunit/tests/rest-api/rest-test-controller.php index d09cb5e7a39bb..f75de9e45899e 100644 --- a/tests/phpunit/tests/rest-api/rest-test-controller.php +++ b/tests/phpunit/tests/rest-api/rest-test-controller.php @@ -36,7 +36,7 @@ public function get_item_schema() { 'title' => 'type', 'type' => 'object', 'properties' => array( - 'somestring' => array( + 'somestring' => array( 'type' => 'string', 'description' => 'A pretty string.', 'minLength' => 3, @@ -44,7 +44,7 @@ public function get_item_schema() { 'pattern' => '[a-zA-Z]+', 'context' => array( 'view' ), ), - 'someinteger' => array( + 'someinteger' => array( 'type' => 'integer', 'multipleOf' => 10, 'minimum' => 100, @@ -53,41 +53,51 @@ public function get_item_schema() { 'exclusiveMaximum' => true, 'context' => array( 'view' ), ), - 'someboolean' => array( + 'someboolean' => array( 'type' => 'boolean', 'context' => array( 'view' ), ), - 'someurl' => array( + 'someurl' => array( 'type' => 'string', 'format' => 'uri', 'context' => array( 'view' ), ), - 'somedate' => array( + 'somedate' => array( 'type' => 'string', 'format' => 'date-time', 'context' => array( 'view' ), ), - 'someemail' => array( + 'someemail' => array( 'type' => 'string', 'format' => 'email', 'context' => array( 'view' ), ), - 'somehex' => array( + 'somehex' => array( 'type' => 'string', 'format' => 'hex-color', 'context' => array( 'view' ), ), - 'someuuid' => array( + 'someuuid' => array( 'type' => 'string', 'format' => 'uuid', 'context' => array( 'view' ), ), - 'someenum' => array( + 'sometextfield' => array( + 'type' => 'string', + 'format' => 'text-field', + 'context' => array( 'view' ), + ), + 'sometextareafield' => array( + 'type' => 'string', + 'format' => 'textarea-field', + 'context' => array( 'view' ), + ), + 'someenum' => array( 'type' => 'string', 'enum' => array( 'a', 'b', 'c' ), 'context' => array( 'view' ), ), - 'someargoptions' => array( + 'someargoptions' => array( 'type' => 'integer', 'required' => true, 'arg_options' => array( @@ -95,13 +105,13 @@ public function get_item_schema() { 'sanitize_callback' => '__return_true', ), ), - 'somedefault' => array( + 'somedefault' => array( 'type' => 'string', 'enum' => array( 'a', 'b', 'c' ), 'context' => array( 'view' ), 'default' => 'a', ), - 'somearray' => array( + 'somearray' => array( 'type' => 'array', 'items' => array( 'type' => 'string', @@ -111,7 +121,7 @@ public function get_item_schema() { 'uniqueItems' => true, 'context' => array( 'view' ), ), - 'someobject' => array( + 'someobject' => array( 'type' => 'object', 'additionalProperties' => array( 'type' => 'string', diff --git a/tests/phpunit/tests/rest-api/rest-users-controller.php b/tests/phpunit/tests/rest-api/rest-users-controller.php index 1705cba2eb699..478148ed56229 100644 --- a/tests/phpunit/tests/rest-api/rest-users-controller.php +++ b/tests/phpunit/tests/rest-api/rest-users-controller.php @@ -15,6 +15,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { protected static $editor; protected static $draft_editor; protected static $subscriber; + protected static $author; protected static $authors = array(); protected static $posts = array(); @@ -55,6 +56,13 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { 'user_email' => 'subscriber@example.com', ) ); + self::$author = $factory->user->create( + array( + 'display_name' => 'author', + 'role' => 'author', + 'user_email' => 'author@example.com', + ) + ); foreach ( array( true, false ) as $show_in_rest ) { foreach ( array( true, false ) as $public ) { @@ -107,7 +115,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { } // Set up users for pagination tests. - for ( $i = 0; $i < self::$total_users - 10; $i++ ) { + for ( $i = 0; $i < self::$total_users - 11; $i++ ) { self::$user_ids[] = $factory->user->create( array( 'role' => 'contributor', @@ -121,6 +129,7 @@ public static function wpTearDownAfterClass() { self::delete_user( self::$user ); self::delete_user( self::$editor ); self::delete_user( self::$draft_editor ); + self::delete_user( self::$author ); foreach ( self::$posts as $post ) { wp_delete_post( $post, true ); @@ -183,8 +192,7 @@ public function test_registered_query_params() { $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $keys = array_keys( $data['endpoints'][0]['args'] ); - sort( $keys ); - $this->assertSame( + $this->assertEqualSets( array( 'context', 'exclude', @@ -195,6 +203,7 @@ public function test_registered_query_params() { 'page', 'per_page', 'roles', + 'capabilities', 'search', 'slug', 'who', @@ -795,32 +804,19 @@ public function test_get_items_slug_csv_query() { public function test_get_items_roles() { wp_set_current_user( self::$user ); - $tango = $this->factory->user->create( - array( - 'display_name' => 'tango', - 'role' => 'subscriber', - ) - ); - $yolo = $this->factory->user->create( - array( - 'display_name' => 'yolo', - 'role' => 'author', - ) - ); - $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); $request->set_param( 'roles', 'author,subscriber' ); $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); - $this->assertCount( 3, $data ); - $this->assertSame( $tango, $data[1]['id'] ); - $this->assertSame( $yolo, $data[2]['id'] ); + $this->assertCount( 2, $data ); + $this->assertSame( self::$author, $data[0]['id'] ); + $this->assertSame( self::$subscriber, $data[1]['id'] ); $request->set_param( 'roles', 'author' ); $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $this->assertCount( 1, $data ); - $this->assertSame( $yolo, $data[0]['id'] ); + $this->assertSame( self::$author, $data[0]['id'] ); wp_set_current_user( 0 ); @@ -838,28 +834,86 @@ public function test_get_items_roles() { public function test_get_items_invalid_roles() { wp_set_current_user( self::$user ); - $lolz = $this->factory->user->create( - array( - 'display_name' => 'lolz', - 'role' => 'author', - ) - ); - $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); $request->set_param( 'roles', 'ilovesteak,author' ); $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); $this->assertCount( 1, $data ); - $this->assertSame( $lolz, $data[0]['id'] ); + $this->assertSame( self::$author, $data[0]['id'] ); $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); $request->set_param( 'roles', 'steakisgood' ); $response = rest_get_server()->dispatch( $request ); $data = $response->get_data(); - $this->assertCount( 0, $data ); - $this->assertSame( array(), $data ); + $this->assertIsArray( $data ); + $this->assertEmpty( $data ); } + /** + * @ticket 16841 + */ + public function test_get_items_capabilities() { + wp_set_current_user( self::$user ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'capabilities', 'edit_posts' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertNotEmpty( $data ); + foreach ( $data as $user ) { + $this->assertTrue( user_can( $user['id'], 'edit_posts' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_get_items_capabilities_no_permission_no_user() { + wp_set_current_user( 0 ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'capabilities', 'edit_posts' ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_user_cannot_view', $response, 401 ); + } + + /** + * @ticket 16841 + */ + public function test_get_items_capabilities_no_permission_editor() { + wp_set_current_user( self::$editor ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'capabilities', 'edit_posts' ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_user_cannot_view', $response, 403 ); + } + + /** + * @ticket 16841 + */ + public function test_get_items_invalid_capabilities() { + wp_set_current_user( self::$user ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'roles', 'ilovesteak,author' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertCount( 1, $data ); + $this->assertSame( self::$author, $data[0]['id'] ); + + $request = new WP_REST_Request( 'GET', '/wp/v2/users' ); + $request->set_param( 'capabilities', 'steakisgood' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertEmpty( $data ); + } + + /** + * @expectedDeprecated WP_User_Query + */ public function test_get_items_who_author_query() { wp_set_current_user( self::$superadmin ); diff --git a/tests/phpunit/tests/rest-api/rest-widget-types-controller.php b/tests/phpunit/tests/rest-api/rest-widget-types-controller.php index cd84b91c488bf..a7d1d47d61f9e 100644 --- a/tests/phpunit/tests/rest-api/rest-widget-types-controller.php +++ b/tests/phpunit/tests/rest-api/rest-widget-types-controller.php @@ -125,6 +125,22 @@ public function test_get_items() { } } + /** + * @ticket 53303 + */ + public function test_get_items_ordering() { + wp_set_current_user( self::$admin_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertGreaterThan( 1, count( $data ) ); + $ids = wp_list_pluck( $data, 'id' ); + $sorted = $ids; + sort( $sorted ); + + $this->assertSame( $sorted, $ids ); + } + /** * @ticket 53305 */ @@ -149,7 +165,7 @@ public function test_get_items_removes_duplicates() { $data = $response->get_data(); $text_widgets = array_filter( $data, - function( $widget ) { + static function( $widget ) { return 'text' === $widget['id']; } ); @@ -177,7 +193,7 @@ public function test_get_widget_legacy() { wp_register_sidebar_widget( $widget_id, 'WP legacy widget', - function() {} + static function() {} ); wp_set_current_user( self::$admin_id ); $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types/' . $widget_id ); @@ -208,7 +224,7 @@ public function test_get_widgets_decodes_html_entities() { wp_register_sidebar_widget( $widget_id, '‘Legacy ‑ Archive ‑ Widget’', - function() {}, + static function() {}, array( 'description' => '“A great & interesting archive of your site’s posts!”', ) diff --git a/tests/phpunit/tests/rest-api/rest-widgets-controller.php b/tests/phpunit/tests/rest-api/rest-widgets-controller.php index 66f14739b92f3..be0d84e430bcd 100644 --- a/tests/phpunit/tests/rest-api/rest-widgets-controller.php +++ b/tests/phpunit/tests/rest-api/rest-widgets-controller.php @@ -108,11 +108,11 @@ public function set_up() { wp_register_widget_control( 'testwidget', 'WP test widget', - function () { - $settings = get_option( 'widget_testwidget' ); - + static function () { // check if anything's been sent. if ( isset( $_POST['update_testwidget'] ) ) { + $settings = get_option( 'widget_testwidget', array() ); + $settings['id'] = $_POST['test_id']; $settings['title'] = $_POST['test_title']; @@ -127,9 +127,9 @@ function () { wp_register_sidebar_widget( 'testwidget', 'WP test widget', - function () { + static function () { $settings = wp_parse_args( - get_option( 'widget_testwidget' ), + get_option( 'widget_testwidget', array() ), array( 'id' => 'Default id', 'title' => 'Default text', diff --git a/tests/phpunit/tests/robots.php b/tests/phpunit/tests/robots.php index 9d71480af2265..60da725e75e66 100644 --- a/tests/phpunit/tests/robots.php +++ b/tests/phpunit/tests/robots.php @@ -43,7 +43,7 @@ public function test_wp_robots_renders_when_relevant() { public function test_wp_robots_parses_directives_correctly() { add_filter( 'wp_robots', - function( array $robots ) { + static function( array $robots ) { // Directives that should have values must use strings. $robots['directive-with-value'] = 'yes'; $robots['directive-with-numeric-value'] = '1'; diff --git a/tests/phpunit/tests/user.php b/tests/phpunit/tests/user.php index 5f94848e05976..c7a04779cd7c6 100644 --- a/tests/phpunit/tests/user.php +++ b/tests/phpunit/tests/user.php @@ -1845,6 +1845,78 @@ function test_wp_session_tokens_personal_data_exporter() { $this->assertSame( 'January 29, 2020 09:13 AM', $actual['data'][1]['data'][3]['value'] ); } + /** + * Test `$user_data['meta_input']` args in `wp_insert_user( $user_data )`. + * + * @ticket 41950 + */ + public function test_wp_insert_user_with_meta() { + $user_data = array( + 'user_login' => 'test_user', + 'user_pass' => 'test_password', + 'user_email' => 'user@example.com', + 'meta_input' => array( + 'test_meta_key' => 'test_meta_value', + 'custom_meta' => 'custom_value', + ), + ); + $create_user = wp_insert_user( $user_data ); + + $this->assertSame( 'test_meta_value', get_user_meta( $create_user, 'test_meta_key', true ) ); + $this->assertSame( 'custom_value', get_user_meta( $create_user, 'custom_meta', true ) ); + + // Update the user meta thru wp_insert_user. + $update_data = array( + 'ID' => $create_user, + 'user_login' => 'test_user', + 'meta_input' => array( + 'test_meta_key' => 'test_meta_updated', + 'custom_meta' => 'updated_value', + 'new_meta_k' => 'new_meta_val', + ), + ); + $update_user = wp_insert_user( $update_data ); + + $this->assertSame( 'test_meta_updated', get_user_meta( $update_user, 'test_meta_key', true ) ); + $this->assertSame( 'updated_value', get_user_meta( $update_user, 'custom_meta', true ) ); + $this->assertSame( 'new_meta_val', get_user_meta( $update_user, 'new_meta_k', true ) ); + + // Create new user. + $new_user_data = array( + 'user_login' => 'new_test', + 'user_pass' => 'new_password', + 'user_email' => 'new_user@newexample.com', + 'meta_input' => array( + 'test_meta_key' => 'test_meta_value', + 'custom_meta' => 'new_user_custom_value', + ), + ); + + // Hook filter + add_filter( 'insert_custom_user_meta', array( $this, 'filter_custom_meta' ) ); + + $new_user = wp_insert_user( $new_user_data ); + + // This meta is updated by the filter. + $this->assertSame( 'update_from_filter', get_user_meta( $new_user, 'test_meta_key', true ) ); + $this->assertSame( 'new_user_custom_value', get_user_meta( $new_user, 'custom_meta', true ) ); + // This meta is inserted by the filter. + $this->assertSame( 'new_from_filter', get_user_meta( $new_user, 'new_meta_from_filter', true ) ); + } + + /** + * Hook a filter to alter custom meta when inserting new user. + * This hook is used in `test_wp_insert_user_with_meta()`. + */ + public function filter_custom_meta( $meta_input ) { + // Update some meta inputs + $meta_input['test_meta_key'] = 'update_from_filter'; + // Add a new meta + $meta_input['new_meta_from_filter'] = 'new_from_filter'; + + return $meta_input; + } + /** * Testing the `wp_privacy_additional_user_profile_data` filter works. * diff --git a/tests/phpunit/tests/user/multisite.php b/tests/phpunit/tests/user/multisite.php index 0b2b1d380a8e2..c73a0bc12b899 100644 --- a/tests/phpunit/tests/user/multisite.php +++ b/tests/phpunit/tests/user/multisite.php @@ -10,19 +10,6 @@ * @group multisite */ class Tests_Multisite_User extends WP_UnitTestCase { - protected $suppress = false; - - function set_up() { - global $wpdb; - parent::set_up(); - $this->suppress = $wpdb->suppress_errors(); - } - - function tear_down() { - global $wpdb; - $wpdb->suppress_errors( $this->suppress ); - parent::tear_down(); - } function test_remove_user_from_blog() { $user1 = self::factory()->user->create_and_get(); @@ -395,9 +382,13 @@ public function test_add_user_to_blog_subscriber() { * @ticket 38356 */ public function test_add_user_to_blog_invalid_user() { + global $wpdb; + $site_id = self::factory()->blog->create(); - $result = add_user_to_blog( 73622, $site_id, 'subscriber' ); + $suppress = $wpdb->suppress_errors(); + $result = add_user_to_blog( 73622, $site_id, 'subscriber' ); + $wpdb->suppress_errors( $suppress ); wp_delete_site( $site_id ); diff --git a/tests/phpunit/tests/user/query.php b/tests/phpunit/tests/user/query.php index f0a0827038625..170e5b24a2ff0 100644 --- a/tests/phpunit/tests/user/query.php +++ b/tests/phpunit/tests/user/query.php @@ -730,6 +730,7 @@ public function test_roles_and_caps_should_be_populated_for_explicit_value_of_di /** * @ticket 32019 * @group ms-required + * @expectedDeprecated WP_User_Query */ public function test_who_authors() { $b = self::factory()->blog->create(); @@ -755,6 +756,7 @@ public function test_who_authors() { /** * @ticket 32019 * @group ms-required + * @expectedDeprecated WP_User_Query */ public function test_who_authors_should_work_alongside_meta_query() { $b = self::factory()->blog->create(); @@ -789,6 +791,7 @@ public function test_who_authors_should_work_alongside_meta_query() { /** * @ticket 36724 * @group ms-required + * @expectedDeprecated WP_User_Query */ public function test_who_authors_should_work_alongside_meta_params() { $b = self::factory()->blog->create(); @@ -1725,4 +1728,242 @@ public static function filter_users_pre_query( $posts, $query ) { return array( 555 ); } + + /** + * @ticket 16841 + * @group ms-excluded + */ + public function test_get_single_capability_by_string() { + $wp_user_search = new WP_User_Query( array( 'capability' => 'install_plugins' ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + // User has the capability, but on Multisite they would also need to be a super admin. + // Hence using get_role_caps() instead of has_cap(). + $role_caps = $user->get_role_caps(); + $this->assertArrayHasKey( 'install_plugins', $role_caps ); + $this->assertTrue( $role_caps['install_plugins'] ); + } + } + + /** + * @ticket 16841 + * @group ms-required + */ + public function test_get_single_capability_by_string_multisite() { + $wp_user_search = new WP_User_Query( array( 'capability' => array( 'install_plugins' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $role_caps = $user->get_role_caps(); + $this->assertArrayHasKey( 'install_plugins', $role_caps ); + $this->assertTrue( $role_caps['install_plugins'] ); + // While the user can have the capability, on Multisite they also need to be a super admin. + if ( is_super_admin( $user->ID ) ) { + $this->assertTrue( $user->has_cap( 'install_plugins' ) ); + } else { + $this->assertFalse( $user->has_cap( 'install_plugins' ) ); + } + } + } + + /** + * @ticket 16841 + */ + public function test_get_single_capability_invalid() { + $wp_user_search = new WP_User_Query( array( 'capability' => 'foo_bar' ) ); + $users = $wp_user_search->get_results(); + + $this->assertEmpty( $users ); + } + + /** + * @ticket 16841 + */ + public function test_get_single_capability_by_array() { + $wp_user_search = new WP_User_Query( array( 'capability' => array( 'install_plugins' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + // User has the capability, but on Multisite they would also need to be a super admin. + // Hence using get_role_caps() instead of has_cap(). + $role_caps = $user->get_role_caps(); + $this->assertArrayHasKey( 'install_plugins', $role_caps ); + $this->assertTrue( $role_caps['install_plugins'] ); + } + } + + /** + * @ticket 16841 + */ + public function test_get_single_capability_added_to_user() { + foreach ( self::$sub_ids as $subscriber ) { + $subscriber = get_user_by( 'ID', $subscriber ); + $subscriber->add_cap( 'custom_cap' ); + } + + $wp_user_search = new WP_User_Query( array( 'capability' => 'custom_cap' ) ); + $users = $wp_user_search->get_results(); + + $this->assertCount( 2, $users ); + $this->assertEqualSets( self::$sub_ids, wp_list_pluck( $users, 'ID' ) ); + + foreach ( $users as $user ) { + $this->assertTrue( $user->has_cap( 'custom_cap' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_get_multiple_capabilities_should_only_match_users_who_have_each_capability_test() { + wp_roles()->add_role( 'role_1', 'Role 1', array( 'role_1_cap' => true ) ); + wp_roles()->add_role( 'role_2', 'Role 2', array( 'role_2_cap' => true ) ); + + $subscriber1 = get_user_by( 'ID', self::$sub_ids[0] ); + $subscriber1->add_role( 'role_1' ); + + $subscriber2 = get_user_by( 'ID', self::$sub_ids[1] ); + $subscriber2->add_role( 'role_1' ); + $subscriber2->add_role( 'role_2' ); + + $wp_user_search = new WP_User_Query( array( 'capability' => array( 'role_1_cap', 'role_2_cap' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertCount( 1, $users ); + $this->assertSame( $users[0]->ID, $subscriber2->ID ); + foreach ( $users as $user ) { + $this->assertTrue( $user->has_cap( 'role_1_cap' ) ); + $this->assertTrue( $user->has_cap( 'role_2_cap' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_get_multiple_capabilities_should_only_match_users_who_have_each_capability_added_to_user() { + $admin1 = get_user_by( 'ID', self::$admin_ids[0] ); + $admin1->add_cap( 'custom_cap' ); + + $wp_user_search = new WP_User_Query( array( 'capability' => array( 'manage_options', 'custom_cap' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertCount( 1, $users ); + $this->assertSame( $users[0]->ID, $admin1->ID ); + $this->assertTrue( $users[0]->has_cap( 'custom_cap' ) ); + $this->assertTrue( $users[0]->has_cap( 'manage_options' ) ); + } + + /** + * @ticket 16841 + */ + public function test_get_multiple_capabilities_or() { + $wp_user_search = new WP_User_Query( array( 'capability__in' => array( 'publish_posts', 'edit_posts' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $this->assertTrue( $user->has_cap( 'publish_posts' ) || $user->has_cap( 'edit_posts' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_get_multiple_capabilities_or_added_to_user() { + $user = self::factory()->user->create_and_get( array( 'role' => 'subscriber' ) ); + $user->add_cap( 'custom_cap' ); + + $wp_user_search = new WP_User_Query( array( 'capability__in' => array( 'publish_posts', 'custom_cap' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $this->assertTrue( $user->has_cap( 'publish_posts' ) || $user->has_cap( 'custom_cap' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_capability_exclusion() { + $wp_user_search = new WP_User_Query( array( 'capability__not_in' => array( 'publish_posts', 'edit_posts' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $this->assertFalse( $user->has_cap( 'publish_posts' ) ); + $this->assertFalse( $user->has_cap( 'edit_posts' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_capability_exclusion_added_to_user() { + $user = self::factory()->user->create_and_get( array( 'role' => 'subscriber' ) ); + $user->add_cap( 'custom_cap' ); + + $wp_user_search = new WP_User_Query( array( 'capability__not_in' => array( 'publish_posts', 'custom_cap' ) ) ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $this->assertFalse( $user->has_cap( 'publish_posts' ) ); + $this->assertFalse( $user->has_cap( 'custom_cap' ) ); + } + } + + /** + * @ticket 16841 + */ + public function test_capability__in_capability__not_in_combined() { + $wp_user_search = new WP_User_Query( + array( + 'capability__in' => array( 'read' ), + 'capability__not_in' => array( 'manage_options' ), + ) + ); + $users = $wp_user_search->get_results(); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $this->assertTrue( $user->has_cap( 'read' ) ); + $this->assertFalse( $user->has_cap( 'manage_options' ) ); + } + } + + /** + * @ticket 16841 + * @group ms-required + */ + public function test_get_single_capability_multisite_blog_id() { + $blog_id = self::factory()->blog->create(); + + add_user_to_blog( $blog_id, self::$author_ids[0], 'subscriber' ); + add_user_to_blog( $blog_id, self::$author_ids[1], 'author' ); + add_user_to_blog( $blog_id, self::$author_ids[2], 'editor' ); + + $wp_user_search = new WP_User_Query( + array( + 'capability' => 'publish_posts', + 'blog_id' => $blog_id, + ) + ); + $users = $wp_user_search->get_results(); + + $found = wp_list_pluck( $wp_user_search->get_results(), 'ID' ); + + $this->assertNotEmpty( $users ); + foreach ( $users as $user ) { + $this->assertTrue( $user->has_cap( 'publish_posts' ) ); + } + + $this->assertNotContains( self::$author_ids[0], $found ); + $this->assertContains( self::$author_ids[1], $found ); + $this->assertContains( self::$author_ids[2], $found ); + } } diff --git a/tests/phpunit/tests/wp/parseRequest.php b/tests/phpunit/tests/wp/parseRequest.php new file mode 100644 index 0000000000000..2f022d7d2dd3a --- /dev/null +++ b/tests/phpunit/tests/wp/parseRequest.php @@ -0,0 +1,42 @@ +wp = new WP(); + } + + /** + * Test that PHP 8.1 "passing null to non-nullable" deprecation notice + * is not thrown when the home URL has no path/trailing slash (default setup). + * + * Note: This does not test the actual functioning of the parse_request() method. + * It just and only tests for/against the deprecation notice. + * + * @ticket 53635 + */ + public function test_no_deprecation_notice_when_home_url_has_no_path() { + // Make sure rewrite rules are not empty. + $this->set_permalink_structure( '/%year%/%monthnum%/%postname%/' ); + + // Make sure the test will function independently of whatever the test user set in wp-tests-config.php. + add_filter( + 'home_url', + static function ( $url ) { + return 'http://example.org'; + } + ); + + $this->wp->parse_request(); + $this->assertSame( '', $this->wp->request ); + } +} diff --git a/tests/phpunit/tests/xmlrpc/wp/getUsers.php b/tests/phpunit/tests/xmlrpc/wp/getUsers.php index 627facea5ce35..4975b68381051 100644 --- a/tests/phpunit/tests/xmlrpc/wp/getUsers.php +++ b/tests/phpunit/tests/xmlrpc/wp/getUsers.php @@ -54,6 +54,9 @@ function test_invalid_role() { $this->assertSame( 403, $results->code ); } + /** + * @expectedDeprecated WP_User_Query + */ function test_role_filter() { $author_id = $this->make_user_by_role( 'author' ); $editor_id = $this->make_user_by_role( 'editor' ); diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 63dbf37f05c88..7852fd34aff37 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -5357,6 +5357,14 @@ mockedApiResponse.Schema = { }, "required": false }, + "capabilities": { + "description": "Limit result set to users matching at least one specific capability provided. Accepts csv list or single capability.", + "type": "array", + "items": { + "type": "string" + }, + "required": false + }, "who": { "description": "Limit result set to users who are considered authors.", "type": "string", @@ -8328,6 +8336,7 @@ mockedApiResponse.TypesCollection = { "post_tag" ], "rest_base": "posts", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8355,6 +8364,7 @@ mockedApiResponse.TypesCollection = { "slug": "page", "taxonomies": [], "rest_base": "pages", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8382,6 +8392,7 @@ mockedApiResponse.TypesCollection = { "slug": "attachment", "taxonomies": [], "rest_base": "media", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8409,6 +8420,7 @@ mockedApiResponse.TypesCollection = { "slug": "wp_block", "taxonomies": [], "rest_base": "blocks", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8436,6 +8448,7 @@ mockedApiResponse.TypesCollection = { "slug": "wp_template", "taxonomies": [], "rest_base": "templates", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8467,7 +8480,8 @@ mockedApiResponse.TypeModel = { "category", "post_tag" ], - "rest_base": "posts" + "rest_base": "posts", + "rest_namespace": "wp/v2" }; mockedApiResponse.StatusesCollection = { @@ -8575,6 +8589,7 @@ mockedApiResponse.TaxonomiesCollection = { ], "hierarchical": true, "rest_base": "categories", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8604,6 +8619,7 @@ mockedApiResponse.TaxonomiesCollection = { ], "hierarchical": false, "rest_base": "tags", + "rest_namespace": "wp/v2", "_links": { "collection": [ { @@ -8634,7 +8650,8 @@ mockedApiResponse.TaxonomyModel = { "post" ], "hierarchical": true, - "rest_base": "categories" + "rest_base": "categories", + "rest_namespace": "wp/v2" }; mockedApiResponse.CategoriesCollection = [