diff --git a/.github/workflows/build-test-measure.yml b/.github/workflows/build-test-measure.yml index facc17fcb1e..b0df89bd4c5 100644 --- a/.github/workflows/build-test-measure.yml +++ b/.github/workflows/build-test-measure.yml @@ -289,6 +289,11 @@ jobs: install-pwa-plugin: [true] coverage: [false] include: + - php: '8.4' + wp: 'trunk' + phpunit: '9.6' + experimental: true + - php: '8.3' wp: 'trunk' phpunit: '9.6' @@ -492,6 +497,10 @@ jobs: php: ['7.4'] wp: ['latest'] include: + - php: '8.4' + wp: 'trunk' + experimental: true + - php: '8.3' wp: 'trunk' experimental: true @@ -565,194 +574,194 @@ jobs: #----------------------------------------------------------------------------------------------------------------------- - build-zip: - name: 'Build: ${{ matrix.build }} build ZIP' - needs: pre-run - # Only run if the PR was not authored by Dependabot and it is not a draft or not from a fork. - if: > - needs.pre-run.outputs.changed-file-count > 0 && - github.event.pull_request.draft == false && - github.event.pull_request.head.repo.fork == false && - github.event.pull_request.user.login != 'dependabot[bot]' - runs-on: ubuntu-latest - permissions: - actions: write - outputs: - branch-name: ${{ steps.retrieve-branch-name.outputs.branch_name }} - git-sha-8: ${{ steps.retrieve-git-sha-8.outputs.sha8 }} - strategy: - matrix: - build: ['dev', 'prod'] - steps: - - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - - - name: Setup NodeJS and NPM - uses: ./.github/actions/setup-node-npm - - - name: Setup PHP and Composer - uses: ./.github/actions/setup-php-composer - with: - php-version: '7.4' - - - name: Create destination directories - run: mkdir -p builds/${{ matrix.build }} - - - name: Build plugin - run: | - npm run package:${{ matrix.build }} - mv amp.zip builds/${{ matrix.build }}/amp.zip - env: - LAST_PR_COMMIT_HASH: ${{ github.event.pull_request.head.sha }} - - - name: Generate checksum file - working-directory: builds/${{ matrix.build }} - run: | - mkdir -p $RUNNER_TEMP/plugin-checksums - find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/plugin-checksums/checksums.txt - shasum -a 256 -U -c $RUNNER_TEMP/plugin-checksums/checksums.txt - cat $RUNNER_TEMP/plugin-checksums/checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done - - - name: Retrieve branch name - id: retrieve-branch-name - run: echo "branch_name=$(REF=${GITHUB_HEAD_REF:-$GITHUB_REF} && echo ${REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_OUTPUT - - - name: Retrieve git SHA-8 string - id: retrieve-git-sha-8 - run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT - - - name: Upload build as artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3 - with: - name: amp-${{ steps.retrieve-branch-name.outputs.branch_name }}-${{ steps.retrieve-git-sha-8.outputs.sha8 }}-${{ matrix.build }} - path: builds/${{ matrix.build }} +# build-zip: +# name: 'Build: ${{ matrix.build }} build ZIP' +# needs: pre-run +# # Only run if the PR was not authored by Dependabot and it is not a draft or not from a fork. +# if: > +# needs.pre-run.outputs.changed-file-count > 0 && +# github.event.pull_request.draft == false && +# github.event.pull_request.head.repo.fork == false && +# github.event.pull_request.user.login != 'dependabot[bot]' +# runs-on: ubuntu-latest +# permissions: +# actions: write +# outputs: +# branch-name: ${{ steps.retrieve-branch-name.outputs.branch_name }} +# git-sha-8: ${{ steps.retrieve-git-sha-8.outputs.sha8 }} +# strategy: +# matrix: +# build: ['dev', 'prod'] +# steps: +# - name: Checkout +# uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 +# +# - name: Setup NodeJS and NPM +# uses: ./.github/actions/setup-node-npm +# +# - name: Setup PHP and Composer +# uses: ./.github/actions/setup-php-composer +# with: +# php-version: '7.4' +# +# - name: Create destination directories +# run: mkdir -p builds/${{ matrix.build }} +# +# - name: Build plugin +# run: | +# npm run package:${{ matrix.build }} +# mv amp.zip builds/${{ matrix.build }}/amp.zip +# env: +# LAST_PR_COMMIT_HASH: ${{ github.event.pull_request.head.sha }} +# +# - name: Generate checksum file +# working-directory: builds/${{ matrix.build }} +# run: | +# mkdir -p $RUNNER_TEMP/plugin-checksums +# find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/plugin-checksums/checksums.txt +# shasum -a 256 -U -c $RUNNER_TEMP/plugin-checksums/checksums.txt +# cat $RUNNER_TEMP/plugin-checksums/checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done +# +# - name: Retrieve branch name +# id: retrieve-branch-name +# run: echo "branch_name=$(REF=${GITHUB_HEAD_REF:-$GITHUB_REF} && echo ${REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_OUTPUT +# +# - name: Retrieve git SHA-8 string +# id: retrieve-git-sha-8 +# run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT +# +# - name: Upload build as artifact +# uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3 +# with: +# name: amp-${{ steps.retrieve-branch-name.outputs.branch_name }}-${{ steps.retrieve-git-sha-8.outputs.sha8 }}-${{ matrix.build }} +# path: builds/${{ matrix.build }} #----------------------------------------------------------------------------------------------------------------------- - upload-to-gcs: - name: Upload plugin ZIPs to Google Cloud Storage - runs-on: ubuntu-latest - permissions: - actions: write - needs: - - build-zip - outputs: - dev-checksum: ${{ steps.output-checksums.outputs.dev-checksum }} - prod-checksum: ${{ steps.output-checksums.outputs.prod-checksum }} - steps: - - name: Download dev build - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e #v4.1.7 - with: - name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-dev - path: builds/dev - - - name: Download prod build - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e #v4.1.7 - with: - name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-prod - path: builds/prod - - - name: Setup Google Cloud SDK - uses: google-github-actions/setup-gcloud@20c93dacc1d70ddbce76c63ab32c35595345bdd1 #v0 - with: - project_id: ${{ secrets.GCS_PROJECT_ID }} - service_account_key: ${{ secrets.GCS_APPLICATION_CREDENTIALS }} - - - name: Output checksums - id: output-checksums - run: | - echo "dev-checksum=$(cat builds/dev/*.sha256)" >> $GITHUB_OUTPUT - echo "prod-checksum=$(cat builds/prod/*.sha256)" >> $GITHUB_OUTPUT - - - name: Upload dev build to bucket - run: gsutil cp -r builds/dev/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip - - - name: Upload dev build checksums to bucket - if: ${{ github.ref == 'refs/heads/develop' }} - run: gsutil cp -r builds/dev/*.sha256 gs://ampwp_github_artifacts/${{ github.ref }}/dev/ - - - name: Upload prod build to bucket - run: gsutil cp -r builds/prod/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip - - - name: Upload prod build checksums to bucket - if: ${{ github.ref == 'refs/heads/develop' }} - run: gsutil cp -r builds/prod/*.sha256 gs://ampwp_github_artifacts/${{ github.ref }}/prod/ +# upload-to-gcs: +# name: Upload plugin ZIPs to Google Cloud Storage +# runs-on: ubuntu-latest +# permissions: +# actions: write +# needs: +# - build-zip +# outputs: +# dev-checksum: ${{ steps.output-checksums.outputs.dev-checksum }} +# prod-checksum: ${{ steps.output-checksums.outputs.prod-checksum }} +# steps: +# - name: Download dev build +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e #v4.1.7 +# with: +# name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-dev +# path: builds/dev +# +# - name: Download prod build +# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e #v4.1.7 +# with: +# name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-prod +# path: builds/prod +# +# - name: Setup Google Cloud SDK +# uses: google-github-actions/setup-gcloud@20c93dacc1d70ddbce76c63ab32c35595345bdd1 #v0 +# with: +# project_id: ${{ secrets.GCS_PROJECT_ID }} +# service_account_key: ${{ secrets.GCS_APPLICATION_CREDENTIALS }} +# +# - name: Output checksums +# id: output-checksums +# run: | +# echo "dev-checksum=$(cat builds/dev/*.sha256)" >> $GITHUB_OUTPUT +# echo "prod-checksum=$(cat builds/prod/*.sha256)" >> $GITHUB_OUTPUT +# +# - name: Upload dev build to bucket +# run: gsutil cp -r builds/dev/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip +# +# - name: Upload dev build checksums to bucket +# if: ${{ github.ref == 'refs/heads/develop' }} +# run: gsutil cp -r builds/dev/*.sha256 gs://ampwp_github_artifacts/${{ github.ref }}/dev/ +# +# - name: Upload prod build to bucket +# run: gsutil cp -r builds/prod/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip +# +# - name: Upload prod build checksums to bucket +# if: ${{ github.ref == 'refs/heads/develop' }} +# run: gsutil cp -r builds/prod/*.sha256 gs://ampwp_github_artifacts/${{ github.ref }}/prod/ #----------------------------------------------------------------------------------------------------------------------- - comment-on-pr: - name: Comment on PR with links to plugin ZIPs - # Only run this job if it's a PR. One way to check for that is if `github.head_ref` is not empty. - if: ${{ github.head_ref && github.head_ref != null }} - runs-on: ubuntu-latest - needs: upload-to-gcs - permissions: - pull-requests: write - steps: - - name: Check if a comment was already made - id: find-comment - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 - with: - script: | - const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - }); - - const comment = comments.find((comment) => comment.body.includes('Plugin builds for')); - - return comment ? comment.id : null; - - - name: Get comment body - id: get-comment-body - # Setting a multi-line output requires escaping line-feeds. See . - run: | - body="Plugin builds for ${{ github.event.pull_request.head.sha }} are ready :bellhop_bell:! - - Download [development build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip?${{ github.sha }}) - - Download [production build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip?${{ github.sha }}) - -
- Checksums - -
-          # Development build checksums
-          ${{ needs.upload-to-gcs.outputs.dev-checksum }}
-
-          # Production build checksums
-          ${{ needs.upload-to-gcs.outputs.prod-checksum }}
-          
- -
- - > [!WARNING] - > These builds are for testing purposes only and should not be used in production." - - delimiter="${body//$'\n'/'%0A'}" - echo "body<<${delimiter}" >> $GITHUB_OUTPUT - echo "$body" >> $GITHUB_OUTPUT - echo "${delimiter}" >> $GITHUB_OUTPUT - - - name: Create comment on PR with links to plugin builds - if: ${{ steps.find-comment.outputs.result == 'null' }} - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 - with: - script: | - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: `${{ steps.get-comment-body.outputs.body }}`, - }); - - - name: Update comment on PR with links to plugin builds - if: ${{ steps.find-comment.outputs.result != 'null' }} - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 - with: - script: | - github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: ${{ steps.find-comment.outputs.result }}, - body: `${{ steps.get-comment-body.outputs.body }}`, - }); +# comment-on-pr: +# name: Comment on PR with links to plugin ZIPs +# # Only run this job if it's a PR. One way to check for that is if `github.head_ref` is not empty. +# if: ${{ github.head_ref && github.head_ref != null }} +# runs-on: ubuntu-latest +# needs: upload-to-gcs +# permissions: +# pull-requests: write +# steps: +# - name: Check if a comment was already made +# id: find-comment +# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 +# with: +# script: | +# const { data: comments } = await github.rest.issues.listComments({ +# owner: context.repo.owner, +# repo: context.repo.repo, +# issue_number: context.issue.number, +# }); +# +# const comment = comments.find((comment) => comment.body.includes('Plugin builds for')); +# +# return comment ? comment.id : null; +# +# - name: Get comment body +# id: get-comment-body +# # Setting a multi-line output requires escaping line-feeds. See . +# run: | +# body="Plugin builds for ${{ github.event.pull_request.head.sha }} are ready :bellhop_bell:! +# - Download [development build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip?${{ github.sha }}) +# - Download [production build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip?${{ github.sha }}) +# +#
+# Checksums +# +#
+#          # Development build checksums
+#          ${{ needs.upload-to-gcs.outputs.dev-checksum }}
+#
+#          # Production build checksums
+#          ${{ needs.upload-to-gcs.outputs.prod-checksum }}
+#          
+# +#
+# +# > [!WARNING] +# > These builds are for testing purposes only and should not be used in production." +# +# delimiter="${body//$'\n'/'%0A'}" +# echo "body<<${delimiter}" >> $GITHUB_OUTPUT +# echo "$body" >> $GITHUB_OUTPUT +# echo "${delimiter}" >> $GITHUB_OUTPUT +# +# - name: Create comment on PR with links to plugin builds +# if: ${{ steps.find-comment.outputs.result == 'null' }} +# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 +# with: +# script: | +# github.rest.issues.createComment({ +# owner: context.repo.owner, +# repo: context.repo.repo, +# issue_number: context.issue.number, +# body: `${{ steps.get-comment-body.outputs.body }}`, +# }); +# +# - name: Update comment on PR with links to plugin builds +# if: ${{ steps.find-comment.outputs.result != 'null' }} +# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 +# with: +# script: | +# github.rest.issues.updateComment({ +# owner: context.repo.owner, +# repo: context.repo.repo, +# comment_id: ${{ steps.find-comment.outputs.result }}, +# body: `${{ steps.get-comment-body.outputs.body }}`, +# }); diff --git a/composer.json b/composer.json index 45d33c66619..adcb2dc15b5 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "ext-json": "*", "ext-libxml": "*", "ext-spl": "*", - "ampproject/amp-toolbox": "0.11.5", + "ampproject/amp-toolbox": "0.11.6", "cweagans/composer-patches": "^1.0", "fasterimage/fasterimage": "1.5.0", "sabberworm/php-css-parser": "8.5.1" @@ -23,7 +23,7 @@ "automattic/vipwpcs": "^3.0", "civicrm/composer-downloads-plugin": "^4.0", "google/cloud-storage": "^1.0", - "mikey179/vfsstream": "1.6.11", + "mikey179/vfsstream": "1.6.12", "mustache/mustache": "^2", "php-stubs/wordpress-stubs": "^6.0", "phpcompatibility/phpcompatibility-wp": "2.1.5", diff --git a/composer.lock b/composer.lock index 68e45fd5dbf..8e509fdb2d6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c672b16c6c4a23f305014e966245c095", + "content-hash": "609f396f85d60e46926a06c18aa6bd63", "packages": [ { "name": "ampproject/amp-toolbox", - "version": "0.11.5", + "version": "0.11.6", "source": { "type": "git", "url": "https://github.com/ampproject/amp-toolbox-php.git", - "reference": "78531851c59fa5f306315372719f0064b5542cf4" + "reference": "72674f17e012ec880efc2e255997dce8fd44ca4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ampproject/amp-toolbox-php/zipball/78531851c59fa5f306315372719f0064b5542cf4", - "reference": "78531851c59fa5f306315372719f0064b5542cf4", + "url": "https://api.github.com/repos/ampproject/amp-toolbox-php/zipball/72674f17e012ec880efc2e255997dce8fd44ca4e", + "reference": "72674f17e012ec880efc2e255997dce8fd44ca4e", "shasum": "" }, "require": { @@ -26,7 +26,7 @@ "ext-iconv": "*", "ext-json": "*", "ext-libxml": "*", - "php": "^5.6 || ^7.0 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "civicrm/composer-downloads-plugin": "^2.1 || ^3.0", @@ -76,9 +76,9 @@ "description": "A collection of AMP tools making it easier to publish and host AMP pages with PHP.", "support": { "issues": "https://github.com/ampproject/amp-toolbox-php/issues", - "source": "https://github.com/ampproject/amp-toolbox-php/tree/0.11.5" + "source": "https://github.com/ampproject/amp-toolbox-php/tree/0.11.6" }, - "time": "2024-02-05T19:10:57+00:00" + "time": "2024-10-17T15:07:03+00:00" }, { "name": "cweagans/composer-patches", @@ -307,20 +307,20 @@ "packages-dev": [ { "name": "antecedent/patchwork", - "version": "2.1.26", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/antecedent/patchwork.git", - "reference": "f2dae0851b2eae4c51969af740fdd0356d7f8f55" + "reference": "b07d4fb37c3c723c8755122160c089e077d5de65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antecedent/patchwork/zipball/f2dae0851b2eae4c51969af740fdd0356d7f8f55", - "reference": "f2dae0851b2eae4c51969af740fdd0356d7f8f55", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/b07d4fb37c3c723c8755122160c089e077d5de65", + "reference": "b07d4fb37c3c723c8755122160c089e077d5de65", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": ">=7.1.0" }, "require-dev": { "phpunit/phpunit": ">=4" @@ -337,7 +337,7 @@ } ], "description": "Method redefinition (monkey-patching) functionality for PHP.", - "homepage": "http://patchwork2.org/", + "homepage": "https://antecedent.github.io/patchwork/", "keywords": [ "aop", "aspect", @@ -349,9 +349,9 @@ ], "support": { "issues": "https://github.com/antecedent/patchwork/issues", - "source": "https://github.com/antecedent/patchwork/tree/2.1.26" + "source": "https://github.com/antecedent/patchwork/tree/2.2.0" }, - "time": "2023-09-18T08:18:37+00:00" + "time": "2024-09-27T16:59:55+00:00" }, { "name": "automattic/vipwpcs", @@ -1964,23 +1964,24 @@ }, { "name": "mikey179/vfsstream", - "version": "v1.6.11", + "version": "v1.6.12", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f" + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "^4.5|^5.0" + "phpunit/phpunit": "^7.5||^8.5||^9.6", + "yoast/phpunit-polyfills": "^2.0" }, "type": "library", "extra": { @@ -2011,20 +2012,20 @@ "source": "https://github.com/bovigo/vfsStream/tree/master", "wiki": "https://github.com/bovigo/vfsStream/wiki" }, - "time": "2022-02-23T02:02:42+00:00" + "time": "2024-08-29T18:43:31+00:00" }, { "name": "mockery/mockery", - "version": "1.6.6", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/b8e0bb7d8c604046539c1115994632c74dcb361e", - "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { @@ -2036,10 +2037,8 @@ "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.10", - "psalm/plugin-phpunit": "^0.18.4", - "symplify/easy-coding-standard": "^11.5.0", - "vimeo/psalm": "^4.30" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", "autoload": { @@ -2096,7 +2095,7 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2023-08-09T00:03:52+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "monolog/monolog", @@ -6620,20 +6619,20 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", - "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -6679,7 +6678,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -6695,7 +6694,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -7014,20 +7013,20 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -7074,7 +7073,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -7090,24 +7089,24 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af" + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/3fb075789fb91f9ad9af537c4012d523085bd5af", - "reference": "3fb075789fb91f9ad9af537c4012d523085bd5af", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -7150,7 +7149,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" }, "funding": [ { @@ -7166,7 +7165,7 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/service-contracts", @@ -7514,16 +7513,16 @@ }, { "name": "symfony/yaml", - "version": "v5.4.40", + "version": "v5.4.44", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "81cad0ceab3d61fe14fe941ff18a230ac9c80f83" + "reference": "7025b964f123bbf1896d7563db6ec7f1f63e918a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/81cad0ceab3d61fe14fe941ff18a230ac9c80f83", - "reference": "81cad0ceab3d61fe14fe941ff18a230ac9c80f83", + "url": "https://api.github.com/repos/symfony/yaml/zipball/7025b964f123bbf1896d7563db6ec7f1f63e918a", + "reference": "7025b964f123bbf1896d7563db6ec7f1f63e918a", "shasum": "" }, "require": { @@ -7569,7 +7568,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.40" + "source": "https://github.com/symfony/yaml/tree/v5.4.44" }, "funding": [ { @@ -7585,7 +7584,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:33:22+00:00" + "time": "2024-09-16T14:36:56+00:00" }, { "name": "theseer/tokenizer", @@ -8376,16 +8375,16 @@ }, { "name": "yoast/phpunit-polyfills", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "a0f7d708794a738f328d7b6c94380fd1d6c40446" + "reference": "e9c8413de4c8ae03d2923a44f17d0d7dad1b96be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/a0f7d708794a738f328d7b6c94380fd1d6c40446", - "reference": "a0f7d708794a738f328d7b6c94380fd1d6c40446", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/e9c8413de4c8ae03d2923a44f17d0d7dad1b96be", + "reference": "e9c8413de4c8ae03d2923a44f17d0d7dad1b96be", "shasum": "" }, "require": { @@ -8400,7 +8399,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -8435,7 +8434,7 @@ "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2024-04-05T16:01:51+00:00" + "time": "2024-09-06T22:03:10+00:00" }, { "name": "yoast/wp-test-utils", @@ -8525,7 +8524,7 @@ "ext-libxml": "*", "ext-spl": "*" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "7.4" }, diff --git a/includes/admin/class-amp-template-customizer.php b/includes/admin/class-amp-template-customizer.php index 8d1dc767c64..6bda727e41e 100644 --- a/includes/admin/class-amp-template-customizer.php +++ b/includes/admin/class-amp-template-customizer.php @@ -76,7 +76,7 @@ protected function __construct( WP_Customize_Manager $wp_customize, ReaderThemeL * @param ReaderThemeLoader|null $reader_theme_loader Reader theme loader. * @return AMP_Template_Customizer Instance. */ - public static function init( WP_Customize_Manager $wp_customize, ReaderThemeLoader $reader_theme_loader = null ) { + public static function init( WP_Customize_Manager $wp_customize, ?ReaderThemeLoader $reader_theme_loader = null ) { if ( null === $reader_theme_loader ) { $reader_theme_loader = Services::get( 'reader_theme_loader' ); } diff --git a/includes/embeds/class-amp-youtube-embed-handler.php b/includes/embeds/class-amp-youtube-embed-handler.php index ddcc6ae4353..a3548a8e6a6 100644 --- a/includes/embeds/class-amp-youtube-embed-handler.php +++ b/includes/embeds/class-amp-youtube-embed-handler.php @@ -275,7 +275,6 @@ private function prepare_attributes( $url, $video_id = '' ) { $query_vars = []; $query_param = wp_parse_url( $url, PHP_URL_QUERY ); wp_parse_str( $query_param, $query_vars ); - $query_vars = ( is_array( $query_vars ) ) ? $query_vars : []; $excluded_param = [ 'start', 'v', 'vi', 'w', 'h' ]; @@ -476,16 +475,14 @@ private function get_start_time_from_url( $url ) { preg_match( $regex, $parsed_url['fragment'], $matches ); - if ( is_array( $matches ) ) { - $matches = wp_parse_args( - $matches, - [ - 'minutes' => 0, - 'seconds' => 0, - ] - ); - $start_time = ( (int) $matches['seconds'] + ( (int) $matches['minutes'] * 60 ) ); - } + $matches = wp_parse_args( + $matches, + [ + 'minutes' => 0, + 'seconds' => 0, + ] + ); + $start_time = ( (int) $matches['seconds'] + ( (int) $matches['minutes'] * 60 ) ); } return $start_time; diff --git a/includes/sanitizers/class-amp-object-sanitizer.php b/includes/sanitizers/class-amp-object-sanitizer.php index 2e2ed25f4e2..5078f5b4d7d 100644 --- a/includes/sanitizers/class-amp-object-sanitizer.php +++ b/includes/sanitizers/class-amp-object-sanitizer.php @@ -87,12 +87,18 @@ public function sanitize_pdf( Element $element ) { $attributes_to_copy = [ Attribute::ID, Attribute::CLASS_ ]; foreach ( $attributes_to_copy as $attribute_name ) { - $attribute = $element->getAttributeNode( $attribute_name ); - if ( $attribute instanceof DOMAttr ) { - // Remove the attribute from the original node so that PHP DOM doesn't fail to set it on the replacement element (as happens with ID). - $element->removeAttributeNode( $attribute ); + /* + * Note: Previously this used $element->getAttributeNode() and $element->removeAttributeNode( $attribute_node ) + * but these would prevent the ID specifically from applying so that the element can be obtained via + * $dom->getElementById(). As noted in : + * > if you want to work with an attribute node instead, make sure you pass that same attribute node to setAttributeNode on the replacement element + * But this was not being done. So this was changed to eliminate the use of attribute nodes altogether. + */ + if ( $element->hasAttribute( $attribute_name ) ) { + $attributes[ $attribute_name ] = $element->getAttribute( $attribute_name ); - $attributes[ $attribute_name ] = $attribute->value; + // Remove the attribute from the original node so that PHP DOM doesn't fail to set it on the replacement element (as happens with ID). + $element->removeAttribute( $attribute_name ); } } diff --git a/includes/utils/class-amp-dom-utils.php b/includes/utils/class-amp-dom-utils.php index 49f9dc0bdf9..3892dacc3a9 100644 --- a/includes/utils/class-amp-dom-utils.php +++ b/includes/utils/class-amp-dom-utils.php @@ -373,7 +373,7 @@ public static function merge_amp_actions( $first, $second ) { $matches = []; $results = preg_match_all( self::AMP_EVENT_ACTIONS_REGEX_PATTERN, $event_action_string, $matches ); - if ( ! $results || ! isset( $matches['event'] ) ) { + if ( ! $results ) { continue; } @@ -391,7 +391,7 @@ static function ( $actions ) use ( &$actions_array ) { $matches = []; $results = preg_match_all( self::AMP_ACTION_REGEX_PATTERN, $actions, $matches ); - if ( ! $results || ! isset( $matches['action'] ) ) { + if ( ! $results ) { $actions_array[] = $actions; return; } diff --git a/includes/validation/class-amp-validation-manager.php b/includes/validation/class-amp-validation-manager.php index cac607113e8..be7a8e25dda 100644 --- a/includes/validation/class-amp-validation-manager.php +++ b/includes/validation/class-amp-validation-manager.php @@ -1659,7 +1659,7 @@ public static function can_output_buffer() { $called_functions = []; $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace -- Only way to find out if we are in a buffering display handler. foreach ( $backtrace as $call_stack ) { - if ( '{closure}' === $call_stack['function'] ) { + if ( '{closure}' === $call_stack['function'] ) { // TODO: This may not be the right format for PHP 8.4. $called_functions[] = 'Closure::__invoke'; } elseif ( isset( $call_stack['class'] ) ) { $called_functions[] = sprintf( '%s::%s', $call_stack['class'], $call_stack['function'] ); diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e54f3d44c64..981b3690ec6 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -35,3 +35,5 @@ parameters: - WP_CLI::error dynamicConstantNames: - INTL_IDNA_VARIANT_2003 + featureToggles: + requireFileExists: false diff --git a/src/DevTools/CallbackReflection.php b/src/DevTools/CallbackReflection.php index e159747ee31..d14c8920200 100644 --- a/src/DevTools/CallbackReflection.php +++ b/src/DevTools/CallbackReflection.php @@ -110,7 +110,32 @@ public function get_source( $callback ) { if ( $reflection instanceof ReflectionMethod ) { $source['function'] = $reflection->getDeclaringClass()->getName() . '::' . $reflection->getName(); } else { - $source['function'] = $reflection->getName(); + $function_name = $reflection->getName(); + + /* + * In PHP 8.4, a closure's string representation changes from {closure} to include the function that contained + * the closure, like {closure:Test_AMP_Validation_Manager::test_decorate_shortcode_and_filter_source():1831}. + * It can even indicate closure nesting like {closure:{closure:Test_AMP_Validation_Manager::get_locate_sources_data():883}:886}. + * So these are normalized here. + */ + $function_name = preg_replace( + '/\{closure.*}/', + '{closure}', + $function_name + ); + + /* + * Additionally, in PHP 8.4 the namespace no longer prefixes the closure. So this is now removed + * for consistency across all PHP versions, replacing AmpProject\AmpWP\Tests\DevTools\{closure} + * with just {closure}. + */ + $function_name = preg_replace( + '/(\w+\\\\)+(?=\{)/', + '', + $function_name + ); + + $source['function'] = $function_name; } return $source; diff --git a/src/Dom/ElementList.php b/src/Dom/ElementList.php index eac2366454f..9e14671c49b 100644 --- a/src/Dom/ElementList.php +++ b/src/Dom/ElementList.php @@ -35,7 +35,7 @@ final class ElementList implements IteratorAggregate, Countable { * @param DOMElement|null $caption The caption for the element. * @return ElementList A clone of this list, with the new element added. */ - public function add( DOMElement $element, DOMElement $caption = null ): ElementList { + public function add( DOMElement $element, ?DOMElement $caption = null ): ElementList { $cloned_list = clone $this; $cloned_list->elements[] = null === $caption ? $element : new CaptionedSlide( $element, $caption ); return $cloned_list; diff --git a/src/Infrastructure/Injector/SimpleInjector.php b/src/Infrastructure/Injector/SimpleInjector.php index 489b2de75dd..924c34463f7 100644 --- a/src/Infrastructure/Injector/SimpleInjector.php +++ b/src/Infrastructure/Injector/SimpleInjector.php @@ -51,7 +51,7 @@ final class SimpleInjector implements Injector { * * @param Instantiator|null $instantiator Optional. Instantiator to use. */ - public function __construct( Instantiator $instantiator = null ) { + public function __construct( ?Instantiator $instantiator = null ) { $this->instantiator = null !== $instantiator ? $instantiator : new FallbackInstantiator(); diff --git a/src/Infrastructure/ServiceBasedPlugin.php b/src/Infrastructure/ServiceBasedPlugin.php index 1574cdf8ab7..ffc6dc61663 100644 --- a/src/Infrastructure/ServiceBasedPlugin.php +++ b/src/Infrastructure/ServiceBasedPlugin.php @@ -67,8 +67,8 @@ abstract class ServiceBasedPlugin implements Plugin { */ public function __construct( $enable_filters = null, - Injector $injector = null, - ServiceContainer $service_container = null + ?Injector $injector = null, + ?ServiceContainer $service_container = null ) { /* * We use what is commonly referred to as a "poka-yoke" here. diff --git a/tests/php/src/DevTools/CallbackReflectionTest.php b/tests/php/src/DevTools/CallbackReflectionTest.php index c88ab786af8..88a0164dc19 100644 --- a/tests/php/src/DevTools/CallbackReflectionTest.php +++ b/tests/php/src/DevTools/CallbackReflectionTest.php @@ -208,7 +208,7 @@ public function data_get_source() { ], 'plugin_closure' => [ function () {}, - __NAMESPACE__ . '\{closure}', + '{closure}', 'amp', 'plugin', 'tests/php/src/DevTools/CallbackReflectionTest.php', @@ -246,7 +246,6 @@ public function test_get_source( $function, $source_function, $name, $type, $fil /** @var ReflectionFunction $reflection */ $reflection = $source['reflection']; $this->assertInstanceOf( $reflection_class, $reflection ); - $this->assertEquals( preg_replace( '/.*::/', '', $source['function'] ), $reflection->getName() ); } /** diff --git a/tests/php/test-amp-gallery-embed-handler.php b/tests/php/test-amp-gallery-embed-handler.php index 3c0a4fed002..2427a598844 100644 --- a/tests/php/test-amp-gallery-embed-handler.php +++ b/tests/php/test-amp-gallery-embed-handler.php @@ -287,6 +287,11 @@ public function test__conversion( $source, $expected, $use_legacy_mode = false ) // Remove decoding attribute. $content = preg_replace( '/\s+decoding="async"/', '', $content ); + // Auto sizes was added in WordPress 6.7 + if ( version_compare( strtok( get_bloginfo( 'version' ), '-' ), '6.7', '>=' ) ) { + $expected = str_replace( ' sizes="', ' sizes="auto, ', $expected ); + } + $this->assertEquals( $this->normalize( $expected ), $this->normalize( $content ) diff --git a/tests/php/test-class-amp-object-sanitizer.php b/tests/php/test-class-amp-object-sanitizer.php index 506c787a567..d7199ace520 100644 --- a/tests/php/test-class-amp-object-sanitizer.php +++ b/tests/php/test-class-amp-object-sanitizer.php @@ -69,6 +69,14 @@ public function test_sanitize( $source, $expected ) { $sanitizer->sanitize(); $content = AMP_DOM_Utils::get_content_from_dom( $dom ); $this->assertEquals( $expected, $content ); + + // Ensure the ID was successfully copied. See / + foreach ( $dom->xpath->query( '//*/@id' ) as $id_attribute ) { + $this->assertSame( + $id_attribute->parentNode, + $dom->getElementById( $id_attribute->nodeValue ) + ); + } } public function get_scripts_data() {