diff --git a/.gitattributes b/.gitattributes index 33422e5d..18e38195 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,4 +10,4 @@ phpunit.*.xml.dist export-ignore .eslintignore export-ignore eslint.config.mjs export-ignore changelog/ export-ignore -.w.org-assets/ export-ignore +w.org-assets/ export-ignore diff --git a/.github/files/autorelease.sh b/.github/files/autorelease.sh deleted file mode 100755 index 1d72c0d3..00000000 --- a/.github/files/autorelease.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -: "${GH_TOKEN:?Build argument needs to be set and non-empty.}" -: "${GITHUB_REF:?Build argument needs to be set and non-empty.}" -: "${GITHUB_SHA:?Build argument needs to be set and non-empty.}" - -if [[ ! -f composer.json ]]; then - echo '::error::No composer.json. Did it get excluded from the mirror?' - exit 1 -fi - -## Determine tag -ROLLING_MODE= -if [[ "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+(\.[0-9]+)+(-[a-z0-9._-]+)?$ ]]; then - TAG="${GITHUB_REF#refs/tags/}" - - ## Check for alphas - if [[ "$TAG" =~ -(alpha|a\.[0-9]*[02468])$ ]]; then - echo "Not creating a release for alpha version $TAG" - exit 0 - fi -elif [[ "$GITHUB_REF" == "refs/heads/trunk" ]]; then - if ! jq -e '.extra.autorelease["rolling-release"]? // false' composer.json > /dev/null; then - echo "::notice::Skipping trunk release because autorelease rolling mode is not enabled." - exit 0 - fi - ROLLING_MODE=true - CURRENT_VER=$( sed -nEe 's/^## \[?([^]]*)\]? - .*/\1/;T;p;q' CHANGELOG.md || true ) - if [[ "$CURRENT_VER" != *-alpha ]]; then - # Bump a non-alpha release to the next alpha to avoid confusing version_compare. - CURRENT_VER=${CURRENT_VER%%-*} - CURRENT_VER=${CURRENT_VER%.*}.$(( ${CURRENT_VER##*.} + 1 ))-alpha - fi - GIT_SUFFIX=$( git log -1 --format="%ct.g%h" . ) - TAG="$CURRENT_VER+rolling.$GIT_SUFFIX" -else - echo "::error::Expected GITHUB_REF like \`refs/tags/v1.2.3\` or \`refs/tags/1.2.3\` or \`refs/heads/trunk\` for rolling releases, got \`$GITHUB_REF\`" - exit 1 -fi - -# Don't auto-release if there's a kill switch tag in place. -kill_switch_tag_name='autorelease_kill_switch' -kill_switch_tag=$( git ls-remote --tags origin "$kill_switch_tag_name" ) -if [[ -n "$kill_switch_tag" ]]; then - echo "::notice::Kill switch tag found ('$kill_switch_tag_name'); aborting auto-release." - exit 0 -fi - -echo "Creating release for $TAG" - -## Determine slug and title format. -SLUG="$(jq -r '.extra.autorelease.slug? // .extra["wp-plugin-slug"] // .extra["beta-plugin-slug"] // ( .name | sub( "^.*/"; "" ) )' composer.json)" -if [[ -z "$SLUG" ]]; then - echo '::error::Failed to get slug from composer.json.' - exit 1 -fi -echo "Using slug $SLUG" - -TITLEFMT="$(jq -r '.extra.autorelease.titlefmt? // "%s"' composer.json)" -if [[ "$TITLEFMT" != *"%s"* ]]; then - echo '::error::Missing or invalid `.extra.autorelease.titlefmt`' - exit 1 -fi -printf -v TITLE "$TITLEFMT" "${TAG#v}" -echo "Creating release \"$TITLE\"" - -## Create the archive artifact. -echo "::group::Creating $SLUG.zip" -git archive -v --output="$SLUG.zip" --prefix="$SLUG/" HEAD 2>&1 -echo "::endgroup::" - -if [[ -z "$ROLLING_MODE" ]]; then - ## Create the release note. - # Extract the changelog section. - echo "::group::Extracting release notes" - if [[ ! -f CHANGELOG.md ]]; then - echo '::endgroup::' - echo '::error::No CHANGELOG.md for release notes.' - exit 1 - fi - SCRIPT=" - /^## \\[?$(sed 's/[.\[\]\\*^$\/()+?{}|]/\\&/g' <<<"${TAG#v}")\\]? - / { - bc - :a - n - /^## / { - q - } - :c - s/^## \[([^]]+)\]/## \1/ - p - ba - } - " - ENTRY=$(sed -n -E -e "$SCRIPT" CHANGELOG.md) - if [[ -z "$ENTRY" ]]; then - echo '::endgroup::' - echo "::error::Failed to find section for ${TAG#v} in CHANGELOG.md" - exit 1 - fi - - # Strip unwanted sections. - SCRIPT=" - :a - /^### .* This section will not be copied to readme\.txt/ { - :b - n - /^#/ ba - bb - } - p - " - ENTRY=$(sed -n -E -e "$SCRIPT" <<<"$ENTRY") - - echo "Release notes:" - echo "-----" - echo "$ENTRY" - echo "-----" - echo "::endgroup::" -else - ## Using a brief explanation for the rolling release note. - ENTRY="### Rolling release based on the trunk branch." -fi - -if [[ -n "$ROLLING_MODE" ]]; then - echo "::group::Deleting stale rolling release" - - for R in $( gh release list --limit 1000000 --json tagName,publishedAt --jq '.[] | select( ( .tagName | contains( "+rolling" ) ) and ( .publishedAt | fromdateiso8601 < now - 86400 ) ) | .tagName' ); do - echo "Found $R, deleting" - gh release delete "$R" --cleanup-tag --yes - done - - echo "::endgroup::" -fi - - -echo "::group::Creating release" -gh release create "$TAG" "$SLUG.zip" \ - --notes "$ENTRY" \ - --target "$GITHUB_SHA" \ - --title "$TITLE" - -echo "::endgroup::" diff --git a/.github/files/wp-svn-autopublish.sh b/.github/files/wp-svn-autopublish.sh deleted file mode 100755 index 744243c9..00000000 --- a/.github/files/wp-svn-autopublish.sh +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -: "${GITHUB_REF:?Build argument needs to be set and non-empty.}" -if [[ -n "$CI" ]]; then - : "${WPSVN_USERNAME:?Build argument needs to be set and non-empty.}" - : "${WPSVN_PASSWORD:?Build argument needs to be set and non-empty.}" -fi - -## Determine tag -if [[ ! "$GITHUB_REF" =~ ^refs/tags/v?[0-9]+(\.[0-9]+)+(-[a-z0-9._-]+)?$ ]]; then - echo "::error::Expected GITHUB_REF like \`refs/tags/v1.2.3\` or \`refs/tags/1.2.3\`, got \`$GITHUB_REF\`" - exit 1 -fi -TAG="${GITHUB_REF#refs/tags/}" -TAG="${TAG#v}" - -## Determine slug -WPSLUG=$(jq -r '.extra["wp-plugin-slug"] // ""' "src/composer.json") -if [[ -z "$WPSLUG" ]]; then - echo '::error::Failed to determine plugin slug.' - exit 1 -fi - -echo "Publishing $WPSLUG version $TAG" - -mkdir svn -cd svn - -echo '::group::Checking out SVN (shallowly)' -svn checkout "https://plugins.svn.wordpress.org/$WPSLUG/" --depth=empty . -echo '::endgroup::' - -echo '::group::Checking out SVN trunk' -svn up trunk -echo '::endgroup::' - -echo "::group::Checking out SVN tags (shallowly)" -svn up tags --depth=immediates -echo '::endgroup::' - -if [[ -e "tags/$TAG" ]]; then - echo "::error::Tag $TAG already exists in SVN. Aborting." - exit 1 -fi - -echo "::group::Deleting everything in trunk except for .svn directories" -find trunk ! \( -path '*/.svn/*' -o -path "*/.svn" \) \( ! -type d -o -empty \) -delete -[[ -e trunk ]] || mkdir -p trunk # If there were no .svn directories, trunk itself might have been removed. -echo '::endgroup::' - -echo "::group::Copying git repo into trunk" -git clone ../src trunk/ -echo '::endgroup::' - -echo "::group::Removing .git files and empty directories" -find trunk -name '.git*' -print -exec rm -rf {} + -find trunk -type d -empty -print -delete -echo '::endgroup::' - -echo "::group::Adding and removing SVN files" -while IFS= read -r LINE; do - FLAGS="${LINE:0:7}" - FILE="${LINE:8}" - if [[ "$FLAGS" != ?' ' ]]; then - echo "Unexpected svn flags: $LINE" - fi - # The appending of an `@` to the filename here avoids problems with filenames containing `@` being interpreted as "peg revisions". - if [[ "${FLAGS:0:1}" == '!' ]]; then - svn rm "${FILE}@" - elif [[ "${FLAGS:0:1}" == "?" ]]; then - svn add "${FILE}@" - fi -done < <( svn status ) -echo '::endgroup::' - -# Check that the stable tag in trunk/readme.txt is not being changed. If it is, try to undo the change. -CHECK="$(svn diff trunk/readme.txt | grep '^[+-]Stable tag:' || true)" -if [[ -n "$CHECK" ]]; then - LINE="$(grep --line-number --max-count=1 '^Stable tag:' trunk/readme.txt)" - if grep -q '^+' <<<"$CHECK" && ! grep -q '^-' <<<"$CHECK"; then - # On the initial commit, it seems there's no way to specify not to immediately have that commit served as the stable version. - # So just print a notice pointing that out in case anyone is looking and leave it as-is. - echo "::notice::This appears to be the initial release of the plugin, which will unavoidably set the stable tag to the version being released now." - elif [[ -n "$LINE" ]]; then - echo "::warning::Stable tag must be updated manually! Update would change it, attempting to undo the change.%0A%0A${CHECK/$'\n'/%0A}" - nl=$'\n' - patch -R trunk/readme.txt <<<"@@ -${LINE%%:*},1 +${LINE%%:*},1 @@$nl$CHECK" - CHECK2="$(svn diff trunk/readme.txt | grep '^[+-]Stable tag:' || true)" - if [[ -n "$CHECK2" ]]; then - echo "::error::Attempt to revert stable tag change failed! Remaining diff:%0A%0A${CHECK2/$'\n'/%0A}" - exit 1 - fi - else - echo "::error::Stable tag must be updated manually! Update would change it.%0A%0A${CHECK/$'\n'/%0A}" - exit 1 - fi -fi - -if [[ -n "$CI" ]]; then - echo "::group::Committing to SVN" - svn commit -m "Update to version $TAG from GitHub" --no-auth-cache --non-interactive --username "$WPSVN_USERNAME" --password "$WPSVN_PASSWORD" - echo '::endgroup::' -else - echo "----" - echo "Not running in CI, skipping commit" - echo " svn commit -m \"Update to version $TAG from GitHub\" --no-auth-cache --non-interactive --username \"\$WPSVN_USERNAME\" --password \"\$WPSVN_PASSWORD\"" - echo "----" -fi - -if [[ -n "$CI" ]]; then - echo "::group::Creating tag" - svn cp "^/$WPSLUG/trunk" "^/$WPSLUG/tags/$TAG" --no-auth-cache --non-interactive --username "$WPSVN_USERNAME" --password "$WPSVN_PASSWORD" -m "Tagging version $TAG" - echo '::endgroup::' -else - echo "----" - echo "Not running in CI, skipping commit" - echo " svn cp \"^/$WPSLUG/trunk\" \"^/$WPSLUG/tags/$TAG\" --no-auth-cache --non-interactive --username \"\$WPSVN_USERNAME\" --password \"\$WPSVN_PASSWORD\" -m \"Tagging version $TAG\"" - echo "----" -fi - -# Update the "Stable tag" in the tag if it's not a beta version. -if [[ "$TAG" =~ ^[0-9]+(\.[0-9]+)+$ ]]; then - if [[ -n "$CI" ]]; then - echo "::group::Checking out new tag" - svn up "tags/$TAG" - echo '::endgroup::' - sed -i -e "s/^Stable tag: .*/Stable tag: $TAG/" "tags/$TAG/readme.txt" - echo "::group::Committing to SVN" - svn commit -m "Updating stable tag in version $TAG" --no-auth-cache --non-interactive --username "$WPSVN_USERNAME" --password "$WPSVN_PASSWORD" - echo '::endgroup::' - else - echo "----" - echo "Not running in CI, skipping tag \"Stable tag\" update" - echo " svn up \"tags/$TAG\"" - echo " sed -i -e \"s/^Stable tag: .*/Stable tag: $TAG/\" \"tags/$TAG/readme.txt\"" - echo " svn commit -m \"Updating stable tag in version $TAG\" --no-auth-cache --non-interactive --username \"\$WPSVN_USERNAME\" --password \"\$WPSVN_PASSWORD\"" - echo "----" - fi -else - echo "This is a prerelease version, not updating \"Stable tag\" in tag." -fi diff --git a/.github/workflows/autorelease.yml b/.github/workflows/autorelease.yml deleted file mode 100644 index 42d523f1..00000000 --- a/.github/workflows/autorelease.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Auto-release - -on: - push: - tags: - - 'v?[0-9]+.[0-9]+' - - 'v?[0-9]+.[0-9]+-*' - - 'v?[0-9]+.[0-9]+.[0-9]+' - - 'v?[0-9]+.[0-9]+.[0-9]+-*' - - 'v?[0-9]+.[0-9]+.[0-9]+.[0-9]+' - - 'v?[0-9]+.[0-9]+.[0-9]+.[0-9]+-*' - branches: - - 'trunk' - workflow_dispatch: - -permissions: - # read: actions/checkout - # write: `gh release` - contents: write - -jobs: - publish: - name: Release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - name: Create release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: ./.github/files/autorelease.sh diff --git a/.github/workflows/autotagger.yml b/.github/workflows/autotagger.yml deleted file mode 100644 index 677fddf9..00000000 --- a/.github/workflows/autotagger.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: Auto-tagger - -on: - push: - branches: - - trunk - - prerelease - - '*/branch-*' - workflow_dispatch: - -# We use secrets.API_TOKEN_GITHUB for everything here, so no need for permissions. -permissions: {} - -jobs: - tag: - name: Tag - runs-on: ubuntu-latest - steps: - - name: Check that the secret is set - env: - TOKEN: ${{ secrets.API_TOKEN_GITHUB }} - run: | - if [[ -z "$TOKEN" ]]; then - echo '::error::The secret API_TOKEN_GITHUB must be set.' - exit 1 - fi - - - uses: actions/checkout@v6 - with: - # We want to potentially trigger "tag" events, but the default GITHUB_TOKEN - # explicitly does not trigger events. - token: ${{ secrets.API_TOKEN_GITHUB }} - - - name: Check branch - id: check-branch - run: | - PREFIXES= - if [[ -e composer.json ]]; then - PREFIXES=$(jq -r '.extra["release-branch-prefix"] // "" | if type == "array" then .[] else . end' composer.json) - fi - if [[ -z "$PREFIXES" && "$GITHUB_REF" != "refs/heads/trunk" && "$GITHUB_REF" != "refs/heads/prerelease" ]]; then - echo "::error::Expected to be called for \"refs/heads/trunk\" or \"refs/heads/prerelease\", not \"$GITHUB_REF\"" - exit 1 - elif [[ -n "$PREFIXES" && ( "$GITHUB_REF" == "refs/heads/trunk" || "$GITHUB_REF" == "refs/heads/prerelease" ) ]]; then - echo "::notice::Ignoring push to $GITHUB_REF, as this project has a release branch prefix set (\"${PREFIXES//$'\n'/'" "'}\")" - echo "run=false" >> "$GITHUB_OUTPUT" - else - if [[ -n "$PREFIXES" ]]; then - OK=false - while IFS= read -r P; do - [[ "$GITHUB_REF" == "refs/heads/$P/branch-"* ]] && OK=true - done <<<"$PREFIXES" - if ! $OK; then - echo "::error::Expected to be called for \"refs/heads/\$PREFIX/branch-*\" for a prefix in \"${PREFIXES//$'\n'/'" "'}\", not \"$GITHUB_REF\"" - exit 1 - fi - fi - - echo "Push to \"$GITHUB_REF\" ok" - echo "run=true" >> "$GITHUB_OUTPUT" - fi - - - name: Check version - id: version - if: steps.check-branch.outputs.run == 'true' - run: | - VER=$(sed -nEe 's/^## \[?([^]]*)\]? - .*/\1/;T;p;q' CHANGELOG.md || true) - echo "Version from changelog is ${VER:-}" - echo "version=$VER" >> "$GITHUB_OUTPUT" - if [[ "$VER" =~ ^[0-9]+(\.[0-9]+)+(-[a-z0-9._-]+)?$ && ! "$VER" =~ -(alpha|a\.[0-9]*[02468])$ ]]; then - echo "Version $VER ok to tag" - echo "run=true" >> "$GITHUB_OUTPUT" - else - echo "::notice::Not tagging version $VER" - echo "run=false" >> "$GITHUB_OUTPUT" - fi - - - name: Check deps - id: check-deps - if: steps.check-branch.outputs.run == 'true' && steps.version.outputs.run == 'true' - run: | - RUN=true - if [[ -e composer.json ]]; then - TMP=$(jq -r '.require // {} | to_entries[] | select( .value | test( "-(alpha|a\\.[0-9]*[02468])$" ) ) | "\(.key) (\(.value))"' composer.json) - if [[ -n "$TMP" ]]; then - echo "::notice::Not tagging due to -alpha deps on ${TMP//$'\n'/ }" - RUN=false - fi - fi - echo "run=$RUN" >> "$GITHUB_OUTPUT" - - - name: Tag - if: steps.check-branch.outputs.run == 'true' && steps.version.outputs.run == 'true' && steps.check-deps.outputs.run == 'true' - env: - VER: ${{ steps.version.outputs.version }} - run: | - export GIT_AUTHOR_NAME=matticbot - export GIT_AUTHOR_EMAIL=matticbot@users.noreply.github.com - export GIT_COMMITTER_NAME=matticbot - export GIT_COMMITTER_EMAIL=matticbot@users.noreply.github.com - if [[ -e composer.json ]] && ! jq -e 'if try ( .extra.autotagger | has("v") ) catch false then .extra.autotagger.v else true end' composer.json >/dev/null; then - TAG="$VER" - else - TAG="v$VER" - fi - echo "::notice::Tagging $TAG" - git tag "$TAG" - git push origin "$TAG" - if [[ -e composer.json ]] && jq -e '.extra.autotagger.major?' composer.json >/dev/null; then - echo "::notice::Tagging ${TAG%%.*}" - git tag --force "${TAG%%.*}" - git push --force origin "${TAG%%.*}" - fi diff --git a/.github/workflows/changelogger.yml b/.github/workflows/changelogger.yml deleted file mode 100644 index f295ce99..00000000 --- a/.github/workflows/changelogger.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Changelogger - -on: - pull_request: - -jobs: - validate: - name: Validate changelog - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: shivammathur/setup-php@v2 - with: - php-version: '8.4' - tools: composer - coverage: none - - run: composer install --no-progress - - name: Check for changelog entry - run: | - BASE_SHA=${{ github.event.pull_request.base.sha }} - HEAD_SHA=${{ github.event.pull_request.head.sha }} - CHANGELOG_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'changelog/*') - if [ -z "$CHANGELOG_FILES" ]; then - echo "::warning::No changelog entry found. If this change is user-facing, please add one with: vendor/bin/changelogger add" - fi diff --git a/.github/workflows/wp-svn-autopublish.yml b/.github/workflows/wp-svn-autopublish.yml deleted file mode 100644 index 6551cbbe..00000000 --- a/.github/workflows/wp-svn-autopublish.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: WordPress SVN auto-publisher - -on: - push: - tags: - - 'v?[0-9]+.[0-9]+' - - 'v?[0-9]+.[0-9]+-*' - - 'v?[0-9]+.[0-9]+.[0-9]+' - - 'v?[0-9]+.[0-9]+.[0-9]+-*' - - 'v?[0-9]+.[0-9]+.[0-9]+.[0-9]+' - - 'v?[0-9]+.[0-9]+.[0-9]+.[0-9]+-*' - -permissions: - # actions/checkout - contents: read - -jobs: - publish: - name: Publish - runs-on: ubuntu-latest - steps: - - name: Check that the secret is set - env: - WPSVN_USERNAME: ${{ secrets.WPSVN_USERNAME }} - WPSVN_PASSWORD: ${{ secrets.WPSVN_PASSWORD }} - run: | - EXIT=0 - if [[ -z "$WPSVN_USERNAME" ]]; then - echo '::error::The secret WPSVN_USERNAME must be set.' - EXIT=1 - fi - if [[ -z "$WPSVN_PASSWORD" ]]; then - echo '::error::The secret WPSVN_PASSWORD must be set.' - EXIT=1 - fi - exit $EXIT - - - name: Install svn - run: command -v svn || sudo apt-get install -y subversion - - - uses: actions/checkout@v6 - with: - path: src - - - name: Publish - env: - WPSVN_USERNAME: ${{ secrets.WPSVN_USERNAME }} - WPSVN_PASSWORD: ${{ secrets.WPSVN_PASSWORD }} - run: ./src/.github/files/wp-svn-autopublish.sh diff --git a/.gitignore b/.gitignore index 140fd587..360e0524 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ vendor/ node_modules/ +build/ +/package-lock.json diff --git a/.wp-env.json b/.wp-env.json new file mode 100644 index 00000000..9112924f --- /dev/null +++ b/.wp-env.json @@ -0,0 +1,15 @@ +{ + "core": null, + "plugins": [ "." ], + "config": { + "WP_DEBUG": true, + "WP_DEBUG_LOG": true, + "WPCACHEHOME": "/var/www/html/wp-content/plugins/wp-super-cache/" + }, + "mappings": { + "wp-content/plugins/wp-super-cache": ".", + "wp-content/mu-plugins": "./tests/dev/mu-plugins" + }, + "testsEnvironment": false, + "phpVersion": "8.1" +} diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 467d4a98..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,875 +0,0 @@ -# Changelog - -### This is a list detailing changes for all Super Cache releases. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [4.0.0-alpha] - unreleased - -This is an alpha version! The changes listed here are not final. - -### Added -- Add a WordPress.org Live Preview Blueprint. - -### Changed -- Device Detection: use an embedded version instead of the Composer dependency -- Switch to Native TypeScript compiler based on Go. -- Update package dependencies. - -### Removed -- General: Update minimum WordPress version to 6.8. - -### Fixed -- Ensure proper flags are used with `json_encode()`. -- Fix a PHP warning when the newest cached pages list is unavailable. -- Fix TS errors detected by tsgo. -- Fix `str_starts_with()` PHP 8.1+ deprecation when `$wp_cache_home_path` is null in `get_current_url_supercache_dir()`. -- Remove `.eslintignore` and fix JS linting errors in `delete-cache-button.js`. - -## [3.0.3] - 2025-11-11 -### Added -- Tested up to WordPress 6.9. [#45571] - -### Changed -- Update package dependencies. [#45478] [#45652] - -### Fixed -- Phan: Address PhanRedundantCondition, PhanRedundantArrayValuesCall, and PhanPluginRedundantAssignment violations. [#45681] -- Remove redundant code. [#45733] - -## [3.0.2] - 2025-10-10 -### Added -- Add typecheck support for E2E tests. [#44788] - -### Changed -- Update package dependencies. [#44725] [#44873] [#44898] [#45096] [#45097] [#45159] -- Use `wp_rand()` instead of `rand()` and `mt_rand()`. [#44964] - -### Fixed -- Code: Resolve PhanImpossibleCondition violations. [#44869] - -## [3.0.1] - 2025-08-05 -### Added -- Caching: Ignore Yandex parameters so those visitors are served from the cache. [#44618] - -### Changed -- Update package dependencies. [#44206] [#44506] - -## [3.0.0] - 2025-06-10 -### Changed -- Code: First pass of style coding standards. [#42734] -- Update package dependencies. [#43425] [#43766] [#43839] - -### Removed -- General: Update minimum WordPress version to 6.7. [#43192] - -### Fixed -- Code: Update stylesheets to use hex instead of named colors. [#42920] -- General: Improve WP CLI support by making variables global. [#43286] -- Linting: Fix more Stylelint violations. [#43213] - -## [2.0.1] - 2025-04-04 -### Changed -- Code: Use function-style `exit()` and `die()` with a default status code of 0. [#41167] -- Update package dependencies. [#40980] [#41659] [#42180] [#42308] [#42762] [#42815] - -## [2.0.0] - 2025-01-10 -### Added -- Enable test coverage. [#39961] - -### Changed -- General: Indicate compatibility with the upcoming version of WordPress - 6.7. [#39786] -- Update package dependencies. [#38822] [#38870] [#39004] [#39278] [#39288] [#39653] [#40116] [#40515] - -### Removed -- Cleaned up legacy code. [#40200] -- General: Update minimum PHP version to 7.2. [#40147] -- General: Update minimum WordPress version to 6.6. [#40146] - -### Fixed -- Caching: make sure there is cache content to serve, even if the cache file was found [#40342] -- Ensure homepage cache gets flushed when a post is unpublished. [#40879] -- Lossless image optimization for images (should improve performance with no visible changes). [#38750] [#38981] -- Move trailing space out of i18n message. [#39305] -- Fix apache_request_headers fallback so it works when that command is disabled. [#39951] - -## [1.12.4] - 2024-07-17 -### Removed -- General: update WordPress version requirements to WordPress 6.5. [#38382] - -### Fixed -- Fixed problem with is_utf8_charset missing in WP 6.6 [#38383] - -## [1.12.3] - 2024-07-10 -### Fixed -- Don't delete the log viewer when doing garbage collection [#38276] -- Fix clearing the cache when scheduled posts are published [#38263] - -## [1.12.2] - 2024-06-27 -### Added -- add an admin notice to encourage migration to Jetpack Boost [#37933] -- modify boost install code so it can be used by multiple buttons [#37824] -- notify Boost of migration to that plugin [#37797] - -### Changed -- General: indicate compatibility with the upcoming version of WordPress - 6.6. [#37962] -- tell user that Cache module of Boost must be deactivated to use WPSC [#37265] -- WP Updated banner designs, added auto-install Jetpack Boost buttons [#37963] - -### Fixed -- Detect when WP_CACHE is defined with "const" in wp-config.php [#38022] -- Align detection of Boost installs with activation of that plugin [#37896] -- create the cache directory before creating the config file [#38028] -- do not show migration notice if already using Boost Cache [#38005] -- fixed a PHP warning when deactivating the plugin. [#37968] -- make sure plugins links is an array before using it. [#37604] -- remove the preload interval based on the post count. Preload as often as you want. [#37618] -- renamed WPSC_VERSION because it conflicted with other plugins [#38007] - -## [1.12.1] - 2024-05-09 -### Changed -- General: update WordPress version requirements to WordPress 6.4. [#37047] -- General: use wp_admin_notice function introduced in WP 6.4 to display notices. [#37051] - -### Fixed -- Fix the CDN functionality when cache is disabled [#37112] -- Do not define DONOTCACHEPAGE if it is already defined [#36423] - -## [1.12.0] - 2024-03-11 -### Added -- Setup: Detect Jetpack Boost cache and suggest troubleshooting steps [#36018] -- WP Super Cache: added WPSC_PRELOAD_POST_INTERVAL and WPSC_PRELOAD_LOOP_INTERVAL to modify preload timings [#36246] - -### Changed -- Code Modernization: Replace usage of strpos() with str_contains() [#34137] -- Code Modernization: Replace usage of strpos() with str_starts_with(). [#34135] -- Code Modernization: Replace usage of substr() with str_starts_with() and str_ends_with(). [#34207] -- Fix blurry Automattic logo. [#34985] -- General: avoid deprecation warnings when trying to get URLs in PHP 8.2 [#34962] -- General: indicate compatibility with the upcoming version of WordPress, 6.5. [#35820] -- General: updated PHP requirement to PHP 7.0+ [#34126] -- General: update WordPress version requirements to WordPress 6.3. [#34127] -- WP Super Cache: check for Boost Cache when creating advanced-cache.php [#36027] -- WP Super Cache: fixed labels on advanced settings page [#36067] -- WP Super Cache: remove notifications that preload started working again. [#35960] - -### Fixed -- Supercache: add "days" to "Next preload scheduled" message. [#34509] -- Super Cache: with rebuild enabled, apply that to subdirectories instead of deleting them. [#35032] -- WP Super Cache - fix the wp_super_cache_clear_post_cache filter so the homepage cache isn't deleted too. [#36069] -- WP Super Cache: bail if the request uri isn't set. It means the plugin isn't configured yet. [#36024] -- WP Super Cache: don't create an output buffer if there's already one active [#36124] -- WP Super Cache: fixed serving a cached page on POST with late init enabled. [#36211] -- WP Super Cache: fix the output buffer check, and make debug logs pre-formatted. [#36158] -- WP Super Cache: if the preload number of posts is not in the list, then add it [#36249] - -## [1.11.0] - 2023-11-08 -### Added -- Super Cache: fix "accept header" check, and add new "wpsc_accept_headers" filter on accept header list [#33972] - -### Changed -- General: indicate full compatibility with the latest version of WordPress, 6.4. [#33776] -- General: update WordPress version requirements to WordPress 6.2. [#32762] -- Overhauled visual styling to match Jetpack branding [#32981] -- Updated package dependencies. [#32307] -- Updated package dependencies. [#32605] -- Updated package dependencies. [#32966] -- Updated package dependencies. [#33498] - -### Fixed -- Caching: make sure $wp_cache_request_uri is defined to avoid warnings about "NULL" parameters. [#32629] -- super-cache: fixed null parameter warning when using $supercachedir [#33970] -- Super Cache: cancel the full preload job correctly. [#33560] - -## [1.10.0] - 2023-08-16 -### Added -- Caching: Added support for the 'Accept' HTTP Header. Prevent caching JSON content. [#29456] -- Preload: Improved preload notification panel shows the last 5 preloaded URLs. [#31017] - -### Changed -- General: Indicate full compatibility with the latest version of WordPress, 6.3. [#31910] -- General: Update Boost install / activate card styles. [#31311] -- General: Update documentation links to point to Jetpack.com docs. [#32164] -- General: Update the contributors list. [#29241] -- Preload: Faster and more robust preloading slower hosts. [#30450] - -### Removed -- Cleanup: Removes unwanted development environment files from production version of the plugin. [#30216] -- Cleanup: Remove unused "object cache" code. [#31783] - -### Fixed -- Cache Compression: Fix PHP warning appearing in gzip output stream. [#31487] -- Caching: Reject unknown or malformed URIs to prevent PHP warnings. [#31786] -- Dynamic Caching: Fixed incorrect encoding headers when using dynamic caching with compression. [#32106] -- Setting page: Fixed boost banner getting oversized when zoomed out -- General: Fix incorrect Debug Log URL for nested WordPress installations. [#29985] -- General: Fix links to cache directory on sites that are in a sub directory. [#30872] -- General: Updated Nginx documentation hyperlink. [#31420] -- Preload: No longer deletes child taxonomies during preload. [#30830] -- Preload: Use a constant instead of hard-coded email numbers in preload dropdown. [#30713] -- Caching: Prevent Super Cache from attempting to gunzip content which is not zipped -- General: Fix null/false warning in PHP8.1 - -## [1.9.4] - 2023-02-28 -### Added -- Added new filter which controls cache clearing on post edit. [#28556] -- Added a check to ensure preload cronjobs exist when updating preload settings. [#28545] - -### Changed -- Updated contributors list. [#28891] - -### Fixed -- Fixed undefined PHP variable when trying to delete a protected folder. [#28524] -- Fixed deprecation warnings on PHP 8.1+. [#28959] - -## [1.9.3] - 2023-01-23 -### Added -- Added new filters to set mod_expires rules and HTTP headers in the cache htaccess file. [#28031] - -### Fixed -- Fixed an issue that caused wp-config.php file permissions to change. [#28164] -- Fixed missing missing action 'wp_cache_cleared' when clearing the cache on post update. [#28481] - -## [1.9.2] - 2022-12-09 -### Added -- Added a dismissable option to install Jetpack Boost. [#26702] -- Improved stability with the start of an end-to-end test suite. [#26462] -- Tested with v6.1 of WordPress. [#26831] - -### Changed -- Updated package dependencies. - -### Fixed -- Compatibility: Avoid use of QUERY_STRING value, which is not available in all environments. [#26251] -- Updated links to related plugins to remove click-tracking redirects. [#26757] - -## [1.9.1] - 2022-11-02 -### Fixed -- Fixes crash when using the “Jetpack Mobile Theme” plugin alongside Jetpack 11.5. - -## [1.9.0] - 2022-09-16 -### Added -- Cache deletion: add new hook to trigger actions after a successful cache deletion from the admin bar. [#26202] - -### Fixed -- Fixes to URL parsing to prevent cache pollution issues around URLs with double-slashes. [#26247] - -## [1.8] - 2022-08-16 -### Added -- PHP 8 Support: Ensure the expected value for the $auto_release in sem_get is used. -- Added a link to give feedback on WP Super Cache -- Added information on Jetpack Boost - -### Fixed -- Fixed jQuery deprecated notice -- Fixed replacing dirname(__FILE__) with __DIR__ - -## 1.7.9 - 2022-06-07 - -- Fix nonces used by "Delete Cache" button and remove JS from it on the frontend admin bar. -- Define the constant WPSCDISABLEDELETEBUTTON to disable the "Delete Cache" button in the admin bar. - -## 1.7.8 - 2022-06-07 - -* Change the admin bar "Delete Cache" button into an AJAX link #808 #810 -* Fix link to log file in custom WordPress structure #807 -* Add an auto updating preload message. #811 #816 -* Use REQUEST_URI instead of GET to check GET status. #813 -* Add commonWP and disclaimer to "recommended links" #812 -* Hide warnings in case files deleted #814 -* Remove the GET param when removing tracking params #818 -* Check that post is private to unpublish it and clear cache 2249e58e6f585d936c0993e9d18e6382fa976a66 -* Check $gc_flag was opened before closing it. #819 - -## 1.7.7 - 2022-02-01 - -* Fixes to settings page - -## 1.7.6 - 2022-01-31 - -* Fix for PHP < 7.3 - -## 1.7.5 - 2022-01-31 - -* Move the text of the settings pages into separate files. #791 -* Allow editors to delete all the cache files. #793 -* Only clear the cache from the current site, not the whole network (admin bar link). #794 -* Check $cache_path is somewhat sane. #797 -* realpath returns false if directory not found. #798 -* Don't reject bots for new installs. They "preload pages" too. #800 - -## 1.7.4 - 2021-07-08 - -* Make config file path configurable, props @sebastianpopp #755 -* Stop a very rare/difficult attack when updating wp-config.php, props @guyasyou for reporting. #780 -* Add textbox to add tracking parameters to ignore when caching. props @markfinst, @radex02 #777 -* Add "Rejected Cookies" setting to the advanced settings page. #774 - -## 1.7.3 - 2021-04-28 - -* Sanitize the settings that are written to the config file #763 -* Fix the display of "direct cached" example urls in some circumstance. #766 - -## 1.7.2 - 2021-03-15 - -* Fixed authenticated RCE in the settings page. Props @m0ze -* Small bug fixes. - -## 1.7.1 - 2020-01-30 - -* Minor fixes to docs. #709 #645 -* Fixed typo on cache contents page. #719 -* Fixed array index warning. #724 -* Updated yellow box links. #725 - -## 1.7.0 - 2020-01-27 - -* Added "wpsc_cdn_urls" filter to modify the URLs used to rewrite URLs. #697 -* Fixed CDN functionality for logged in users. #698 -* Disable settings that don't work in Expert mode. #699 -* Don't enable mobile support by default, but it can still be enabled manually. #700 -* Change "admin bar" to "Toolbar". Props @garrett-eclipse. #701 -* Show settings enabled by "easy" settings page. #703 - -## 1.6.9 - 2019-07-25 - -* Improve the variables and messaging used by advanced-cache.php code. #687 -* Add a warning message to the debug log viewer. #688 -* Disable raw viewing of the debug log. #691 -* Clean up the debug log. #692 #694 -* Added wpsc_update_check() in 9659af156344a77ae247dc582d52053d95c79b93. - -## 1.6.8 - 2019-06-27 - -* Added new constants, WPSC_SERVE_DISABLED (disable serving of cached files) and WPSC_SUPERCACHE_ONLY (only serve supercache cache files). #682 and #672 -* Hide get_post() warning on some sites. #684 -* Check if WPCACHEHOME is set correctly before maybe updating it. #683 -* Remove object cache support as it never worked properly. #681 -* Add "logged in users" to the "do not cache for users" setting and rename that setting to "Cache Restrictions" #657 - -## 1.6.7 - 2019-05-30 - -* wp_cache_setting() can now save boolean values since many of the settings are bools. #676 -* Check if $super_cache_enabled is true in a less strict way because it might be '1' rather than true. #677 - -## 1.6.6 - 2019-05-28 - -* Fix problems with saving settings. Returns false ONLY when there's an issue with the config file, not when the setting isn't changed. Change other code to cope with that, including updating WPCACHEHOME (#670) -* When saving settings rename the temporary config file correctly, and delete wp-admin/.php if it exists. (#673) -* Fix adding WPCACHEHOME to wp-config.php when advanced-cache.php is not found and wp-config.php is RO. (#674) - -## 1.6.5 - 2019-05-27 - -* Check advanced-cache.php was created by the plugin before modifying/deleting it. (#666) -* When saving settings, save blank lines. Fixes problems with WP_CACHE and WPCACHEHOME in wp-config.php. Related to #652. (#667) -* Update outdated code and use is_multisite() (#600) -* Fix the delete cache button in the Toolbar. (#603) -* Code cleanup in #602 -* Use get_post_status instead of post_status (#623) -* Fixes button - Update Direct Pages (#622) -* Removes apache_response_headers and uses only headers_list (#618) -* Function is_site_admin has been deprecated (#611) -* Fixes action urls in wp_cache_manager (#610) -* Remove the link to the HibbsLupusTrust tweet. (#635) -* Don't load wp-cache-config.php if it's already loaded (#605) -* PHPCS fixes and optimization for plugins/domain-mapping.php (#615) -* Introduces PHP_VERSION_ID for faster checking (#604) -* Fixes regex and optimizes ossdl-cdn.php (#596) -* Only update new settings and use a temporary file to avoid corruption. (#652) -* Serve cached files to rejected user agents, don't cache them. (#658) -* Combine multiple headers with the same name (#641) -* Open ‘Delete Cache’ link in same window (#656) -* Promote the Jetpack Site Accelerator on the CDN page. (#636) - -## 1.6.4 - 2018-08-22 - -* Changes between [1.6.3 and 1.6.4](https://github.com/Automattic/wp-super-cache/compare/1.6.3...1.6.4) -* Fixes for WP-CLI (#587) (#592) -* Bumped the minimum WordPress version to 3.1 to use functions introduced then. (#591) -* Fixes to wpsc_post_transition to avoid a fatal error using get_sample_permalink. (#595) -* Fixed the Toolbar "Delete Cache" link. (#589) -* Fixed the headings used in the settings page. (#597) - -## 1.6.3 - 2018-08-10 - -* Changes between [1.6.2 and 1.6.3](https://github.com/Automattic/wp-super-cache/compare/1.6.2...1.6.3) -* Added cookie helper functions (#580) -* Added plugin helper functions (#574) -* Added actions to modify cookie and plugin lists. (#582) -* Really disable garbage collection when timeout = 0 (#571) -* Added warnings about DISABLE_WP_CRON (#575) -* Don't clean expired cache files after preload if garbage collection is disabled (#572) -* On preload, if deleting a post don't delete the sub directories if it's the homepage. (#573) -* Fix generation of semaphores when using WP CLI (#576) -* Fix deleting from the Toolbar (#578) -* Avoid a strpos() warning. (#579) -* Improve deleting of cache in edit/delete/publish actions (#577) -* Fixes to headers code (#496) - -## 1.6.2 - 2018-06-19 - -* Fixed serving expired supercache files (#562) -* Write directly to the config file to avoid permission problems with wp-content. (#563) -* Correctly set the .htaccess rules on the main site of a multisite. (#557) -* Check if set_transient() exists before using it. (#565) -* Removed searchengine.php example plugin as it sets a cookie to track users. Still available [here](https://github.com/Automattic/wp-super-cache/blob/4cda5c0f2218e40e118232b5bf22d227fb3206b7/plugins/searchengine.php). (#567) -* For advanced users only. Change the vary and cache control headers. See https://github.com/Automattic/wp-super-cache/pull/555 (#555) - -## 1.6.1 - 2018-05-15 - -* Fix the name of the WP Crontrol plugin. (#549) -* Handle errors during deactivation/uninstall by email rather than exiting. (#551) -* Add a notice when settings can't be updated. (#552 and #553) - -## 1.6.0 - 2018-04-30 - -* Fix issues in multisite plugin (#501) -* Fixes wp-cli plugin deactivate/activate (#499) -* Cleanup - change quotes. (#495) -* $htaccess_path defines the path to the global .htacess file. (#507) -* Fix 'cannot redeclare gzip_accepted()' (#511) -* Correct the renaming of tmp_wpcache_filename (removed unnecessary slash in path) which caused renaming to fail. (#516) -* Add check for Jetpack mobile theme cookie (#515) -* Optimize wp_cache_phase2 and create wpsc_register_post_hooks (#508) -* WPCACHEHOME has a trailing slash (#513) -* Cleanup cache enable/disable and update_mod_rewrite_rules (#500) -* Post Update now clears category cache (#519) -* Various fixes for saving the debug page form (#542) -* Expert-caching and empty parameters, like ?amp, should not serve cached page (#533) -* Tiny Yslow description fix (#527) -* Add ipad to mobile list (#525) -* Hide opcache_invalidate() warnings since it's disabled some places. (#543) -* Check that HTTP_REFERER exists before checking it. (#544) -* Replace Cron View" with WP Crontrol because it's still updated. (#546) -* adding hook (wp_cache_cleared) for full cache purges (#537) - -## 1.5.9 - 2017-12-15 - -* Fixed fatal error if the debug log was deleted while debugging was enabled and a visitor came to the site. -* Fixed the dynamic caching test plugin because of PHP7 changes. Dynamic cache mode must be enabled now. -* Lots of WordPress coding style formatting fixes to the code. -* All changes: https://github.com/Automattic/wp-super-cache/compare/1.5.8...1.5.9 - -## 1.5.8 - 2017-10-31 - -* PHP 7 fixes. (#429) -* Fix debug comments checkbox. (#433) -* Only register uninstall function in admin pages to save queries. (#430) -* Check that wp-cache-phase1.php is loaded before saving settings page. (#428) -* If a url has a "?" in it then don't delete the associated cache. It'll delete the whole cache after stripping out ?... part. (#427 & #420) -* Allow static functions in classes to be used in cacheactions. (#425) -* Don't make AJAX requests anonymous. (#423) -* Fixed link to chmod explanation. (#421) -* Add more escaping to the CDN settings page. (#416) -* Use SERVER_PROTOCOL to determine http protocol. (#412 & #413) -* If preload stalls only send one email per day, but do display an admin notice. (#432) -* Fixed more PHP warnings in #438 and #437 -* Hide mod_rewrite warnings for Nginx users. #434 - -## 1.5.7.1 - 2017-10-11 - -* If the HTTP HOST is empty then don't use it in strpos to avoid a PHP warning. (#408) -* Don't preload posts with permalinks that contain rejected strings. (#407) -* Generate a list of archive feeds that can be deleted when the site is updated. Also fixes corrupted config file issue and fatal error with older versions of WordPress. (#403) - -## 1.5.7 - 2017-10-06 - -* Fix fatal error in plugins/searchengine.php (#398) - -## 1.5.6 - 2017-10-04 - -* REST API: Added /plugins endpoint to handle the plugins settings page. (#382) -* Minor changes to indentaion and spaces to tabs conversion (#371) (#395) -* Don't set $wp_super_cache_comments here as it's not saved. (#379) -* realpath() only works on directories. The cache_file wasn't set correctly. (#377) -* Fix problem deleting cache from Toolbar because of realpath() (#381) -* Use trigger_error() instead of echoing to the screen if a config file isn't writeable. (#394) -* Added the "wpsc_enable_wp_config_edit" filter to disable editing the wp-config.php (#392) -* Fix some PHP notices when comments are edited/published/maintained. (#386) -* Minor changes to description on plugins page. (#393) - -## 1.5.5 - 2017-08-29 - -* Catch fatal errors so they're not cached, improve code that catches unknown page types. (#367) -* Fix caching on older WP installs, and if the plugin is inactive on a blog, but still caching, give feeds a short TTL to ensure they're fresh. (#366) -* When preloading don't delete sub-directories, or child pages, when caching pages. (#363) -* Avoid PHP warnings from the REST API for settings that are not yet defined. (#361) -* Added missing settings to the config file. (#360) - -## 1.5.4 - 2017-08-23 - -* Fix messages related to creating advanced-cache.php (#355, #354) -* Deleting the plugin doesn't need to delete the cache directory as it's already done on deactivation. (#323) -* Disable Jetpack mobile detection if Jetpack Beta is detected. (#298) -* Add more checks on directories to make sure they exist before deleting them. (#324) -* Add siteurl setting to CDN page for users who have WordPress in it's own directory. (#332) -* Don't enable and then not save debug comments when toggling logging. (#334) -* Show plugin activity html comments to users who disable caching for logged in users. (#335) -* Better notifications on Preload page, and redo sql to fetch posts. Added "wpsc_preload_post_types_args" filter on post visibility, and wpsc_preload_post_types filter on post types used. (#336) -* Use a cached feed if it is newer than the last time a post was updated. (#337) -* Better define a sitemap (#340) but when the content type is unknown add more checks to find out what it is. (#346) -* Save cache location correctly on the advanced settings page. (#345) -* Make sure the debug log exists before toggling it on/off to ensure the http auth code is added to it. -* Return the correct cache type to the REST API. Ignore supercache enabled status. (#352) -* Fix cache contents in REST API showing double count of supercache files. (#353) -* Move the nonce in the CDN page back into a function. (#346) -* Use realpath to compare directories when loading the sample config file to account for symlinked directories. (#342) -* Other minor changes to html or typos -(Numbers are [pull requests](https://github.com/Automattic/wp-super-cache/pulls) on Github.) - -## 1.5.3 - 2017-07-26 - -* Fix a critical bug that caused unlink to be run on null while deleting the plugin. - -## 1.5.2 - 2017-07-26 - -* Add a trailing slash to home path. Fixes problems with finding the .htaccess file. -* Delete WPCACHEHOME and WP_CACHE from wp-config.php when plugin deactivated. -* Check that WPCACHEHOME is the right path on each load of the settings page. -* Load the REST API code without using WPCACHEHOME. -* Fixed mobile browser caching when using WP-Cache caching. -* Fixed directory checks on Windows machines. -* Reverted CDN changes in 1.5.0 as they caused problems in older "WordPress in a separate directory" installs. -* Added note to CDN page when site url != home url. Site owners can use a filter to adjust the URL used. -* Stop preload quicker when requested while preloading taxonomies. -* Added more information for when updating the .htaccess file fails. -* "Served by" header is now optional. Enable it by setting $wpsc_served_header to true in the config file. - -## 1.5.1 - 2017-07-20 - -* Don't use anonymous functions in REST API -* Check that REST API Controller is available before loading the REST API. -* Don't use multibyte string functions because some sites don't have it enabled. - -## 1.5.0 - 2017-07-19 - -* REST API settings endpoints. -* Simplified settings page. -* WP-Cache files reorganised. -* Caching of more http headers. -* Lots of bug fixes. - -## 1.4.9 - 2017-06-01 - -* Fixed bug when not running sem_remove after sem_release. See https://github.com/Automattic/wp-super-cache/issues/85 -* Fixed a PHP error impacting PHP 7.1. -* Fixed a bug where we cached PUT and DELETE requests. We're treating them like POST requests now. -* Delete supercache cache files, even when supercache is disabled, because mod_rewrite rules might still be active. -* Updated the settings page, moving things around. [#173](https://github.com/Automattic/wp-super-cache/pull/173) -* Make file locking less attractive on the settings page and fixed the WPSC_DISABLE_LOCKING constant so it really disables file locking even if the user has enabled it already. -* Added a WPSC_REMOVE_SEMAPHORE constant that must be defined if sem_remove() is to be used as it may cause problems. [#174](https://github.com/Automattic/wp-super-cache/pull/174) -* Added a "wpsc_delete_related_pages_on_edit" filter that on returning 0 will disable deletion of pages outside of page being edited. [#175](https://github.com/Automattic/wp-super-cache/pull/175) -* Fixed plugin deleting all cached pages when a site had a static homepage. [#175](https://github.com/Automattic/wp-super-cache/pull/175) -* Make sure $cache_path has a trailing slash [#177](https://github.com/Automattic/wp-super-cache/pull/77) -* Remove flush() [#127](https://github.com/Automattic/wp-super-cache/pull/127) but also check if headers are empty and flush and get headers again. [#179](https://github.com/Automattic/wp-super-cache/pull/179) -* Add fix for customizer [#161](https://github.com/Automattic/wp-super-cache/pull/161) and don't cache PUT AND DELETE requests [#178](https://github.com/Automattic/wp-super-cache/pull/178) -* Check for superglobals before using them. [#131](https://github.com/Automattic/wp-super-cache/pull/131) - -## 1.4.8 - 2017-01-11 - -* Removed malware URL in a code comment. (harmless to operation of plugin but gets flagged by A/V software) -* Updated translation file. - -## 1.4.7 - 2016-12-09 - -* Update the settings page for WordPress 4.4. layout changes. - -## 1.4.6 - 2015-10-09 - -* Generate the file cache/.htaccess even when one exists so gzip rules are created and gzipped pages are served correctly. Props Tigertech. https://wordpress.org/support/topic/all-website-pages-downloading-gz-file-after-latest-update?replies=36#post-7494087 - -## 1.4.5 - 2015-09-25 - -* Enhancement: Only preload public post types. Props webaware. -* Added an uninstall function that deletes the config file. Deactivate function doesn't delete it any more. -* Possible to deactivate the plugin without visiting the settings page now. -* Fixed the cache rebuild system. Rebuild files now survive longer than the request that generate them. -* Minor optimisations: prune_super_cache() exits immediately if the file doesn't exist. The output of wp_cache_get_cookies_values() is now cached. -* Added PHP pid to the debug log to aid debugging. -* Various small bug fixes. -* Fixed reset of expiry time and GC settings when updating advanced settings. -* Removed CacheMeta class to avoid APC errors. It's not used any more. -* Fixed reset of advanced settings when using "easy" settings page. -* Fixed XSS in settings page. -* Hide cache files when servers display directory indexes. -* Prevent PHP object injection through use of serialize(). - -## 1.4.4 - 2015-05-15 - -* Fixed fatal error in output handler if GET parameters present in query. Props webaware. -* Fixed debug log. It wasn't logging the right message. - -## 1.4.3 - 2015-04-03 - -* Security release fixing an XSS bug in the settings page. Props Marc Montpas from Sucuri. -* Added wp_debug_log(). Props Jen Heilemann. -* Minor fixes. - -## 1.4.2 - 2014-12-18 - -* Fixed "acceptable file list". -* Fixed "Don't cache GET requests" feature. -* Maybe fixed "304 not modified" problem for some users. -* Fixed some PHP warnings. - -## 1.4.1 - 2014-08-07 - -* Fixed XSS in settings page. Props Simon Waters, Surevine Limited. -* Fix to object cache so entries may now be deleted when posts updated. (object cache still experimental) -* Documentation updates and cleanup of settings page. - -## 1.4 - 2014-04-17 - -* Replace legacy mfunc/mnclude/dynamic-cached-content functionality with a "wpsc_cachedata" cacheaction filter. -* Added dynamic-cache-test.php plugin example wpsc_cachedata filter plugin. -* Delete post, tag and category cache when a post changes from draft to publish or vice versa. Props @Biranit. -* Update advanced-cache.php and wp-config.php if wp-cache-phase1.php doesn't load, usually happening after migrating to a new hosting service. -* Misc bugfixes. - -## 1.3.2 - 2013-08-19 - -* Any mfunc/mclude/dynamic-cached-content tags in comments are now removed. -* Dynamic cached content feature disabled by default and must be enabled on the Advanced Settings page. -* Support for the mobile theme in Jetpack via helper plugin on script's Plugins tab. - -## 1.3.1 - 2013-04-12 - -* Minor updates to documentation -* Fixed XSS in settings page. - -## 1.3 - 2013-04-11 - -* mfunc tags could be executed in comments. Fixed. -* More support for sites that use the LOGGED_IN_COOKIE constant and custom cookies. - -## 1.2 - 2012-12-13 - -* Garbage collection of old cache files is significantly improved. I added a scheduled job that keeps an eye on things and restarts the job if necessary. Also, if you enable caching from the Easy page garbage collection will be enabled too. -* Editors can delete single cached files from the Toolbar now. -* Fixed the cached page counter on the settings page. -* Some sites that updated to 1.0 experienced too much garbage collection. There are still stragglers out there who haven't upgraded but that's fixed now! -* Supercached mobile files are now used as there was a tiny little typo that needed fixing. -* If your site is in a directory and you saw problems updating a page then that should be fixed now. -* The deactivate hook has been changed so your configuration isn.t hosed when you upgrade. Unfortunately this will only happen after you do this upgrade. -* Some sites use custom cookies with the LOGGED_IN_COOKIE constant. Added support for that. -* Added support for WPTouch Pro, but it appears to be flaky still. Anyone have time to work on that? I don.t. -* Some sites had problems with scheduled posts. For some reason the plugin thought the post was in draft mode and then because it only checked the same post once, when the post magically became published the cache wasn.t cleared. That.s fixed, thanks to the debug logging of several patient users. -* And more bug fixes and translation updates. - -## 1.1 - 2012-06-13 - -* Use $_SERVER[ 'SERVER_NAME' ] to create cache directories. -* Only create blogs cached directories if valid requests and blogs exist. -* Only clear current blog's cache files if navigation menu is modified -* Added clean_post_cache action to clear cache on post actions -* Removed garbage collection details on Contents tab -* Added wp_cache_check_mobile cacheaction filter to shortcircuit mobile device check. -* Don't delete cache files for draft posts -* Added action on wp_trash_post to clear the cache when trashed posts are deleted -* Show a warning when 304 browser caching is disabled (because mod_rewrite caching is on) -* New check for safe mode if using less that PHP 5.3.0 -* Added wp_supercache_remove_cookies filter to disable anonymous browsing mode. -* Fixed garbage collection schedule dropdown -* Fixed preload problem clearing site's cache on "page on front" sites. -* Fix for PHP variable not defined warnings -* Fixed problem refreshing cache when comments made as siteurl() sometimes didn't work -* Preloading of taxonomies is now optional -* Domain mapping fixes. -* Better support for https sites. Remove https:// to get cache paths. -* Added AddDefaultCharset .htaccess rule back in and added an option to remove it if required. -* Added multisite plugin that adds a "Cached" column to Network->Sites to disable caching on a per site basis. -* Added WPTouch plugin to modify browser and prefix list in mobile detection code. Added support for that plugin's exclude list. -* Fixed cache tester -* Filter the tags that are used to detect end-of-page using the wp_cache_eof_tags filter. -* Removed debug level from logging as it wasn't helpful. -* Removed mention of wp-minify. - -## 1.0 - 2012-01-30 - -* Removed AddDefaultCharset .htaccess rule -* Fixed problem with blogs in a folder and don't have a trailing slash -* New scheduling of garbage collection -* Added a "Delete cache" link to Toolbar to delete cache of current page. -* Updated documentation -* Sorry Digg, Stephen Fry power now! -* Updated translations -* Preload taxonomies and all post types except revisionsand nav menu items -* Fixed previews by logged in users. -* Added option to make logged in users anonymous -* Use WP 3.0 variables to detect multisite installs -* Hash filenames so files are served from the same CDNs - -## 0.9.9.9 - 2011-07-12 - -* Fixed typo, is_front_page. -* Serve repeated static files from the same CDN hostname. -* Updated translations. -* Make supercache dir lowercase to avoid problems with unicode URLs. -* Add option to skip https loaded static content. -* Remove 5 second check on age of existing cache files. Should help with posts that get lots of comments and traffic. -* Lots of bugs fixed. - -## 0.9.9.8 - 2011-01-07 - -* CDN updates: can be switched off, multiple CNAMEs. -* Uninstall process improved. It removes generated files and fixes edited files. -* Cached dynamic pages can now be stored in Supercache files and compressed. -* 1and1 Webhosting fix (/kunden/) -* Remove log by email functionality as it caused problems for users who were inundated by email -* Many more minor fixes and changes. - -## 0.9.9.6 - 2010-09-29 - -* Fixed problem serving cached files with PHP -* Added support for 304 "file not modified" header to help browser caching. (PHP caching only) -* Added French & German translations, updated Italian translation and fixed translation strings. -* Sleep 4 seconds between preload urls to reduce load on the server -* Updated docs and FAQs. - -## 0.9.9.5 - 2010-09-24 - -* Disable compression on on easy setup page. Still causes problems on some hosts. -* Remove footerlink on easy setup page. -* Don't delete mod_rewrite rules when caching is disabled. -* Don't stop users using settings page when in safe mode. - -## 0.9.9.4 - 2010-09-22 - -* Settings page split into tabbed pages. -* Added new "Easy" settings page for new users. -* New PHP caching mode to serve supercached files. -* Mobile support fixes. -* Added Domain mapping support plugin. -* Added "awaiting moderation" plugin that removes that text from posts. -* Terminology change. Changed "half on" to "legacy caching". -* Fixed cache tester on some installs of WordPress. -* Updated documentation -* Added $wp_super_cache_lock_down config variable to hide lockdown and directly cached pages admin items. -* Preloaded checks if it has stalled and reschedules the job to continue. -* Serve the gzipped page when first cached if the client supports compression. -* Lots more bug fixes.. - -## 0.9.9.3 - 2010-06-16 - -* Fixed division by zero error in half on mode. -* Always show "delete cache" button. -* Fixed "Update mod_rewrite rules" button. -* Minor text changes to admin page. - -## 0.9.9.2 - 2010-06-15 - -* Forgot to change version number in wp-cache.php - -## 0.9.9.1 - 2010-06-15 - -* Added preloading of static cache. -* Better mobile plugin support -* .htaccess rules can be updated now. Added wpsc_update_htaccess(). -* Fixed "page on front" cache clearing bug. -* Check for wordpress_logged_in cookie so test cookie isn't detected. -* Added clear_post_supercache() to clear supercache for a single post. -* Put quotes around rewrite rules in case paths have spaces. - -## 0.9.9 - 2010-02-08 - -* Added experimental object cache support. -* Added Chinese(Traditional) translation by Pseric. -* Added FAQ on WP-Cache vs Supercache files. -* Use Supercache file if WP-Cache file not found. Useful if mod_rewrite rules are broken or not working. -* Get mobile browser list from WP Mobile Edition if found. Warn user if .htaccess out of date. -* Make sure writer lock is unlocked after writing cache files. -* Added link to developer docs in readme. -* Added Ukranian translation by Vitaly Mylo. -* Added Upgrade Notice section to readme. -* Warn if zlib compression in PHP is enabled. -* Added compression troubleshooting answer. Props Vladimir (http://blog.sjinks.pro/) -* Added Japanese translation by Tai (http://tekapo.com/) -* Updated Italian translation. -* Link to WP Mobile Edition from admin page for mobile support. - -## 0.9.8 - 2009-11-18 - -* Added Spanish translation by Omi. -* Added Italian translation by Gianni Diurno. -* Addded advanced debug code to check front page for category problem. Enable by setting $wp_super_cache_advanced_debug to 1 in the config file. -* Fixed wordpress vs wordpress_logged_in cookie mismatch in cookie checking function. -* Correctly check if WP_CACHE is set or not. PHP is weird. -* Added wp_cache_clear_cache() to clear out cache directory. -* Only show logged in message when debugging enabled. -* Added troubleshooting point 20. PHP vs Apache user. -* Fixed problem deleting cache file. -* Don't delete cache files when moderated comments are deleted. - -## 0.9.7 - 2009-10-02 - -* Fixed problem with blogs in folders. -* Added cache file listing and delete links to admin page. -* Added "Newest Cached Pages" listing in sidebox. -* Made admin page translatable. -* Added "How do I make certain parts of the page stay dynamic?" to FAQ. -* Advanced: added "late init" feature so that plugin activates on "init". Set $wp_super_cache_late_init to true in config file to use. -* Disable supercaching when GET parameters present instead of disabling all caching. Disable on POST (as normal) and preview. -* Fixed problem with cron job and mutex filename. -* Warn users they must enable mobile device support if rewrite rules detected. Better detection of when to warn that .htaccess rules must be updated (no need when rewrite rules not present) -* Advanced: Added "wpsupercache_404" filter. Return true to cache 404 error pages. -* Use the wordpress_test_cookie in the cache key. -* Show correct number of cache files when compression off. -* Fixed problem with PHP safe_mode detection. -* Various bugfixes and documentation updates. See Changelog.txt - -## 0.9.6.1 - 2009-07-29 - -* Move "not logged in" message init below check for POST. -* Add is_admin() check so plugin definitely can't cache the backend. -* Add "do not cache" page type to admin page. - -## 0.9.6 - 2009-07-27 - -* Add uninstall.php uninstall script. -* Updated cache/.htaccess rules (option to upgrade that) -* Added FAQ about category and static homepage problem. -* Add wp_cache_user_agent_is_rejected() back to wp-cache-phase2.php -* Show message for logged in users when caching disable for them. -* Check filemtime on correct supercache file - -## 0.9.5 - 2009-07-17 - -* Show next and last GC times in minutes, not local time. -* Don't serve wp_cache cache files to rejected user agents. Supercache files are still served to them. -* If enabled, mobile support now serves php cached files to mobile clients and static cached files to everyone else. -* Added checks for "WPSC_DISABLE_COMPRESSION" and "WPSC_DISABLE_LOCKING" constants to disable compression and file locking. For hosting companies primarily. -* Added check for DONOTCACHEPAGE constant to avoid caching a page. -* Use PHP_DOCUMENT_ROOT when creating .htaccess if necessary. - -## 0.9.4.3 - 2009-04-25 - -1. Added "Don't cache for logged in users" option. -2. Display file size stats on admin page. -3. Clear the cache when profile page is updated. -4. Don't cache post previews. -5. Added backslashes to rejected URI regex list. -6. Fixed problems with posts and comments not refreshing. - -Misc fixes - -[4.0.0-alpha]: https://github.com/Automattic/wp-super-cache/compare/v3.0.3...v4.0.0-alpha -[3.0.3]: https://github.com/Automattic/wp-super-cache/compare/v3.0.2...v3.0.3 -[3.0.2]: https://github.com/Automattic/wp-super-cache/compare/v3.0.1...v3.0.2 -[3.0.1]: https://github.com/Automattic/wp-super-cache/compare/v3.0.0...v3.0.1 -[3.0.0]: https://github.com/Automattic/wp-super-cache/compare/v2.0.1...v3.0.0 -[2.0.1]: https://github.com/Automattic/wp-super-cache/compare/v2.0.0...v2.0.1 -[2.0.0]: https://github.com/Automattic/wp-super-cache/compare/v1.12.4...v2.0.0 -[1.12.4]: https://github.com/Automattic/wp-super-cache/compare/v1.12.3...v1.12.4 -[1.12.3]: https://github.com/Automattic/wp-super-cache/compare/v1.12.2...v1.12.3 -[1.12.2]: https://github.com/Automattic/wp-super-cache/compare/v1.12.1...v1.12.2 -[1.12.1]: https://github.com/Automattic/wp-super-cache/compare/v1.12.0...v1.12.1 -[1.12.0]: https://github.com/Automattic/wp-super-cache/compare/v1.11.0...v1.12.0 -[1.11.0]: https://github.com/Automattic/wp-super-cache/compare/v1.10.0...v1.11.0 -[1.10.0]: https://github.com/Automattic/wp-super-cache/compare/v1.9.4...v1.10.0 -[1.9.4]: https://github.com/Automattic/wp-super-cache/compare/v1.9.3...v1.9.4 -[1.9.3]: https://github.com/Automattic/wp-super-cache/compare/v1.9.2...v1.9.3 -[1.9.2]: https://github.com/Automattic/wp-super-cache/compare/v1.9.1...v1.9.2 -[1.9.1]: https://github.com/Automattic/wp-super-cache/compare/v1.9.0...v1.9.1 -[1.9.0]: https://github.com/Automattic/wp-super-cache/compare/v1.8...v1.9 -[1.8]: https://github.com/Automattic/wp-super-cache/compare/v1.7.9...v1.8 diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..dce5eca0 --- /dev/null +++ b/Makefile @@ -0,0 +1,62 @@ +.DEFAULT_GOAL := help +SHELL := /bin/bash + +PLUGIN_NAME := wp-super-cache +WP_ENV := COMPOSE_PROJECT_NAME=$(PLUGIN_NAME) npx --yes @wordpress/env + +## Development environment +install: ## Install PHP (Composer) and JS (npm) dependencies + composer install + npm install + +up: ## Start WordPress in Docker (http://localhost:8888, admin/password) + $(WP_ENV) start + +down: ## Stop the WordPress containers + $(WP_ENV) stop + +destroy: ## Remove the WordPress containers and database + $(WP_ENV) destroy + +logs: ## Tail the WordPress container logs + $(WP_ENV) logs + +cli: ## Open a shell inside the cli container + $(WP_ENV) run cli bash + +wp: ## Run an arbitrary wp-cli command, e.g. `make wp CMD="plugin list"` + $(WP_ENV) run cli wp $(CMD) + +## Test content +seed: ## Create 100 randomly named posts and 100 pages for cache testing + $(WP_ENV) run cli wp eval-file wp-content/plugins/wp-super-cache/tests/dev/seed.php + +unseed: ## Delete content created by `make seed` + $(WP_ENV) run cli wp eval-file wp-content/plugins/wp-super-cache/tests/dev/unseed.php + +## Lint +lint: ## Run PHP CodeSniffer + composer lint + +lint-all: ## Run PHP CodeSniffer on all files + composer phpcs + +lint-fix: ## Auto-fix PHP CodeSniffer issues + composer lint-fix + +## Release +pre-build: ## Prepare a release PR. Usage: make pre-build VERSION=x.y.z + @test -n "$(VERSION)" || { echo "Usage: make pre-build VERSION=x.y.z"; exit 1; } + ./scripts/pre-build.sh $(VERSION) + +build: ## Build build/wp-super-cache.zip (run pre-build and merge the PR first) + ./scripts/build-plugin.sh + +publish: ## Create a GitHub release from readme.txt + build/wp-super-cache.zip + ./scripts/publish.sh + +## Help +help: ## Show this help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-12s\033[0m %s\n", $$1, $$2}' + +.PHONY: install up down destroy logs cli wp seed unseed lint lint-all lint-fix pre-build build publish help diff --git a/README.md b/README.md index 854a2a36..c7cc37ba 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ partials/ Admin settings page tab templates tests/php/ PHPUnit tests tests/e2e/ End-to-end tests (Docker + Jest) -changelog/ Individual changelog entries (Jetpack Changelogger format) +scripts/ Release tooling (pre-build, build, publish, exclude list) .phan/ Phan static analysis configuration and stubs ``` @@ -39,8 +39,35 @@ changelog/ Individual changelog entries (Jetpack Changelogger for - PHP 7.4+ - [Composer](https://getcomposer.org/) +- Node.js 20+ and Docker (only needed for the Makefile / wp-env workflow) -### Installation +### Quick start with the Makefile + +A `Makefile` is provided to spin up a disposable WordPress site in Docker (via [`@wordpress/env`](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/)) with the plugin pre-mounted. Run `make help` to see every target. + +```bash +make install # composer install + npm install +make up # start WordPress at http://localhost:8888 (admin / password) +make seed # create 100 random posts + 100 random pages for cache testing +# ... hack on the plugin; files are live-mounted into the container ... +make unseed # delete only the content created by `make seed` +make down # stop containers +make destroy # stop and wipe the database +``` + +Other useful targets: + +| Target | Purpose | +|--------|---------| +| `make cli` | Open a shell inside the `wp-cli` container | +| `make wp CMD="super-cache status"` | Run an arbitrary `wp-cli` command | +| `make logs` | Tail the WordPress container logs | +| `make lint` / `make lint-fix` | Run / auto-fix PHPCS on changed PHP files | +| `make lint-all` | Run PHPCS on the full codebase | + +The seed script tags every item it creates with `_wpsc_seed=1` post meta, so `make unseed` only removes content it generated — it will not touch posts or pages you created by hand. + +### Manual installation ```bash composer install @@ -59,8 +86,11 @@ composer test-coverage ### Linting ```bash -# PHPCS (WordPress/Jetpack coding standards) -vendor/bin/phpcs +# Changed PHP files only (matches CI) +make lint + +# Full-tree PHPCS (WordPress/Jetpack coding standards) +make lint-all ``` ### Static analysis @@ -81,20 +111,53 @@ docker compose up -d pnpm test ``` +## Releases + +Releases are cut manually from `trunk` in three stages. See `scripts/pre-build.sh`, `scripts/build-plugin.sh`, and `scripts/publish.sh` for the full implementation; `scripts/exclude.lst` is the single source of truth for which files are excluded from the shipped plugin (shared by `rsync` and `zip`). + +### 1. Prepare the release PR + +```bash +make pre-build VERSION=x.y.z +``` + +Run from a clean, up-to-date `trunk`. This target: + +1. Creates a `release/x.y.z` branch. +2. Bumps `Stable tag:` in `readme.txt` and `Version:` in `wp-cache.php`. +3. Generates a list of PRs merged in the last six months (via `gh pr list`) into a temp file and opens it alongside `readme.txt` in `vim` for manual changelog editing. +4. Shows the diff and prompts for confirmation. +5. Pushes the branch and opens a PR via `gh pr create`. + +Review, merge the PR into `trunk`, and pull the merge commit locally. + +### 2. Build the zip + +```bash +make build +``` + +Rsyncs the plugin tree into `build/wp-super-cache/` (excluding everything in `scripts/exclude.lst`) and zips it to `build/wp-super-cache.zip`. + +### 3. Publish + +```bash +make publish +``` + +1. Reads `Stable tag:` from `readme.txt` and extracts the matching section of `== Changelog ==` as release notes. +2. Creates a GitHub release `vX.Y.Z` with `build/wp-super-cache.zip` attached. +3. Prompts whether to also publish to the WordPress.org SVN repository. If accepted, shallow-checks out `plugins.svn.wordpress.org/wp-super-cache/` into `build/svn/`, rsyncs `build/wp-super-cache/` into `trunk/`, stages SVN adds/removes based on `svn status`, commits trunk, then server-side-copies trunk to `tags/X.Y.Z`. SVN prompts for your wp.org credentials. + ## Contributing 1. Branch from `trunk`. 2. Make your changes. -3. Add a changelog entry: - ```bash - vendor/bin/changelogger add - ``` -4. Push and open a pull request against `trunk`. +3. Push and open a pull request against `trunk`. CI will automatically run: - **PHP tests** across PHP 8.2, 8.3, 8.4, and 8.5 - **PHPCS linting** on changed lines -- **Changelog validation** (warns if no entry is included) ### Translations diff --git a/composer.json b/composer.json index 61cb24cf..76dbf137 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,6 @@ "license": "GPL-2.0-or-later", "require-dev": { "yoast/phpunit-polyfills": "^4.0.0", - "automattic/jetpack-changelogger": "^6.0.14", "automattic/phpunit-select-config": "^1.0.4", "phan/phan": "^5.4", "php-stubs/wordpress-stubs": "^6.8", @@ -19,6 +18,18 @@ ] }, "scripts": { + "phpcs": [ + "./tools/phpcs-wrapper.sh --standard=.phpcs.xml.dist ." + ], + "phpcbf": [ + "./tools/phpcbf-wrapper.sh --standard=.phpcs.xml.dist ." + ], + "lint": [ + "./tools/run-phpcs-changed.sh" + ], + "lint-fix": [ + "./tools/run-phpcbf-changed.sh" + ], "phpunit": [ "phpunit-select-config phpunit.#.xml.dist --colors=always" ], @@ -37,14 +48,7 @@ "minimum-stability": "dev", "prefer-stable": true, "extra": { - "autorelease": true, - "autotagger": true, - "changelogger": { - "link-template": "https://github.com/Automattic/wp-super-cache/compare/v${old}...v${new}" - }, - "release-branch-prefix": "super-cache", - "wp-plugin-slug": "wp-super-cache", - "wp-svn-autopublish": true + "wp-plugin-slug": "wp-super-cache" }, "config": { "autoloader-suffix": "6fe342bc02f0b440f7b3c8d8ade42286_super_cacheⓥ4_0_0_alpha", diff --git a/composer.lock b/composer.lock index ad986d85..7c3960db 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "42809df693a35c59c13127d0c2e03c79", + "content-hash": "0515dcf403f76a6c057722ebc610dfe9", "packages": [], "packages-dev": [ { diff --git a/readme.txt b/readme.txt index bd7abbbe..eedb3d68 100644 --- a/readme.txt +++ b/readme.txt @@ -281,4 +281,4 @@ Your theme is probably responsive which means it resizes the page to suit whatev -------- -[See the previous changelogs here](https://github.com/Automattic/jetpack/blob/trunk/projects/plugins/super-cache/CHANGELOG.md#changelog) +[See previous releases on GitHub.](https://github.com/Automattic/wp-super-cache/releases) diff --git a/scripts/build-plugin.sh b/scripts/build-plugin.sh new file mode 100755 index 00000000..bc2dca22 --- /dev/null +++ b/scripts/build-plugin.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# +# Builds build/wp-super-cache/ and build/wp-super-cache.zip from the current +# working tree, excluding files listed in scripts/exclude.lst. + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)" +if [[ "$CURRENT_BRANCH" != "trunk" ]]; then + echo "build must be run from trunk (currently on: $CURRENT_BRANCH)." >&2 + exit 1 +fi + +echo "Fetching origin..." +git fetch origin trunk +if ! git merge-base --is-ancestor origin/trunk HEAD; then + echo "Local trunk is behind origin/trunk. Pull before running build." >&2 + exit 1 +fi + +if ! git diff-index --quiet HEAD --; then + echo "Working tree has uncommitted changes. Commit or stash first." >&2 + exit 1 +fi + +read -r -p "Have you run pre-build and merged the release PR? [y/N] " confirm +if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then + echo "Aborted." + exit 1 +fi + +PLUGIN_SLUG="wp-super-cache" +BUILD_DIR="build" +PLUGIN_DIR="$BUILD_DIR/$PLUGIN_SLUG" +ZIP_FILE="$PLUGIN_SLUG.zip" +EXCLUDE_LIST="scripts/exclude.lst" + +rm -rf "$BUILD_DIR" +mkdir -p "$PLUGIN_DIR" + +# rsync paths are relative to the source dir, so strip the leading +# wp-super-cache/ prefix that the exclude list carries for zip's benefit. +RSYNC_EXCLUDE="$(mktemp)" +trap 'rm -f "$RSYNC_EXCLUDE"' EXIT +sed "s|^$PLUGIN_SLUG/||" "$EXCLUDE_LIST" > "$RSYNC_EXCLUDE" + +rsync -a \ + --exclude "$BUILD_DIR" \ + --exclude-from "$RSYNC_EXCLUDE" \ + ./ "$PLUGIN_DIR/" + +# Zip from build/ so archive paths start with wp-super-cache/, matching +# the prefixes in exclude.lst. +( cd "$BUILD_DIR" && zip -rq "$ZIP_FILE" "$PLUGIN_SLUG" -x@"../$EXCLUDE_LIST" ) + +echo "Built $BUILD_DIR/$ZIP_FILE" diff --git a/scripts/exclude.lst b/scripts/exclude.lst new file mode 100644 index 00000000..9e0234d2 --- /dev/null +++ b/scripts/exclude.lst @@ -0,0 +1,28 @@ +wp-super-cache/.DS_Store +wp-super-cache/.editorconfig +wp-super-cache/.eslintignore +wp-super-cache/.git +wp-super-cache/.claude +wp-super-cache/.gitattributes +wp-super-cache/.github +wp-super-cache/.gitignore +wp-super-cache/.phan +wp-super-cache/.phpcs.xml.dist +wp-super-cache/w.org-assets +wp-super-cache/.wp-env.json +wp-super-cache/CHANGELOG.md +wp-super-cache/Makefile +wp-super-cache/README.md +wp-super-cache/build +wp-super-cache/changelog +wp-super-cache/composer.json +wp-super-cache/composer.lock +wp-super-cache/eslint.config.mjs +wp-super-cache/node_modules +wp-super-cache/package-lock.json +wp-super-cache/package.json +wp-super-cache/phpunit.*.xml.dist +wp-super-cache/scripts +wp-super-cache/tests +wp-super-cache/tools +wp-super-cache/vendor diff --git a/scripts/pre-build.sh b/scripts/pre-build.sh new file mode 100755 index 00000000..d7fa7a95 --- /dev/null +++ b/scripts/pre-build.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash +# +# Prepares a release: creates a release/ branch, bumps the version +# in readme.txt and wp-cache.php, generates a commit-log summary of the last +# six months, opens readme.txt in vim so the changelog section can be +# updated by hand, then pushes the branch and opens a PR. + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +VERSION="${1:-}" +if [[ -z "$VERSION" ]]; then + echo "Usage: $0 VERSION (e.g. 4.0.0)" >&2 + exit 1 +fi +if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9.-]+)?$ ]]; then + echo "Version must look like x.y.z or x.y.z-suffix, got: $VERSION" >&2 + exit 1 +fi + +CURRENT_VERSION="$(sed -nE 's/^Stable tag: ([0-9A-Za-z.+-]+).*/\1/p' readme.txt | head -1)" +if [[ -z "$CURRENT_VERSION" ]]; then + echo "Could not read current Stable tag from readme.txt." >&2 + exit 1 +fi +if [[ "$CURRENT_VERSION" == "$VERSION" ]]; then + echo "Version $VERSION already matches the Stable tag in readme.txt." >&2 + exit 1 +fi +highest="$(printf '%s\n%s\n' "$CURRENT_VERSION" "$VERSION" | sort -V | tail -1)" +if [[ "$highest" != "$VERSION" ]]; then + echo "Version $VERSION is not greater than current Stable tag $CURRENT_VERSION." >&2 + exit 1 +fi + +# Portable in-place sed across BSD (macOS) and GNU. +inplace_sed() { + local expr="$1" file="$2" tmp + tmp="$(mktemp)" + sed -E "$expr" "$file" > "$tmp" && mv "$tmp" "$file" +} + +CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)" +if [[ "$CURRENT_BRANCH" != "trunk" ]]; then + echo "pre-build must be run from trunk (currently on: $CURRENT_BRANCH)." >&2 + exit 1 +fi + +echo "Fetching origin..." +git fetch origin trunk +if ! git merge-base --is-ancestor origin/trunk HEAD; then + echo "Local trunk is behind origin/trunk. Pull before running pre-build." >&2 + exit 1 +fi + +if ! git diff-index --quiet HEAD --; then + echo "Working tree has uncommitted changes. Commit or stash first." >&2 + exit 1 +fi + +BRANCH="release/$VERSION" +if git rev-parse --verify "$BRANCH" >/dev/null 2>&1; then + echo "Branch $BRANCH already exists." >&2 + exit 1 +fi + +echo "Creating branch $BRANCH" +git checkout -b "$BRANCH" + +echo "Bumping version to $VERSION" +inplace_sed "s/^(Stable tag: ).*/\1$VERSION/" readme.txt +inplace_sed "s/^( \* Version: ).*/\1$VERSION/" wp-cache.php + +LOG_FILE="$(mktemp -t wpsc-changelog.XXXXXX)" +if date -v-6m +%Y-%m-%d >/dev/null 2>&1; then + SINCE_DATE="$(date -v-6m +%Y-%m-%d)" +else + SINCE_DATE="$(date -d '6 months ago' +%Y-%m-%d)" +fi +TODAY="$(date +%Y-%m-%d)" +{ + echo "### [$VERSION] - $TODAY" + gh pr list \ + --state merged \ + --base trunk \ + --limit 500 \ + --search "merged:>=$SINCE_DATE" \ + --json number,title,author,mergedAt \ + --template '{{range .}}- {{.title}} (#{{.number}}) — @{{.author.login}}{{"\n"}}{{end}}' +} > "$LOG_FILE" + +cat <&2 + exit 1 +fi + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +PLUGIN_SLUG="wp-super-cache" +BUILD_DIR="build/$PLUGIN_SLUG" +ZIP_FILE="build/$PLUGIN_SLUG.zip" +SVN_DIR="build/svn" +SVN_URL="https://plugins.svn.wordpress.org/$PLUGIN_SLUG/" + +if [[ ! -f "$ZIP_FILE" ]] || [[ ! -d "$BUILD_DIR" ]]; then + echo "$ZIP_FILE or $BUILD_DIR missing. Run \`make build\` first." >&2 + exit 1 +fi + +VERSION="$(sed -nE 's/^Stable tag: ([0-9A-Za-z.+-]+).*/\1/p' readme.txt | head -1)" +if [[ -z "$VERSION" ]]; then + echo "Could not read Stable tag from readme.txt." >&2 + exit 1 +fi + +ZIP_VERSION="$(unzip -p "$ZIP_FILE" "$PLUGIN_SLUG/readme.txt" 2>/dev/null | sed -nE 's/^Stable tag: ([0-9A-Za-z.+-]+).*/\1/p' | head -1)" +if [[ -z "$ZIP_VERSION" ]]; then + echo "Could not read Stable tag from $ZIP_FILE. Rebuild with \`make build\`." >&2 + exit 1 +fi +if [[ "$ZIP_VERSION" != "$VERSION" ]]; then + echo "Stable tag in $ZIP_FILE ($ZIP_VERSION) does not match readme.txt ($VERSION). Rebuild with \`make build\`." >&2 + exit 1 +fi + +TAG="v$VERSION" + +if gh release view "$TAG" >/dev/null 2>&1; then + echo "Release $TAG already exists on GitHub." >&2 + exit 1 +fi + +# Extract the changelog block for this version: from `### ` up to +# the next `### ` heading or a `--------` divider, whichever comes first. +NOTES="$(awk -v ver="$VERSION" ' + BEGIN { gsub(/\./, "\\.", ver) } + $0 ~ "^### " ver "( |$|-)" { inblock = 1; print; next } + inblock && /^### / { exit } + inblock && /^--------/ { exit } + inblock { print } +' readme.txt)" + +if [[ -z "$NOTES" ]]; then + echo "No changelog section found for $VERSION in readme.txt." >&2 + exit 1 +fi + +cat </dev/null 2>&1; then + echo "svn is not installed." >&2 + exit 1 +fi + +rm -rf "$SVN_DIR" +mkdir -p "$SVN_DIR" + +echo "Shallow-checking out $SVN_URL" +svn checkout "$SVN_URL" "$SVN_DIR" --depth=empty +( cd "$SVN_DIR" && svn up trunk && svn up tags --depth=immediates && svn up assets ) + +if [[ -e "$SVN_DIR/tags/$VERSION" ]]; then + echo "Tag $VERSION already exists in SVN. Aborting." >&2 + exit 1 +fi + +if [[ -z "$(ls -A "$BUILD_DIR")" ]]; then + echo "$BUILD_DIR is empty. Refusing to rsync --delete into SVN trunk." >&2 + exit 1 +fi + +echo "Syncing $BUILD_DIR/ into $SVN_DIR/trunk/" +rsync -a --delete --exclude='.svn/' "$BUILD_DIR/" "$SVN_DIR/trunk/" + +if [[ -d w.org-assets ]]; then + echo "Syncing w.org-assets/ into $SVN_DIR/assets/" + mkdir -p "$SVN_DIR/assets" + rsync -a --delete --exclude='.svn/' w.org-assets/ "$SVN_DIR/assets/" +fi + +# Stage SVN adds/removes based on `svn status`. +( + cd "$SVN_DIR" + while IFS= read -r line; do + flag="${line:0:1}" + # svn status prints flags in cols 1-7 and a space, then the path at col 9. + path="${line:8}" + # Append @ to avoid svn interpreting @ in filenames as peg revisions. + case "$flag" in + '?') svn add "${path}@" ;; + '!') svn rm "${path}@" ;; + esac + done < <(svn status) +) + +echo +echo "----- svn status -----" +( cd "$SVN_DIR" && svn status ) +echo "----------------------" +read -r -p "Commit trunk and create tags/$VERSION on WordPress.org SVN? [y/N] " commit_confirm +if [[ "$commit_confirm" != "y" && "$commit_confirm" != "Y" ]]; then + echo "Aborted before SVN commit. $SVN_DIR is left in place for inspection." + exit 1 +fi + +( + cd "$SVN_DIR" + svn commit -m "Update to version $VERSION" + svn cp "^/$PLUGIN_SLUG/trunk" "^/$PLUGIN_SLUG/tags/$VERSION" -m "Tagging version $VERSION" +) + +echo "Published $PLUGIN_SLUG $VERSION to WordPress.org SVN." diff --git a/tests/dev/mu-plugins/wpsc-loopback-fix.php b/tests/dev/mu-plugins/wpsc-loopback-fix.php new file mode 100644 index 00000000..182b5770 --- /dev/null +++ b/tests/dev/mu-plugins/wpsc-loopback-fix.php @@ -0,0 +1,56 @@ +' . str_repeat( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', wp_rand( 3, 8 ) ) . "

