diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 4716bd5..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,56 +0,0 @@ -version: 2.1 - -orbs: - newspack: newspack/newspack@1.5.6 - -jobs: - release_wporg: - docker: - - image: cimg/php:7.4-browsers - steps: - - checkout - - attach_workspace: - at: ~/ - - run: - name: Release new version on wordpress.org - command: ./node_modules/newspack-scripts/release-wporg.sh - -workflows: - version: 2 - all: - jobs: - - newspack/build: - filters: - branches: - only: - - release - - alpha - - /^hotfix\/.*/ - - /^epic\/.*/ - - newspack/release: - requires: - - newspack/build - filters: - branches: - only: - - release - - alpha - - /^hotfix\/.*/ - - /^epic\/.*/ - - newspack/post-release: - requires: - - newspack/release - filters: - branches: - only: - - release - - release_wporg: - requires: - - newspack/release - filters: - branches: - only: - - release - php: - jobs: - - newspack/test-php diff --git a/.circleci/dependabot.yml b/.github/dependabot.yml similarity index 100% rename from .circleci/dependabot.yml rename to .github/dependabot.yml diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 13e2553..1f52d7d 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -1,18 +1,38 @@ on: pull_request_target: - types: [labeled] name: Dependabot auto-merge jobs: auto-merge: name: Auto-merge dependabot PRs for minor and patch updates runs-on: ubuntu-latest - if: | - contains( github.event.pull_request.labels.*.name, 'dependencies' ) - && ! contains( github.event.pull_request.labels.*.name, '[Status] Approved' ) + if: github.actor == 'dependabot[bot]' + permissions: + contents: write + pull-requests: write steps: - - uses: actions/checkout@v2 - - uses: ahmadnassri/action-dependabot-auto-merge@v2 + - name: Fetch Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2 with: - target: minor # includes patch updates. - github-token: ${{ secrets.DEPENDABOT_TOKEN }} + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Approve PR + if: >- + (contains(steps.metadata.outputs.update-type, 'version-update:semver-minor') || + contains(steps.metadata.outputs.update-type, 'version-update:semver-patch')) && + !contains(steps.metadata.outputs.update-type, 'version-update:semver-major') + run: gh pr review --approve "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.DEPENDABOT_TOKEN }} + + - name: Enable auto-merge for minor and patch updates + if: >- + (contains(steps.metadata.outputs.update-type, 'version-update:semver-minor') || + contains(steps.metadata.outputs.update-type, 'version-update:semver-patch')) && + !contains(steps.metadata.outputs.update-type, 'version-update:semver-major') + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.DEPENDABOT_TOKEN }} diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..cd1207b --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,24 @@ +name: Build and Test + +on: + pull_request: + push: + branches: + - trunk + - release + - alpha + - 'hotfix/**' + - 'epic/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + uses: Automattic/newspack-scripts/.github/workflows/reusable-build.yml@trunk + + lint-js-scss: + needs: build + uses: Automattic/newspack-scripts/.github/workflows/reusable-lint-js-scss.yml@trunk + diff --git a/.github/workflows/build-distributable.yml b/.github/workflows/build-distributable.yml new file mode 100644 index 0000000..eb3e053 --- /dev/null +++ b/.github/workflows/build-distributable.yml @@ -0,0 +1,15 @@ +name: Build distributable + +on: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-distributable: + uses: Automattic/newspack-scripts/.github/workflows/reusable-build-distributable.yml@trunk + with: + archive-name: republication-tracker-tool + diff --git a/.github/workflows/i18n.yml b/.github/workflows/i18n.yml new file mode 100644 index 0000000..db16c94 --- /dev/null +++ b/.github/workflows/i18n.yml @@ -0,0 +1,16 @@ +name: Internationalization + +on: + push: + branches: + - trunk + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + i18n: + uses: Automattic/newspack-scripts/.github/workflows/reusable-i18n.yml@trunk + secrets: + GIT_COMMITTER_TOKEN: ${{ secrets.GIT_COMMITTER_TOKEN }} diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..45d4ab1 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,23 @@ +name: PHP + +on: + pull_request: + push: + branches: + - trunk + - release + - alpha + - 'hotfix/**' + - 'epic/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint-php: + uses: Automattic/newspack-scripts/.github/workflows/reusable-lint-php.yml@trunk + + test-php: + uses: Automattic/newspack-scripts/.github/workflows/reusable-test-php.yml@trunk + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3ab742e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: Release + +on: + push: + branches: + - release + - alpha + - 'hotfix/**' + - 'epic/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + uses: Automattic/newspack-scripts/.github/workflows/reusable-build.yml@trunk + + release: + needs: build + uses: Automattic/newspack-scripts/.github/workflows/reusable-release.yml@trunk + secrets: + GIT_COMMITTER_TOKEN: ${{ secrets.GIT_COMMITTER_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + post-release: + if: github.ref == 'refs/heads/release' + needs: release + uses: Automattic/newspack-scripts/.github/workflows/reusable-post-release.yml@trunk + secrets: + GIT_COMMITTER_TOKEN: ${{ secrets.GIT_COMMITTER_TOKEN }} + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + SLACK_AUTH_TOKEN: ${{ secrets.SLACK_AUTH_TOKEN }} + + release-wporg: + if: github.ref == 'refs/heads/release' + needs: release + uses: Automattic/newspack-scripts/.github/workflows/reusable-release-wporg.yml@trunk + secrets: + WP_ORG_USERNAME: ${{ secrets.WP_ORG_USERNAME }} + WP_ORG_PASSWORD: ${{ secrets.WP_ORG_PASSWORD }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5275e28..8b9110c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [2.8.1](https://github.com/Automattic/republication-tracker-tool/compare/v2.8.0...v2.8.1) (2026-03-30) + + +### Bug Fixes + +* bump newspack-scripts version ([#314](https://github.com/Automattic/republication-tracker-tool/issues/314)) ([9a61262](https://github.com/Automattic/republication-tracker-tool/commit/9a61262768ad16508797b08be7ac6bccefe52f34)) +* force release ([e2adf96](https://github.com/Automattic/republication-tracker-tool/commit/e2adf965c8559f02a1e1ef0d89b13aced3ca2c80)) + # [2.8.0](https://github.com/Automattic/republication-tracker-tool/compare/v2.7.0...v2.8.0) (2025-11-24) diff --git a/composer.json b/composer.json index 0a6690f..428865b 100644 --- a/composer.json +++ b/composer.json @@ -4,9 +4,9 @@ "type": "wordpress-plugin", "require-dev": { "composer/installers": "~1.6", - "automattic/vipwpcs": "^2.0.0", + "automattic/vipwpcs": "^3.0", + "wp-coding-standards/wpcs": "^3.0", "brainmaestro/composer-git-hooks": "^2.6", - "wp-coding-standards/wpcs": "*", "dealerdirect/phpcodesniffer-composer-installer": "*", "phpcompatibility/phpcompatibility-wp": "*", "phpunit/phpunit": "^9.6", @@ -37,4 +37,4 @@ "dealerdirect/phpcodesniffer-composer-installer": true } } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index cfa86b4..33703ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,36 +4,37 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "08ee5aa2ed591da1635cd521d22288f6", + "content-hash": "db45f7c00252d6e2846a50e7ccad4aad", "packages": [], "packages-dev": [ { "name": "automattic/vipwpcs", - "version": "2.3.4", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/Automattic/VIP-Coding-Standards.git", - "reference": "b8610e3837f49c5f2fcc4b663b6c0a7c9b3509b6" + "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/b8610e3837f49c5f2fcc4b663b6c0a7c9b3509b6", - "reference": "b8610e3837f49c5f2fcc4b663b6c0a7c9b3509b6", + "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/2b1d206d81b74ed999023cffd924f862ff2753c8", + "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", "php": ">=5.4", - "sirbrillig/phpcs-variable-analysis": "^2.11.17", - "squizlabs/php_codesniffer": "^3.7.1", - "wp-coding-standards/wpcs": "^2.3" + "phpcsstandards/phpcsextra": "^1.2.1", + "phpcsstandards/phpcsutils": "^1.0.11", + "sirbrillig/phpcs-variable-analysis": "^2.11.18", + "squizlabs/php_codesniffer": "^3.9.2", + "wp-coding-standards/wpcs": "^3.1.0" }, "require-dev": { "php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-parallel-lint": "^1.3.2", "phpcompatibility/php-compatibility": "^9", "phpcsstandards/phpcsdevtools": "^1.0", - "phpunit/phpunit": "^4 || ^5 || ^6 || ^7" + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7 || ^8 || ^9" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -58,7 +59,7 @@ "source": "https://github.com/Automattic/VIP-Coding-Standards", "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" }, - "time": "2023-08-24T15:11:13+00:00" + "time": "2024-05-10T20:31:09+00:00" }, { "name": "brainmaestro/composer-git-hooks", @@ -286,29 +287,29 @@ }, { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.1.2", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1" + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1", - "reference": "e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1", + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1", "shasum": "" }, "require": { "composer-plugin-api": "^2.2", "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", @@ -378,7 +379,7 @@ "type": "thanks_dev" } ], - "time": "2025-07-17T20:45:56+00:00" + "time": "2025-11-11T04:32:07+00:00" }, { "name": "doctrine/instantiator", @@ -452,16 +453,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.3", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", - "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -500,7 +501,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -508,20 +509,20 @@ "type": "tidelift" } ], - "time": "2025-07-05T12:25:42+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nikic/php-parser", - "version": "v5.5.0", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -540,7 +541,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -564,9 +565,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-05-31T08:24:38+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", @@ -750,16 +751,16 @@ }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", "shasum": "" }, "require": { @@ -816,22 +817,26 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:30:46+00:00" + "time": "2025-09-19T17:43:28+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.7", + "version": "2.1.8", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "5bfbbfbabb3df2b9a83e601de9153e4a7111962c" + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/5bfbbfbabb3df2b9a83e601de9153e4a7111962c", - "reference": "5bfbbfbabb3df2b9a83e601de9153e4a7111962c", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa", "shasum": "" }, "require": { @@ -893,7 +898,182 @@ "type": "thanks_dev" } ], - "time": "2025-05-12T16:38:37+00:00" + "time": "2025-10-18T00:05:59+00:00" + }, + { + "name": "phpcsstandards/phpcsextra", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "b598aa890815b8df16363271b659d73280129101" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101", + "reference": "b598aa890815b8df16363271b659d73280129101", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.2.0", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" + } + ], + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-12T23:06:57+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-12-08T14:27:58+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1216,16 +1396,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.23", + "version": "9.6.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", "shasum": "" }, "require": { @@ -1236,7 +1416,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.1", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -1247,11 +1427,11 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", + "sebastian/comparator": "^4.0.10", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", + "sebastian/exporter": "^4.0.8", + "sebastian/global-state": "^5.0.8", "sebastian/object-enumerator": "^4.0.4", "sebastian/resource-operations": "^3.0.4", "sebastian/type": "^3.2.1", @@ -1299,7 +1479,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.23" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" }, "funding": [ { @@ -1323,7 +1503,7 @@ "type": "tidelift" } ], - "time": "2025-05-02T06:40:34+00:00" + "time": "2026-01-27T05:45:00+00:00" }, { "name": "psr/container", @@ -1547,16 +1727,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", "shasum": "" }, "require": { @@ -1609,15 +1789,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2026-01-24T09:22:56+00:00" }, { "name": "sebastian/complexity", @@ -1807,16 +1999,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -1872,28 +2064,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", "shasum": "" }, "require": { @@ -1936,15 +2140,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2025-08-10T07:10:35+00:00" }, { "name": "sebastian/lines-of-code", @@ -2117,16 +2333,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", "shasum": "" }, "require": { @@ -2168,15 +2384,27 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2025-08-10T06:57:39+00:00" }, { "name": "sebastian/resource-operations", @@ -2343,28 +2571,27 @@ }, { "name": "sirbrillig/phpcs-variable-analysis", - "version": "v2.12.0", + "version": "v2.13.0", "source": { "type": "git", "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", - "reference": "4debf5383d9ade705e0a25121f16c3fecaf433a7" + "reference": "a15e970b8a0bf64cfa5e86d941f5e6b08855f369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/4debf5383d9ade705e0a25121f16c3fecaf433a7", - "reference": "4debf5383d9ade705e0a25121f16c3fecaf433a7", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/a15e970b8a0bf64cfa5e86d941f5e6b08855f369", + "reference": "a15e970b8a0bf64cfa5e86d941f5e6b08855f369", "shasum": "" }, "require": { "php": ">=5.4.0", - "squizlabs/php_codesniffer": "^3.5.6" + "squizlabs/php_codesniffer": "^3.5.7 || ^4.0.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", - "phpcsstandards/phpcsdevcs": "^1.1", - "phpstan/phpstan": "^1.7", + "phpstan/phpstan": "^1.7 || ^2.0", "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0 || ^10.5.32 || ^11.3.3", - "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0" + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0 || ^6.0 || ^7.0" }, "type": "phpcodesniffer-standard", "autoload": { @@ -2396,20 +2623,20 @@ "source": "https://github.com/sirbrillig/phpcs-variable-analysis", "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" }, - "time": "2025-03-17T16:17:38+00:00" + "time": "2025-09-30T22:22:48+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.13.2", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "5b5e3821314f947dd040c70f7992a64eac89025c" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5b5e3821314f947dd040c70f7992a64eac89025c", - "reference": "5b5e3821314f947dd040c70f7992a64eac89025c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -2426,11 +2653,6 @@ "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -2480,7 +2702,7 @@ "type": "thanks_dev" } ], - "time": "2025-06-17T22:17:01+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "symfony/console", @@ -2650,7 +2872,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2709,7 +2931,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -2720,6 +2942,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2729,16 +2955,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -2787,7 +3013,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -2798,16 +3024,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -2868,7 +3098,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -2879,6 +3109,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2888,7 +3122,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -2949,7 +3183,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -2960,6 +3194,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2969,7 +3207,7 @@ }, { "name": "symfony/polyfill-php73", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", @@ -3025,7 +3263,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" }, "funding": [ { @@ -3036,6 +3274,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3045,7 +3287,7 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -3105,7 +3347,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -3116,6 +3358,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3125,16 +3371,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -3188,7 +3434,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -3199,25 +3445,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", - "version": "v6.4.21", + "version": "v6.4.30", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" + "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", - "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", + "url": "https://api.github.com/repos/symfony/string/zipball/50590a057841fa6bf69d12eceffce3465b9e32cb", + "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb", "shasum": "" }, "require": { @@ -3231,7 +3481,6 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", "symfony/http-client": "^5.4|^6.0|^7.0", "symfony/intl": "^6.2|^7.0", "symfony/translation-contracts": "^2.5|^3.0", @@ -3274,7 +3523,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.21" + "source": "https://github.com/symfony/string/tree/v6.4.30" }, "funding": [ { @@ -3285,25 +3534,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-18T15:23:29+00:00" + "time": "2025-11-21T18:03:05+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -3332,7 +3585,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -3340,34 +3593,42 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "wp-coding-standards/wpcs", - "version": "2.3.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "7da1894633f168fe244afc6de00d141f27517b62" + "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", - "reference": "7da1894633f168fe244afc6de00d141f27517b62", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7795ec6fa05663d716a549d0b44e47ffc8b0d4a6", + "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6", "shasum": "" }, "require": { - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.3.1" + "ext-filter": "*", + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", + "php": ">=7.2", + "phpcsstandards/phpcsextra": "^1.5.0", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.4" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", - "phpcompatibility/php-compatibility": "^9.0", - "phpcsstandards/phpcsdevtools": "^1.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^10.0.0@dev", + "phpcsstandards/phpcsdevtools": "^1.2.0", + "phpunit/phpunit": "^8.0 || ^9.0" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + "ext-iconv": "For improved results", + "ext-mbstring": "For improved results" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -3384,6 +3645,7 @@ "keywords": [ "phpcs", "standards", + "static analysis", "wordpress" ], "support": { @@ -3391,7 +3653,13 @@ "source": "https://github.com/WordPress/WordPress-Coding-Standards", "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" }, - "time": "2020-05-13T23:57:56+00:00" + "funding": [ + { + "url": "https://opencollective.com/php_codesniffer", + "type": "custom" + } + ], + "time": "2025-11-25T12:08:04+00:00" }, { "name": "yoast/phpunit-polyfills", @@ -3459,11 +3727,11 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": {}, - "platform-dev": {}, + "platform": [], + "platform-dev": [], "platform-overrides": { "php": "8.3" }, diff --git a/docs/img/google-analytics-segment-settings.png b/docs/img/google-analytics-segment-settings.png index 7318085..c05b12a 100644 Binary files a/docs/img/google-analytics-segment-settings.png and b/docs/img/google-analytics-segment-settings.png differ diff --git a/docs/tracking-republished-posts.md b/docs/tracking-republished-posts.md index 56030d2..f4e57d1 100644 --- a/docs/tracking-republished-posts.md +++ b/docs/tracking-republished-posts.md @@ -12,13 +12,28 @@ Metrics for republished/shared posts are tracked as `page_view` events in Google - `page_referrer`: URL where the post was republished (ex: https://nytimes.com/story-1) - `page_title`: Title of the page where the post was republished (ex: Story Title) +## Register Custom Dimensions in GA4 + +Before you can use `shared_post_url` in Explorations, you must register it as a custom dimension in your GA4 property. Without this step, events will still be collected in GA4, but the `shared_post_url` parameter won't be available in your reports. +1. In Google Analytics, go to **Admin** (gear icon) → **Data display** → **Custom dimensions**. +2. Click **Create custom dimension** with the following settings: + +| Dimension name | Scope | Event parameter | +|---|---|---| +| `shared_post_url` | Event | `shared_post_url` | + +3. Make sure the **Scope** is set to **Event** (not User). +4. Click **Save** to create the custom dimension. + +> **Note:** Custom dimensions only apply to data collected **after** they are registered. Historical event data will not retroactively include this dimension. + ## See How Stories are Performing In order to see how stories are performing, you’ll need to log into your Google Analytics account. Once logged into your dashboard, select the “Explore” tab on the left sidebar. Once the “Explore” pane opens up, select “Blank” to create a new Exploration report. ![google analytics new exploration](img/google-analytics-new-exploration.png) -Once inside the new Exploration, you'll need to add a Segment of users to analyze, and Dimensions and Metrics to display. To view a report of articles that were shared via this plugin, click the + button next to the Segments panel and create a new User segment. Add a new Condition with a `shared_post_url` containing part or all of the URL of the post you want to view metrics for. +Once inside the new Exploration, you'll need to add a segment, dimensions, and metrics. To view a report of articles that were shared via this plugin, click the + button next to the Segments panel and create a new **Event segment**. Add a new Condition with a `shared_post_url` containing part or all of the URL of the post you want to view metrics for. Here you can enter a value that will return multiple articles (such as your root domain or a category slug to view all republished articles on the site or in a specific category) or a particular story (such as the post slug for the story). @@ -39,7 +54,7 @@ In the Settings column, you can choose Visualization options. For example, to vi - Technique: Free form - Visualization: Table -- Segment Comparisons: Your user segment as created above +- Segment Comparisons: Your event segment as created above - Rows: Page location - Columns: Page referrer (this will show each shared URL in its own column of the report) - Values: Event count diff --git a/includes/class-article-settings.php b/includes/class-article-settings.php index ab7e73e..5a2fe08 100644 --- a/includes/class-article-settings.php +++ b/includes/class-article-settings.php @@ -74,14 +74,13 @@ public function register_meta_boxes() { '__block_editor_compatible_meta_box' => true, ) ); - } /** * Save the value of the hide widget metabox checkbox * * @since 1.0.2 - * @param int $post_id The post ID + * @param int $post_id The post ID. */ public function save_hide_widget_metabox( $post_id ) { @@ -89,11 +88,11 @@ public function save_hide_widget_metabox( $post_id ) { return; } - if ( ! isset( $_POST['republication-tracker-tool-hide-widget-submit'] ) ) { + if ( ! isset( $_POST['republication-tracker-tool-hide-widget-submit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return; } - if ( isset( $_POST['republication-tracker-tool-hide-widget'] ) ) { + if ( isset( $_POST['republication-tracker-tool-hide-widget'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing update_post_meta( $post_id, 'republication-tracker-tool-hide-widget', true ); @@ -102,15 +101,14 @@ public function save_hide_widget_metabox( $post_id ) { update_post_meta( $post_id, 'republication-tracker-tool-hide-widget', false ); } - } /** - * Render a custom metabox + * Render a custom metabox. * * @since 1.0 - * @param obj $post Post object. - * @param obj $args Arguments object. + * @param WP_Post $post Post object. + * @param array $args Arguments object. */ public function render_metabox( $post, $args ) { $shares = get_post_meta( $post->ID, 'republication_tracker_tool_sharing', true ); @@ -124,12 +122,12 @@ public function render_metabox( $post, $args ) { if ( is_array( $shares ) && ! empty( $shares ) ) { echo ''; echo ''; - echo sprintf( '', esc_html__( 'Republished URL', 'republication-tracker-tool' ) ); - echo sprintf( '', esc_html__( 'Views', 'republication-tracker-tool' ) ); + printf( '', esc_html__( 'Republished URL', 'republication-tracker-tool' ) ); + printf( '', esc_html__( 'Views', 'republication-tracker-tool' ) ); echo ''; echo ''; foreach ( $shares as $url => $count ) { - echo sprintf( + printf( '', wp_kses_post( $url ), wp_kses_post( $count ) @@ -137,8 +135,8 @@ public function render_metabox( $post, $args ) { } echo ''; echo ''; - echo sprintf( '', esc_html__( 'Republished URL', 'republication-tracker-tool' ) ); - echo sprintf( '', esc_html__( 'Views', 'republication-tracker-tool' ) ); + printf( '', esc_html__( 'Republished URL', 'republication-tracker-tool' ) ); + printf( '', esc_html__( 'Views', 'republication-tracker-tool' ) ); echo ''; echo '
%s%s%s%s
%1$s%2$s
%s%s%s%s
'; } else { @@ -174,24 +172,41 @@ public function render_hide_widget_metabox( $post, $args ) { echo ''; } - } + /** + * Add custom columns to the post list table. + * + * @param array $columns The columns. + * @return array The columns. + */ public function add_custom_columns( $columns ) { $columns['republication_tracker_tool'] = esc_html__( 'Total Views', 'republication-tracker-tool' ); return $columns; } + /** + * Add sortable columns to the post list table. + * + * @param array $columns The columns. + * @return array The columns. + */ public function add_sortable_columns( $columns ) { $columns['republication_tracker_tool'] = esc_html__( 'Total Views', 'republication-tracker-tool' ); return $columns; } + /** + * Display the content of the custom columns in the post list table. + * + * @param string $column The column name. + * @param int $post_id The post ID. + */ public function custom_column_content( $column, $post_id ) { switch ( $column ) { case 'republication_tracker_tool': @@ -202,7 +217,7 @@ public function custom_column_content( $column, $post_id ) { $total_count = $total_count + $count; } } - echo sprintf( '%s', number_format( $total_count ) ); + printf( '%s', number_format( $total_count ) ); break; } } @@ -215,7 +230,7 @@ public function custom_column_content( $column, $post_id ) { * @param bool $update Whether this is an existing post being updated. */ public function apply_default_post_distribution( $post_id, $post, $update ) { - // Only apply to new posts + // Only apply to new posts. if ( ! $update && 'post' === $post->post_type ) { $default_post_distribution = get_option( 'republication_tracker_tool_default_post_distribution', 'off' ); @@ -224,5 +239,4 @@ public function apply_default_post_distribution( $post_id, $post, $update ) { } } } - } diff --git a/includes/class-content.php b/includes/class-content.php index 33dc633..e2c9fba 100644 --- a/includes/class-content.php +++ b/includes/class-content.php @@ -27,7 +27,7 @@ public static function get_republishable_content( $content, $post_id = false, $e // Remove shortcodes from the content. $content = strip_shortcodes( $content ); - // Remove comments from the content. (Lookin' at you, Gutenberg.) + // Remove comments from the content (Lookin' at you, Gutenberg). $content = preg_replace( '//i', ' ', $content ); // Remove scripts from the content. @@ -37,7 +37,7 @@ public static function get_republishable_content( $content, $post_id = false, $e * What tags do we want to keep in the embed? * Not things from our server. * - * Generall: wp_kses_post, but not allowing the terms listed below because + * Generally: wp_kses_post, but not allowing the terms listed below because: * - they're referencing assets on our server: audio, figure, img, track, video * - they're referencing the referenced asset: figure, figcaption * - they're not likely to work: form, button @@ -70,7 +70,7 @@ public static function get_republishable_content( $content, $post_id = false, $e // And finally, remove some tags. $content = wp_kses( $content, $allowed_tags_excerpt ); - // remove spare p tags and clean up these paragraphs + // Remove spare p tags and clean up these paragraphs. $content = str_replace( '

