diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7f08bc53..fb4d15c4 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -23,6 +23,9 @@ jobs:
- image: quay.io/pantheon-public/build-tools-ci:8.x-php8.2
steps:
- checkout
+ - run:
+ name: Check if we need to run Behat
+ command: ./bin/maybe-skip-tests.sh
- restore_cache:
keys:
- test-behat-dependencies-{{ checksum "composer.json" }}
diff --git a/README.md b/README.md
index 245bba5e..c4e19f7f 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
**Contributors:** [getpantheon](https://profiles.wordpress.org/getpantheon), [danielbachhuber](https://profiles.wordpress.org/danielbachhuber), [kporras07](https://profiles.wordpress.org/kporras07), [jspellman](https://profiles.wordpress.org/jspellman/), [jazzs3quence](https://profiles.wordpress.org/jazzs3quence/), [ryanshoover](https://profiles.wordpress.org/ryanshoover/), [rwagner00](https://profiles.wordpress.org/rwagner00/), [pwtyler](https://profiles.wordpress.org/pwtyler)
**Tags:** pantheon, cdn, cache
-**Requires at least:** 4.7
-**Tested up to:** 6.4.3
-**Stable tag:** 1.5.0-dev
+**Requires at least:** 6.4
+**Tested up to:** 6.5.3
+**Stable tag:** 2.0.0-dev
**License:** GPLv2 or later
**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
@@ -12,7 +12,9 @@ Automatically clear related pages from Pantheon's Edge when you update content.
## Description ##
-[![Actively Maintained](https://img.shields.io/badge/Pantheon-Actively_Maintained-yellow?logo=pantheon&color=FFDC28)](https://pantheon.io/docs/oss-support-levels#actively-maintained-support) [![CircleCI](https://circleci.com/gh/pantheon-systems/pantheon-advanced-page-cache.svg?style=svg)](https://circleci.com/gh/pantheon-systems/pantheon-advanced-page-cache)
+[![Actively Maintained](https://img.shields.io/badge/Pantheon-Actively_Maintained-yellow?logo=pantheon&color=FFDC28)](https://pantheon.io/docs/oss-support-levels#actively-maintained-support)
+[![Lint and Test](https://github.com/pantheon-systems/pantheon-advanced-page-cache/actions/workflows/lint-test.yml/badge.svg)](https://github.com/pantheon-systems/pantheon-advanced-page-cache/actions/workflows/lint-test.yml)
+[![CircleCI](https://circleci.com/gh/pantheon-systems/pantheon-advanced-page-cache.svg?style=svg)](https://circleci.com/gh/pantheon-systems/pantheon-advanced-page-cache)
For sites wanting fine-grained control over how their responses are represented in their edge cache, Pantheon Advanced Page Cache is the golden ticket. Here's a high-level overview of how the plugin works:
@@ -353,7 +355,10 @@ Pantheon Advanced Page Cache integrates with WordPress plugins, including:
See [CONTRIBUTING.md](https://github.com/pantheon-systems/pantheon-advanced-page-cache/blob/master/CONTRIBUTING.md) for information on contributing.
## Changelog ##
-### 1.5.0-dev (March 11, 2024) ###
+### 2.0.0-dev ###
+* Adds new admin alerts and Site Health tests about default cache max-age settings and recommendations [[#268](https://github.com/pantheon-systems/pantheon-advanced-page-cache/pull/268)]. The default Pantheon GCDN cache max-age value has been updated to 1 week in the [Pantheon MU plugin](https://github.com/pantheon-systems/pantheon-mu-plugin). For more information, see the [release note](https://docs.pantheon.io/release-notes/2024/04/pantheon-mu-plugin-1-4-0-update).
+
+### 1.5.0 (March 11, 2024) ###
* Adds filter `pantheon_purge_post_type_ignored` to allow an array of post types to ignore before purging cache [[#258](https://github.com/pantheon-systems/pantheon-advanced-page-cache/pull/258)]
* Adds [wpunit-helpers](https://github.com/pantheon-systems/wpunit-helpers) for running/setting up WP Unit tests
diff --git a/bin/maybe-skip-tests.sh b/bin/maybe-skip-tests.sh
new file mode 100755
index 00000000..c49d309e
--- /dev/null
+++ b/bin/maybe-skip-tests.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# Paths to ignore.
+ignored_paths=(
+ .editorconfig
+ .gitattributes
+ .gitignore
+ CODEOWNERS
+ CONTRIBUTING.md
+ LICENSE
+ phpcs.xml.dist
+ phpunit.xml.dist
+ README.md
+ readme.txt
+ .circleci/config.yml
+ bin/maybe-skip-tests.sh
+ bin/helpers.sh
+ bin/install-local-tests.sh
+ bin/install-wp-tests.sh
+ bin/phpunit-test.sh
+ .wordpress-org/*
+ .github/*
+ tests/phpunit/*
+)
+
+# Fetch list of changed files from the last commit
+changed_files=$(git diff-tree --no-commit-id --name-only -r HEAD)
+should_run_tests=true
+
+
+is_ignored_file(){
+ for ignore in "${ignored_paths[@]}"; do
+ if [[ "${1:-}" == "$ignore" ]]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+for file in $changed_files; do
+ if ! is_ignored_file "$file"; then
+ echo "Running tests because $file was changed."
+ break
+ fi
+ should_run_tests=false
+ echo "Skipping $file..."
+done
+
+if [ "$should_run_tests" = false ]; then
+ echo "Only ignored files modified. Skipping Behat tests."
+ circleci-agent step halt
+fi
diff --git a/composer.lock b/composer.lock
index bca61323..8563bfe2 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1136,16 +1136,16 @@
},
{
"name": "nikic/php-parser",
- "version": "v5.0.1",
+ "version": "v5.0.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69"
+ "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69",
- "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
+ "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
"shasum": ""
},
"require": {
@@ -1188,22 +1188,22 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
},
- "time": "2024-02-21T19:24:10+00:00"
+ "time": "2024-03-05T20:51:40+00:00"
},
{
"name": "pantheon-systems/pantheon-wordpress-upstream-tests",
"version": "dev-master",
"source": {
"type": "git",
- "url": "git@github.com:pantheon-systems/pantheon-wordpress-upstream-tests.git",
- "reference": "004fc97a604950aef4f62773417691d23b3d75b0"
+ "url": "https://github.com/pantheon-systems/pantheon-wordpress-upstream-tests.git",
+ "reference": "612d7d3e5ce064d7d30cc9752bc0e06d4a22f933"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pantheon-systems/pantheon-wordpress-upstream-tests/zipball/004fc97a604950aef4f62773417691d23b3d75b0",
- "reference": "004fc97a604950aef4f62773417691d23b3d75b0",
+ "url": "https://api.github.com/repos/pantheon-systems/pantheon-wordpress-upstream-tests/zipball/612d7d3e5ce064d7d30cc9752bc0e06d4a22f933",
+ "reference": "612d7d3e5ce064d7d30cc9752bc0e06d4a22f933",
"shasum": ""
},
"require": {
@@ -1225,7 +1225,11 @@
"email": "noreply@pantheon.io"
}
],
- "time": "2023-08-11T17:05:44+00:00"
+ "support": {
+ "issues": "https://github.com/pantheon-systems/pantheon-wordpress-upstream-tests/issues",
+ "source": "https://github.com/pantheon-systems/pantheon-wordpress-upstream-tests/tree/master"
+ },
+ "time": "2024-05-07T20:24:56+00:00"
},
{
"name": "pantheon-systems/pantheon-wp-coding-standards",
@@ -1317,20 +1321,21 @@
},
{
"name": "phar-io/manifest",
- "version": "2.0.3",
+ "version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
- "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
- "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
"shasum": ""
},
"require": {
"ext-dom": "*",
+ "ext-libxml": "*",
"ext-phar": "*",
"ext-xmlwriter": "*",
"phar-io/version": "^3.0.1",
@@ -1371,9 +1376,15 @@
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
"support": {
"issues": "https://github.com/phar-io/manifest/issues",
- "source": "https://github.com/phar-io/manifest/tree/2.0.3"
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
},
- "time": "2021-07-20T11:28:43+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
},
{
"name": "phar-io/version",
@@ -1490,28 +1501,28 @@
},
{
"name": "phpcompatibility/phpcompatibility-paragonie",
- "version": "1.3.2",
+ "version": "1.3.3",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git",
- "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26"
+ "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/bba5a9dfec7fcfbd679cfaf611d86b4d3759da26",
- "reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac",
+ "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac",
"shasum": ""
},
"require": {
"phpcompatibility/php-compatibility": "^9.0"
},
"require-dev": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"paragonie/random_compat": "dev-master",
"paragonie/sodium_compat": "dev-master"
},
"suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
@@ -1541,22 +1552,37 @@
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
+ "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy",
"source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
},
- "time": "2022-10-25T01:46:02+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/PHPCompatibility",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2024-04-24T21:30:46+00:00"
},
{
"name": "phpcompatibility/phpcompatibility-wp",
- "version": "2.1.4",
+ "version": "2.1.5",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git",
- "reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5"
+ "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5",
- "reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082",
+ "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082",
"shasum": ""
},
"require": {
@@ -1564,10 +1590,10 @@
"phpcompatibility/phpcompatibility-paragonie": "^1.0"
},
"require-dev": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7"
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0"
},
"suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
@@ -1596,9 +1622,24 @@
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
+ "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy",
"source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
},
- "time": "2022-10-24T09:00:36+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/PHPCompatibility",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2024-04-24T21:37:59+00:00"
},
{
"name": "phpcsstandards/phpcsextra",
@@ -1680,22 +1721,22 @@
},
{
"name": "phpcsstandards/phpcsutils",
- "version": "1.0.9",
+ "version": "1.0.11",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHPCSUtils.git",
- "reference": "908247bc65010c7b7541a9551e002db12e9dae70"
+ "reference": "c457da9dabb60eb7106dd5e3c05132b1a6539c6a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/908247bc65010c7b7541a9551e002db12e9dae70",
- "reference": "908247bc65010c7b7541a9551e002db12e9dae70",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c457da9dabb60eb7106dd5e3c05132b1a6539c6a",
+ "reference": "c457da9dabb60eb7106dd5e3c05132b1a6539c6a",
"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.8.0 || 4.0.x-dev@dev"
+ "squizlabs/php_codesniffer": "^3.9.0 || 4.0.x-dev@dev"
},
"require-dev": {
"ext-filter": "*",
@@ -1764,20 +1805,20 @@
"type": "open_collective"
}
],
- "time": "2023-12-08T14:50:00+00:00"
+ "time": "2024-04-24T11:47:18+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.26.0",
+ "version": "1.29.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "231e3186624c03d7e7c890ec662b81e6b0405227"
+ "reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227",
- "reference": "231e3186624c03d7e7c890ec662b81e6b0405227",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/536889f2b340489d328f5ffb7b02bb6b183ddedc",
+ "reference": "536889f2b340489d328f5ffb7b02bb6b183ddedc",
"shasum": ""
},
"require": {
@@ -1809,22 +1850,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.0"
},
- "time": "2024-02-23T16:05:55+00:00"
+ "time": "2024-05-06T12:04:23+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.30",
+ "version": "9.2.31",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089"
+ "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089",
- "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965",
+ "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965",
"shasum": ""
},
"require": {
@@ -1881,7 +1922,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31"
},
"funding": [
{
@@ -1889,7 +1930,7 @@
"type": "github"
}
],
- "time": "2023-12-22T06:47:57+00:00"
+ "time": "2024-03-02T06:37:42+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -2134,16 +2175,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "9.6.17",
+ "version": "9.6.19",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd"
+ "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd",
- "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8",
+ "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8",
"shasum": ""
},
"require": {
@@ -2217,7 +2258,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.17"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19"
},
"funding": [
{
@@ -2233,7 +2274,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-23T13:14:51+00:00"
+ "time": "2024-04-05T04:35:58+00:00"
},
{
"name": "psr/container",
@@ -2432,16 +2473,16 @@
},
{
"name": "sebastian/cli-parser",
- "version": "1.0.1",
+ "version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
- "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
+ "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
- "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
+ "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
"shasum": ""
},
"require": {
@@ -2476,7 +2517,7 @@
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
- "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2"
},
"funding": [
{
@@ -2484,7 +2525,7 @@
"type": "github"
}
],
- "time": "2020-09-28T06:08:49+00:00"
+ "time": "2024-03-02T06:27:43+00:00"
},
{
"name": "sebastian/code-unit",
@@ -2730,16 +2771,16 @@
},
{
"name": "sebastian/diff",
- "version": "4.0.5",
+ "version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
+ "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
- "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc",
+ "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc",
"shasum": ""
},
"require": {
@@ -2784,7 +2825,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
- "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
+ "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6"
},
"funding": [
{
@@ -2792,7 +2833,7 @@
"type": "github"
}
],
- "time": "2023-05-07T05:35:17+00:00"
+ "time": "2024-03-02T06:30:58+00:00"
},
{
"name": "sebastian/environment",
@@ -2859,16 +2900,16 @@
},
{
"name": "sebastian/exporter",
- "version": "4.0.5",
+ "version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
+ "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
- "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
+ "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
"shasum": ""
},
"require": {
@@ -2924,7 +2965,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6"
},
"funding": [
{
@@ -2932,20 +2973,20 @@
"type": "github"
}
],
- "time": "2022-09-14T06:03:37+00:00"
+ "time": "2024-03-02T06:33:00+00:00"
},
{
"name": "sebastian/global-state",
- "version": "5.0.6",
+ "version": "5.0.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "bde739e7565280bda77be70044ac1047bc007e34"
+ "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
- "reference": "bde739e7565280bda77be70044ac1047bc007e34",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
+ "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
"shasum": ""
},
"require": {
@@ -2988,7 +3029,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7"
},
"funding": [
{
@@ -2996,7 +3037,7 @@
"type": "github"
}
],
- "time": "2023-08-02T09:26:13+00:00"
+ "time": "2024-03-02T06:35:11+00:00"
},
{
"name": "sebastian/lines-of-code",
@@ -3232,16 +3273,16 @@
},
{
"name": "sebastian/resource-operations",
- "version": "3.0.3",
+ "version": "3.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
- "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
+ "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
- "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
+ "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
"shasum": ""
},
"require": {
@@ -3253,7 +3294,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -3274,8 +3315,7 @@
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"support": {
- "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
- "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
+ "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4"
},
"funding": [
{
@@ -3283,7 +3323,7 @@
"type": "github"
}
],
- "time": "2020-09-28T06:45:17+00:00"
+ "time": "2024-03-14T16:00:52+00:00"
},
{
"name": "sebastian/type",
@@ -3396,16 +3436,16 @@
},
{
"name": "sirbrillig/phpcs-variable-analysis",
- "version": "v2.11.17",
+ "version": "v2.11.18",
"source": {
"type": "git",
"url": "https://github.com/sirbrillig/phpcs-variable-analysis.git",
- "reference": "3b71162a6bf0cde2bff1752e40a1788d8273d049"
+ "reference": "ca242a0b7309e0f9d1f73b236e04ecf4ca3248d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/3b71162a6bf0cde2bff1752e40a1788d8273d049",
- "reference": "3b71162a6bf0cde2bff1752e40a1788d8273d049",
+ "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/ca242a0b7309e0f9d1f73b236e04ecf4ca3248d0",
+ "reference": "ca242a0b7309e0f9d1f73b236e04ecf4ca3248d0",
"shasum": ""
},
"require": {
@@ -3450,36 +3490,36 @@
"source": "https://github.com/sirbrillig/phpcs-variable-analysis",
"wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki"
},
- "time": "2023-08-05T23:46:11+00:00"
+ "time": "2024-04-13T16:42:46+00:00"
},
{
"name": "slevomat/coding-standard",
- "version": "8.14.1",
+ "version": "8.15.0",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926"
+ "reference": "7d1d957421618a3803b593ec31ace470177d7817"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/fea1fd6f137cc84f9cba0ae30d549615dbc6a926",
- "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817",
+ "reference": "7d1d957421618a3803b593ec31ace470177d7817",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0",
"php": "^7.2 || ^8.0",
"phpstan/phpdoc-parser": "^1.23.1",
- "squizlabs/php_codesniffer": "^3.7.1"
+ "squizlabs/php_codesniffer": "^3.9.0"
},
"require-dev": {
"phing/phing": "2.17.4",
"php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.10.37",
+ "phpstan/phpstan": "1.10.60",
"phpstan/phpstan-deprecation-rules": "1.1.4",
- "phpstan/phpstan-phpunit": "1.3.14",
- "phpstan/phpstan-strict-rules": "1.5.1",
- "phpunit/phpunit": "8.5.21|9.6.8|10.3.5"
+ "phpstan/phpstan-phpunit": "1.3.16",
+ "phpstan/phpstan-strict-rules": "1.5.2",
+ "phpunit/phpunit": "8.5.21|9.6.8|10.5.11"
},
"type": "phpcodesniffer-standard",
"extra": {
@@ -3503,7 +3543,7 @@
],
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/8.14.1"
+ "source": "https://github.com/slevomat/coding-standard/tree/8.15.0"
},
"funding": [
{
@@ -3515,20 +3555,20 @@
"type": "tidelift"
}
],
- "time": "2023-10-08T07:28:08+00:00"
+ "time": "2024-03-09T15:20:58+00:00"
},
{
"name": "spryker/code-sniffer",
- "version": "0.17.21",
+ "version": "0.17.23",
"source": {
"type": "git",
"url": "https://github.com/spryker/code-sniffer.git",
- "reference": "a1ab7fa30981a57b43d1eab5339fd52b600e2f60"
+ "reference": "1cb5550e11f25c200016d0d3cd7021b2dfeadaf5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spryker/code-sniffer/zipball/a1ab7fa30981a57b43d1eab5339fd52b600e2f60",
- "reference": "a1ab7fa30981a57b43d1eab5339fd52b600e2f60",
+ "url": "https://api.github.com/repos/spryker/code-sniffer/zipball/1cb5550e11f25c200016d0d3cd7021b2dfeadaf5",
+ "reference": "1cb5550e11f25c200016d0d3cd7021b2dfeadaf5",
"shasum": ""
},
"require": {
@@ -3573,20 +3613,20 @@
"issues": "https://github.com/spryker/code-sniffer/issues",
"source": "https://github.com/spryker/code-sniffer"
},
- "time": "2024-01-30T11:39:44+00:00"
+ "time": "2024-03-22T09:53:22+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.9.0",
+ "version": "3.9.2",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
- "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b"
+ "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/d63cee4890a8afaf86a22e51ad4d97c91dd4579b",
- "reference": "d63cee4890a8afaf86a22e51ad4d97c91dd4579b",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/aac1f6f347a5c5ac6bc98ad395007df00990f480",
+ "reference": "aac1f6f347a5c5ac6bc98ad395007df00990f480",
"shasum": ""
},
"require": {
@@ -3653,7 +3693,7 @@
"type": "open_collective"
}
],
- "time": "2024-02-16T15:06:51+00:00"
+ "time": "2024-04-23T20:25:34+00:00"
},
{
"name": "symfony/browser-kit",
@@ -3807,16 +3847,16 @@
},
{
"name": "symfony/console",
- "version": "v5.4.35",
+ "version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "dbdf6adcb88d5f83790e1efb57ef4074309d3931"
+ "reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/dbdf6adcb88d5f83790e1efb57ef4074309d3931",
- "reference": "dbdf6adcb88d5f83790e1efb57ef4074309d3931",
+ "url": "https://api.github.com/repos/symfony/console/zipball/f3e591c48688a0cfa1a3296205926c05e84b22b1",
+ "reference": "f3e591c48688a0cfa1a3296205926c05e84b22b1",
"shasum": ""
},
"require": {
@@ -3886,7 +3926,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v5.4.35"
+ "source": "https://github.com/symfony/console/tree/v5.4.39"
},
"funding": [
{
@@ -3902,20 +3942,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:28:09+00:00"
+ "time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v5.4.35",
+ "version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "9e615d367e2bed41f633abb383948c96a2dbbfae"
+ "reference": "0934c9f1d433776f25c629bdc93f3e157d139e08"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/9e615d367e2bed41f633abb383948c96a2dbbfae",
- "reference": "9e615d367e2bed41f633abb383948c96a2dbbfae",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/0934c9f1d433776f25c629bdc93f3e157d139e08",
+ "reference": "0934c9f1d433776f25c629bdc93f3e157d139e08",
"shasum": ""
},
"require": {
@@ -3952,7 +3992,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v5.4.35"
+ "source": "https://github.com/symfony/css-selector/tree/v5.4.39"
},
"funding": [
{
@@ -3968,7 +4008,7 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T13:51:25+00:00"
+ "time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/dependency-injection",
@@ -4058,16 +4098,16 @@
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.4.0",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
+ "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
- "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
+ "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"shasum": ""
},
"require": {
@@ -4076,7 +4116,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -4105,7 +4145,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -4121,7 +4161,7 @@
"type": "tidelift"
}
],
- "time": "2023-05-23T14:45:45+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/dom-crawler",
@@ -4199,16 +4239,16 @@
},
{
"name": "symfony/event-dispatcher",
- "version": "v5.4.35",
+ "version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38"
+ "reference": "d40fae9fd85c762b6ba378152fdd1157a85d7e4f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7a69a85c7ea5bdd1e875806a99c51a87d3a74b38",
- "reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d40fae9fd85c762b6ba378152fdd1157a85d7e4f",
+ "reference": "d40fae9fd85c762b6ba378152fdd1157a85d7e4f",
"shasum": ""
},
"require": {
@@ -4264,7 +4304,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.35"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.39"
},
"funding": [
{
@@ -4280,20 +4320,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T13:51:25+00:00"
+ "time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
- "version": "v3.4.0",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
- "reference": "a76aed96a42d2b521153fb382d418e30d18b59df"
+ "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df",
- "reference": "a76aed96a42d2b521153fb382d418e30d18b59df",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50",
+ "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50",
"shasum": ""
},
"require": {
@@ -4303,7 +4343,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -4340,7 +4380,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0"
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -4356,27 +4396,28 @@
"type": "tidelift"
}
],
- "time": "2023-05-23T14:45:45+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v5.4.35",
+ "version": "v5.4.39",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086"
+ "reference": "e6edd875d5d39b03de51f3c3951148cfa79a4d12"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/5a553607d4ffbfa9c0ab62facadea296c9db7086",
- "reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/e6edd875d5d39b03de51f3c3951148cfa79a4d12",
+ "reference": "e6edd875d5d39b03de51f3c3951148cfa79a4d12",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8",
- "symfony/polyfill-php80": "^1.16"
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/process": "^5.4|^6.4"
},
"type": "library",
"autoload": {
@@ -4404,7 +4445,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v5.4.35"
+ "source": "https://github.com/symfony/filesystem/tree/v5.4.39"
},
"funding": [
{
@@ -4420,7 +4461,7 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T13:51:25+00:00"
+ "time": "2024-04-18T08:26:06+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -5129,18 +5170,79 @@
],
"time": "2024-01-29T20:11:03+00:00"
},
+ {
+ "name": "symfony/process",
+ "version": "v6.4.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "cdb1c81c145fd5aa9b0038bab694035020943381"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/cdb1c81c145fd5aa9b0038bab694035020943381",
+ "reference": "cdb1c81c145fd5aa9b0038bab694035020943381",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v6.4.7"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-04-18T09:22:46+00:00"
+ },
{
"name": "symfony/service-contracts",
- "version": "v2.5.2",
+ "version": "v2.5.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
+ "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
- "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3",
+ "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3",
"shasum": ""
},
"require": {
@@ -5194,7 +5296,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v2.5.2"
+ "source": "https://github.com/symfony/service-contracts/tree/v2.5.3"
},
"funding": [
{
@@ -5210,20 +5312,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-30T19:17:29+00:00"
+ "time": "2023-04-21T15:04:16+00:00"
},
{
"name": "symfony/string",
- "version": "v6.4.3",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "7a14736fb179876575464e4658fce0c304e8c15b"
+ "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/7a14736fb179876575464e4658fce0c304e8c15b",
- "reference": "7a14736fb179876575464e4658fce0c304e8c15b",
+ "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69",
+ "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69",
"shasum": ""
},
"require": {
@@ -5280,7 +5382,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.4.3"
+ "source": "https://github.com/symfony/string/tree/v6.4.7"
},
"funding": [
{
@@ -5296,7 +5398,7 @@
"type": "tidelift"
}
],
- "time": "2024-01-25T09:26:29+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/translation",
@@ -5389,16 +5491,16 @@
},
{
"name": "symfony/translation-contracts",
- "version": "v2.5.2",
+ "version": "v2.5.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
- "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe"
+ "reference": "b0073a77ac0b7ea55131020e87b1e3af540f4664"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe",
- "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b0073a77ac0b7ea55131020e87b1e3af540f4664",
+ "reference": "b0073a77ac0b7ea55131020e87b1e3af540f4664",
"shasum": ""
},
"require": {
@@ -5447,7 +5549,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2"
+ "source": "https://github.com/symfony/translation-contracts/tree/v2.5.3"
},
"funding": [
{
@@ -5463,20 +5565,20 @@
"type": "tidelift"
}
],
- "time": "2022-06-27T16:58:25+00:00"
+ "time": "2024-01-23T13:51:25+00:00"
},
{
"name": "symfony/yaml",
- "version": "v6.4.3",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "d75715985f0f94f978e3a8fa42533e10db921b90"
+ "reference": "53e8b1ef30a65f78eac60fddc5ee7ebbbdb1dee0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/d75715985f0f94f978e3a8fa42533e10db921b90",
- "reference": "d75715985f0f94f978e3a8fa42533e10db921b90",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/53e8b1ef30a65f78eac60fddc5ee7ebbbdb1dee0",
+ "reference": "53e8b1ef30a65f78eac60fddc5ee7ebbbdb1dee0",
"shasum": ""
},
"require": {
@@ -5519,7 +5621,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v6.4.3"
+ "source": "https://github.com/symfony/yaml/tree/v6.4.7"
},
"funding": [
{
@@ -5535,20 +5637,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-28T10:28:08+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.2.2",
+ "version": "1.2.3",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
- "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"shasum": ""
},
"require": {
@@ -5577,7 +5679,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.2"
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
},
"funding": [
{
@@ -5585,20 +5687,20 @@
"type": "github"
}
],
- "time": "2023-11-20T00:12:19+00:00"
+ "time": "2024-03-03T12:36:25+00:00"
},
{
"name": "wp-coding-standards/wpcs",
- "version": "3.0.1",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/WordPress/WordPress-Coding-Standards.git",
- "reference": "b4caf9689f1a0e4a4c632679a44e638c1c67aff1"
+ "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/b4caf9689f1a0e4a4c632679a44e638c1c67aff1",
- "reference": "b4caf9689f1a0e4a4c632679a44e638c1c67aff1",
+ "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/9333efcbff231f10dfd9c56bb7b65818b4733ca7",
+ "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7",
"shasum": ""
},
"require": {
@@ -5607,16 +5709,16 @@
"ext-tokenizer": "*",
"ext-xmlreader": "*",
"php": ">=5.4",
- "phpcsstandards/phpcsextra": "^1.1.0",
- "phpcsstandards/phpcsutils": "^1.0.8",
- "squizlabs/php_codesniffer": "^3.7.2"
+ "phpcsstandards/phpcsextra": "^1.2.1",
+ "phpcsstandards/phpcsutils": "^1.0.10",
+ "squizlabs/php_codesniffer": "^3.9.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.0",
"phpcsstandards/phpcsdevtools": "^1.2.0",
- "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"suggest": {
"ext-iconv": "For improved results",
@@ -5647,24 +5749,24 @@
},
"funding": [
{
- "url": "https://opencollective.com/thewpcc/contribute/wp-php-63406",
+ "url": "https://opencollective.com/php_codesniffer",
"type": "custom"
}
],
- "time": "2023-09-14T07:06:09+00:00"
+ "time": "2024-03-25T16:39:00+00:00"
},
{
"name": "yoast/phpunit-polyfills",
- "version": "2.0.0",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/Yoast/PHPUnit-Polyfills.git",
- "reference": "c758753e8f9dac251fed396a73c8305af3f17922"
+ "reference": "4a088f125c970d6d6ea52c927f96fe39b330d0f1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/c758753e8f9dac251fed396a73c8305af3f17922",
- "reference": "c758753e8f9dac251fed396a73c8305af3f17922",
+ "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/4a088f125c970d6d6ea52c927f96fe39b330d0f1",
+ "reference": "4a088f125c970d6d6ea52c927f96fe39b330d0f1",
"shasum": ""
},
"require": {
@@ -5672,7 +5774,9 @@
"phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0"
},
"require-dev": {
- "yoast/yoastcs": "^2.3.0"
+ "php-parallel-lint/php-console-highlighter": "^1.0.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "yoast/yoastcs": "^3.1.0"
},
"type": "library",
"extra": {
@@ -5709,9 +5813,10 @@
],
"support": {
"issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues",
+ "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy",
"source": "https://github.com/Yoast/PHPUnit-Polyfills"
},
- "time": "2023-06-06T20:28:24+00:00"
+ "time": "2024-04-05T16:36:44+00:00"
}
],
"aliases": [],
diff --git a/inc/admin-interface.php b/inc/admin-interface.php
new file mode 100644
index 00000000..be6feae2
--- /dev/null
+++ b/inc/admin-interface.php
@@ -0,0 +1,319 @@
+ 1.4.0.
+ if ( version_compare( PANTHEON_MU_PLUGIN_VERSION, '1.4.0', '>' ) ) {
+ // Do stuff, e.g. add_action().
+ add_action( 'admin_notices', __NAMESPACE__ . '\\admin_notice_maybe_recommend_higher_max_age' );
+ } else {
+ add_action( 'admin_notices', __NAMESPACE__ . '\\admin_notice_old_mu_plugin' );
+ }
+ } else {
+ add_action( 'admin_notices', __NAMESPACE__ . '\\admin_notice_no_mu_plugin' );
+ }
+
+ add_filter( 'site_status_tests', __NAMESPACE__ . '\\default_cache_max_age_test' );
+ add_action( 'update_option_pantheon-cache', __NAMESPACE__ . '\\clear_max_age_compare_cache' );
+}
+
+/**
+ * Display an admin notice if the Pantheon MU plugin was not found.
+ *
+ * @since 2.0.0
+ * @return void
+ */
+function admin_notice_no_mu_plugin() {
+ /**
+ * Allow disabling the admin notice.
+ *
+ * @param bool $disable_admin_notices Whether to disable the admin notice.
+ */
+ if ( apply_filters( 'pantheon_apc_disable_admin_notices', false ) ) {
+ return;
+ }
+
+ wp_admin_notice(
+ // translators: %s is a link to the Pantheon MU plugin.
+ sprintf( __( 'Pantheon Advanced Page Cache works best on the Pantheon platform. If you are working inside a Pantheon environment, ensure your site is using the Pantheon MU plugin.', 'pantheon-advanced-page-cache' ), 'https://github.com/pantheon-systems/pantheon-mu-plugin' ),
+ [
+ 'type' => 'error',
+ 'dismissible' => true,
+ ]
+ );
+}
+
+/**
+ * Display an admin notice if the Pantheon MU plugin is out of date.
+ *
+ * @since 2.0.0
+ * @return void
+ */
+function admin_notice_old_mu_plugin() {
+ $current_screen = get_current_screen();
+
+ if ( apply_filters( 'pantheon_apc_disable_admin_notices', false ) || 'settings_page_pantheon-cache' !== $current_screen->id ) {
+ return;
+ }
+
+ $mu_plugin_version = PANTHEON_MU_PLUGIN_VERSION;
+ $message = sprintf(
+ // translators: %1$s is a link to the Pantheon MU plugin, %2$s is the version of the MU plugin.
+ __( 'You appear to have an old version of the Pantheon MU plugin. 1.4.0 or above expected but %2$s found.', 'pantheon-advanced-page-cache' ),
+ 'https://github.com/pantheon-systems/pantheon-mu-plugin',
+ $mu_plugin_version
+ );
+
+ // Check if there's a composer.json file in the root of the site.
+ if ( file_exists( ABSPATH . 'composer.json' ) ) {
+ $message .= ' ' . __( 'If you are using Composer, you can update the MU plugin by running composer update
.', 'pantheon-advanced-page-cache' );
+ } else {
+ $message .= ' ' . __( 'You should Apply Updates from the Pantheon Dashboard to get the latest version of WordPress and the Pantheon MU plugin.', 'pantheon-advanced-page-cache' );
+ }
+
+ wp_admin_notice(
+ // translators: %s is a link to the Pantheon MU plugin.
+ $message,
+ [
+ 'type' => 'warning',
+ 'dismissible' => true,
+ ]
+ );
+}
+
+/**
+ * Display an admin notice if the max-age is less than a week but not equal to 600 seconds.
+ *
+ * @since 2.0.0
+ * @return void
+ */
+function admin_notice_maybe_recommend_higher_max_age() {
+ $current_screen = get_current_screen();
+
+ if ( apply_filters( 'pantheon_apc_disable_admin_notices', false ) || 'settings_page_pantheon-cache' !== $current_screen->id ) {
+ return;
+ }
+
+ $max_age_rank = max_age_compare();
+ $current_max_age = get_current_max_age();
+ if (
+ $max_age_rank > 0 &&
+ $current_max_age < WEEK_IN_SECONDS &&
+ $current_max_age !== 600
+ ) {
+ // If the current max-age value has a rank of 3 or more (10 is the highest), we'll note that it's very low.
+ $very_low = $max_age_rank > 3 ? __( 'This is a very low value and may not be optimal for your site.', 'pantheon-advanced-page-cache' ) : '';
+ $message = sprintf(
+ // translators: %1$s is the current max-age, %2$d is the current max-age in seconds, %3$s is a message that displays if the value is very low, %44d is the recommended max age in seconds, %5$s is the humanized recommended max age, %6$s is debug information that is written to the HTML DOM but not displayed.
+ __( 'The cache max-age is currently set to %1$s (%2$s seconds). %3$s Consider increasing the cache max-age to at least %4$d seconds (%5$s).%6$s', 'pantheon-advanced-page-cache' ),
+ humanized_max_age(),
+ $current_max_age,
+ $very_low,
+ WEEK_IN_SECONDS,
+ humanized_max_age( true ),
+ sprintf( '', $max_age_rank )
+ );
+
+ // Escalating notice types based on the max-age rank.
+ $notice_type = ( $max_age_rank === 1 ? 'info' : $max_age_rank > 3 ) ? 'error' : 'warning';
+
+ wp_admin_notice(
+ $message,
+ [
+ 'type' => $notice_type,
+ 'dismissible' => true,
+ ]
+ );
+ }
+}
+
+/**
+ * Get the current max-age value.
+ *
+ * This comes from the Pantheon mu-plugin and only exists if settings were actually saved.
+ *
+ * If the site existed prior to 1.4.0 of the mu-plugin, the default value is 600 seconds. Otherwise, the default value is 1 week.
+ *
+ * @since 2.0.0
+ * @return int
+ */
+function get_current_max_age() {
+ $options = get_option( 'pantheon-cache', [] );
+
+ // If the default_ttl option is not set, we're using the default, which is 1 week.
+ if ( ! isset( $options['default_ttl'] ) ) {
+ return get_default_max_age();
+ }
+
+ return apply_filters( 'pantheon_cache_default_max_age', $options['default_ttl'] );
+}
+
+/**
+ * Add a test to the Site Health page to check the cache max-age.
+ *
+ * @param array $tests The Site Health tests.
+ *
+ * @since 2.0.0
+ * @return array
+ */
+function default_cache_max_age_test( $tests ) {
+ $tests['direct']['pantheon_edge_cache'] = [
+ 'label' => __( 'Pantheon Edge Cache', 'pantheon-advanced-page-cache' ),
+ 'test' => __NAMESPACE__ . '\\test_cache_max_age',
+ ];
+
+ return $tests;
+}
+
+/**
+ * Get the humanized max-age.
+ *
+ * @param bool $recommended Whether to get the recommended max-age.
+ *
+ * @since 2.0.0
+ * @return string
+ */
+function humanized_max_age( $recommended = false ) {
+ $time = time();
+ $current_max_age = $recommended ? get_default_max_age() : get_current_max_age();
+ $humanized_time = human_time_diff( $time, $time + $current_max_age );
+
+ return $humanized_time;
+}
+
+/**
+ * Get the default max-age.
+ *
+ * @since 2.0.0
+ * @return int
+ */
+function get_default_max_age() {
+ return apply_filters( 'pantheon_cache_default_max_age', WEEK_IN_SECONDS );
+}
+
+/**
+ * Compare the current max-age to the default max-age.
+ *
+ * @since 2.0.0
+ * @return int A ranked value from 0 to 10 where 0 is optimal (equal to or greater than the recommended max age) and 10 is very bad.
+ */
+function max_age_compare() {
+ $cached_rank = get_transient( 'papc_max_age_compare' );
+
+ if ( false !== $cached_rank ) {
+ return $cached_rank;
+ }
+
+ $current_max_age = get_current_max_age();
+ $default_max_age = get_default_max_age();
+ $diff = $current_max_age - $default_max_age;
+
+ if ( $diff >= 0 ) {
+ return 0;
+ }
+
+ // Rank the difference on a scale of 0 ($current_max_age >= $default_max_age) to 10 and return the rank int.
+ $rank = round( abs( $diff ) / $default_max_age * 10 );
+
+ $cached_rank = min( max( $rank, 1 ), 10 );
+ set_transient( 'papc_max_age_compare', $cached_rank, WEEK_IN_SECONDS );
+ return $cached_rank;
+}
+
+/**
+ * The GCDN cache max-age Site Health test.
+ *
+ * @since 2.0.0
+ * @return array
+ */
+function test_cache_max_age() {
+ $default_max_age = get_default_max_age();
+ $current_max_age = get_current_max_age();
+ $humanized_time = humanized_max_age();
+ $humanized_reccomended_time = humanized_max_age( true );
+ $recommend_color = max_age_compare() > 3 ? 'red' : 'orange';
+
+ if ( $current_max_age < $default_max_age ) {
+ $result = [
+ 'label' => __( 'Pantheon GCDN Cache Max-Age', 'pantheon-advanced-page-cache' ),
+ 'status' => 'recommended',
+ 'badge' => [
+ 'label' => __( 'Performance', 'pantheon-advanced-page-cache' ),
+ 'color' => $recommend_color,
+ ],
+ 'description' => sprintf(
+ // translators: %1$s is the current max-age, %2$s is the recommended max-age, %3$d is the recommended max-age in seconds.
+ __( 'The Pantheon GCDN cache max-age is currently set to %1$s (%2$d seconds). We recommend increasing to %3$s (%4$d seconds).', 'pantheon-advanced-page-cache' ),
+ $humanized_time,
+ $current_max_age,
+ $humanized_reccomended_time,
+ $default_max_age
+ ),
+ 'test' => 'pantheon_edge_cache',
+ ];
+
+ return $result;
+ }
+
+ $result = [
+ 'label' => sprintf(
+ // translators: %s is the humanized time.
+ __( 'Pantheon GCDN Cache Max-Age set to %1$s', 'pantheon-advanced-page-cache' ),
+ $humanized_time,
+ $humanized_reccomended_time
+ ),
+ 'status' => 'good',
+ 'badge' => [
+ 'label' => __( 'Performance', 'pantheon-advanced-page-cache' ),
+ 'color' => 'blue',
+ ],
+ 'description' => sprintf(
+ '%1$s
%2$s',
+ sprintf(
+ // translators: %1$s is the current max-age, %2$s is the recommended max-age, %3$d is the recommended max-age in seconds.
+ __( 'The Pantheon cache max-age is currently set to %1$s (%2$s seconds). Our recommendation is %3$s (%4$d seconds) or more.', 'pantheon-advanced-page-cache' ),
+ $humanized_time,
+ $current_max_age,
+ $humanized_reccomended_time,
+ $default_max_age
+ ),
+ sprintf(
+ // translators: %s is a link to the cache configuration guide.
+ __( 'View our cache configuration guide for more information.', 'pantheon-advanced-page-cache' ),
+ 'https://docs.pantheon.io/guides/wordpress-configurations/wordpress-cache-plugin#pantheon-page-cache-plugin-configuration'
+ )
+ ),
+ 'test' => 'pantheon_edge_cache',
+ ];
+
+ return $result;
+}
+
+/**
+ * Clear the max-age compare cache when the max-age is updated.
+ *
+ * @since 2.0.0
+ * @return void
+ */
+function clear_max_age_compare_cache() {
+ delete_transient( 'papc_max_age_compare' );
+}
diff --git a/pantheon-advanced-page-cache.php b/pantheon-advanced-page-cache.php
index b574ff34..06b130ff 100644
--- a/pantheon-advanced-page-cache.php
+++ b/pantheon-advanced-page-cache.php
@@ -1,13 +1,15 @@
__DIR__ . '/inc/admin-interface.php',
+ ];
+
+ foreach ( $namespaced_files as $namespace => $file ) {
+ if ( file_exists( $file ) ) {
+ require $file;
+ call_user_func( $namespace . '\\bootstrap' );
+ } else {
+ wp_die( esc_html( "Could not find $file" ), 'Pantheon Advanced Page Cache error' );
+
+ }
+ }
+}
+
/**
* Registers the class autoloader.
*/
@@ -122,6 +148,11 @@ function ( $class_autoloader ) {
}
);
+/**
+ * Init namespaced files.
+ */
+add_action( 'plugins_loaded', 'pantheon_bootstrap_namespaces' );
+
/**
* Registers relevant UI
*/
diff --git a/readme.txt b/readme.txt
index cf1c1f43..2dc976d3 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,9 +1,9 @@
=== Pantheon Advanced Page Cache ===
Contributors: getpantheon, danielbachhuber, kporras07, jspellman, jazzs3quence, ryanshoover, rwagner00, pwtyler
Tags: pantheon, cdn, cache
-Requires at least: 4.7
-Tested up to: 6.4.3
-Stable tag: 1.5.0
+Requires at least: 6.4
+Tested up to: 6.5.3
+Stable tag: 2.0.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -332,6 +332,9 @@ Pantheon Advanced Page Cache integrates with WordPress plugins, including:
See [CONTRIBUTING.md](https://github.com/pantheon-systems/wp-saml-auth/blob/master/CONTRIBUTING.md) for information on contributing.
== Changelog ==
+= 2.0.0-dev =
+* Adds new admin alerts and Site Health tests about default cache max-age settings and recommendations [[#268](https://github.com/pantheon-systems/pantheon-advanced-page-cache/pull/268)]. The default Pantheon GCDN cache max-age value has been updated to 1 week in the [Pantheon MU plugin](https://github.com/pantheon-systems/pantheon-mu-plugin). For more information, see the [release note](https://docs.pantheon.io/release-notes/2024/04/pantheon-mu-plugin-1-4-0-update).
+
= 1.5.0 (11 March 2024) =
* Adds filter `pantheon_purge_post_type_ignored` to allow an array of post types to ignore before purging cache [[#258](https://github.com/pantheon-systems/pantheon-advanced-page-cache/pull/258)]
* Adds [wpunit-helpers](https://github.com/pantheon-systems/wpunit-helpers) for running/setting up WP Unit tests
@@ -409,6 +412,8 @@ See [CONTRIBUTING.md](https://github.com/pantheon-systems/wp-saml-auth/blob/mast
* Initial release.
== Upgrade Notice ==
+= 2.0.0 =
+This release requires a minimum WordPress version of 6.4.0. It uses Site Health checks and the `wp_admin_notices` function to alert users to the new cache max-age default settings and recommendations. The plugin will still function with earlier versions, but you will not get the benefit of the alerts and Site Health checks.
= Latest =
Note that the Pantheon Advanced Page Cache 1.3.0 release now prefixes keys on a WordPress Multisite (WPMS) with the blog ID. For users who already have this plugin installed on a WPMS, they will need to click the Clear Cache button on the settings page to generate the prefixed keys.
diff --git a/tests/behat/admin-interface.feature b/tests/behat/admin-interface.feature
new file mode 100644
index 00000000..044f877f
--- /dev/null
+++ b/tests/behat/admin-interface.feature
@@ -0,0 +1,23 @@
+Feature: Adjust the Default Max Age setting
+
+Background:
+ Given I log in as an admin
+
+Scenario: Change the cache max age
+ When I go to "/wp-admin/options-general.php?page=pantheon-cache"
+ And I fill in "pantheon-cache[default_ttl]" with "300"
+ And I press "Save Changes"
+ Then I should see "This is a very low value and may not be optimal for your site" in the ".notice" element
+ And I should see "Consider increasing the cache max-age to at least 604800 seconds (1 week)" in the ".notice" element
+
+Scenario: Change the cache max age to 5 days
+ When I go to "/wp-admin/options-general.php?page=pantheon-cache"
+ And I fill in "pantheon-cache[default_ttl]" with "432000"
+ And I press "Save Changes"
+ Then I should see "Consider increasing the cache max-age to at least 604800 seconds (1 week)" in the ".notice" element
+
+Scenario: Change the cache max age to 1 week
+ When I go to "/wp-admin/options-general.php?page=pantheon-cache"
+ And I fill in "pantheon-cache[default_ttl]" with "604800"
+ And I press "Save Changes"
+ Then I should see "Settings saved."
diff --git a/tests/behat/site-health.feature b/tests/behat/site-health.feature
new file mode 100644
index 00000000..a07875be
--- /dev/null
+++ b/tests/behat/site-health.feature
@@ -0,0 +1,28 @@
+Feature: Site Health tests based on Cache Max Age
+
+Background:
+ Given I log in as an admin
+
+Scenario: Site Health should report when Max Age is a low value
+ When I go to "/wp-admin/options-general.php?page=pantheon-cache"
+ And I fill in "pantheon-cache[default_ttl]" with "300"
+ And I press "Save Changes"
+ And I go to "/wp-admin/site-health.php"
+ Then I should see "Pantheon GCDN Cache Max-Age"
+ And I should see "The Pantheon GCDN cache max-age is currently set to 5 mins (300 seconds). We recommend increasing to 1 week (604800 seconds)"
+
+Scenario: Site Health should report when Max age is less than the recommendation
+ When I go to "/wp-admin/options-general.php?page=pantheon-cache"
+ And I fill in "pantheon-cache[default_ttl]" with "432000"
+ And I press "Save Changes"
+ And I go to "/wp-admin/site-health.php"
+ Then I should see "Pantheon GCDN Cache Max-Age"
+ And I should see "The Pantheon GCDN cache max-age is currently set to 5 days (432000 seconds). We recommend increasing to 1 week (604800 seconds)"
+
+Scenario: Site Health check should pass when Max Age is the recommneded value
+ When I go to "/wp-admin/options-general.php?page=pantheon-cache"
+ And I fill in "pantheon-cache[default_ttl]" with "604800"
+ And I press "Save Changes"
+ And I go to "/wp-admin/site-health.php"
+ Then I should see "Pantheon GCDN Cache Max-Age set to 1 week"
+ And I should see "The Pantheon cache max-age is currently set to 1 week (604800 seconds). Our recommendation is 1 week (604800 seconds) or more."
diff --git a/tests/phpunit/test-admin-interface.php b/tests/phpunit/test-admin-interface.php
new file mode 100644
index 00000000..8da3f335
--- /dev/null
+++ b/tests/phpunit/test-admin-interface.php
@@ -0,0 +1,160 @@
+ 300 ] );
+ }
+
+ /**
+ * Tear down tests.
+ */
+ public function tearDown(): void {
+ parent::tearDown();
+ delete_option( 'pantheon-cache' );
+ delete_transient( 'papc_max_age_compare' );
+ }
+
+ /**
+ * Test the get_current_max_age and get_default_max_age functions.
+ */
+ public function test_get_max_age() {
+ $this->assertEquals( 300, get_current_max_age() );
+ $this->assertNotEquals( get_default_max_age(), get_current_max_age() );
+ $this->assertEquals( WEEK_IN_SECONDS, get_default_max_age() );
+ }
+
+ /**
+ * Test the Site Health tests with very low cache max age.
+ */
+ public function test_site_health_tests_300_seconds() {
+ $tests = apply_filters( 'site_status_tests', [] );
+
+ $this->assertContains( 'pantheon_edge_cache', array_keys( $tests['direct'] ) );
+
+ // Base test with 300 second max-age.
+ $test_results = test_cache_max_age();
+ $this->assertEquals( 'recommended', $test_results['status'] );
+ $this->assertEquals( 'red',$test_results['badge']['color'] );
+ $this->assertStringContainsString( '300 seconds', $test_results['description'] );
+ $this->assertStringContainsString( 'We recommend increasing to 1 week', $test_results['description'] );
+ }
+
+ /**
+ * Test the Site Health tests with 5 day cache max age.
+ */
+ public function test_site_health_tests_5_days() {
+ // Update the option and rerun.
+ update_option( 'pantheon-cache', [ 'default_ttl' => 5 * DAY_IN_SECONDS ] );
+ $test_results = test_cache_max_age();
+ $this->assertEquals( 'recommended', $test_results['status'] );
+ $this->assertEquals( 'orange',$test_results['badge']['color'] );
+ $this->assertStringContainsString( '5 days', $test_results['description'] );
+ $this->assertStringContainsString( 'We recommend increasing to 1 week', $test_results['description'] );
+ }
+
+ /**
+ * Test the Site Health tests with 1 week cache max age.
+ */
+ public function test_site_health_tests_1_week() {
+ // Update the option to the default and rerun.
+ update_option( 'pantheon-cache', [ 'default_ttl' => WEEK_IN_SECONDS ] );
+ $test_results = test_cache_max_age();
+ $this->assertEquals( 'good', $test_results['status'] );
+ $this->assertEquals( 'blue',$test_results['badge']['color'] );
+ $this->assertStringContainsString( '1 week', $test_results['label'] );
+ $this->assertStringContainsString( 'Pantheon GCDN Cache Max-Age set to 1 week', $test_results['label'] );
+ }
+
+ /**
+ * Test the humanized_max_age function.
+ *
+ * @dataProvider humanized_max_age_provider
+ */
+ public function test_humanized_max_age( $max_age, $expected ) {
+ update_option( 'pantheon-cache', [ 'default_ttl' => $max_age ] );
+ $this->assertEquals( $expected, humanized_max_age() );
+ }
+
+ /**
+ * Data provider for test_humanized_max_age.
+ *
+ * @return array
+ */
+ public function humanized_max_age_provider() {
+ return [
+ [ 300, '5 mins' ], // 300 seconds is humanized to 5 mins.
+ [ 5 * DAY_IN_SECONDS, '5 days' ],
+ [ WEEK_IN_SECONDS, '1 week' ],
+ ];
+ }
+
+ /**
+ * Test the max_age_compare function.
+ *
+ * @dataProvider max_age_compare_provider
+ */
+ public function test_max_age_compare( $max_age, $expected ){
+ update_option( 'pantheon-cache', [ 'default_ttl' => $max_age ] );
+ $this->assertEquals( $expected, max_age_compare() );
+ }
+
+ /**
+ * Data provider for test_max_age_compare.
+ *
+ * @return array
+ */
+ public function max_age_compare_provider() {
+ return [
+ [ 300, 10 ], // 300 seconds is bad. It should rank the highest.
+ [ 5 * DAY_IN_SECONDS, 3 ], // 5 days is better.
+ [ WEEK_IN_SECONDS, 0 ], // Default recommendation should always return 0.
+ [ 2 * WEEK_IN_SECONDS, 0 ], // More than the recommendation is also good and should always return 0.
+ ];
+ }
+
+ /**
+ * Test the delete transient on option update hook.
+ *
+ * @dataProvider delete_transient_on_option_update_provider
+ */
+ public function test_delete_transient_on_option_update( $expected, $max_age ) {
+ update_option( 'pantheon-cache', [ 'default_ttl' => $max_age] );
+ max_age_compare();
+ $cached_max_age_compare = get_transient( 'papc_max_age_compare' );
+ // When the max_age_compare rank is zero, which is the case when it is at least the recommended 1 week, the transient will be deleted.
+ if ( $max_age === WEEK_IN_SECONDS ) {
+ $this->assertFalse( $cached_max_age_compare );
+ } else {
+ $this->assertNotFalse( $cached_max_age_compare );
+ }
+ $this->assertEquals( $expected, $cached_max_age_compare );
+ }
+
+ /**
+ * Data provider for delete_transient_on_option_update.
+ *
+ * @return array
+ */
+ public function delete_transient_on_option_update_provider() {
+ return [
+ [ 10, 300 ],
+ [ 3, 5 * DAY_IN_SECONDS ],
+ [ 0, WEEK_IN_SECONDS ],
+ ];
+ }
+
+}