\n\n"; + } + return $body; +} + +$created = array( + 'post' => 0, + 'page' => 0, +); + +foreach ( array( 'post', 'page' ) as $content_type ) { + for ( $i = 0; $i < $count; $i++ ) { + $inserted_post_id = wp_insert_post( + array( + 'post_title' => wpsc_seed_random_title( ucfirst( $content_type ) ), + 'post_content' => wpsc_seed_random_body(), + 'post_status' => 'publish', + 'post_type' => $content_type, + ), + true + ); + + if ( is_wp_error( $inserted_post_id ) ) { + WP_CLI::warning( sprintf( 'Failed to insert %s: %s', $content_type, $inserted_post_id->get_error_message() ) ); + continue; + } + + update_post_meta( $inserted_post_id, '_wpsc_seed', 1 ); + ++$created[ $content_type ]; + } +} + +WP_CLI::success( sprintf( 'Seeded %d posts and %d pages.', $created['post'], $created['page'] ) ); diff --git a/tests/dev/unseed.php b/tests/dev/unseed.php new file mode 100644 index 00000000..81f035a8 --- /dev/null +++ b/tests/dev/unseed.php @@ -0,0 +1,31 @@ + array( 'post', 'page' ), + 'post_status' => 'any', + 'posts_per_page' => -1, + 'fields' => 'ids', + 'meta_key' => '_wpsc_seed', + 'meta_value' => 1, + ) +); + +$deleted = 0; +foreach ( $ids as $post_to_delete_id ) { + if ( wp_delete_post( $post_to_delete_id, true ) ) { + ++$deleted; + } +} + +WP_CLI::success( sprintf( 'Deleted %d seeded posts/pages.', $deleted ) ); diff --git a/tools/phpcbf-wrapper.sh b/tools/phpcbf-wrapper.sh new file mode 100755 index 00000000..22dfe5bc --- /dev/null +++ b/tools/phpcbf-wrapper.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +exec php -d error_reporting='E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED' "$ROOT_DIR/vendor/bin/phpcbf" "$@" diff --git a/tools/phpcs-wrapper.sh b/tools/phpcs-wrapper.sh new file mode 100755 index 00000000..641f1945 --- /dev/null +++ b/tools/phpcs-wrapper.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +exec php -d error_reporting='E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED' "$ROOT_DIR/vendor/bin/phpcs" "$@" diff --git a/tools/run-phpcbf-changed.sh b/tools/run-phpcbf-changed.sh new file mode 100755 index 00000000..44df2129 --- /dev/null +++ b/tools/run-phpcbf-changed.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PHPCBF_WRAPPER="$ROOT_DIR/tools/phpcbf-wrapper.sh" +STANDARD="$ROOT_DIR/.phpcs.xml.dist" + +dedupe_files() { + awk 'NF && !seen[$0]++' +} + +base_ref="" +if git rev-parse --verify origin/trunk >/dev/null 2>&1; then + base_ref="origin/trunk" +elif git rev-parse --verify trunk >/dev/null 2>&1; then + base_ref="trunk" +fi + +files="$( + { + if [ -n "$base_ref" ]; then + merge_base="$(git merge-base HEAD "$base_ref")" + git diff --name-only --diff-filter=ACMR "$merge_base"...HEAD -- '*.php' + fi + git diff --cached --name-only --diff-filter=ACMR -- '*.php' + git diff --name-only --diff-filter=ACMR -- '*.php' + git ls-files --others --exclude-standard -- '*.php' + } | dedupe_files +)" + +if [ -z "$files" ]; then + echo "No changed PHP files found, skipping PHPCBF." + exit 0 +fi + +mapfile -t file_list <<<"$files" + +echo "Running PHPCBF on changed PHP files..." +"$PHPCBF_WRAPPER" --standard="$STANDARD" "${file_list[@]}" diff --git a/tools/run-phpcs-changed.sh b/tools/run-phpcs-changed.sh new file mode 100755 index 00000000..f6a649b2 --- /dev/null +++ b/tools/run-phpcs-changed.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +PHPCS_CHANGED="$ROOT_DIR/vendor/bin/phpcs-changed" +PHPCS_WRAPPER="$ROOT_DIR/tools/phpcs-wrapper.sh" +STANDARD="$ROOT_DIR/.phpcs.xml.dist" + +dedupe_files() { + awk 'NF && !seen[$0]++' +} + +collect_files() { + local cmd=("$@") + "${cmd[@]}" | dedupe_files +} + +run_changed() { + local description="$1" + shift + + local files=() + while IFS= read -r file; do + [ -n "$file" ] && files+=("$file") + done + + if [ "${#files[@]}" -eq 0 ]; then + return 0 + fi + + echo "Running PHPCS for $description..." + + local rc=0 + php -d error_reporting='E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED' "$PHPCS_CHANGED" \ + --phpcs-path "$PHPCS_WRAPPER" \ + --standard="$STANDARD" \ + "$@" \ + "${files[@]}" || rc=$? + + return "$rc" +} + +status=0 +checks_run=0 + +staged_files="$(collect_files git diff --cached --name-only --diff-filter=ACMR -- '*.php')" +unstaged_files="$(collect_files git diff --name-only --diff-filter=ACMR -- '*.php')" +untracked_files="$(collect_files git ls-files --others --exclude-standard -- '*.php')" + +base_ref="" +if git rev-parse --verify origin/trunk >/dev/null 2>&1; then + base_ref="origin/trunk" +elif git rev-parse --verify trunk >/dev/null 2>&1; then + base_ref="trunk" +fi + +if [ -n "$base_ref" ]; then + merge_base="$(git merge-base HEAD "$base_ref")" + branch_files="$(collect_files git diff --name-only --diff-filter=ACMR "$merge_base"...HEAD -- '*.php')" + if [ -n "$branch_files" ]; then + checks_run=1 + if ! run_changed "branch PHP changes against $base_ref" --git --git-base "$merge_base" <<<"$branch_files"; then + status=1 + fi + fi +fi + +if [ -n "$staged_files" ]; then + checks_run=1 + if ! run_changed "staged PHP changes" --git --git-staged <<<"$staged_files"; then + status=1 + fi +fi + +if [ -n "$unstaged_files" ]; then + checks_run=1 + if ! run_changed "unstaged PHP changes" --git --git-unstaged <<<"$unstaged_files"; then + status=1 + fi +fi + +if [ -n "$untracked_files" ]; then + checks_run=1 + echo "Running PHPCS for untracked PHP files..." + while IFS= read -r file; do + [ -n "$file" ] || continue + if ! "$PHPCS_WRAPPER" --standard="$STANDARD" "$file"; then + status=1 + fi + done <<<"$untracked_files" +fi + +if [ "$checks_run" -eq 0 ]; then + echo "No changed PHP files found, skipping PHPCS." +fi + +exit "$status" diff --git a/.w.org-assets/README.md b/w.org-assets/README.md similarity index 100% rename from .w.org-assets/README.md rename to w.org-assets/README.md diff --git a/.w.org-assets/banner-1544x500.png b/w.org-assets/banner-1544x500.png similarity index 100% rename from .w.org-assets/banner-1544x500.png rename to w.org-assets/banner-1544x500.png diff --git a/.w.org-assets/banner-772x250.png b/w.org-assets/banner-772x250.png similarity index 100% rename from .w.org-assets/banner-772x250.png rename to w.org-assets/banner-772x250.png diff --git a/.w.org-assets/blueprints/blueprint.json b/w.org-assets/blueprints/blueprint.json similarity index 100% rename from .w.org-assets/blueprints/blueprint.json rename to w.org-assets/blueprints/blueprint.json diff --git a/.w.org-assets/icon-128x128.png b/w.org-assets/icon-128x128.png similarity index 100% rename from .w.org-assets/icon-128x128.png rename to w.org-assets/icon-128x128.png diff --git a/.w.org-assets/icon-256x256.png b/w.org-assets/icon-256x256.png similarity index 100% rename from .w.org-assets/icon-256x256.png rename to w.org-assets/icon-256x256.png diff --git a/wp-cache.php b/wp-cache.php index 88c15585..5249288a 100644 --- a/wp-cache.php +++ b/wp-cache.php @@ -3,7 +3,7 @@ * Plugin Name: WP Super Cache * Plugin URI: https://wordpress.org/plugins/wp-super-cache/ * Description: Very fast caching plugin for WordPress. - * Version: 4.0.0-alpha + * Version: 3.0.3 * Author: Automattic * Author URI: https://automattic.com/ * License: GPL2+