', '', wpautop( $content ) ); // Remove non-distributable images. @@ -137,35 +137,35 @@ public static function get_republishable_plain_text_content( $post_object ) { return ''; } - // Start building the plain text content + // Start building the plain text content. $plain_text_content = ''; - // Get article metadata + // Get article metadata. $article_title = get_the_title( $post_object ); $author_byline = sprintf( '%1$s, %2$s', apply_filters( 'republication_tracker_tool_byline', __( 'By ', 'republication-tracker-tool' ) . get_the_author_meta( 'display_name', $post_object->post_author ) ), get_bloginfo( 'name' ) ); - $article_date = date( 'F j, Y', strtotime( $post_object->post_date ) ); + $article_date = gmdate( 'F j, Y', strtotime( $post_object->post_date ) ); - // Add the article title + // Add the article title. if ( ! empty( $article_title ) ) { $plain_text_content .= $article_title . "\n\n"; } - // Add the author byline (strip HTML tags) + // Add the author byline (strip HTML tags). if ( ! empty( $author_byline ) ) { $plain_text_content .= wp_strip_all_tags( $author_byline ) . "\n"; } - // Add the article date + // Add the article date. if ( ! empty( $article_date ) ) { $plain_text_content .= $article_date . "\n\n"; } - // Process the main content + // Process the main content. if ( ! empty( $post_object->post_content ) ) { - // Get HTML content without escaping for plain text conversion + // Get HTML content without escaping for plain text conversion. $html_content = self::get_republishable_content( $post_object->post_content, $post_object->ID, false ); - // Convert HTML to plain text + // Convert HTML to plain text. $plain_content = self::convert_html_to_plain_text( $html_content ); $plain_text_content .= $plain_content . "\n\n"; @@ -206,29 +206,29 @@ private static function convert_html_to_plain_text( $html_content ) { $html_content = preg_replace( '//i', "\n", $html_content ); $html_content = preg_replace( '/]*?>.*?<\/style>/si', '', $html_content ); - // ul to bullet points + // ul to bullet points. $html_content = preg_replace_callback( '/]*>(.*?)<\/ul>/is', function( $matches ) { $list_content = $matches[1]; - // Convert each list item to a bullet point + // Convert each list item to a bullet point. $list_content = preg_replace( '/]*>(.*?)<\/li>/is', "• $1\n", $list_content ); return "\n" . $list_content . "\n"; }, $html_content ); - // ol to numbered points + // ol to numbered points. $html_content = preg_replace_callback( '/]*>(.*?)<\/ol>/is', function( $matches ) { $list_content = $matches[1]; $counter = 1; - // Convert each list item to a numbered point + // Convert each list item to a numbered point. $list_content = preg_replace_callback( '/]*>(.*?)<\/li>/is', function( $item_matches ) use ( &$counter ) { - return $counter++ . ". " . $item_matches[1] . "\n"; + return ( $counter++ ) . '. ' . $item_matches[1] . "\n"; }, $list_content ); @@ -237,13 +237,13 @@ function( $item_matches ) use ( &$counter ) { $html_content ); - // Handle tags containing information + // Handle tags containing information. $html_content = preg_replace( '/]*>(.*?)<\/blockquote>/is', "\n> $1\n\n", $html_content ); $html_content = preg_replace( '/]*>(.*?)<\/a>/is', '$1', $html_content ); $html_content = preg_replace( '/<(strong|b)[^>]*>(.*?)<\/\1>/is', '$2', $html_content ); $html_content = preg_replace( '/<(em|i)[^>]*>(.*?)<\/\1>/is', '$2', $html_content ); - // Remove all remaining HTML tags + // Remove all remaining HTML tags. $plain_text = wp_strip_all_tags( $html_content ); $plain_text = preg_replace( '/\n\s*\n\s*\n/', "\n\n", $plain_text ); $plain_text = preg_replace( '/[ \t]+/', ' ', $plain_text ); diff --git a/includes/class-republication-rewrite.php b/includes/class-republication-rewrite.php index 1810bcf..9a7ece3 100644 --- a/includes/class-republication-rewrite.php +++ b/includes/class-republication-rewrite.php @@ -73,7 +73,7 @@ public function filter_template_include( $template ) { if ( function_exists( 'wpcom_vip_url_to_postid' ) ) { $post_id = wpcom_vip_url_to_postid( $endpoint ); } else { - $post_id = url_to_postid( $endpoint ); + $post_id = url_to_postid( $endpoint ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid } // If there is no post ID then redirect to 404. @@ -161,7 +161,7 @@ public function enqueue_scripts_and_styles() { REPUBLICATION_TRACKER_TOOL_VERSION ); - // Enqueue the clipboard utility first + // Enqueue the clipboard utility first. wp_enqueue_script( 'republication-tracker-tool-clipboard-utils', REPUBLICATION_TRACKER_TOOL_URL . 'assets/clipboard-utils.js', diff --git a/includes/class-settings.php b/includes/class-settings.php index 1fd6136..def8a9b 100644 --- a/includes/class-settings.php +++ b/includes/class-settings.php @@ -114,9 +114,12 @@ public function create_settings() { } } + /** + * Republication Tracker Tool section callback. + */ public function republication_tracker_tool_section_callback() { - // if our republication_tracker_tool_analytics_id field has been set and is not empty, let's display - // a sample tracking code for users to manually input into articles + // If our republication_tracker_tool_analytics_id field has been set and is not empty, let's display + // a sample tracking code for users to manually input into articles. if ( ! empty( get_option( 'republication_tracker_tool_analytics_ga4_id', false ) ) && ! empty( get_option( 'republication_tracker_tool_analytics_ga4_secret', false ) ) ) { $pixel = Republication_Tracker_Tool::create_tracking_pixel_markup( 'YOUR-POST-ID' ); printf( @@ -142,16 +145,19 @@ public function republication_tracker_tool_section_callback() { */ public function republication_tracker_additional_tracking_code_callback() { $content = html_entity_decode( get_option( 'republication_tracker_additional_tracking_code' ) ); - echo sprintf( '

%s

', wp_kses_post( __( 'Use placeholders: {{post-id}} will be replaced with the post ID, and {{post-url}} will be replaced with the post URL.', 'republication-tracker-tool' ) ) ); - echo sprintf( + printf( '

%s

', wp_kses_post( __( 'Use placeholders: {{post-id}} will be replaced with the post ID, and {{post-url}} will be replaced with the post URL.', 'republication-tracker-tool' ) ) ); + printf( '', 'republication_tracker_additional_tracking_code', esc_textarea( $content ) ); - echo sprintf( '

%s

', wp_kses_post( __( 'The additional Tracking Code field is where you will be able to input your additional tracking code that will be appended to your copied content.', 'republication-tracker-tool' ) ) ); - echo sprintf( '

%s

', wp_kses_post( __( 'Allowed HTML: script, img, iframe, noscript, div, span, p with safe attributes only.', 'republication-tracker-tool' ) ) ); + printf( '

%s

', wp_kses_post( __( 'The additional Tracking Code field is where you will be able to input your additional tracking code that will be appended to your copied content.', 'republication-tracker-tool' ) ) ); + printf( '

%s

', wp_kses_post( __( 'Allowed HTML: script, img, iframe, noscript, div, span, p with safe attributes only.', 'republication-tracker-tool' ) ) ); } + /** + * Republication Tracker Tool policy callback. + */ public function republication_tracker_tool_policy_callback() { $content = get_option( 'republication_tracker_tool_policy' ); wp_editor( @@ -168,6 +174,9 @@ public function republication_tracker_tool_policy_callback() { printf( '

%s

', wp_kses_post( __( 'The Republication Tracker Tool Policy field is where you will be able to input your rules and policies for users to see before they copy and paste your content to republish.As an example of a republication policy hat uses a Creative Commons license, check out the list in this plugin\'s documentation on GitHub.', 'republication-tracker-tool' ) ) ); } + /** + * Republication Tracker Tool analytics ID callback. + */ public function republication_tracker_tool_analytics_id_callback() { $content = get_option( 'republication_tracker_tool_analytics_id' ); printf( @@ -178,6 +187,9 @@ public function republication_tracker_tool_analytics_id_callback() { ); } + /** + * Republication Tracker Tool analytics GA4 ID callback. + */ public function republication_tracker_tool_analytics_ga4_id_callback() { $content = get_option( 'republication_tracker_tool_analytics_ga4_id' ); printf( @@ -188,6 +200,9 @@ public function republication_tracker_tool_analytics_ga4_id_callback() { ); } + /** + * Republication Tracker Tool analytics GA4 secret callback. + */ public function republication_tracker_tool_analytics_ga4_secret_callback() { $content = get_option( 'republication_tracker_tool_analytics_ga4_secret' ); printf( @@ -198,6 +213,9 @@ public function republication_tracker_tool_analytics_ga4_secret_callback() { ); } + /** + * Republication Tracker Tool display attribution callback. + */ public function republication_tracker_tool_display_attribution_callback() { $display_attribution = get_option( 'republication_tracker_tool_display_attribution', 'on' ); ?> @@ -213,6 +231,9 @@ public function republication_tracker_tool_display_attribution_callback() { @@ -231,6 +252,9 @@ public function republication_tracker_tool_media_distribution_callback() { @@ -249,6 +273,9 @@ public function republication_tracker_tool_default_attachment_distribution_callb checked @@ -293,6 +320,9 @@ public function republication_tracker_tool_license_callback() { @@ -308,6 +338,9 @@ public function republication_tracker_tool_default_post_distribution_callback() diff --git a/includes/class-widget.php b/includes/class-widget.php index e833146..90056cb 100644 --- a/includes/class-widget.php +++ b/includes/class-widget.php @@ -13,10 +13,15 @@ */ class Republication_Tracker_Tool_Widget extends WP_Widget { + /** + * Whether the widget has been instantiated. + * + * @var bool + */ public $has_instance = false; /** - * Sets up the widgets name etc + * Sets up the widgets name etc. */ public function __construct() { $widget_ops = array( @@ -27,7 +32,7 @@ public function __construct() { } /** - * Outputs the content of the widget + * Outputs the content of the widget. * * If this is not a single post, don't output the widget. It won't work outside single posts. * @@ -45,11 +50,11 @@ public function widget( $args, $instance ) { $using_license = isset( REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ] ); - // our post `republication-tracker-tool-hide-widget` meta is our default filter value + // our post `republication-tracker-tool-hide-widget` meta is our default filter value. $hide_republication_widget_on_post = apply_filters( 'hide_republication_widget', get_post_meta( $post->ID, 'republication-tracker-tool-hide-widget', true ), $post ); - // if `republication-tracker-tool-hide-widget` meta is set to true, don't show the shareable content widget - // OR if the `hide_republication_widget` filter is set to true, don't show the shareable content widget + // if `republication-tracker-tool-hide-widget` meta is set to true, don't show the shareable content widget. + // OR if the `hide_republication_widget` filter is set to true, don't show the shareable content widget. if ( true == $hide_republication_widget_on_post ) { return; } @@ -57,10 +62,10 @@ public function widget( $args, $instance ) { $is_amp = self::is_amp(); if ( ! $is_amp ) { - wp_enqueue_script( 'republication-tracker-tool-clipboard-utils', plugins_url( 'assets/clipboard-utils.js', dirname( __FILE__ ) ), array(), filemtime( plugin_dir_path( __FILE__ ) ), false ); - wp_enqueue_script( 'republication-tracker-tool-js', plugins_url( 'assets/widget.js', dirname( __FILE__ ) ), array( 'jquery', 'republication-tracker-tool-clipboard-utils' ), filemtime( plugin_dir_path( __FILE__ ) ), false ); + wp_enqueue_script( 'republication-tracker-tool-clipboard-utils', plugins_url( 'assets/clipboard-utils.js', __DIR__ ), array(), filemtime( plugin_dir_path( __FILE__ ) ), false ); + wp_enqueue_script( 'republication-tracker-tool-js', plugins_url( 'assets/widget.js', __DIR__ ), array( 'jquery', 'republication-tracker-tool-clipboard-utils' ), filemtime( plugin_dir_path( __FILE__ ) ), false ); } - wp_enqueue_style( 'republication-tracker-tool-css', plugins_url( 'assets/widget.css', dirname( __FILE__ ) ), array(), filemtime( plugin_dir_path(__FILE__) ) ); + wp_enqueue_style( 'republication-tracker-tool-css', plugins_url( 'assets/widget.css', __DIR__ ), array(), filemtime( plugin_dir_path( __FILE__ ) ) ); echo wp_kses_post( $args['before_widget'] ); @@ -71,45 +76,45 @@ public function widget( $args, $instance ) { echo '
'; if ( empty( $instance['layout'] ) || 'modal' === $instance['layout'] ) { - echo sprintf( + printf( '

', esc_html__( 'Republish This Story', 'republication-tracker-tool' ) ); } - if ( ! empty($instance['layout']) && 'page' === $instance['layout'] ) { - echo sprintf( + if ( ! empty( $instance['layout'] ) && 'page' === $instance['layout'] ) { + printf( '

', esc_html__( 'Republish This Story', 'republication-tracker-tool' ), - esc_url( '/republish' . $_SERVER['REQUEST_URI'] ) + esc_url( '/republish' . ( isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' ) ) ); } if ( $using_license ) { - echo sprintf( + printf( '

%s

', - REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['url'], + esc_url( REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['url'] ), esc_html__( 'Creative Commons License', 'republication-tracker-tool' ), - esc_url( plugin_dir_url( dirname( __FILE__ ) ) ) . 'assets/img/' . $license_key . '.png' + esc_url( plugin_dir_url( __DIR__ ) ) . 'assets/img/' . esc_attr( $license_key ) . '.png' ); } echo '
'; - echo sprintf( + printf( '
%s
', wp_kses_post( wpautop( esc_html( $instance['text'] ) ) ) ); echo wp_kses_post( $args['after_widget'] ); - // if has_instance is false, we can continue with displaying the modal + // if has_instance is false, we can continue with displaying the modal. if ( isset( $this->has_instance ) && false === $this->has_instance ) { - // update has_instance so the next time the widget is created on the same page, it does not create a second modal + // update has_instance so the next time the widget is created on the same page, it does not create a second modal. $this->has_instance = true; - // define our path to grab file content from + // define our path to grab file content from. $modal_content_path = plugin_dir_path( __FILE__ ) . 'shareable-content.php'; if ( $is_amp ) { @@ -129,30 +134,30 @@ public function widget( $args, $instance ) { } /** - * Outputs the options form on admin + * Outputs the options form on admin. * * @param array $instance The widget options. */ public function form( $instance ) { - echo sprintf( '

%s

', esc_html__( 'This widget will only display on single articles.', 'republication-tracker-tool' ) ); - $title = ! empty( $instance['title'] ) ? $instance['title'] : ''; - $text = ! empty( $instance['text'] ) ? $instance['text'] : esc_html__( 'Republish our articles for free, online or in print, under a Creative Commons license.', 'republication-tracker-tool' ); + printf( '

%s

', esc_html__( 'This widget will only display on single articles.', 'republication-tracker-tool' ) ); + $title = ! empty( $instance['title'] ) ? $instance['title'] : ''; + $text = ! empty( $instance['text'] ) ? $instance['text'] : esc_html__( 'Republish our articles for free, online or in print, under a Creative Commons license.', 'republication-tracker-tool' ); $layout = ! empty( $instance['layout'] ) ? $instance['layout'] : 'modal' ?>

- +

- +

@@ -177,6 +182,11 @@ public function update( $new_instance, $old_instance ) { return $instance; } + /** + * Checks if the current page is an AMP endpoint. + * + * @return bool + */ public static function is_amp() { return function_exists( 'is_amp_endpoint' ) && is_amp_endpoint(); } diff --git a/includes/compatibility-co-authors-plus.php b/includes/compatibility-co-authors-plus.php index 737e1e1..2a4dde0 100644 --- a/includes/compatibility-co-authors-plus.php +++ b/includes/compatibility-co-authors-plus.php @@ -4,6 +4,7 @@ * * @link https://wpvip.com/plugins/co-authors-plus/ * @link https://github.com/Automattic/Co-Authors-Plus + * @package Republication_Tracker_Tool */ /** @@ -14,7 +15,7 @@ * * @link https://github.com/Automattic/Co-Authors-Plus/blob/3.4.3/php/class-coauthors-template-filters.php#L18-L20 the filter that does not trigger * - * @param String $author_string The string returned by get_the_author + * @param String $author_string The string returned by get_the_author. * @since Co-Authors Plus 3.4.3 * @uses coauthors https://github.com/Automattic/Co-Authors-Plus/blob/3.4.3/template-tags.php#L210-L227 * @return String the plain-text byline diff --git a/includes/licenses.php b/includes/licenses.php index 11ea703..e5a1e1d 100644 --- a/includes/licenses.php +++ b/includes/licenses.php @@ -1,47 +1,59 @@ [ - 'label' => 'CC BY 4.0', + 'cc-by-4.0' => [ + 'label' => 'CC BY 4.0', 'description' => 'Creative Commons Attribution 4.0 International License', - 'url' => 'https://creativecommons.org/licenses/by/4.0/', - 'badge' => 'https://licensebuttons.net/l/by/4.0/88x31.png' + 'url' => 'https://creativecommons.org/licenses/by/4.0/', + 'badge' => 'https://licensebuttons.net/l/by/4.0/88x31.png', ], - 'cc-by-sa-4.0' => [ - 'label' => 'CC BY-SA 4.0', + 'cc-by-sa-4.0' => [ + 'label' => 'CC BY-SA 4.0', 'description' => 'Creative Commons Attribution-ShareAlike 4.0 International License', - 'url' => 'https://creativecommons.org/licenses/by-sa/4.0/', - 'badge' => 'https://licensebuttons.net/l/by-sa/4.0/88x31.png' + 'url' => 'https://creativecommons.org/licenses/by-sa/4.0/', + 'badge' => 'https://licensebuttons.net/l/by-sa/4.0/88x31.png', ], - 'cc-by-nc-4.0' => [ - 'label' => 'CC BY-NC 4.0', + 'cc-by-nc-4.0' => [ + 'label' => 'CC BY-NC 4.0', 'description' => 'Creative Commons Attribution-NonCommercial 4.0 International License', - 'url' => 'https://creativecommons.org/licenses/by-nc/4.0/', - 'badge' => 'https://licensebuttons.net/l/by-nc/4.0/88x31.png' + 'url' => 'https://creativecommons.org/licenses/by-nc/4.0/', + 'badge' => 'https://licensebuttons.net/l/by-nc/4.0/88x31.png', ], - 'cc-by-nc-sa-4.0' => [ - 'label' => 'CC BY-NC-SA 4.0', + 'cc-by-nc-sa-4.0' => [ + 'label' => 'CC BY-NC-SA 4.0', 'description' => 'Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License', - 'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/', - 'badge' => 'https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png' + 'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/', + 'badge' => 'https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png', ], REPUBLICATION_TRACKER_TOOL_DEFAULT_LICENSE => [ - 'label' => 'CC BY-ND 4.0', + 'label' => 'CC BY-ND 4.0', 'description' => 'Creative Commons Attribution-NoDerivatives 4.0 International License', - 'url' => 'https://creativecommons.org/licenses/by-nd/4.0/', - 'badge' => 'https://licensebuttons.net/l/by-nd/4.0/88x31.png' + 'url' => 'https://creativecommons.org/licenses/by-nd/4.0/', + 'badge' => 'https://licensebuttons.net/l/by-nd/4.0/88x31.png', ], - 'cc-by-nc-nd-4.0' => [ - 'label' => 'CC BY-NC-ND 4.0', + 'cc-by-nc-nd-4.0' => [ + 'label' => 'CC BY-NC-ND 4.0', 'description' => 'Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License', - 'url' => 'https://creativecommons.org/licenses/by-nc-nd/4.0/', - 'badge' => 'https://licensebuttons.net/l/by-nc-nd/4.0/88x31.png' + 'url' => 'https://creativecommons.org/licenses/by-nc-nd/4.0/', + 'badge' => 'https://licensebuttons.net/l/by-nc-nd/4.0/88x31.png', ], - 'cc-zero-1.0' => [ - 'label' => 'CC0 1.0', + 'cc-zero-1.0' => [ + 'label' => 'CC0 1.0', 'description' => 'CC0 1.0 Universal License', - 'url' => 'https://creativecommons.org/publicdomain/zero/1.0/', - 'badge' => 'https://licensebuttons.net/l/zero/1.0/88x31.png' + 'url' => 'https://creativecommons.org/publicdomain/zero/1.0/', + 'badge' => 'https://licensebuttons.net/l/zero/1.0/88x31.png', ], ]; diff --git a/includes/pixel.php b/includes/pixel.php index 163a065..1b294ed 100644 --- a/includes/pixel.php +++ b/includes/pixel.php @@ -1,14 +1,18 @@ post_name ); - $shared_post_permalink = \get_permalink( $shared_post_id ); + $shared_post_permalink = get_permalink( $shared_post_id ); if ( array_key_exists( 'HTTP_REFERER', $_SERVER ) ) { if ( isset( $_SERVER['HTTP_REFERER'] ) ) { - $url = \esc_url_raw( $_SERVER['HTTP_REFERER'] ); + $url = esc_url_raw( $_SERVER['HTTP_REFERER'] ); } - $url_title = \wprtt_get_referring_page_title( $url, $shared_post_id ); + $url_title = wprtt_get_referring_page_title( $url, $shared_post_id ); - $url_host = \wp_parse_url( $url, PHP_URL_HOST ); - $url_path = \wp_parse_url( $url, PHP_URL_PATH ); + $url_host = wp_parse_url( $url, PHP_URL_HOST ); + $url_path = wp_parse_url( $url, PHP_URL_PATH ); } else { @@ -103,7 +106,7 @@ function wprtt_extract_cid_from_cookies() { exit; } - $value = \get_post_meta( $shared_post_id, 'republication_tracker_tool_sharing', true ); + $value = get_post_meta( $shared_post_id, 'republication_tracker_tool_sharing', true ); if ( $value ) { if ( isset( $value[ $url ] ) ) { $value[ $url ]++; @@ -115,16 +118,16 @@ function wprtt_extract_cid_from_cookies() { $url => 1, ); } - $update = \update_post_meta( $shared_post_id, 'republication_tracker_tool_sharing', $value ); + $update = update_post_meta( $shared_post_id, 'republication_tracker_tool_sharing', $value ); // If we have the necessary GA4 info, let's push data to it. // We need both a Measurement ID and an API secret for GA4. // https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#required_parameters. - $ga4_id = \get_option( 'republication_tracker_tool_analytics_ga4_id' ); - $ga4_secret = \get_option( 'republication_tracker_tool_analytics_ga4_secret', false ); + $ga4_id = get_option( 'republication_tracker_tool_analytics_ga4_id' ); + $ga4_secret = get_option( 'republication_tracker_tool_analytics_ga4_secret', false ); - if ( $ga4_id && $ga4_secret && isset( $_GET['ga4'] ) && $_GET['ga4'] === $ga4_id ) { - $base_url = \add_query_arg( + if ( $ga4_id && $ga4_secret && isset( $_GET['ga4'] ) && $_GET['ga4'] === $ga4_id ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $base_url = add_query_arg( [ 'api_secret' => $ga4_secret, 'measurement_id' => $ga4_id, @@ -149,7 +152,7 @@ function wprtt_extract_cid_from_cookies() { ], ]; - \wp_remote_post( + wp_remote_post( $base_url, [ 'body' => wp_json_encode( $payload ), @@ -160,5 +163,5 @@ function wprtt_extract_cid_from_cookies() { header( 'Content-Type: image/png' ); // A transparent 1x1 px .gif image. -echo base64_decode( 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=' ); +echo base64_decode( 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped exit; diff --git a/includes/shareable-content.php b/includes/shareable-content.php index 83b0c75..970307c 100644 --- a/includes/shareable-content.php +++ b/includes/shareable-content.php @@ -6,17 +6,19 @@ * * Expected URLs is something like /wp-content/plugins/republication-tracker-tool/includes/shareable-content.php?post=22078&_=1512494948576 or something * We aren't passing a NONCE; this isn't a form. + * + * @package Republication_Tracker_Tool */ /** - * The article WP_Post object + * The article WP_Post object. * * @var WP_Post $post the post object */ global $post; /** - * The content of the aforementioned post + * The content of the aforementioned post. * * @var HTML $content */ @@ -45,12 +47,12 @@ */ wp_kses_post( apply_filters( 'republication_tracker_tool_byline', get_the_author() ) ), wp_kses_post( get_bloginfo( 'name' ) ), - wp_kses_post( date( 'F j, Y', strtotime( $post->post_date ) ) ) + wp_kses_post( gmdate( 'F j, Y', strtotime( $post->post_date ) ) ) ); // strip empty tags after automatically applying p tags. $article_info = str_replace( '

', '', wpautop( $article_info ) ); -// Check if plain text feature is enabled +// Check if plain text feature is enabled. $plain_text_enabled = Republication_Tracker_Tool_Settings::is_plain_text_enabled(); $plain_text_content = ''; if ( $plain_text_enabled ) { @@ -80,36 +82,36 @@ echo '
'; echo ''; + echo '' . esc_html__( 'Close window', 'republication-tracker-tool' ) . ''; printf( '

%s

', esc_html__( 'Republish this article', 'republication-tracker-tool' ) ); - // Explain Creative Commons + // Explain Creative Commons. echo '
'; echo '
'; - if ( $using_license ) { - printf( '%s', REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['url'], REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['description'], REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['badge'] ); - echo wp_kses_post( - wpautop( - sprintf( - // translators: %1$s is the URL to the particular Creative Commons license. - __( 'This work is licensed under a %2$s.', 'republication-tracker-tool' ), - REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['url'], - REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['description'], - ) - ) - ); - } +if ( $using_license ) { + printf( '%s', esc_url( REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['url'] ), esc_html( REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['description'] ), esc_url( REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['badge'] ) ); + echo wp_kses_post( + wpautop( + sprintf( + // translators: %1$s is the URL to the particular Creative Commons license. + __( 'This work is licensed under a %2$s.', 'republication-tracker-tool' ), + REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['url'], + REPUBLICATION_TRACKER_TOOL_LICENSES[ $license_key ]['description'] + ) + ) + ); +} echo '
'; // .cc-license - echo "

" . wp_kses_post( $license_statement ) . "

"; + echo '

' . wp_kses_post( $license_statement ) . '

'; echo '
'; // .cc-policy - // what we display to the embedder + // What we display to the embedder. echo ''; // .article-info - // the text area that is copyable - ?> + // The text area that is copyable. +?>
@@ -130,7 +132,7 @@ class="republish-content__textarea " - > + >
@@ -143,7 +145,7 @@ class="republish-content__textarea " + value="" aria-label="" /> @@ -177,7 +179,7 @@ class="republish-content__textarea" class="plain-text-field__input" readonly aria-label="" - value="" + value="" /> @@ -274,7 +274,7 @@ class="republish-content__textarea" class="republish-content__input" readonly aria-label="" - value="" + value="" />