diff --git a/.github/actions/process-changelog/action.yml b/.github/actions/process-changelog/action.yml new file mode 100644 index 0000000000..e100bfeb48 --- /dev/null +++ b/.github/actions/process-changelog/action.yml @@ -0,0 +1,52 @@ +name: "Process the changelog" +description: "Generate or amend the changelog entries" + +inputs: + release-version: + description: "The release version for which the action should generate the changelog (e.g. 4.5.0)" + required: true + release-date: + description: "The release date (format: YYYY-MM-DD) for which the action should generate the changelog (default: unreleased)" + required: false + default: "unreleased" + action-type: + description: 'Whether this is to generate or amend the changelog entries (generate or amend)' + required: false + default: "generate" + +outputs: + changelog: + description: "The escaped changelog content" + value: ${{ steps.process_changelog.outputs.CHANGELOG }} + +runs: + using: composite + steps: + - name: "Verify the action type" + id: verify_action_type + if: ${{ inputs.action-type == 'generate' }} + shell: bash + env: + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + ACTION_TYPE: ${{ inputs.action-type }} + run: | + FINAL_RELEASE_VERSION=$(echo "$RELEASE_VERSION" | grep -Po '\d+\.\d+\.\d+(\.\d+)?') # Keep only x.y.z(.k) from x.y.z(.k)(-test-n) + CURRENT_RELEASE_VERSION=$(jq '.version' package.json -r) + + # If the changelog directory is empty (except .gitkeep) and the final release version is already defined in package.json, we need to switch to amend + # This use case is mainly for the last test package created from the release branch, to avoid an empty changelog + if [ "$(ls -A changelog | wc -l)" -eq 1 ] && [[ "$FINAL_RELEASE_VERSION" == "$CURRENT_RELEASE_VERSION" ]]; then + echo "ACTION_TYPE=amend-version" >> $GITHUB_OUTPUT + echo "CURRENT_VERSION=$CURRENT_RELEASE_VERSION" >> $GITHUB_OUTPUT + fi + + - name: "Process changelog for changelog.md" + id: process_changelog + shell: bash + env: + ACTION_TYPE: ${{ steps.verify_action_type.outputs.ACTION_TYPE || inputs.action-type }} + CURRENT_VERSION: ${{ steps.verify_action_type.outputs.CURRENT_VERSION || 'dont-care' }} + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + run: ./bin/process-changelog.sh $RELEASE_VERSION $CURRENT_VERSION $ACTION_TYPE $RELEASE_DATE diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml index dcebcd2fca..ac4ba9d7f6 100644 --- a/.github/workflows/phpcs.yml +++ b/.github/workflows/phpcs.yml @@ -1,9 +1,45 @@ name: 'PHPCS' on: [pull_request] jobs: + conditional: + runs-on: ubuntu-latest + outputs: + has_no_php_changes: ${{ steps.skip.outputs.has_no_php_changes }} + steps: + # ------------------------------------------------------------------------------ + # Checkout the repo + # ------------------------------------------------------------------------------ + - name: Checkout the repository + uses: actions/checkout@v4 + with: + fetch-depth: 1000 + token: ${{ secrets.GH_BOT_TOKEN }} + submodules: recursive + # ------------------------------------------------------------------------------ + # Check if any PHP files have changed + # ------------------------------------------------------------------------------ + - name: Check PHP file changes + id: skip + run: | + php_files=$(git diff ${{ github.event.pull_request.base.sha }} HEAD --name-only | grep -E '\.php$' || true) + num_php_files=$(echo "$php_files" | grep -c '^' || echo 0) + + if [[ -z "$php_files" || "$num_php_files" -eq 0 ]]; then + echo "has_no_php_changes=1" >> $GITHUB_OUTPUT + echo "## No PHP files changed" >> $GITHUB_STEP_SUMMARY + echo "PHPCS will not run." >> $GITHUB_STEP_SUMMARY + else + echo "has_no_php_changes=0" >> $GITHUB_OUTPUT + echo "## Found PHP file changes" >> $GITHUB_STEP_SUMMARY + echo "Total changed PHP files: $num_php_files" >> $GITHUB_STEP_SUMMARY + echo "$php_files" | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY + fi phpcs: + needs: + - conditional + if: needs.conditional.outputs.has_no_php_changes == '0' uses: stellarwp/github-actions/.github/workflows/phpcs.yml@main with: ref: ${{ github.event.inputs.ref }} secrets: - access-token: ${{ secrets.GH_BOT_TOKEN }} \ No newline at end of file + access-token: ${{ secrets.GH_BOT_TOKEN }} diff --git a/.github/workflows/process-changelog.yml b/.github/workflows/process-changelog.yml new file mode 100644 index 0000000000..c289d2abb1 --- /dev/null +++ b/.github/workflows/process-changelog.yml @@ -0,0 +1,140 @@ +name: "Release - Changelog" + +# This action will run when it is triggered manually +on: + workflow_dispatch: + inputs: + release-version: + description: "The release version for which the action should process the changelog (e.g. 4.5.0) (default: will try to figure it out)" + default: 'figure-it-out' + required: true + type: string + release-date: + description: "The release date in human-readable format (default: 'today')." + required: false + default: "today" + type: string + action-type: + description: "Whether this is to amend or generate the changelog entries (default: 'generate')." + required: true + default: "generate" + type: choice + options: + - amend + - generate + +defaults: + run: + shell: bash + +jobs: + process-changelog: + name: "Process the changelog" + runs-on: ubuntu-latest + env: + CHANGELOG_ACTION: ${{ inputs.action-type }} + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + fetch-depth: 0 + + - name: Configure PHP environment + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + + - name: Set up Composer + run: composer install + + - name: Set Variables + id: vars + run: echo "sha_short=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_OUTPUT + + - name: Set up Git configuration + run: | + git config --global user.email "actions@github.com" + git config --global user.name "github-actions" + + - name: Check for .puprc file and paths.versions + id: check-puprc + run: | + if [ ! -f ".puprc" ]; then + echo "Error: .puprc file not found" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + if ! jq -e '.paths.versions' .puprc > /dev/null; then + echo "Error: paths.versions not found in .puprc" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + - name: Figure out Version + id: figure_out_version + run: | + if [ "$RELEASE_VERSION" == "figure-it-out" ]; then + existing_version="" + while read -r version; do + echo "Processing version info: $version" + file=$(echo "$version" | jq -r '.file') + regex=$(echo "$version" | jq -r '.regex') + + existing_version=$(grep -Po "$regex" "$file" | grep -Po '(\d+\.\d+\.\d+(\.\d+)?)') + + if [ -n "$existing_version" ]; then + echo "Release version: $existing_version" + echo "RELEASE_VERSION=$existing_version" >> $GITHUB_OUTPUT + break + fi + done < <(jq -c '.paths.versions[]' .puprc) + else + echo "Release version: $RELEASE_VERSION" + echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_OUTPUT + fi + + - name: "Format the release date" + id: format_date + run: | + RELEASE_DATE=$( date "+%Y-%m-%d" -d "$RELEASE_DATE" ) # Release date formatted as YYYY-MM-DD + echo "Release date: $RELEASE_DATE" + echo "RELEASE_DATE=$RELEASE_DATE" >> $GITHUB_OUTPUT + + - name: Create new branch + id: versions + run: | + changeBranch="task/process-changelog/${{ steps.format_date.outputs.RELEASE_DATE }}/${{ steps.figure_out_version.outputs.RELEASE_VERSION }}/${{ steps.vars.outputs.sha_short }}" + git checkout -b "$changeBranch" + git push origin "$changeBranch" + + - name: "Process changelog" + id: process_changelog + uses: ./.github/actions/process-changelog + with: + release-version: ${{ steps.figure_out_version.outputs.RELEASE_VERSION }} + release-date: ${{ steps.format_date.outputs.RELEASE_DATE }} + action-type: ${{ env.CHANGELOG_ACTION }} + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + id: cpr + with: + token: ${{ secrets.GITHUB_TOKEN }} + base: ${{ github.ref }} + branch: "task/process-changelog/${{ steps.format_date.outputs.RELEASE_DATE }}/${{ steps.figure_out_version.outputs.RELEASE_VERSION }}/${{ steps.vars.outputs.sha_short }}" + title: "Process changelog for ${{ github.ref }}" + body: | + This is an automated PR created by ${{ github.actor }}. + It was generated by [this GitHub Action](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}). + labels: "automation" + commit-message: | + Process changelog for ${{ github.ref }} + This is an automated PR created by ${{ github.actor }}. + Generated by: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + - name: Check outputs + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "## Pull Request" >> $GITHUB_STEP_SUMMARY + echo "* Number - ${{ steps.cpr.outputs.pull-request-number }}" >> $GITHUB_STEP_SUMMARY + echo "* URL - [${{ steps.cpr.outputs.pull-request-url }}](${{ steps.cpr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release-branch.yml b/.github/workflows/release-branch.yml index a0bcbd7eab..7cc6099f02 100644 --- a/.github/workflows/release-branch.yml +++ b/.github/workflows/release-branch.yml @@ -145,7 +145,7 @@ jobs: uses: peter-evans/create-pull-request@v6 id: cpr with: - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.GHA_BOT_TOKEN_MANAGER }} base: "${{ github.event.inputs.new-branch }}" branch: "task/version-bump-${{ github.event.inputs.new-branch }}-${{ steps.vars.outputs.sha_short }}" title: "Version bump for ${{ github.event.inputs.new-branch }}" diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index b55fc4370d..3cc0a05787 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -37,7 +37,6 @@ 'callback' => \Tribe__Utils__Callback::class, 'pue.notices' => \Tribe__PUE__Notices::class, 'admin.notice.php.version' => \Tribe__Admin__Notice__Php_Version::class, - 'admin.notice.marketing' => \Tribe__Admin__Notice__Marketing::class, // Custom alias with tribe namespace. 'tooltip.view' => \Tribe\Tooltip\View::class, diff --git a/bin/clean-composer.sh b/bin/clean-composer.sh new file mode 100644 index 0000000000..d9769194d7 --- /dev/null +++ b/bin/clean-composer.sh @@ -0,0 +1,5 @@ +files=("vendor/composer/autoload_files.php" "vendor/composer/autoload_static.php") +search="symfony/deprecation-contracts/function.php" +for file in "${files[@]}"; do + grep -v "$search" "$file" > temp && mv temp "$file" +done diff --git a/changelog.md b/changelog.md index c3d562ccd2..6350f817e5 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # Changelog +### [6.1.1] 2024-10-17 + +* Fix - allow more svg attributes through the fields sanitization. [TEC-5282] + ### [6.1.0] 2024-09-26 * Feature - Update core settings functionality and styles to allow for new plugin settings layout. [TEC-5124] @@ -13,7 +17,7 @@ * Feature - Adding the method `tec_copy_to_clipboard_button` which can be used to print a button which on click would copy a text to the user's clipboard. [ET-2158] * Fix - Bug when term slugs were numeric. -* Fix - Optimized prime_term_cache to return early when no posts are provided [TECTRIA-229] +* Fix - Optimized prime_term_cache to return early when no posts are provided [TEC-5150] ### [6.0.0.2] 2024-07-24 @@ -42,26 +46,26 @@ ### [5.3.0.5] 2024-07-11 -* Fix - Ensure compatibility with WordPress 6.6 for removed polyfill `regenerator-runtime`. [TECTRIA-149] +* Fix - Ensure compatibility with WordPress 6.6 for removed polyfill `regenerator-runtime`. [TEC-5120] ### [5.3.0.4] 2024-06-18 -* Fix - In installations where the plugins or wp-content directories were symbolic linked, assets would fail to be located. [TECTRIA-91] +* Fix - In installations where the plugins or wp-content directories were symbolic linked, assets would fail to be located. [TEC-5106] * Language - 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted ### [5.3.0.3] 2024-06-14 -* Fix - Issue where scripts would not be enqueued as modules. [TECTRIA-86] +* Fix - Issue where scripts would not be enqueued as modules. [ET-2136] * Language - 0 new strings added, 0 updated, 1 fuzzied, and 0 obsoleted ### [5.3.0.2] 2024-06-14 -* Fix - Windows Server compatibility issues with updated Assets handling. [TECTRIA-83] +* Fix - Windows Server compatibility issues with updated Assets handling. [TEC-5104] * Language - 0 new strings added, 0 updated, 1 fuzzied, and 0 obsoleted ### [5.3.0.1] 2024-06-13 -* Fix - Issue on which some assets (css,js) would not be located in WP installs which could have some WP constant modified (WP_CONTENT_DIR, WP_PLUGIN_DIR)[TECTRIA-83] +* Fix - Issue on which some assets (css,js) would not be located in WP installs which could have some WP constant modified (WP_CONTENT_DIR, WP_PLUGIN_DIR)[TEC-5104] * Language - 0 new strings added, 0 updated, 1 fuzzied, and 0 obsoleted ### [5.3.0] 2024-06-11 diff --git a/changelog/fix-EVA-160-endpoint-issues-automated-tests b/changelog/fix-EVA-160-endpoint-issues-automated-tests deleted file mode 100644 index 77beda17ee..0000000000 --- a/changelog/fix-EVA-160-endpoint-issues-automated-tests +++ /dev/null @@ -1,5 +0,0 @@ -Significance: patch -Type: fix -Comment: fixing tests - - diff --git a/composer.json b/composer.json index 90137f4b0d..7cacf605b9 100644 --- a/composer.json +++ b/composer.json @@ -25,13 +25,15 @@ "lucatume/di52": "^3.3.7", "monolog/monolog": "1.24.*", "psr/container": "^1.0.0", + "stellarwp/arrays": "1.2.2", "stellarwp/container-contract": "^1.0.4", "stellarwp/db": "^1.0.3", "stellarwp/installer": "^1.1.0", "stellarwp/models": "dev-main", "stellarwp/schema": "^1.1.3", "stellarwp/telemetry": "^2.3.1", - "stellarwp/assets": "^1.2.6" + "stellarwp/assets": "^1.2.6", + "stellarwp/uplink": "2.2.1" }, "require-dev": { "automattic/vipwpcs": "^3.0", @@ -63,16 +65,24 @@ } }, "scripts": { + "clean-strauss-static-function-autoload": "bash bin/clean-composer.sh", "strauss": [ - "test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/download/0.19.2/strauss.phar", + "test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/download/0.19.4/strauss.phar", "vendor/stellarwp/installer/bin/set-domain domain=tribe-common", - "@php bin/strauss.phar" + "@php -d display_errors=on bin/strauss.phar", + "@composer dump-autoload", + "@clean-strauss-static-function-autoload" ], "post-install-cmd": [ - "@strauss" + "@strauss", + "@stellar-uplink" ], "post-update-cmd": [ - "@strauss" + "@strauss", + "@stellar-uplink" + ], + "stellar-uplink": [ + "vendor/bin/stellar-uplink domain=tribe-common" ] }, "extra": { @@ -82,12 +92,15 @@ "classmap_prefix": "TEC__Common__", "constant_prefix": "TEC_COMMON_", "packages": [ + "stellarwp/arrays", + "stellarwp/assets", "stellarwp/container-contract", "stellarwp/db", "stellarwp/models", "stellarwp/schema", "stellarwp/installer", "stellarwp/telemetry", + "stellarwp/uplink", "lucatume/di52", "monolog/monolog", "firebase/php-jwt", diff --git a/composer.lock b/composer.lock index 3f58c1ac89..2c8d9e99c9 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": "3ae5bc47eb9353a360f97b3691e81473", + "content-hash": "debf13c4d057fe67d06acfa7ae9872b2", "packages": [ { "name": "firebase/php-jwt", @@ -293,6 +293,63 @@ }, "time": "2021-05-03T11:20:27+00:00" }, + { + "name": "stellarwp/arrays", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/stellarwp/arrays.git", + "reference": "fe0a4cec1a299c196cc89bdba18ac99dea6bf5a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stellarwp/arrays/zipball/fe0a4cec1a299c196cc89bdba18ac99dea6bf5a2", + "reference": "fe0a4cec1a299c196cc89bdba18ac99dea6bf5a2", + "shasum": "" + }, + "require-dev": { + "codeception/module-asserts": "^1.0", + "codeception/module-cli": "^1.0", + "codeception/module-db": "^1.0", + "codeception/module-filesystem": "^1.0", + "codeception/module-phpbrowser": "^1.0", + "codeception/module-rest": "^1.0", + "codeception/module-webdriver": "^1.0", + "codeception/util-universalframework": "^1.0", + "lucatume/wp-browser": "^3.0.14", + "phpunit/phpunit": "~6.0", + "saggre/phpdocumentor-markdown": "^0.1.3", + "symfony/event-dispatcher-contracts": "^2.5.1", + "symfony/string": "^5.4", + "szepeviktor/phpstan-wordpress": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "StellarWP\\Arrays\\": "src/Arrays/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0" + ], + "authors": [ + { + "name": "StellarWP", + "email": "dev@stellarwp.com" + }, + { + "name": "Matthew Batchelder", + "email": "matt.batchelder@stellarwp.com" + } + ], + "description": "A library for array manipulation.", + "support": { + "issues": "https://github.com/stellarwp/arrays/issues", + "source": "https://github.com/stellarwp/arrays/tree/1.2.2" + }, + "time": "2023-11-14T12:48:06+00:00" + }, { "name": "stellarwp/assets", "version": "1.2.9", @@ -669,6 +726,73 @@ "source": "https://github.com/stellarwp/telemetry/tree/2.3.2" }, "time": "2024-01-08T18:55:26+00:00" + }, + { + "name": "stellarwp/uplink", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/stellarwp/uplink.git", + "reference": "57eb6264994662cb8da368cc3a9227ec716edc70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stellarwp/uplink/zipball/57eb6264994662cb8da368cc3a9227ec716edc70", + "reference": "57eb6264994662cb8da368cc3a9227ec716edc70", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.1", + "stellarwp/container-contract": "^1.0" + }, + "require-dev": { + "codeception/module-asserts": "^1.0", + "codeception/module-cli": "^1.0", + "codeception/module-db": "^1.0", + "codeception/module-filesystem": "^1.0", + "codeception/module-phpbrowser": "^1.0", + "codeception/module-rest": "^1.0", + "codeception/module-webdriver": "^1.0", + "codeception/util-universalframework": "^1.0", + "lucatume/codeception-snapshot-assertions": "^0.4.0", + "lucatume/di52": "^3.0", + "lucatume/wp-browser": "^3.0.14", + "phpspec/prophecy": "^1.0", + "phpspec/prophecy-phpunit": "^1.0|^2.0", + "phpunit/phpunit": "^6.0|^7.0|^8.0|^9.0", + "symfony/event-dispatcher-contracts": "^2.5.1", + "symfony/string": "^5.4", + "szepeviktor/phpstan-wordpress": "^1.1" + }, + "bin": [ + "bin/stellar-uplink" + ], + "type": "library", + "autoload": { + "psr-4": { + "StellarWP\\Uplink\\": "src/Uplink/", + "StellarWP\\Uplink\\Views\\": "src/views/", + "StellarWP\\Uplink\\Assets_Dir\\": "src/assets/", + "StellarWP\\Uplink\\Admin_Views\\": "src/admin-views/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "StellarWP", + "homepage": "https://stellarwp.com" + } + ], + "description": "A library that integrates a WordPress product with the StellarWP Licensing system.", + "support": { + "issues": "https://github.com/stellarwp/uplink/issues", + "source": "https://github.com/stellarwp/uplink/tree/v2.2.1" + }, + "time": "2024-09-30T22:46:40+00:00" } ], "packages-dev": [ diff --git a/lang/tribe-common.pot b/lang/tribe-common.pot index d12033c06c..fe86ddcda9 100644 --- a/lang/tribe-common.pot +++ b/lang/tribe-common.pot @@ -2,15 +2,15 @@ # This file is distributed under the GPLv2 or later. msgid "" msgstr "" -"Project-Id-Version: Tribe Common 6.1.0\n" +"Project-Id-Version: Tribe Common 6.3.0\n" "Report-Msgid-Bugs-To: https://evnt.is/191x\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2024-09-24T13:02:18-07:00\n" -"PO-Revision-Date: 2024-09-24 20:02\n" +"POT-Creation-Date: 2024-10-25T08:33:12-07:00\n" +"PO-Revision-Date: 2024-10-25 15:33\n" "X-Generator: WP-CLI 2.7.1\n" "X-Domain: tribe-common\n" @@ -34,9 +34,7 @@ msgstr "" msgid "http://evnt.is/1x" msgstr "" -#: src/admin-views/app-shop.php:34 -#: src/admin-views/conditional_content/black-friday.php:17 -#: src/admin-views/conditional_content/end-of-year-sale.php:17 +#: src/admin-views/app-shop.php:37 #: src/admin-views/help.php:35 #: src/admin-views/help.php:104 #: src/admin-views/troubleshooting/footer-logo.php:12 @@ -44,109 +42,109 @@ msgstr "" msgid "The Events Calendar brand logo" msgstr "" -#: src/admin-views/app-shop.php:39 +#: src/admin-views/app-shop.php:42 msgid "All Solutions" msgstr "" -#: src/admin-views/app-shop.php:40 +#: src/admin-views/app-shop.php:43 msgid "Save with Bundles" msgstr "" -#: src/admin-views/app-shop.php:41 +#: src/admin-views/app-shop.php:44 msgid "Extensions" msgstr "" -#: src/admin-views/app-shop.php:42 +#: src/admin-views/app-shop.php:45 msgid "Stellar Discounts" msgstr "" -#: src/admin-views/app-shop.php:51 -#: src/admin-views/app-shop.php:113 -#: src/admin-views/app-shop.php:171 -#: src/admin-views/app-shop.php:205 +#: src/admin-views/app-shop.php:54 +#: src/admin-views/app-shop.php:119 +#: src/admin-views/app-shop.php:177 +#: src/admin-views/app-shop.php:211 msgid "Shapes and lines for visual interest" msgstr "" -#: src/admin-views/app-shop.php:57 +#: src/admin-views/app-shop.php:63 msgid "One calendar. Countless ways to make it your own." msgstr "" -#: src/admin-views/app-shop.php:58 +#: src/admin-views/app-shop.php:64 msgid "Calendars, ticketing, and powerful WordPress tools to manage your events from start to finish." msgstr "" -#: src/admin-views/app-shop.php:60 +#: src/admin-views/app-shop.php:66 msgid "Already Installed" msgstr "" -#: src/admin-views/app-shop.php:66 -#: src/admin-views/app-shop.php:123 -#: src/admin-views/app-shop.php:145 +#: src/admin-views/app-shop.php:72 +#: src/admin-views/app-shop.php:129 +#: src/admin-views/app-shop.php:151 msgid "TEC Logo" msgstr "" -#: src/admin-views/app-shop.php:70 +#: src/admin-views/app-shop.php:76 #: src/admin-views/help-calendar.php:45 #: src/admin-views/help-community.php:43 #: src/admin-views/help-ticketing.php:50 msgid "Active" msgstr "" -#: src/admin-views/app-shop.php:72 -#: src/admin-views/app-shop.php:181 +#: src/admin-views/app-shop.php:78 +#: src/admin-views/app-shop.php:187 msgid "FREE" msgstr "" -#: src/admin-views/app-shop.php:97 +#: src/admin-views/app-shop.php:103 msgid "Manage" msgstr "" -#: src/admin-views/app-shop.php:99 +#: src/admin-views/app-shop.php:105 #: src/admin-views/help-calendar.php:77 #: src/admin-views/help-community.php:57 #: src/admin-views/help-ticketing.php:82 msgid "Learn More" msgstr "" -#: src/admin-views/app-shop.php:117 +#: src/admin-views/app-shop.php:123 msgid "The plugins you need at one discounted price" msgstr "" -#: src/admin-views/app-shop.php:118 +#: src/admin-views/app-shop.php:124 msgid "We've packaged our most popular plugins into bundles jam-packed with value." msgstr "" -#: src/admin-views/app-shop.php:130 -#: src/admin-views/app-shop.php:157 +#: src/admin-views/app-shop.php:136 +#: src/admin-views/app-shop.php:163 msgid "Save With A Bundle" msgstr "" -#: src/admin-views/app-shop.php:136 +#: src/admin-views/app-shop.php:142 msgid "Includes" msgstr "" -#: src/admin-views/app-shop.php:175 +#: src/admin-views/app-shop.php:181 msgid "Free extensions to power up your plugins" msgstr "" -#: src/admin-views/app-shop.php:176 +#: src/admin-views/app-shop.php:182 msgid "Extensions are quick solutions our team came up with to solve specific issues you may need. (Note - extensions are not covered by our support team.)" msgstr "" -#: src/admin-views/app-shop.php:190 +#: src/admin-views/app-shop.php:196 msgid "Download" msgstr "" -#: src/admin-views/app-shop.php:194 +#: src/admin-views/app-shop.php:200 msgid "Browse Extensions" msgstr "" -#: src/admin-views/app-shop.php:213 +#: src/admin-views/app-shop.php:219 msgid "Stellar is a collective of WordPress innovators, and home to WordPress products done right." msgstr "" #. translators: %s is the coupon code -#: src/admin-views/app-shop.php:220 +#: src/admin-views/app-shop.php:226 msgid "$25 towards any Stellar product using code %s" msgstr "" @@ -174,17 +172,12 @@ msgstr "" msgid "Loading..." msgstr "" -#: src/admin-views/conditional_content/black-friday.php:24 -msgid "Our biggest
sale of the
year ends
soon

" -msgstr "" - -#: src/admin-views/conditional_content/black-friday.php:31 -#: src/admin-views/conditional_content/end-of-year-sale.php:32 -msgid "Save now" -msgstr "" - -#: src/admin-views/conditional_content/end-of-year-sale.php:24 -msgid "End of Year Sale!
Save 30% on
all our plugins.
Offer expires soon!" +#. translators: %1$s: Black Friday sale year (numeric) +#. translators: %1$s: Black Friday year +#: src/admin-views/conditional_content/black-friday.php:16 +#: src/Common/Admin/Conditional_Content/Black_Friday.php:244 +msgctxt "Alt text for the Black Friday Ad" +msgid "%1$s Black Friday Sale for The Events Calendar plugins, add-ons and bundles." msgstr "" #: src/admin-views/dashboard/components/clear-button.php:27 @@ -587,7 +580,7 @@ msgid "(Event Tickets Plus)" msgstr "" #: src/admin-views/help.php:38 -#: src/Tribe/Settings.php:751 +#: src/Tribe/Settings.php:752 msgid "Help" msgstr "" @@ -616,54 +609,6 @@ msgstr "" msgid "Visit Troubleshooting next" msgstr "" -#: src/admin-views/notices/end-of-year-sale.php:17 -msgid "End of year savings!" -msgstr "" - -#: src/admin-views/notices/end-of-year-sale.php:19 -msgid "Get 30% off on all plugins from now through December 31." -msgstr "" - -#: src/admin-views/notices/end-of-year-sale.php:26 -msgid "Shop now" -msgstr "" - -#: src/admin-views/notices/tribe-bf-general.php:18 -msgid "Save 40% on The Events Calendar" -msgstr "" - -#: src/admin-views/notices/tribe-bf-general.php:21 -msgid "Upgrade and purchase new products during the Black Friday Sale." -msgstr "" - -#: src/admin-views/notices/tribe-bf-general.php:26 -#: src/admin-views/notices/tribe-stellar-sale-premium.php:25 -#: src/admin-views/notices/tribe-stellar-sale-premium.php:46 -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:61 -msgctxt "Shop now link text" -msgid "Shop now" -msgstr "" - -#: src/admin-views/notices/tribe-stellar-sale-premium.php:17 -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:81 -msgid "Make it stellar." -msgstr "" - -#: src/admin-views/notices/tribe-stellar-sale-premium.php:20 -msgid "Save 30% on all StellarWP products." -msgstr "" - -#. translators: %1$s and %2$s are bold tags used to wrap the discount percentages -#: src/admin-views/notices/tribe-stellar-sale-premium.php:36 -msgid "Purchase any StellarWP product during the sale and get %1$s100%%%2$s off WP Business Reviews and take %1$s40%%%2$s off all other brands." -msgstr "" - -#: src/admin-views/notices/tribe-stellar-sale-premium.php:54 -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:63 -msgctxt "View all StellarWP Deals link text" -msgid "View all StellarWP Deals" -msgstr "" - #: src/admin-views/notices/upsell/icon.php:18 msgid "The Events Calendar important notice icon" msgstr "" @@ -1054,8 +999,8 @@ msgid "License & Usage" msgstr "" #: src/admin-views/troubleshooting/ea-status/license-key.php:43 -#: src/Tribe/PUE/Checker.php:634 -#: src/Tribe/PUE/Checker.php:645 +#: src/Tribe/PUE/Checker.php:636 +#: src/Tribe/PUE/Checker.php:647 msgid "License Key" msgstr "" @@ -1966,17 +1911,17 @@ msgctxt "The message to display to confirm a user would like to revoke a Zapier msgid "Are you sure you want to revoke this Zapier API Key pair? This operation cannot be undone. Existing Zapier connections tied to this API Key will no longer work." msgstr "" -#: src/Common/Event_Automator/Zapier/Api.php:250 +#: src/Common/Event_Automator/Zapier/Api.php:251 msgctxt "Zapier API Key pair is missing information to delete failure message." msgid "Zapier API Key pair was not deleted, the consumer id or the API Key information were not found." msgstr "" -#: src/Common/Event_Automator/Zapier/Api.php:263 +#: src/Common/Event_Automator/Zapier/Api.php:264 msgctxt "Zapier API Key pair has been deleted success message." msgid "Zapier API Key pair was successfully deleted" msgstr "" -#: src/Common/Event_Automator/Zapier/Api.php:274 +#: src/Common/Event_Automator/Zapier/Api.php:275 msgctxt "Zapier API Key pair could not be deleted failure message." msgid "Zapier API Key pair was not deleted" msgstr "" @@ -2667,42 +2612,6 @@ msgstr "" msgid "This extension allows you to add custom HTML content to the top of the Community submission form." msgstr "" -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:58 -msgid "Make it yours." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:59 -msgid "Save 40% on all The Events Calendar products." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:60 -msgid "Take 40% off all premium The Events Calendar products during the annual Stellar Sale. Now through July 30." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:75 -msgid "Save 40% on Filter Bar." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:76 -msgid "Add filters to your calendar during the annual Stellar Sale. Now through July 30." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:78 -msgid "Save 40% on The Events Calendar Bundles." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:79 -msgid "Take 40% off when you upgrade to a bundle during the annual Stellar Sale. Now through July 30." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:82 -msgid "Save 40% on all StellarWP products." -msgstr "" - -#: src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php:83 -msgid "Take 40% off all brands during the annual Stellar Sale. Now through July 30." -msgstr "" - #: src/Tribe/Admin/Notice/Php_Version.php:59 #: src/Tribe/Admin/Notice/Plugin_Download.php:147 msgctxt "separator used in a list of items" @@ -3258,39 +3167,39 @@ msgctxt "extension disallowed" msgid "This extension has been programmatically disallowed. The most common reason is due to another The Events Calendar plugin having absorbed or replaced this extension's functionality. This extension plugin has been deactivated, and you should likely delete it." msgstr "" -#: src/Tribe/Field.php:468 +#: src/Tribe/Field.php:510 msgid "Invalid field type specified" msgstr "" -#: src/Tribe/Field.php:791 +#: src/Tribe/Field.php:833 msgid "No radio options specified" msgstr "" -#: src/Tribe/Field.php:827 +#: src/Tribe/Field.php:869 msgid "No checkbox options specified" msgstr "" -#: src/Tribe/Field.php:889 +#: src/Tribe/Field.php:931 msgid "No select options specified" msgstr "" -#: src/Tribe/Field.php:991 -#: src/Tribe/Field.php:1037 +#: src/Tribe/Field.php:1033 +#: src/Tribe/Field.php:1079 msgid "Select Image" msgstr "" -#: src/Tribe/Field.php:992 -#: src/Tribe/Field.php:1038 +#: src/Tribe/Field.php:1034 +#: src/Tribe/Field.php:1080 msgid "Remove Image" msgstr "" -#: src/Tribe/Field.php:996 -#: src/Tribe/Field.php:1042 +#: src/Tribe/Field.php:1038 +#: src/Tribe/Field.php:1084 msgid "Select an image" msgstr "" -#: src/Tribe/Field.php:997 -#: src/Tribe/Field.php:1043 +#: src/Tribe/Field.php:1039 +#: src/Tribe/Field.php:1085 msgid "Use this image" msgstr "" @@ -4891,102 +4800,102 @@ msgstr "" msgid "Promoter Key" msgstr "" -#: src/Tribe/PUE/Checker.php:618 +#: src/Tribe/PUE/Checker.php:620 msgid "A valid license key is required for support and updates" msgstr "" #. Translators: %1$s and %2$s are opening and closing tags, respectively. -#: src/Tribe/PUE/Checker.php:622 +#: src/Tribe/PUE/Checker.php:624 msgid "%1$sBuy a license%2$s for the Event Aggregator service to access additional import features." msgstr "" -#: src/Tribe/PUE/Checker.php:654 -#: src/Tribe/PUE/Checker.php:688 +#: src/Tribe/PUE/Checker.php:656 +#: src/Tribe/PUE/Checker.php:690 msgid "License Key Status:" msgstr "" -#: src/Tribe/PUE/Checker.php:663 +#: src/Tribe/PUE/Checker.php:665 msgid "Override network license key" msgstr "" -#: src/Tribe/PUE/Checker.php:664 +#: src/Tribe/PUE/Checker.php:666 msgid "Check this box if you wish to override the network license key with your own" msgstr "" -#: src/Tribe/PUE/Checker.php:675 +#: src/Tribe/PUE/Checker.php:677 msgid "Site License Key" msgstr "" -#: src/Tribe/PUE/Checker.php:776 +#: src/Tribe/PUE/Checker.php:778 msgid "License key(s) updated." msgstr "" #. Translators: %1$s and %2$s are opening and closing tags, respectively. -#: src/Tribe/PUE/Checker.php:1027 +#: src/Tribe/PUE/Checker.php:1035 msgid "Hmmm... something's wrong with this validator. Please contact %1$ssupport%2$s." msgstr "" -#: src/Tribe/PUE/Checker.php:1046 +#: src/Tribe/PUE/Checker.php:1054 msgid "unknown date" msgstr "" -#: src/Tribe/PUE/Checker.php:1052 +#: src/Tribe/PUE/Checker.php:1060 msgid "Sorry, key validation server is not available." msgstr "" #. Translators: %s is the expiration date. -#: src/Tribe/PUE/Checker.php:1081 +#: src/Tribe/PUE/Checker.php:1089 msgid "Valid Key! Expires on %s" msgstr "" #. Translators: %s is the expiration date. -#: src/Tribe/PUE/Checker.php:1092 +#: src/Tribe/PUE/Checker.php:1100 msgid "Thanks for setting up a valid key. It will expire on %s" msgstr "" -#: src/Tribe/PUE/Checker.php:1130 +#: src/Tribe/PUE/Checker.php:1138 #: src/Tribe/PUE/Notices.php:360 msgid "Renew Your License Now" msgstr "" -#: src/Tribe/PUE/Checker.php:1132 +#: src/Tribe/PUE/Checker.php:1140 #: src/Tribe/PUE/Notices.php:362 msgid " (opens in a new window)" msgstr "" -#: src/Tribe/PUE/Checker.php:1149 +#: src/Tribe/PUE/Checker.php:1157 msgid "Please refresh the page and try your request again." msgstr "" #. Translators: %1$s is the plugin name. %2$s and %3$s are opening and closing tags, respectively. -#: src/Tribe/PUE/Checker.php:1170 +#: src/Tribe/PUE/Checker.php:1178 msgid "There is an update for %1$s. You'll need to %2$scheck your license%3$s to have access to updates, downloads, and support." msgstr "" #. Translators: %1$s is the plugin name. %2$s and %3$s are opening and closing tags, respectively. -#: src/Tribe/PUE/Checker.php:1234 +#: src/Tribe/PUE/Checker.php:1242 msgid "There is an update for %1$s. %2$sRenew your license%3$s to get access to bug fixes, security updates, and new features." msgstr "" #. Translators: %s is the plugin version number. -#: src/Tribe/PUE/Checker.php:1266 +#: src/Tribe/PUE/Checker.php:1274 msgid "Update now to version %s." msgstr "" #. Translators: %1$s is the plugin name. %2$s is the update now link. -#: src/Tribe/PUE/Checker.php:1281 +#: src/Tribe/PUE/Checker.php:1289 msgid "There is a new version of %1$s available. %2$s" msgstr "" -#: src/Tribe/PUE/Checker.php:1897 +#: src/Tribe/PUE/Checker.php:1905 msgid "A valid license has been entered by your network administrator." msgstr "" -#: src/Tribe/PUE/Checker.php:1898 +#: src/Tribe/PUE/Checker.php:1906 msgid "No license entered. Consult your network administrator." msgstr "" -#: src/Tribe/PUE/Checker.php:1899 +#: src/Tribe/PUE/Checker.php:1907 msgid "Expired license. Consult your network administrator." msgstr "" @@ -5043,36 +4952,36 @@ msgstr "" msgid "You've requested a non-existent tab." msgstr "" -#: src/Tribe/Settings.php:748 +#: src/Tribe/Settings.php:749 msgid "Save Changes" msgstr "" -#: src/Tribe/Settings.php:790 +#: src/Tribe/Settings.php:791 msgid "Skip to tab content" msgstr "" -#: src/Tribe/Settings.php:824 -#: src/Tribe/Settings.php:862 +#: src/Tribe/Settings.php:825 +#: src/Tribe/Settings.php:863 msgid "Close" msgstr "" -#: src/Tribe/Settings.php:1010 +#: src/Tribe/Settings.php:1011 msgid "Open settings navigation" msgstr "" -#: src/Tribe/Settings.php:1033 +#: src/Tribe/Settings.php:1034 msgid "For you, Jack!" msgstr "" -#: src/Tribe/Settings.php:1107 +#: src/Tribe/Settings.php:1108 msgid "You don't have permission to do that." msgstr "" -#: src/Tribe/Settings.php:1113 +#: src/Tribe/Settings.php:1114 msgid "The request was sent insecurely." msgstr "" -#: src/Tribe/Settings.php:1119 +#: src/Tribe/Settings.php:1120 msgid "The request wasn't sent from this tab." msgstr "" diff --git a/package-lock.json b/package-lock.json index e4402b02cc..81ed60f19c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tribe-common", - "version": "6.1.0", + "version": "6.2.0-dev", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "tribe-common", - "version": "6.1.0", + "version": "6.2.0-dev", "dependencies": { "@babel/runtime": "^7.15.3", "@moderntribe/common": "file:src/modules", diff --git a/package.json b/package.json index c93e2554c9..933a6cebe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tribe-common", - "version": "6.1.0", + "version": "6.3.0", "repository": "git@github.com:the-events-calendar/tribe-common.git", "_resourcepath": "src/resources", "_domainPath": "lang", diff --git a/readme.txt b/readme.txt index e8069c2a77..ff8ebf19c8 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,21 @@ == Changelog == += [6.3.0] 2024-10-30 = + +* Feature - Added integration with new premium Seating product for Event Tickets. +* Language - 0 new strings added, 23 updated, 1 fuzzied, and 0 obsoleted + += [6.2.0] 2024-10-17 = + +* Feature - New Conditional Content supporting classes with available Traits for User targeted Dismissal. +* Fix - Allow more svg attributes through the fields sanitization. [TEC-5282] +* Tweak - Remove all of the deprecated Marketing related classes and files, as they are no longer used. +* Tweak - Added filters: `tec_settings_sidebar_sections` +* Tweak - Removed filters: `tribe_black_friday_start_time`, `tribe_black_friday_end_time` +* Tweak - Added actions: `tec_conditional_content_black_friday` +* Deprecated - Removed deprecated classes: `Tribe\Admin\Notice\Marketing`, `Tribe\Admin\Notice\Marketing\Black_Friday`, `Tribe\Admin\Notice\Marketing\End_Of_Year_Sale`, `Tribe\Admin\Notice\Marketing\Stellar_Sale`, `Tribe\Admin\Notice\Conditional_Content\`, `Tribe\Admin\Notice\Marketing\Black_Friday`, `Tribe\Admin\Notice\Marketing\End_Of_Year_Sale`, `Tribe\Admin\Notice\Marketing\Stellar_Sale` +* Language - 1 new strings added, 44 updated, 1 fuzzied, and 22 obsoleted + = [6.1.0] 2024-09-26 = * Feature - Update core settings functionality and styles to allow for new plugin settings layout. [TEC-5124] @@ -17,7 +33,7 @@ * Feature - Adding the method `tec_copy_to_clipboard_button` which can be used to print a button which on click would copy a text to the user's clipboard. [ET-2158] * Fix - Correct bug when term slugs were numeric. -* Fix - Optimized prime_term_cache to return early when no posts are provided [TECTRIA-229] +* Fix - Optimized prime_term_cache to return early when no posts are provided [TEC-5150] * Language - 2 new strings added, 21 updated, 1 fuzzied, and 0 obsoleted = [6.0.2] 2024-08-20 = @@ -62,26 +78,26 @@ = [5.3.0.5] 2024-07-11 = -* Fix - Ensure compatibility with WordPress 6.6 for removed polyfill `regenerator-runtime`. [TECTRIA-149] +* Fix - Ensure compatibility with WordPress 6.6 for removed polyfill `regenerator-runtime`. [TEC-5120] = [5.3.0.4] 2024-06-18 = -* Fix - In installations where the plugins or wp-content directories were symbolic linked, assets would fail to be located. [TECTRIA-91] +* Fix - In installations where the plugins or wp-content directories were symbolic linked, assets would fail to be located. [TEC-5106] * Language - 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted = [5.3.0.3] 2024-06-14 = -* Fix - Issue where scripts would not be enqueued as modules. [TECTRIA-86] +* Fix - Issue where scripts would not be enqueued as modules. [ET-2136] * Language - 0 new strings added, 0 updated, 1 fuzzied, and 0 obsoleted = [5.3.0.2] 2024-06-14 = -* Fix - Windows Server compatibility issues with updated Assets handling. [TECTRIA-83] +* Fix - Windows Server compatibility issues with updated Assets handling. [TEC-5104] * Language - 0 new strings added, 0 updated, 1 fuzzied, and 0 obsoleted = [5.3.0.1] 2024-06-13 = -* Fix - Issue on which some assets (css,js) would not be located in WP installs which could have some WP constant modified (WP_CONTENT_DIR, WP_PLUGIN_DIR)[TECTRIA-83] +* Fix - Issue on which some assets (css,js) would not be located in WP installs which could have some WP constant modified (WP_CONTENT_DIR, WP_PLUGIN_DIR)[TEC-5104] * Language - 0 new strings added, 0 updated, 1 fuzzied, and 0 obsoleted = [5.3.0] 2024-06-11 = diff --git a/src/Common/Admin/Conditional_Content/Black_Friday.php b/src/Common/Admin/Conditional_Content/Black_Friday.php new file mode 100644 index 0000000000..ddb3e70bb3 --- /dev/null +++ b/src/Common/Admin/Conditional_Content/Black_Friday.php @@ -0,0 +1,302 @@ +setTime( 4, 0 ); + + return $date; + } + + /** + * @inheritdoc + */ + protected function get_end_time(): ?Date_I18n { + $date = parent::get_end_time(); + if ( null === $date ) { + return null; + } + + $date = $date->setTime( 4, 0 ); + + return $date; + } + + /** + * @inheritdoc + */ + protected function should_display(): bool { + if ( $this->has_user_dismissed() ) { + return false; + } + + if ( tec_should_hide_upsell( $this->slug ) ) { + return false; + } + + return parent::should_display(); + } + + /** + * Gets the content for the Black Friday promo. + * + * @since 6.3.0 + * + * @return string + */ + protected function get_wide_banner_html(): string { + $template_args = [ + 'image_src' => tribe_resource_url( 'images/hero-section-wide.jpg', false, null, \Tribe__Main::instance() ), + 'link' => 'https://evnt.is/tec-bf-2024', + 'nonce' => $this->get_nonce(), + 'slug' => $this->slug, + ]; + + return $this->get_template()->template( 'black-friday', $template_args, false ); + } + + /** + * Render the wide banner HTML. + * + * @since 6.3.0 + * + * @return void + */ + public function render_wide_banner_html(): void { + if ( ! $this->should_display() ) { + return; + } + + /** + * Fires before the wide banner is rendered. + * This hook is used to add additional content before the narrow banner. + * + * @since 6.3.0 + * + * @param string $slug The slug of the conditional content. + * @param Black_Friday $this The Black Friday instance. + */ + do_action( 'tec_conditional_content_black_friday', 'wide_banner', $this ); + + echo $this->get_wide_banner_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,StellarWP.XSS.EscapeOutput.OutputNotEscaped + } + + /** + * Gets the content for the Black Friday promo. + * + * @since 6.3.0 + * + * @return string + */ + protected function get_narrow_banner_html(): string { + $template_args = [ + 'image_src' => tribe_resource_url( 'images/hero-section-narrow.jpg', false, null, \Tribe__Main::instance() ), + 'link' => 'https://evnt.is/tec-bf-2024', + 'is_narrow' => true, + 'nonce' => $this->get_nonce(), + 'slug' => $this->slug, + ]; + + return $this->get_template()->template( 'black-friday', $template_args, false ); + } + + /** + * Render the narrow banner HTML. + * + * @since 6.3.0 + * + * @return void + */ + public function render_narrow_banner_html(): void { + if ( ! $this->should_display() ) { + return; + } + /** + * Fires before the narrow banner is rendered. + * This hook is used to add additional content before the narrow banner. + * + * @since 6.3.0 + * + * @param string $slug The slug of the conditional content. + * @param Black_Friday $this The Black Friday instance. + */ + do_action( 'tec_conditional_content_black_friday', 'narrow_banner', $this ); + + echo $this->get_narrow_banner_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,StellarWP.XSS.EscapeOutput.OutputNotEscaped + } + + /** + * Include the Black Friday promo in the tickets settings section. + * + * @since 6.3.0 + * + * @return void + */ + public function include_tickets_settings_section(): void { + if ( ! $this->should_display() ) { + return; + } + + $page = tribe_get_request_var( 'page' ); + if ( $page !== 'tec-tickets-settings' ) { + return; + } + + $this->render_narrow_banner_html(); + } + + /** + * Replace the opening markup for the general settings info box. + * + * @since 6.3.0 + * + * @param Settings_Sidebar $sidebar Sidebar instance. + * + * @return void + */ + public function include_sidebar_section( $sidebar ): void { + $cache = tribe_cache(); + if ( $cache[ __METHOD__ ] ) { + return; + } + + $cache[ __METHOD__ ] = true; + + // Check if the content should currently be displayed. + if ( ! $this->should_display() ) { + return; + } + + $year = date_i18n( 'Y' ); + + /** + * Fires before the settings sidebar is rendered. + * This hook is used to add additional content before the narrow banner. + * + * @since 6.3.0 + * + * @param string $slug The slug of the conditional content. + * @param Black_Friday $this The Black Friday instance. + */ + do_action( 'tec_conditional_content_black_friday', 'settings-sidebar', $this ); + + $translated_title = sprintf( + /* translators: %1$s: Black Friday year */ + esc_attr_x( '%1$s Black Friday Sale for The Events Calendar plugins, add-ons and bundles.', 'Alt text for the Black Friday Ad', 'tribe-common' ), + esc_attr( $year ) + ); + + $container = new Container(); + + $button_attr = new Attributes( + [ + 'style' => 'position: absolute; top: 0; right: 0; background: transparent; border: 0; color: #fff; padding: 0.5em; cursor: pointer;', + + // Dismiss button attributes. + 'data-tec-conditional-content-dismiss-button' => true, + 'data-tec-conditional-content-dismiss-slug' => $this->slug, + 'data-tec-conditional-content-dismiss-nonce' => $this->get_nonce(), + ] + ); + $button = new Button( null, $button_attr ); + $button->add_child( + new Div( new Element_Classes( [ 'dashicons', 'dashicons-dismiss' ] ) ) + ); + + $container->add_child( $button ); + $container->add_child( + new Image( + tribe_resource_url( 'images/hero-section-settings-sidebar.jpg', false, null, \Tribe__Main::instance() ), + new Attributes( + [ + 'alt' => $translated_title, + 'role' => 'presentation', + ] + ) + ) + ); + + $sidebar->prepend_section( + ( new Settings_Section() ) + ->add_elements( + [ + new Link( + 'https://evnt.is/tec-bf-2024', + $container, + null, + new Attributes( + [ + 'title' => $translated_title, + 'target' => '_blank', + 'rel' => 'noopener nofollow', + 'style' => 'position: relative; display:block;', + + // Dismiss container attributes. + 'data-tec-conditional-content-dismiss-container' => true, + ] + ) + ), + ] + ) + ); + } +} diff --git a/src/Common/Admin/Conditional_Content/Controller.php b/src/Common/Admin/Conditional_Content/Controller.php new file mode 100644 index 0000000000..90f9358e4d --- /dev/null +++ b/src/Common/Admin/Conditional_Content/Controller.php @@ -0,0 +1,69 @@ +container->singleton( Black_Friday::class, Black_Friday::class, [ 'hook' ] ); + + $this->hooks(); + } + + /** + * Set up hooks for classes. + * + * @since 4.14.7 + */ + protected function hooks(): void { + add_action( 'tribe_plugins_loaded', [ $this, 'plugins_loaded' ] ); + } + + /** + * Setup for things that require plugins loaded first. + * + * @since 6.3.0 + */ + public function plugins_loaded(): void { + $this->container->make( Black_Friday::class ); + + $plugin = Common::instance(); + + tribe_asset( + $plugin, + 'tec-conditional-content', + 'admin/conditional-content.js', + [ + 'wp-data', + 'tribe-common', + ], + 'tec_conditional_content_black_friday', + ); + } +} diff --git a/src/Common/Admin/Conditional_Content/Datetime_Conditional_Abstract.php b/src/Common/Admin/Conditional_Content/Datetime_Conditional_Abstract.php new file mode 100644 index 0000000000..de90bc79e1 --- /dev/null +++ b/src/Common/Admin/Conditional_Content/Datetime_Conditional_Abstract.php @@ -0,0 +1,182 @@ +start_date, 'UTC' ); + // If not set, set to midnight. + if ( empty( $this->start_time ) ) { + $this->start_time = 0; + } + + $date = $date->setTime( $this->start_time, 0 ); + + /** + * Allow filtering of the start date for testing. + * + * @since 6.3.0 + * + * @param Date_i18n $date - Date object for the end date. + * @param static $this + */ + $date = apply_filters( "tec_admin_conditional_content_{$this->slug}_start_date", $date, $this ); + + if ( ! $date instanceof Date_I18n ) { + return null; + } + + return $date; + } + + /** + * Unix datetime for content end. + * + * @since 6.3.0 + * + * @return ?Date_I18n - Date Object + */ + protected function get_end_time(): ?Date_I18n { + $date = Dates::build_date_object( $this->end_date, 'UTC' ); + // If not set, set to midnight. + if ( empty( $this->end_time ) ) { + $this->end_time = 0; + } + + $date = $date->setTime( $this->end_time, 0 ); + + /** + * Allow filtering of the end date for testing. + * + * @since 6.3.0 + * + * @param Date_i18n $date - Date object for the end date. + * @param object $this + */ + $date = apply_filters( "tec_admin_conditional_content_{$this->slug}_end_date", $date, $this ); + + if ( ! $date instanceof Date_I18n ) { + return null; + } + + return $date; + } + + /** + * Whether the content should display. + * + * @since 6.3.0 + * + * @return boolean - Whether the content should display + */ + protected function should_display(): bool { + $now = Dates::build_date_object( 'now', 'UTC' ); + $notice_start = $this->get_start_time(); + $notice_end = $this->get_end_time(); + + // Failed dates should yield false. + if ( $notice_end === null || $notice_start === null ) { + return false; + } + + $display = $notice_start <= $now && $now < $notice_end; + + /** + * Allow filtering whether the content should display. + * + * @since 6.3.0 + * + * @param bool $should_display - whether the content should display + * @param object $this - the conditional content object + */ + return (bool) apply_filters( "tec_admin_conditional_content_{$this->slug}_should_display", $display, $this ); + } + + /** + * Gets the instance of the template engine used for rendering the conditional template. + * + * @since 6.3.0 + * + * @return Template + */ + public function get_template(): Template { + if ( empty( $this->template ) ) { + $this->template = new Template(); + $this->template->set_template_origin( \Tribe__Main::instance() ); + $this->template->set_template_folder( 'src/admin-views/conditional_content' ); + $this->template->set_template_context_extract( true ); + $this->template->set_template_folder_lookup( false ); + } + + return $this->template; + } +} diff --git a/src/Common/Admin/Conditional_Content/Dismissible_Trait.php b/src/Common/Admin/Conditional_Content/Dismissible_Trait.php new file mode 100644 index 0000000000..a6ac3832f7 --- /dev/null +++ b/src/Common/Admin/Conditional_Content/Dismissible_Trait.php @@ -0,0 +1,190 @@ +slug ) ) { + return ''; + } + + return $this->nonce_action_prefix . $this->slug; + } + + /** + * Get the nonce for this dismissible content. + * + * @since 6.3.0 + * + * @return string + */ + public function get_nonce(): string { + return wp_create_nonce( $this->get_nonce_action() ); + } + + /** + * This will allow the user to Dismiss the Notice using JS. + * + * We will dismiss the notice without checking to see if the slug was already + * registered (via a call to exists()) for the reason that, during dismissal + * ajax request, some valid notices may not have been registered yet. + * + * @since 6.3.0 + * + * @return void + */ + public function handle_dismiss(): void { + if ( empty( $this->slug ) ) { + wp_send_json( false ); + } + + $slug = tribe_get_request_var( 'slug', false ); + if ( empty( $slug ) ) { + wp_send_json( false ); + } + + $slug = sanitize_key( $slug ); + + if ( $this->slug !== $slug ) { + wp_send_json( false ); + } + + $nonce = tribe_get_request_var( 'nonce', false ); + $nonce_action = $this->get_nonce_action(); + + if ( ! wp_verify_nonce( $nonce, $nonce_action ) ) { + wp_send_json( false ); + } + + // Send a JSON answer with the status of dismissal. + wp_send_json( $this->dismiss() ); + } + + /** + * A Method to actually add the Meta value recording that this content has been dismissed. + * + * @since 6.3.0 + * + * @param int|null|string $user_id The user ID. + * + * @return boolean + */ + protected function dismiss( $user_id = null ): bool { + if ( empty( $this->slug ) ) { + return false; + } + + if ( is_null( $user_id ) ) { + $user_id = get_current_user_id(); + } + + // If this user has dismissed we don't care either. + if ( $this->has_user_dismissed( $user_id ) ) { + return true; + } + + update_user_meta( $user_id, $this->meta_key_time_prefix . $this->slug, time() ); + + return add_user_meta( $user_id, $this->meta_key, $this->slug ); + } + + /** + * Removes the user meta that holds if this content has been dismissed. + * + * @since 6.3.0 + * + * @param int|null|string $user_id The user ID. + * + * @return boolean + */ + public function undismiss( $user_id = null ): bool { + if ( empty( $this->slug ) ) { + return false; + } + + if ( null === $user_id ) { + $user_id = get_current_user_id(); + } + + // If this user has dismissed we don't care either. + if ( ! $this->has_user_dismissed( $user_id ) ) { + return false; + } + + return delete_user_meta( $user_id, $this->meta_key, $this->slug ); + } + + /** + * Checks if a given user has dismissed a given notice. + * + * @since 6.3.0 + * + * @param int|null|string $user_id The user ID. + * + * @return boolean + */ + public function has_user_dismissed( $user_id = null ): bool { + if ( empty( $this->slug ) ) { + return false; + } + + if ( null === $user_id ) { + $user_id = get_current_user_id(); + } + + $dismissed_notices = get_user_meta( $user_id, $this->meta_key ); + + if ( ! is_array( $dismissed_notices ) ) { + return false; + } + + if ( ! in_array( $this->slug, $dismissed_notices, true ) ) { + return false; + } + + return true; + } +} diff --git a/src/Common/Admin/Entities/Button.php b/src/Common/Admin/Entities/Button.php new file mode 100644 index 0000000000..bf0ea7909e --- /dev/null +++ b/src/Common/Admin/Entities/Button.php @@ -0,0 +1,57 @@ +set_classes( $classes ); + } + + if ( $attributes ) { + $this->set_attributes( $attributes ); + } + } + + /** + * Render the element. + * + * @since 6.3.0 + * + * @return void + */ + public function render() { + ?> + + url = $url; - $this->text = $text; + public function __construct( string $url, $content, ?Classes $classes = null, ?Attributes $attributes = null ) { + $this->url = $url; + + if ( is_string( $content ) ) { + $this->content = new Plain_Text( $content ); + } elseif ( $content instanceof Base_Entity ) { + $this->content = $content; + } else { + throw new InvalidArgumentException( 'Content must be a string or an instance of Base_Entity' ); + } if ( $classes ) { $this->set_classes( $classes ); @@ -64,12 +72,14 @@ public function __construct( string $url, string $text, ?Classes $classes = null * @return void */ public function render() { - printf( - '%s', - esc_url( $this->url ), - esc_attr( $this->get_classes() ), - $this->get_attributes(), // phpcs:ignore StellarWP.XSS.EscapeOutput,WordPress.Security.EscapeOutput - esc_html( $this->text ) - ); + ?> + get_attributes(); // phpcs:ignore StellarWP.XSS.EscapeOutput,WordPress.Security.EscapeOutput ?> + > + content->render(); ?> + +
- -
- - render_header_image(); - $this->render_title(); - ?> - -
- - sections as $section ) : ?> + + get_sections() as $section ) : ?>
render(); ?>
- +
header_image = $image; + public function add_section( Section $section ): self { + $this->sections[] = $section; + + return $this; } /** - * Add a section to the sidebar. + * Add a section to the start of the sidebar array of sections * - * @since 6.1.0 + * @since 6.3.0 * * @param Section $section The section to add. * - * @return void + * @return self */ - public function add_section( Section $section ) { - $this->sections[] = $section; + public function prepend_section( Section $section ): self { + array_unshift( $this->sections, $section ); + + return $this; } /** - * Render the header image for the sidebar. + * Get the sidebar sections. * - * @since 6.1.0 + * @since 6.3.0 * - * @return void + * @return array */ - protected function render_header_image() { - if ( ! $this->header_image ) { - return; - } + public function get_sections(): array { + /** + * Filter the sidebar sections. + * + * @since 6.3.0 + * + * @param Section[] $sections The sidebar sections. + * @param Settings_Sidebar $sidebar The sidebar object. + */ + return apply_filters( 'tec_settings_sidebar_sections', $this->sections, $this ); + } - $this->header_image->render(); + /** + * Set the header image for the sidebar. + * + * @since 6.1.0 + * + * @deprecated 6.3.0 + * + * @param Image $deprecated Deprecated. + */ + public function set_header_image( Image $deprecated ) { + _deprecated_function( __METHOD__, '6.3.0', 'Sidebar no longer has headers, they can be added to individual sections.' ); } } diff --git a/src/Common/Admin/Settings_Sidebar_Section.php b/src/Common/Admin/Settings_Sidebar_Section.php new file mode 100644 index 0000000000..fa717dbbf2 --- /dev/null +++ b/src/Common/Admin/Settings_Sidebar_Section.php @@ -0,0 +1,135 @@ +header_image = $image; + + return $this; + } + + /** + * Alias to prepending a sub-section to the sidebar. + * + * @since 6.1.0 + * + * @param Section $section The section to add. + * + * @return self + */ + public function add_section( Section $section ): self { + $this->sections[] = $section; + + return $this; + } + + /** + * Add a sub-section to the start of the sidebar array of sections + * + * @since 6.3.0 + * + * @param Section $section The section to add. + * + * @return self + */ + public function prepend_section( Section $section ): self { + array_unshift( $this->sections, $section ); + + return $this; + } + + /** + * Render the header image for the sidebar. + * + * @since 6.3.0 + * + * @return void + */ + protected function render_header_image(): void { + if ( ! $this->header_image ) { + return; + } + + $this->header_image->render(); + } + + /** + * Render the sidebar Section. + * + * @since 6.3.0 + * + * @return void + */ + public function render(): void { + ?> +
+ render_header_image(); + $this->render_title(); + + /** + * Fires after the sidebar header is rendered. + * + * @since 6.3.0 + */ + do_action( 'tec_settings_sidebar_header_end' ); + ?> +
+ sections as $section ) : ?> +
+ render(); ?> +
+ + container->singleton( static::class, $this ); tribe_register_provider( Installer\Provider::class ); + tribe_register_provider( Uplink_Controller::class ); DB\Config::setHookPrefix( $this->get_hook_prefix() ); Assets\Config::set_hook_prefix( $this->get_hook_prefix() ); Assets\Config::set_path( Common::instance()->plugin_path . 'src/resources/' ); Assets\Config::set_version( Common::VERSION ); Assets\Config::set_relative_asset_path( 'src/resources/' ); + Schema\Config::set_db( DB\DB::class ); + Schema\Config::set_container( tribe() ); } /** diff --git a/src/Common/Libraries/Uplink_Controller.php b/src/Common/Libraries/Uplink_Controller.php new file mode 100644 index 0000000000..368b5e8127 --- /dev/null +++ b/src/Common/Libraries/Uplink_Controller.php @@ -0,0 +1,174 @@ +add_actions(); + } + + /** + * Unregister the controller. + * + * @since 6.3.0 + * + * @return void + */ + public function unregister(): void { + $this->remove_actions(); + } + + /** + * Add the action hooks. + * + * @since 6.3.0 + */ + public function add_actions(): void { + add_action( 'init', [ $this, 'register_uplink' ], 8 ); + add_filter( 'tribe_license_fields', [ $this, 'register_license_fields' ], 20 ); + add_action( 'tribe_settings_save', [ $this, 'save_empty_license_keys' ] ); + } + + /** + * Remove the action hooks. + * + * @since 6.3.0 + */ + public function remove_actions(): void { + remove_action( 'init', [ $this, 'register_uplink' ], 8 ); + remove_filter( 'tribe_license_fields', [ $this, 'register_license_fields' ], 20 ); + } + + /** + * Register the license fields. + * + * @since 6.3.0 + * + * @param array $fields_array The array of fields. + * + * @return array + */ + public function register_license_fields( $fields_array ) { + $plugins = get_plugins(); + + $fields_to_inject = []; + + foreach ( $plugins as $plugin ) { + $legacy_slug = str_replace( '-', '_', $plugin->get_slug() ); + + $field = get_field( $plugin->get_slug() ); + $field->set_field_name( 'pue_install_key_' . $legacy_slug )->show_label( false ); + + $prefix = tribe( Libraries_Provider::class )->get_hook_prefix(); + + // If there is a license registered prior Uplink but not with Uplink. Return license registered prior Uplink. + add_filter( + 'stellarwp/uplink/' . $prefix . '/' . $plugin->get_slug() . '/license_get_key', + function ( $license, Resource $plugin ) { + if ( $license ) { + return $license; + } + + return get_option( 'pue_install_key_' . str_replace( '-', '_', $plugin->get_slug() ), '' ); + }, + 10, + 2 + ); + + $field_html = $field->get_render_html(); + + // Remove duplicate entries of plugins migrated to uplink. + if ( isset( $fields_array[ 'pue_install_key_' . $legacy_slug . '-heading' ] ) ) { + unset( $fields_array[ 'pue_install_key_' . $legacy_slug . '-heading' ] ); + } + + // Remove duplicate entries of plugins migrated to uplink. + if ( isset( $fields_array[ 'pue_install_key_' . $legacy_slug ] ) ) { + unset( $fields_array[ 'pue_install_key_' . $legacy_slug ] ); + } + + $fields_to_inject[ 'stellarwp-uplink_' . $plugin->get_slug() . '-heading' ] = [ + 'type' => 'heading', + 'label' => $plugin->get_name(), + ]; + + $fields_to_inject[ 'stellarwp-uplink_' . $plugin->get_slug() ] = [ + 'type' => 'html', + 'label' => '', + 'html' => $field_html, + ]; + } + + $fields_array = Arr::insert_after_key( 'tribe-form-content-start', $fields_array, $fields_to_inject ); + + return $fields_array; + } + + /** + * Save empty license keys. + * + * @since 6.3.0 + */ + public function save_empty_license_keys() { + $plugins = get_plugins(); + + foreach ( $plugins as $plugin ) { + $legacy_slug = str_replace( '-', '_', $plugin->get_slug() ); + + if ( ! isset( $_POST[ 'pue_install_key_' . $legacy_slug ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing + continue; + } + + $license_key = sanitize_text_field( $_POST[ 'pue_install_key_' . $legacy_slug ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing + + // If the license key has a value, it will be validated and stored by uplink. + // We only want to give our users the option to remove a license key if they want to. + if ( $license_key ) { + continue; + } + + $plugin->set_license_key( '' ); + } + } + + /** + * Register the uplink library. + * + * @since 6.3.0 + * + * @return void + */ + public function register_uplink(): void { + $prefix = tribe( Libraries_Provider::class )->get_hook_prefix(); + + Config::set_container( tribe() ); + Config::set_hook_prefix( $prefix ); + Config::set_token_auth_prefix( $prefix ); + Uplink::init(); + } +} diff --git a/src/Tribe/Admin/Conditional_Content/Black_Friday.php b/src/Tribe/Admin/Conditional_Content/Black_Friday.php index 320d41f7eb..9f45aa5b1b 100644 --- a/src/Tribe/Admin/Conditional_Content/Black_Friday.php +++ b/src/Tribe/Admin/Conditional_Content/Black_Friday.php @@ -1,84 +1,25 @@ modify( '-3 days' ); - - return $date; - } - - /** - * Replace the opening markup for the general settings info box. - * - * @since 4.14.7 - * @return void - */ - public function add_conditional_content( $fields ) { - // Check if the content should currently be displayed. - if( ! $this->should_display() ) { - return $fields; - } - - // Set up template variables. - $images_dir = \Tribe__Main::instance()->plugin_url . 'src/resources/images/'; - $template_args = [ - 'branding_logo' => $images_dir . 'logo/tec-brand.svg', - 'background_image' => $images_dir . 'marketing/bf-promo.png', - 'button_link' => 'https://evnt.is/1aqi', - ]; - - // Get the Black Friday promo content. - $content = $this->get_template()->template( 'conditional_content/black-friday', $template_args, false ); - - // Replace starting info box markup. - $fields['info-start']['html'] .= $content; - - return $fields; + public static function __callStatic( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Admin/Conditional_Content/Datetime_Conditional_Abstract.php b/src/Tribe/Admin/Conditional_Content/Datetime_Conditional_Abstract.php index 47c93351c3..e7344f5e01 100644 --- a/src/Tribe/Admin/Conditional_Content/Datetime_Conditional_Abstract.php +++ b/src/Tribe/Admin/Conditional_Content/Datetime_Conditional_Abstract.php @@ -1,160 +1,17 @@ start_date, 'UTC' ); - // If not set, set to midnight. - if ( empty( $this->start_time ) ) { - $this->start_time = 0; - } - - $date = $date->setTime( $this->start_time, 0 ); - - /** - * Allow filtering of the start date for testing. - * - * @since 4.14.7 - * @param \DateTime $date - Unix timestamp for start date - * @param object $this - */ - $date = apply_filters( "tec_admin_conditional_content_{$this->slug}_start_date", $date, $this ); - - return $date; - } - - /** - * Unix datetime for content end. - * - * @since 4.14.7 - * @return \Tribe\Utils\Date_I18n - Date Object - */ - protected function get_end_time() { - $date = Dates::build_date_object( $this->end_date, 'UTC' ); - // If not set, set to midnight. - if ( empty( $this->end_time ) ) { - $this->end_time = 0; - } - - $date = $date->setTime( $this->end_time, 0 ); - - /** - * Allow filtering of the end date for testing. - * - * @since 4.14.7 - * @param \DateTime $date - Unix timestamp for end date - * @param object $this - */ - $date = apply_filters( "tec_admin_conditional_content_{$this->slug}_end_date", $date, $this ); - - return $date; - } - - /** - * Whether the content should display. - * - * @since 4.14.7 - * @return boolean - Whether the content should display - */ - protected function should_display() { - $now = Dates::build_date_object( 'now', 'UTC' ); - $notice_start = $this->get_start_time(); - $notice_end = $this->get_end_time(); - $display = $notice_start <= $now && $now < $notice_end; - - /** - * Allow filtering whether the content should display. - * - * @since 4.14.7 - * @param bool $should_display - whether the content should display - * @param object $this - the conditional content object - */ - $should_display = apply_filters( "tec_admin_conditional_content_{$this->slug}_should_display", $display, $this ); - - return $should_display; - } - - /** - * Gets the template instance used to setup the rendering of the page. - * - * @since 4.14.7 - * - * @return \Tribe__Template - */ - public function get_template() { - if ( empty( $this->template ) ) { - $this->template = new \Tribe__Template(); - $this->template->set_template_origin( \Tribe__Main::instance() ); - $this->template->set_template_folder( 'src/admin-views' ); - $this->template->set_template_context_extract( true ); - $this->template->set_template_folder_lookup( false ); - } +abstract class Datetime_Conditional_Abstract extends \TEC\Common\Admin\Conditional_Content\Datetime_Conditional_Abstract { - return $this->template; - } } diff --git a/src/Tribe/Admin/Conditional_Content/End_Of_Year_Sale.php b/src/Tribe/Admin/Conditional_Content/End_Of_Year_Sale.php index ffded7f29a..a6453b2d84 100644 --- a/src/Tribe/Admin/Conditional_Content/End_Of_Year_Sale.php +++ b/src/Tribe/Admin/Conditional_Content/End_Of_Year_Sale.php @@ -1,85 +1,25 @@ should_display() ) { - return $fields; - } - - // Set up template variables. - $images_dir = \Tribe__Main::instance()->plugin_url . 'src/resources/images/'; - $template_args = [ - 'branding_logo' => $images_dir . 'logo/tec-brand.svg', - 'background_image' => $images_dir . 'marketing/eoy-sale-promo.png', - 'button_link' => 'https://evnt.is/1a-x', - ]; - - // Get the promo content. - $content = $this->get_template()->template( 'conditional_content/end-of-year-sale', $template_args, false ); - - // Replace starting info box markup. - $fields['info-start']['html'] .= $content; - - return $fields; - } - - /** - * Unix time for notice end. - * - * @since 4.14.9 - * - * @return \Tribe\Utils\Date_I18n - Date Object - */ - public function get_end_time() { - $date = parent::get_end_time(); - $date = $date->setTime( 23, 59 ); - - return $date; + public static function __callStatic( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Admin/Conditional_Content/Service_Provider.php b/src/Tribe/Admin/Conditional_Content/Service_Provider.php index f02671b36e..a944ec218c 100644 --- a/src/Tribe/Admin/Conditional_Content/Service_Provider.php +++ b/src/Tribe/Admin/Conditional_Content/Service_Provider.php @@ -1,52 +1,25 @@ container->singleton( Black_Friday::class, Black_Friday::class, [ 'hook' ] ); - // EOY Sale disabled for 2022 - // $this->container->singleton( End_Of_Year_Sale::class, End_Of_Year_Sale::class, [ 'hook' ] ); - $this->hooks(); - } - - /** - * Set up hooks for classes. - * - * @since 4.14.7 - */ - protected function hooks() { - add_action( 'tribe_plugins_loaded', [ $this, 'plugins_loaded' ] ); +class Service_Provider { + public function __call( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } - /** - * Setup for things that require plugins loaded first. - * - * @since 4.14.7 - */ - public function plugins_loaded() { - $this->container->make( Black_Friday::class ); - // EOY Sale disabled for 2022 - // $this->container->make( End_Of_Year_Sale::class ); + public static function __callStatic( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Admin/Notice/Marketing.php b/src/Tribe/Admin/Notice/Marketing.php deleted file mode 100644 index ecb017af2e..0000000000 --- a/src/Tribe/Admin/Notice/Marketing.php +++ /dev/null @@ -1,207 +0,0 @@ -tec_is_active = $tribe_dependency->is_plugin_active( 'Tribe__Events__Main' ); - $this->et_is_active = $tribe_dependency->is_plugin_active( 'Tribe__Tickets__Main' ); - } - - /** - * Register the various Marketing notices. - * - * @since 4.7.23 - * @deprecated 5.1.10 - */ - public function hook() { - _deprecated_function( __METHOD__, '5.1.10', 'See Tribe\Admin\Notice\Date_Based.' ); - $this->black_friday_hook_notice(); - } - - /** - * Register the Black Friday notice. - * - * @since 4.12.14 - * @deprecated 5.1.10 - */ - public function black_friday_hook_notice() { - _deprecated_function( __METHOD__, '5.1.10', 'See Tribe\Admin\Notice\Marketing\Black_Friday.' ); - - tribe_notice( - 'black-friday', - [ $this, 'black_friday_display_notice' ], - [ - 'type' => 'tribe-banner', - 'dismiss' => 1, - 'priority' => -1, - 'wrap' => false, - ], - [ $this, 'black_friday_should_display' ] - ); - } - - /** - * Unix time for Monday of Thanksgiving week @ 11am UTC. (11am UTC is 6am EST). - * - * @since 4.12.14 - * @deprecated 5.1.10 - * - * @return int - */ - public function get_black_friday_start_time() { - _deprecated_function( __METHOD__, '5.1.10', 'See Tribe\Admin\Notice\Marketing\Black_Friday.' ); - - $date = Dates::build_date_object( 'fourth Thursday of November ' . date( 'Y' ), 'UTC' ); - $date = $date->modify( '-3 days' ); - $date = $date->setTime( 11, 0 ); - - $start_time = $date->format( 'U' ); - - /** - * Allow filtering of the Black Friday sale start date, mainly for testing purposes. - * - * @since 4.12.14 - * - * @param int $bf_start_date Unix time for the Monday of Thanksgiving week @ 6am UTC. - */ - return apply_filters( 'tribe_black_friday_start_time', $start_time ); - } - - /** - * Unix time for Dec 1 @ 5am UTC. (5am UTC is 12am EST). - * - * @since 4.12.14 - * @deprecated 5.1.10 - * - * @return int - */ - public function get_black_friday_end_time() { - _deprecated_function( __METHOD__, '5.1.10', 'See Tribe\Admin\Notice\Marketing\Black_Friday.' ); - - $date = Dates::build_date_object( 'December 1st', 'UTC' ); - $date = $date->setTime( 5, 0 ); - - $end_time = $date->format( 'U' ); - - /** - * Allow filtering of the Black Friday sale end date, mainly for testing purposes. - * - * @since 4.12.14 - * - * @param int $bf_end_date Unix time for Dec 1 @ 6am UTC. - */ - return apply_filters( 'tribe_black_friday_end_time', $end_time ); - } - - /** - * Whether the Black Friday notice should display. - * - * Unix times for Monday of Thanksgiving week @ 6am UTC and Dec 1 2020 @ 6am UTC. - * 6am UTC is midnight for TheEventsCalendar.com, which uses the America/Los_Angeles time zone. - * - * @since 4.12.14 - * @deprecated 5.1.10 - * - * @return boolean - */ - public function black_friday_should_display() { - _deprecated_function( __METHOD__, '5.1.10', 'See Tribe\Admin\Notice\Marketing\Black_Friday.' ); - - // If upsells have been manually hidden, respect that. - if ( tec_should_hide_upsell() ) { - return false; - } - - $now = Dates::build_date_object( 'now', 'UTC' )->format( 'U' ); - $bf_sale_start = $this->get_black_friday_start_time(); - $bf_sale_end = $this->get_black_friday_end_time(); - - $current_screen = get_current_screen(); - - $screens = [ - 'tribe_events_page_tribe-app-shop', // App shop. - 'events_page_tribe-app-shop', // App shop. - 'tribe_events_page_tribe-common', // Settings & Welcome. - 'tribe_events_page_tec-events-settings', // New Settings & Welcome. - 'events_page_tribe-common', // Settings & Welcome. - 'toplevel_page_tribe-common', // Settings & Welcome. - ]; - - // If not a valid screen, don't display. - if ( empty( $current_screen->id ) || ! in_array( $current_screen->id, $screens, true ) ) { - return false; - } - - return $bf_sale_start <= $now && $now < $bf_sale_end; - } - - /** - * HTML for the Black Friday notice. - * - * @since 4.12.14 - * @deprecated 5.1.10 - * - * @return string - */ - public function black_friday_display_notice() { - _deprecated_function( __METHOD__, '5.1.10', 'See Tribe\Admin\Notice\Marketing\Black_Friday.' ); - - Tribe__Assets::instance()->enqueue( [ 'tribe-common-admin' ] ); - - $current_screen = get_current_screen(); - - $icon_url = Tribe__Main::instance()->plugin_url . 'src/resources/images/icons/sale-burst.svg'; - $cta_url = 'https://evnt.is/bf' . date( 'Y' ); - $screens = [ - 'tribe_events_page_tribe-common', - 'tribe_events_page_tec-events-settings', - 'events_page_tribe-common', - 'toplevel_page_tribe-common', - ]; - - // If we are on the settings page or a welcome page, change the Black Friday URL. - if ( - ! empty( $current_screen->id ) - && in_array( $current_screen->id, $screens ) - ) { - if ( isset( $_GET['welcome-message-the-events-calendar'] ) || isset( $_GET['welcome-message-event-tickets' ] ) ) { - $cta_url .= 'welcome'; - } else { - $cta_url .= 'settings'; - } - } - - ob_start(); - - include Tribe__Main::instance()->plugin_path . 'src/admin-views/notices/tribe-bf-general.php'; - - return ob_get_clean(); - } -} diff --git a/src/Tribe/Admin/Notice/Marketing/Black_Friday.php b/src/Tribe/Admin/Notice/Marketing/Black_Friday.php index 8025e40226..6ae29d1be0 100644 --- a/src/Tribe/Admin/Notice/Marketing/Black_Friday.php +++ b/src/Tribe/Admin/Notice/Marketing/Black_Friday.php @@ -1,98 +1,25 @@ enqueue( [ 'tribe-common-admin' ] ); - - // Set up template variables. - $template_args = [ - 'icon_url' => tribe_resource_url( $this->icon_url, false, null, \Tribe__Main::instance() ), - 'cta_url' => 'https://evnt.is/1aqi', - 'start_date' => $this->get_start_time()->format( 'F jS' ), - 'end_date' => $this->get_end_time()->format( 'F jS' ), - ]; - - // Get the Black Friday notice content. - $content = $this->get_template()->template( 'notices/tribe-bf-general', $template_args, false ); - - return $content; - } - - /** - * Unix time for notice start. - * - * @since 4.14.2 - * - * @return \Tribe\Utils\Date_I18n - Date Object - */ - public function get_start_time() { - $date = parent::get_start_time(); - $date = $date->modify( '-3 days' ); - - return $date; +class Black_Friday { + public function __call( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } - /** - * Enqueue additional assets for the notice. - * - * @since 5.1.10 - */ - public function enqueue_additional_assets() { - // Adds the Montserrat font from Google Fonts. - tribe_asset( - \Tribe__Main::instance(), - 'tec-black-friday-font', - 'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700', - null, - 'admin_enqueue_scripts', - [ - 'type' => 'css', - 'conditionals' => [ $this, 'should_display' ] - ] - ); + public static function __callStatic( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Admin/Notice/Marketing/End_Of_Year_Sale.php b/src/Tribe/Admin/Notice/Marketing/End_Of_Year_Sale.php index 30de2a3c3f..75e2a27bde 100644 --- a/src/Tribe/Admin/Notice/Marketing/End_Of_Year_Sale.php +++ b/src/Tribe/Admin/Notice/Marketing/End_Of_Year_Sale.php @@ -1,66 +1,25 @@ \Tribe__Main::instance()->plugin_url . 'src/resources/images/marketing/eoy-sale-2021.svg', - 'cta_url' => 'https://evnt.is/1a-x', - ]; - - // Get the sale notice content. - $content = $this->get_template()->template( 'notices/end-of-year-sale', $template_args, false ); - - return $content; +class End_Of_Year_Sale { + public function __call( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } - /** - * Unix time for notice end. - * - * @since 4.14.9 - * - * @return \Tribe\Utils\Date_I18n - Date Object - */ - public function get_end_time() { - $date = parent::get_end_time(); - $date = $date->setTime( 23, 59 ); - - return $date; + public static function __callStatic( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php b/src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php index 34976b9a19..c264f97b26 100644 --- a/src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php +++ b/src/Tribe/Admin/Notice/Marketing/Stellar_Sale.php @@ -1,89 +1,25 @@ enqueue( [ 'tribe-common-admin' ] ); - - // Used in the template. - $cta_url = 'https://evnt.is/1bdv'; - $stellar_url = 'https://evnt.is/1bdw'; - - $template_args = [ - 'heading' => __( 'Make it yours.', 'tribe-common' ), - 'sub_heading' => __( 'Save 40% on all The Events Calendar products.', 'tribe-common' ), - 'content' => __( 'Take 40% off all premium The Events Calendar products during the annual Stellar Sale. Now through July 30.', 'tribe-common' ), - 'cta_link_text' => _x( 'Shop now', 'Shop now link text', 'tribe-common' ), - 'cta_url' => $cta_url, - 'stellar_link_text' => _x( 'View all StellarWP Deals', 'View all StellarWP Deals link text', 'tribe-common' ), - 'stellar_url' => $stellar_url, - ]; - - $dependency = tribe( \Tribe__Dependency::class ); - - if ( $dependency->has_active_premium_plugin() ) { - // Determine the copy based on the active plugins. - $has_events_calendar_pro = $dependency->is_plugin_active( 'Tribe__Events__Pro__Main' ); - $has_event_tickets_plus = $dependency->is_plugin_active( 'Tribe__Tickets_Plus__Main' ); - - if ( $has_events_calendar_pro && ! $has_event_tickets_plus ) { - $template_args['sub_heading'] = __( 'Save 40% on Filter Bar.', 'tribe-common' ); - $template_args['stellar_copy'] = __( 'Add filters to your calendar during the annual Stellar Sale. Now through July 30.', 'tribe-common' ); - } elseif ( $has_event_tickets_plus && ! $has_events_calendar_pro ) { - $template_args['sub_heading'] = __( 'Save 40% on The Events Calendar Bundles.', 'tribe-common' ); - $template_args['stellar_copy'] = __( 'Take 40% off when you upgrade to a bundle during the annual Stellar Sale. Now through July 30.', 'tribe-common' ); - } else { - $template_args['heading'] = __( 'Make it stellar.', 'tribe-common' ); - $template_args['sub_heading'] = __( 'Save 40% on all StellarWP products.', 'tribe-common' ); - $template_args['stellar_copy'] = __( 'Take 40% off all brands during the annual Stellar Sale. Now through July 30.', 'tribe-common' ); - } - } +class Stellar_Sale { + public function __call( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); + } - return $this->get_template()->template( 'notices/tribe-stellar-sale', $template_args, false ); + public static function __callStatic( $name, $arguments ) { + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Admin/Notice/Service_Provider.php b/src/Tribe/Admin/Notice/Service_Provider.php index 8bdc0d2503..2ea1302370 100644 --- a/src/Tribe/Admin/Notice/Service_Provider.php +++ b/src/Tribe/Admin/Notice/Service_Provider.php @@ -30,7 +30,6 @@ public function register() { tribe_singleton( 'pue.notices', 'Tribe__PUE__Notices' ); tribe_singleton( WP_Version::class, WP_Version::class, [ 'hook' ] ); tribe_singleton( 'admin.notice.php.version', \Tribe__Admin__Notice__Php_Version::class, [ 'hook' ] ); - tribe_singleton( Marketing\Stellar_Sale::class, Marketing\Stellar_Sale::class, [ 'hook' ] ); $this->hooks(); } @@ -42,7 +41,6 @@ public function register() { */ private function hooks() { add_action( 'tribe_plugins_loaded', [ $this, 'plugins_loaded'] ); - add_action( 'current_screen', [ $this, 'enqueue_additional_assets' ] ); } /** @@ -54,24 +52,16 @@ public function plugins_loaded() { tribe( 'pue.notices' ); tribe( 'admin.notice.php.version' ); tribe( WP_Version::class ); - - if ( defined( 'TRIBE_HIDE_MARKETING_NOTICES' ) ) { - return; - } - - tribe( Marketing\Stellar_Sale::class ); - tribe( Marketing\Black_Friday::class ); - // EOY Sale disabled for 2022 - // tribe( Marketing\End_Of_Year_Sale::class ); } - /** +/** * This method is used to enqueue additional assets for the admin notices. * Each should conditionally call an internal `enqueue_additional_assets()` function to handle the enqueueing. * * @since 5.1.10 + * @deprecated 6.3.0 */ public function enqueue_additional_assets() { - tribe( Marketing\Black_Friday::class )->enqueue_additional_assets(); + _deprecated_function( __METHOD__, '6.3.0', 'No replacement.' ); } } diff --git a/src/Tribe/Field.php b/src/Tribe/Field.php index 3a73c0c43f..202f4a4e14 100755 --- a/src/Tribe/Field.php +++ b/src/Tribe/Field.php @@ -242,7 +242,12 @@ public function __construct( $id, $field, $value = null ) { $class = empty( $args['class'] ) ? '' : $this->sanitize_class_attribute( $args['class'] ); $label = is_null( $args['label'] ) ? null : wp_kses( $args['label'], [ - 'a' => [ 'href' => [], 'title' => [] ], + 'a' => [ + 'href' => [], + 'title' => [], + 'class' => [], + 'style' => [], + ], 'br' => [], 'em' => [], 'strong' => [], @@ -254,13 +259,23 @@ public function __construct( $id, $field, $value = null ) { 'src' => [], 'alt' => [], ], - 'span' => [ 'class' => [] ], + 'span' => [ + 'class' => [], + 'style' => [], + ], ] ); $label_attributes = $args['label_attributes']; $tooltip = is_null( $args['tooltip'] ) ? null : wp_kses( $args['tooltip'], [ - 'a' => [ 'class' => [], 'href' => [], 'title' => [], 'target' => [], 'rel' => [] ], + 'a' => [ + 'class' => [], + 'href' => [], + 'title' => [], + 'target' => [], + 'rel' => [], + 'style' => [], + ], 'br' => [], 'em' => [ 'class' => [] ], 'strong' => [ 'class' => [] ], @@ -272,9 +287,15 @@ public function __construct( $id, $field, $value = null ) { 'title' => [], 'src' => [], 'alt' => [], + 'style' => [], + ], + 'code' => [ + 'class' => [], + 'style' => [],], + 'span' => [ + 'class' => [], + 'style' => [], ], - 'code' => [ 'span' => [] ], - 'span' => [ 'class' => [] ], ] ); $fieldset_attributes = []; @@ -441,13 +462,31 @@ public function do_field() { ); $tags['input'] = $common_attributes; + $tags['span'] = [ + 'class' => true, + 'style' => true, + ]; $tags['textarea'] = $common_attributes; $tags['select'] = $common_attributes; $tags['option'] = $common_attributes; $tags['fieldset'] = _wp_add_global_attributes( [] ); - // Allow svgs and paths for icons. - $tags['svg'] = _wp_add_global_attributes( [ 'fill' => [], 'xmlns' => [], 'viewbox' => [] ] ); - $tags['path'] = [ 'd' => [], 'fill' => [] ]; + // Allow svg and paths for icons. + $tags['svg'] = _wp_add_global_attributes( + [ + 'fill' => [], + 'g' => [], + 'height' => [], + 'viewbox' => [], + 'width' => [], + 'xmlns' => [], + ] + ); + $tags['path'] = [ + 'd' => [], + 'fill' => [], + 'stroke' => [], + 'stroke-linecap' => [], + ]; // Allow the script and template tags for HTML fields (inserting script localization, js templates). if ( $this->type === 'html' || $this->type === 'wrapped_html' ) { diff --git a/src/Tribe/Main.php b/src/Tribe/Main.php index a6550f67c9..d47e7160c1 100644 --- a/src/Tribe/Main.php +++ b/src/Tribe/Main.php @@ -1,9 +1,9 @@ get_slug() ); + $license_key = $resource ? $resource->get_license_key( $type ) : false; + if ( $license_key ) { + return $license_key; + } + $license_key = ''; $license_origin = 'm'; diff --git a/src/Tribe/Settings.php b/src/Tribe/Settings.php index 5f7b93b380..faa97c314b 100755 --- a/src/Tribe/Settings.php +++ b/src/Tribe/Settings.php @@ -734,6 +734,7 @@ public function do_footer( $saving = false ): void { if ( $saving ) { wp_nonce_field( 'saving', 'tribe-save-settings' ); } + $current_tab = $this->get_current_tab(); if ( empty( $this->get_tab( $current_tab ) ) ) { return; @@ -1244,8 +1245,7 @@ public function save() { // Figure out the parent option [could be set to false] and filter it. if ( is_network_admin() ) { $parent_option = ( isset( $validated_field->field['parent_option'] ) ) ? $validated_field->field['parent_option'] : Tribe__Main::OPTIONNAMENETWORK; - } - if ( ! is_network_admin() ) { + } else { $parent_option = ( isset( $validated_field->field['parent_option'] ) ) ? $validated_field->field['parent_option'] : Tribe__Main::OPTIONNAME; } diff --git a/src/admin-views/app-shop.php b/src/admin-views/app-shop.php index 8fda1d02df..e4c9c133df 100644 --- a/src/admin-views/app-shop.php +++ b/src/admin-views/app-shop.php @@ -1,4 +1,7 @@ " />
+ + render_wide_banner_html(); ?> +
$some_products ) : ?> diff --git a/src/admin-views/conditional_content/black-friday.php b/src/admin-views/conditional_content/black-friday.php index 77cc2b6687..3935199862 100644 --- a/src/admin-views/conditional_content/black-friday.php +++ b/src/admin-views/conditional_content/black-friday.php @@ -1,36 +1,38 @@ -
-
- <?php echo esc_attr__( 'The Events Calendar brand logo', 'tribe-common' ); ?> -
-
-
-

- sale of the
year ends
soon

', 'tribe-common' ); ?> - - - -

-
-
-
+ + + + src="" + alt="" + /> + diff --git a/src/admin-views/conditional_content/end-of-year-sale.php b/src/admin-views/conditional_content/end-of-year-sale.php deleted file mode 100644 index 220be41e37..0000000000 --- a/src/admin-views/conditional_content/end-of-year-sale.php +++ /dev/null @@ -1,36 +0,0 @@ - - -
-
- <?php echo esc_attr__( 'The Events Calendar brand logo', 'tribe-common' ); ?> -
-
-
-

- Save 30% on
all our plugins.
Offer expires soon!', 'tribe-common' ); ?> -

- - - -
-
-
diff --git a/src/admin-views/notices/end-of-year-sale.php b/src/admin-views/notices/end-of-year-sale.php deleted file mode 100644 index 58a9122733..0000000000 --- a/src/admin-views/notices/end-of-year-sale.php +++ /dev/null @@ -1,31 +0,0 @@ - -
-
- -
-
-

-

- - - - - - -

-
-
diff --git a/src/admin-views/notices/tribe-bf-general.php b/src/admin-views/notices/tribe-bf-general.php deleted file mode 100644 index ce1d92ec16..0000000000 --- a/src/admin-views/notices/tribe-bf-general.php +++ /dev/null @@ -1,39 +0,0 @@ - -
-
-

- -

-

- -

-

- - - - - -

-
- -
- -
- -
diff --git a/src/admin-views/notices/tribe-stellar-sale-premium.php b/src/admin-views/notices/tribe-stellar-sale-premium.php deleted file mode 100644 index b7d3c386a3..0000000000 --- a/src/admin-views/notices/tribe-stellar-sale-premium.php +++ /dev/null @@ -1,68 +0,0 @@ - -
-
-
-

- -

-

- -

-

- - - - - -

-
- -
-

- ', - '' - ); - ?> -

-
-

- - - - - -

- -

- - - - - -

-
-
- -
- -
-
-
diff --git a/src/admin-views/notices/tribe-stellar-sale.php b/src/admin-views/notices/tribe-stellar-sale.php deleted file mode 100644 index c4bc8eb7f3..0000000000 --- a/src/admin-views/notices/tribe-stellar-sale.php +++ /dev/null @@ -1,61 +0,0 @@ - -
-
-
-

- -

-

- -

-

- - - - - -

-
- -
-

- -

-
-

- - - - - -

- -

- - - - - -

-
-
- -
- -
-
-
diff --git a/src/resources/images/hero-section-narrow.jpg b/src/resources/images/hero-section-narrow.jpg new file mode 100644 index 0000000000..1491fb80ab Binary files /dev/null and b/src/resources/images/hero-section-narrow.jpg differ diff --git a/src/resources/images/hero-section-settings-sidebar.jpg b/src/resources/images/hero-section-settings-sidebar.jpg new file mode 100644 index 0000000000..c9ba16facb Binary files /dev/null and b/src/resources/images/hero-section-settings-sidebar.jpg differ diff --git a/src/resources/images/hero-section-wide.jpg b/src/resources/images/hero-section-wide.jpg new file mode 100644 index 0000000000..a4fa46d0d2 Binary files /dev/null and b/src/resources/images/hero-section-wide.jpg differ diff --git a/src/resources/images/marketing/bf-promo.png b/src/resources/images/marketing/bf-promo.png deleted file mode 100644 index fdc21940eb..0000000000 Binary files a/src/resources/images/marketing/bf-promo.png and /dev/null differ diff --git a/src/resources/images/marketing/eoy-sale-2021.svg b/src/resources/images/marketing/eoy-sale-2021.svg deleted file mode 100644 index ba63a4b3ee..0000000000 --- a/src/resources/images/marketing/eoy-sale-2021.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/resources/images/marketing/eoy-sale-promo.png b/src/resources/images/marketing/eoy-sale-promo.png deleted file mode 100644 index 55455cb92e..0000000000 Binary files a/src/resources/images/marketing/eoy-sale-promo.png and /dev/null differ diff --git a/src/resources/images/marketing/stellar-sale-banner-bg.svg b/src/resources/images/marketing/stellar-sale-banner-bg.svg deleted file mode 100644 index 1090b0b04d..0000000000 --- a/src/resources/images/marketing/stellar-sale-banner-bg.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/src/resources/images/mascot.png b/src/resources/images/mascot.png index 5676c29f3b..1ba2e02c96 100644 Binary files a/src/resources/images/mascot.png and b/src/resources/images/mascot.png differ diff --git a/src/resources/images/promos/bf-promo.png b/src/resources/images/promos/bf-promo.png deleted file mode 100644 index b327d438c8..0000000000 Binary files a/src/resources/images/promos/bf-promo.png and /dev/null differ diff --git a/src/resources/js/admin/conditional-content.js b/src/resources/js/admin/conditional-content.js new file mode 100644 index 0000000000..1090d58383 --- /dev/null +++ b/src/resources/js/admin/conditional-content.js @@ -0,0 +1,79 @@ +/** + * Notice Dismiss structure + */ +( function( $, wp, obj ) { + const { tec } = window; + + /** + * Selectors used for configuration and setup. + * + * @since 6.3.0 + * + * @type {{}} + */ + obj.selectors = { + dismissButton: '[data-tec-conditional-content-dismiss-button]', + dismissedContainer: '[data-tec-conditional-content-dismiss-container]', + }; + + + /** + * Handles the click event on the dismiss button. + * + * @since 6.3.0 + * + * @param {Event} event + */ + obj.onDismissClick = ( event ) => { + event.preventDefault(); + + let $button = $( event.target ); + if ( ! $button.is( obj.selectors.dismissButton ) ) { + $button = $button.parents( obj.selectors.dismissButton ).eq( 0 ); + } + + const $container = $button.parents( obj.selectors.dismissedContainer ).eq( 0 ); + + if ( ! $container.length ) { + return; + } + + let slug = $button.data( 'tecConditionalContentDismissSlug' ); + + if ( ! slug ) { + slug = $container.data( 'tecConditionalContentDismissSlug' ); + } + + let nonce = $button.data( 'tecConditionalContentDismissNonce' ); + + if ( ! nonce ) { + nonce = $container.data( 'tecConditionalContentDismissNonce' ); + } + + if ( ! slug || ! nonce ) { + return; + } + + $.ajax( ajaxurl, { + dataType: 'json', + method: 'POST', + data: { + action: 'tec_conditional_content_dismiss', + slug: slug, + nonce: nonce, + }, + complete: () => { + $container.remove(); + }, + } ); + }; + + $( document ).on( + 'click', + obj.selectors.dismissButton, + obj.onDismissClick + ); + + // Expose the object to the global scope. + tec.conditionalContent = obj; +}( jQuery, window.wp, {} ) ); diff --git a/src/resources/js/dependency.js b/src/resources/js/dependency.js index 3fb851cc16..53cf1659c8 100644 --- a/src/resources/js/dependency.js +++ b/src/resources/js/dependency.js @@ -35,7 +35,7 @@ }; /** - * Replacemente for jQuery $.isNumeric that was deprecated on version 5.7 of WP. + * Replacement for jQuery $.isNumeric that was deprecated on version 5.7 of WP. * * @param {string|int} number * diff --git a/src/resources/js/tribe-common.js b/src/resources/js/tribe-common.js index 1f4c0d9084..509dcd60d2 100644 --- a/src/resources/js/tribe-common.js +++ b/src/resources/js/tribe-common.js @@ -85,3 +85,14 @@ String.prototype.varName = function () { * @type {object} */ var tribe = tribe || {}; // eslint-disable-line no-redeclare + + +/** + * Creates a `window.tec` variable where we should start to store all the things. + * Eventually we will migrate all the things from `window.tribe` to `window.tec`. + * + * @since 6.3.0 + * + * @type {object} + */ +window.tec = window.tec || {}; // eslint-disable-line no-redeclare diff --git a/src/resources/postcss/dialog.pcss b/src/resources/postcss/dialog.pcss index dca8d876dd..231159cda7 100644 --- a/src/resources/postcss/dialog.pcss +++ b/src/resources/postcss/dialog.pcss @@ -84,7 +84,8 @@ This can include modals, toasters, confirms. alerts. /* The "close" button */ .tribe-dialog__close-button { background: var(--tec-dialog-close-background); - background-image: svg-inline(close-secondary); + /* We overwrite this for twentytwenty while we still need it. */ + background-image: svg-inline(close-secondary) !important; background-repeat: no-repeat; background-size: contain; cursor: pointer; diff --git a/src/resources/postcss/tribe-common-admin/_licensing.pcss b/src/resources/postcss/tribe-common-admin/_licensing.pcss new file mode 100644 index 0000000000..f1d209739d --- /dev/null +++ b/src/resources/postcss/tribe-common-admin/_licensing.pcss @@ -0,0 +1,12 @@ +.stellarwp-uplink__settings-field { + max-width: 450px; + width: 100%; + + @media (--viewport-medium) { + width: 450px; + } +} + +.license-test-results { + margin-bottom: 5px; +} diff --git a/src/resources/postcss/tribe-common-admin/settings/_fields.pcss b/src/resources/postcss/tribe-common-admin/settings/_fields.pcss index 82a64b748f..586ac2aa58 100644 --- a/src/resources/postcss/tribe-common-admin/settings/_fields.pcss +++ b/src/resources/postcss/tribe-common-admin/settings/_fields.pcss @@ -86,7 +86,7 @@ @media (--viewport-full) { margin-bottom: var(--tec-spacer-1); } - } + } .tec-settings-teaser-pill { background-color: var(--tec-color-border-default); diff --git a/src/resources/postcss/tribe-common-admin/settings/_form.pcss b/src/resources/postcss/tribe-common-admin/settings/_form.pcss index 8598e78930..265764f4aa 100644 --- a/src/resources/postcss/tribe-common-admin/settings/_form.pcss +++ b/src/resources/postcss/tribe-common-admin/settings/_form.pcss @@ -46,7 +46,7 @@ background-color: var(--tec-color-background); border: 1px solid var(--tec-admin-core-grey-10); border-radius: var(--tec-border-radius-default); - margin-top: var(--tec-spacer-4); + margin-top: var(--tec-spacer-5); padding-top: var(--tec-spacer-7); &.tec-settings-form__subnav-active { @@ -72,7 +72,7 @@ border-radius: var(--tec-border-radius-default); column-gap: var(--tec-spacer-settings-form-col-gap); grid-template-columns: var(--tec-spacer-settings-form-width-left-col) 1fr; - margin: var(--tec-spacer-7) 0 0 var(--tec-spacer-5); + margin: var(--tec-spacer-5) 0 0 var(--tec-spacer-7); &.tec-settings-form__subnav-active { padding-top: calc(var(--tec-spacer-9) + var(--tec-spacer-6) - 2px); diff --git a/src/resources/postcss/tribe-common-admin/settings/_modal-sidebar.pcss b/src/resources/postcss/tribe-common-admin/settings/_modal-sidebar.pcss index ad77584a04..45d90d5e8d 100644 --- a/src/resources/postcss/tribe-common-admin/settings/_modal-sidebar.pcss +++ b/src/resources/postcss/tribe-common-admin/settings/_modal-sidebar.pcss @@ -18,6 +18,7 @@ } #tec-settings-form__sidebar-modal { + background: transparent; margin: 0 0 0 auto; max-width: var(--tec-width-sidebar); padding: 0; diff --git a/src/resources/postcss/tribe-common-admin/settings/_sidebar.pcss b/src/resources/postcss/tribe-common-admin/settings/_sidebar.pcss index 921a57019e..6054bdb43d 100644 --- a/src/resources/postcss/tribe-common-admin/settings/_sidebar.pcss +++ b/src/resources/postcss/tribe-common-admin/settings/_sidebar.pcss @@ -10,22 +10,23 @@ .tec-settings-form__sidebar { align-items: flex-start; align-self: stretch; - background-color: var(--tec-color-background); box-sizing: border-box; display: none; flex-direction: column; gap: var(--tec-spacer-3); max-width: var(--tec-width-sidebar); min-height: 100vh; - padding-bottom: var(--tec-spacer-4); width: 100%; @media (--viewport-xlarge) { - border: 1px solid var(--tec-color-border-default); - border-radius: var(--tec-border-radius-default); display: flex; - margin: var(--tec-spacer-4) auto auto 0; + margin: var(--tec-spacer-5) auto auto 0; min-height: fit-content; + + > .tec-settings-form__sidebar-section { + margin: 0 auto auto 0; + border: 1px solid var(--tec-color-border-default); + } } h2, @@ -43,38 +44,52 @@ } img { + display: block; width: 100%; } - .tec-settings-form__sidebar-section { - margin: 0 var(--tec-spacer-4); + > .tec-settings-form__sidebar-section { + background-color: var(--tec-color-background); + border-radius: var(--tec-border-radius-default); + overflow: hidden; + display: flex; + flex-direction: column; + gap: var(--tec-spacer-3); - &.tec-settings-form__sidebar-header { - margin: 0; + .tec-settings-form__sidebar-section { + margin: 0 var(--tec-spacer-4); - h2 { - margin: 0 var(--tec-spacer-4); + &:last-child { + margin-bottom: var(--tec-spacer-4); } - img { - border-top-left-radius: var(--tec-border-radius-default); - border-top-right-radius: var(--tec-border-radius-default); + &.tec-settings-form__sidebar-header { + margin: 0; + + h2 { + margin: 0 var(--tec-spacer-4); + } + + img { + border-top-left-radius: var(--tec-border-radius-default); + border-top-right-radius: var(--tec-border-radius-default); + } } - } - > * { - letter-spacing: -0.28px; - line-height: 150%; - margin: 0; - } + > * { + letter-spacing: -0.28px; + line-height: 150%; + margin: 0; + } - a, - p { - font-size: var(--tec-font-size-2); - } + a, + p { + font-size: var(--tec-font-size-2); + } - p { - margin: 0; + p { + margin: 0; + } } } } diff --git a/src/resources/postcss/tribe-common-admin/settings/_tabbed-nav.pcss b/src/resources/postcss/tribe-common-admin/settings/_tabbed-nav.pcss index 6e1d0ac6e4..7405618d56 100644 --- a/src/resources/postcss/tribe-common-admin/settings/_tabbed-nav.pcss +++ b/src/resources/postcss/tribe-common-admin/settings/_tabbed-nav.pcss @@ -18,6 +18,11 @@ box-sizing: border-box; display: block; overflow-x: scroll; + + scrollbar-width: none; /* Firefox 64 */ + &::-webkit-scrollbar { + display: none; + } } @media (--viewport-full) { @@ -145,7 +150,7 @@ border-top-right-radius: var(--tec-border-radius-default); flex-direction: row; margin-left: 0; - margin-top: calc(var(--tec-spacer-7) + 1px); + margin-top: calc(var(--tec-spacer-7) + 5px); overflow: hidden; > .tec-nav__tab { @@ -183,7 +188,7 @@ } @media (--viewport-xlarge) { - left: var(--tec-spacer-5); + left: var(--tec-spacer-7); max-width: min(calc((100vw - 160px - var(--tec-width-sidebar)) - (var(--tec-spacer-7) * 3)), var(--tec-spacer-settings-form-width)); width: min(calc((100vw - 160px - var(--tec-width-sidebar)) - (var(--tec-spacer-7) * 3)), var(--tec-spacer-settings-form-width)); } diff --git a/src/resources/postcss/tribe-common-admin/settings/_upsell.pcss b/src/resources/postcss/tribe-common-admin/settings/_upsell.pcss index 8dc099fe8e..d37630622a 100644 --- a/src/resources/postcss/tribe-common-admin/settings/_upsell.pcss +++ b/src/resources/postcss/tribe-common-admin/settings/_upsell.pcss @@ -5,107 +5,116 @@ * This file contains styles/overrides specific to the upsell tabs. * * ----------------------------------------------------------------------------- */ +.tec-admin__upsell-container { + max-width:1000px; + margin: var(--tec-spacer-4) var(--tec-spacer-7) 0 var(--tec-spacer-1); +} -.tribe_events_page_tec-events-settings { - #tec-settings-form .tec-settings-form__upsell { - background-color: var(--tec-admin-core-grey-0); - border: 1px solid var(--tec-admin-core-grey-10); - border-radius: var(--tec-border-radius-default); - box-sizing: border-box; - display: flex; - flex-direction: column-reverse; - margin: 0; - max-width: calc(100vw - (2 * var(--tec-spacer-7))); - padding: var(--tec-spacer-4); - width: 100%; +.tec-admin__upsell-banner, +.tribe_events_page_tec-events-settings #tec-settings-form .tec-settings-form__upsell { + background-color: var(--tec-admin-core-grey-0); + border: 1px solid var(--tec-admin-core-grey-10); + border-radius: var(--tec-border-radius-default); + box-sizing: border-box; + display: flex; + flex-direction: column-reverse; + margin: 0; + max-width: calc(100vw - (2 * var(--tec-spacer-7))); + padding: var(--tec-spacer-4); + width: 100%; - @media (--viewport-full) { - align-items: center; - flex-direction: row; - grid-column: 1 / span 2; - max-width: 100%; - padding: var(--tec-spacer-8); - } + @media (--viewport-full) { + align-items: center; + flex-direction: row; + grid-column: 1 / span 2; + max-width: 100%; + padding: var(--tec-spacer-8); + } - @media (--viewport-xlarge) { - margin-right: 0; - } + @media (--viewport-xlarge) { + margin-right: 0; + } - .tec-settings-form__upsell-content { - color: var(--tec-admin-core-grey-80); - display: flex; - flex-direction: column; - max-width: 100%; + .tec-admin__upsell-banner-content, + .tec-settings-form__upsell-content { + color: var(--tec-admin-core-grey-80); + display: flex; + flex-direction: column; + max-width: 100%; - p { - font-size: var(--tec-font-size-7); - line-height: var(--tec-line-height-2); + p { + font-size: var(--tec-font-size-7); + line-height: var(--tec-line-height-2); - &:last-of-type { - margin-bottom: 0; - } + &:last-of-type { + margin-bottom: 0; + } - @media (--viewport-xsmall) { - font-size: var(--tec-font-size-5); - } + @media (--viewport-xsmall) { + font-size: var(--tec-font-size-5); } } + } - .tec-settings-form__upsell-header { - display: flex; - flex-flow: row nowrap; - margin-bottom: var(--tec-spacer-2); + .tec-admin__upsell-banner-header, + .tec-settings-form__upsell-header { + display: flex; + flex-flow: row nowrap; + margin-bottom: var(--tec-spacer-2); - .tec-settings-form__upsell-logo { - height: var(--tec-spacer-5); - object-fit: contain; - vertical-align: middle; - } + .tec-admin__upsell-banner-logo, + .tec-settings-form__upsell-logo { + height: var(--tec-spacer-5); + object-fit: contain; + vertical-align: middle; + } - .tec-settings-form__upsell-title { - color: var(--tec-admin-core-grey-80); - font-size: var(--tec-font-size-7); - font-weight: bold; - line-height: 1; - margin: 0 0 0 var(--tec-spacer-1); - } + .tec-admin__upsell-banner-title, + .tec-settings-form__upsell-title { + color: var(--tec-admin-core-grey-80); + font-size: var(--tec-font-size-7); + font-weight: bold; + line-height: 1; + margin: 0 0 0 var(--tec-spacer-1); } + } - .tec-settings-form__upsell-image { - align-self: center; - height: auto; - margin-bottom: var(--tec-spacer-5); - max-width: 100%; - object-fit: contain; + .tec-admin__upsell-banner-image, + .tec-settings-form__upsell-image { + align-self: center; + height: auto; + margin-bottom: var(--tec-spacer-5); + max-width: 100%; + object-fit: contain; - @media (--viewport-full) { - margin-bottom: 0; - margin-left: var(--tec-spacer-8); - max-width: 240px; - } + @media (--viewport-full) { + margin-bottom: 0; + margin-left: var(--tec-spacer-8); + max-width: 240px; } + } - .tec-settings-form__upsell-btn { - background: var(--tec-color-button-primary); - border: 2px var(--tec-color-button-primary) solid; - border-radius: var(--tec-border-radius-default); - color: var(--tec-color-background); - display: inline-block; - font-size: var(--tec-font-size-3); - font-weight: 500; - margin-top: var(--tec-spacer-5); - padding: var(--tec-spacer-3); - text-decoration: none; - width: fit-content; + .tec-admin__upsell-banner-btn, + .tec-settings-form__upsell-btn { + background: var(--tec-color-button-primary); + border: 2px var(--tec-color-button-primary) solid; + border-radius: var(--tec-border-radius-default); + color: var(--tec-color-background); + display: inline-block; + font-size: var(--tec-font-size-3); + font-weight: 500; + margin-top: var(--tec-spacer-5); + padding: var(--tec-spacer-3); + text-decoration: none; + width: fit-content; - &:hover, - &:active, - &:focus { - background: transparent; - box-shadow: none; - color: var(--tec-color-button-primary); - outline: none; - } + &:hover, + &:active, + &:focus { + background: transparent; + box-shadow: none; + color: var(--tec-color-button-primary); + outline: none; } } } diff --git a/tests/_support/Traits/Create_attendees.php b/tests/_support/Traits/Create_Attendees.php similarity index 99% rename from tests/_support/Traits/Create_attendees.php rename to tests/_support/Traits/Create_Attendees.php index 81bc2eb3a4..28b133f718 100644 --- a/tests/_support/Traits/Create_attendees.php +++ b/tests/_support/Traits/Create_Attendees.php @@ -24,8 +24,7 @@ use WC_Product_Simple; use WP_Post; -trait Create_attendees { - +trait Create_Attendees { use RSVP_Ticket_Maker; use TC_Ticket_Maker; use TC_Order_Maker; diff --git a/tests/_support/Traits/Create_events.php b/tests/_support/Traits/Create_Events.php similarity index 99% rename from tests/_support/Traits/Create_events.php rename to tests/_support/Traits/Create_Events.php index 3715758b3e..2b38da54ad 100644 --- a/tests/_support/Traits/Create_events.php +++ b/tests/_support/Traits/Create_Events.php @@ -6,7 +6,7 @@ use Tribe\Events\Event_Status\Classic_Editor; use Tribe__Utils__Array as Arr; -trait Create_events { +trait Create_Events { protected function generate_event( $mock_date, $overrides = [] ) { $timezone_string = 'America/New_York'; diff --git a/tests/_support/Traits/Function_Spy.php b/tests/_support/Traits/Function_Spy.php new file mode 100644 index 0000000000..f89b0085b4 --- /dev/null +++ b/tests/_support/Traits/Function_Spy.php @@ -0,0 +1,141 @@ +name; + } + + /** + * Registers a call to the function. + * + * @param array $args + * + * @return void + */ + public function register_call( array $args ): void { + $this->calls[] = $args; + } + + /** + * Sets whether the function is expected to be called or not. + * + * @since TBD + * + * @return void + */ + public function should_be_called(): void { + $this->expects_calls = true; + } + + /** + * Sets whether the function is not expected to be called or not. + * + * @since TBD + * + * @return void + */ + public function should_not_be_called(): void { + $this->expects_calls = false; + } + + /** + * Returns whether the function is expected to be called or not. + * + * @return bool + */ + public function expects_calls(): bool { + return $this->expects_calls; + } + + /** + * Returns whether the function has been called or not. + * + * @return bool + */ + public function was_called(): bool { + $this->was_verified = true; + return count( $this->calls ) > 0; + } + + public function was_called_times_with( int $times, ...$args ): bool { + if ( count( $this->calls ) < $times ) { + return false; + } + + $matching_calls = 0; + + foreach ( $this->calls as $call ) { + $match = true; + foreach ( $args as $k => $arg ) { + if ( $arg == $call[ $k ] ) { + continue; + } + + $match = false; + break; + } + + $matching_calls += (int) $match; + } + + return $matching_calls === $times; + } + + /** + * Returns whether the function has been verified by a query method or not. + * + * @return bool + */ + public function was_verified(): bool { + return $this->was_verified; + } +} diff --git a/tests/_support/Traits/Service_Locator_Mocks.php b/tests/_support/Traits/Service_Locator_Mocks.php new file mode 100644 index 0000000000..ce78d58447 --- /dev/null +++ b/tests/_support/Traits/Service_Locator_Mocks.php @@ -0,0 +1,114 @@ + + */ + private array $service_locator_mock_unsets = []; + + /** + * Mocks a singleton service annd replaces it with a mock. + * + * @param string $slug The service slug. + * @param array $methods An array of methods and their return values. + * If a closure is provided, it will be called when the method is called. + * + * @return Closure A closure that will restore the original service when called. + */ + protected function mock_singleton_service( $slug, array $methods ): Closure { + $original_service = tribe( $slug ); + $original_class_name = get_class( $original_service ); + $mock = $this->createPartialMock( $original_class_name, array_keys( $methods ) ); + $mock_class_name = get_class( $mock ); + tribe()->singleton( $slug, $mock_class_name ); + $built_by_service_locator = tribe()->get( $slug ); + tribe()->singleton( $slug, function () use ( $built_by_service_locator, $methods ) { + foreach ( $methods as $method => $return ) { + if ( $return instanceof Closure ) { + $built_by_service_locator->method( $method )->willreturncallback( $return ); + continue; + } + $built_by_service_locator->method( $method )->willreturn( $return ); + } + + return $built_by_service_locator; + } ); + + $unsets = $this->service_locator_mock_unsets; + $unset = static function () use ( $slug, $original_service, &$unsets, &$unset ) { + tribe()->singleton( $slug, $original_service ); + $unsets = array_values( array_diff( $unsets, [ $unset ] ) ); + }; + + $this->service_locator_mock_unsets[] = $unset; + + return $unset; + } + + /** + * Mocks a prototype service. i.e. a service that is not bound as a singleton, and replaces it with a mock. + * + * @param string $slug The service slug. + * @param array $methods An array of methods and their return values. + * If a closure is provided, it will be called when the method is called. + * + * @return Closure A closure that will restore the original service when called. + */ + protected function mock_prototype_service( $slug, array $methods ): Closure { + $original_service = tribe( $slug ); + $original_class_name = get_class( $original_service ); + $mock = $this->createPartialMock( $original_class_name, array_keys( $methods ) ); + $mock_class_name = get_class( $mock ); + tribe()->bind( $slug, $mock_class_name ); + $built_by_service_locator = tribe()->get( $slug ); + tribe()->bind( $slug, function () use ( $built_by_service_locator, $methods ) { + $built_by_service_locator_clone = clone $built_by_service_locator; + foreach ( $methods as $method => $return ) { + if ( $return instanceof Closure ) { + $built_by_service_locator_clone->method( $method )->willreturncallback( $return ); + continue; + } + $built_by_service_locator_clone->method( $method )->willreturn( $return ); + } + + return $built_by_service_locator_clone; + } ); + + $unsets = $this->service_locator_mock_unsets; + $unset = static function () use ( $slug, $original_service, &$unsets, &$unset ) { + tribe()->bind( $slug, $original_service ); + $unsets = array_values( array_diff( $unsets, [ $unset ] ) ); + }; + + $this->service_locator_mock_unsets[] = $unset; + + return $unset; + } + + /** + * @after + */ + public function unset_all_service_locator_mocks(): void { + foreach ( $this->service_locator_mock_unsets as $unset ) { + $unset(); + } + + $this->service_locator_mock_unsets = []; + } +} diff --git a/tests/_support/Traits/WP_Remote_Mocks.php b/tests/_support/Traits/WP_Remote_Mocks.php new file mode 100644 index 0000000000..82e84617be --- /dev/null +++ b/tests/_support/Traits/WP_Remote_Mocks.php @@ -0,0 +1,191 @@ +name = $name; + $this->method = strtoupper( $method ); + $this->url = $url; + } + + public function get_url(): string { + return $this->url; + } + + public function get_http_method(): string { + return $this->method; + } + + public function tear_down(): void { + $this->was_verified = true; + uopz_unset_return( $this->name ); + } +} + +/** + * Class WP_Request_Mocking. + * + * @since TBD + * + * @package Traits; + */ +trait WP_Remote_Mocks { + /** + * A map from the hash of the mock function to the calls that were made to it. + * + * @var WP_Remote_Mock_Spy[] + */ + private array $wp_remote_spies = []; + + /** + * Mocks a `wp_remote_` function based on the URL. + * + * Note this function will not throw an exception if the mock is never called. + * + * @since TBD + * + * @param string $type The type of function to mock, e.g. `post` will mock `wp_remote_post`. + * @param string $mock_url The URL to mock requests for; requests that do not match this will not + * be mocked. Requests for another URL will be passed through to the + * original function. + * @param array|callable $expected_args The set of arguments to check against the request. + * This does not have to be a comprehensive list of all + * arguments, but it should be enough to cover the ones that are + * relevant to the test. If the callable returns a Generator, it will + * be called to get the expected arguments at each step. + * @param mixed $mock_response The response to return for the mocked request; it can be a WP_Error + * to simulate an HTTP API failure. If the callable + * returns a Generator, it will be called to get the response at each + * step. + * + * @return WP_Remote_Mock_Spy The spy object that can be used to assert the calls. + * + * @throws \ReflectionException + */ + protected function mock_wp_remote( string $type, string $mock_url, $expected_args, $mock_response ): WP_Remote_Mock_Spy { + // Extract the expected arguments' generator. + if ( + is_callable( $expected_args ) + && ( $return_type = ( new \ReflectionFunction( $expected_args ) )->getReturnType() ) + && $return_type->getName() === Generator::class + ) { + $expected_args = $expected_args(); + } + + // Extract the mock response generator. + if ( + is_callable( $mock_response ) + && ( $return_type = ( new \ReflectionFunction( $mock_response ) )->getReturnType() ) + && $return_type->getName() === Generator::class + ) { + $mock_response = $mock_response(); + } + + $name = in_array( $type, [ 'get', 'head', 'post' ], true ) ? 'wp_remote_' . $type : 'wp_remote_request'; + $spy = new WP_Remote_Mock_Spy( $name, $type, $mock_url ); + + $mock = function ( string $url, array $args ) use ( $mock_url, $expected_args, $mock_response, &$spy ) { + if ( $url !== $mock_url ) { + return wp_remote_post( $url, $args ); + } + + $compare_args = $expected_args; + if ( is_callable( $expected_args ) ) { + $compare_args = $expected_args( $args ); + } elseif ( $expected_args instanceof \Generator ) { + $compare_args = $expected_args->current(); + $expected_args->next(); + } + + foreach ( $compare_args as $key => $value ) { + Assert::assertEquals( $value, $args[ $key ], 'Argument ' . $key . ' does not match.' ); + } + + $current_mock_response = $mock_response; + if ( is_callable( $mock_response ) ) { + $current_mock_response = $mock_response(); + } elseif ( $mock_response instanceof \Generator ) { + $current_mock_response = $mock_response->current(); + $mock_response->next(); + } + + $spy->register_call( $args ); + + return $current_mock_response; + }; + + $this->wp_remote_spies[] = $spy; + + if ( in_array( $type, [ 'get', 'head', 'post' ], true ) ) { + $this->set_fn_return( "wp_remote_{$type}", $mock, true ); + } else { + $this->set_fn_return( "wp_remote_request", $mock, true ); + } + + return $spy; + } + + /** + * @after + */ + public function assert_wp_remote_mocks_post_conditions(): void { + foreach ( $this->wp_remote_spies as $spy ) { + if ( ! $spy->was_verified() && $spy->expects_calls() ) { + if($spy->expects_calls()){ + $this->assertTrue( $spy->was_called(), + sprintf( + "The %s mock function for [%s %s] was not called.", + $spy->get_name(), + $spy->get_http_method(), + $spy->get_url(), + ) + ); + } else { + $this->assertFalse( $spy->was_called(), + sprintf( + "The %s mock function for [%s %s] was called.", + $spy->get_name(), + $spy->get_http_method(), + $spy->get_url(), + ) + ); + } + } + } + + $this->wp_remote_spies = []; + } +} \ No newline at end of file diff --git a/tests/_support/Traits/WP_Send_Json_Mocks.php b/tests/_support/Traits/WP_Send_Json_Mocks.php new file mode 100644 index 0000000000..efedcf7c51 --- /dev/null +++ b/tests/_support/Traits/WP_Send_Json_Mocks.php @@ -0,0 +1,164 @@ +name = $name; + } + + public function get_pretty_arguments(): string { + return json_encode( $this->calls, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES ); + } + + public function get_pretty_calls(): array { + return array_map( static function ( $call ) { + return var_export( $call, true ); + }, $this->calls ); + } + + public function get_calls_as_string(): string { + return var_export( $this->calls, true ); + } +} + +/** + * Class WP_Send_Json_Mocks. + * + * @since TBD + * + * @package Traits; + */ +trait WP_Send_Json_Mocks { + /** + * A map from the hash of the mock function to the calls that were made to it. + * + * @var WP_Send_Json_Mock_Spy[] + */ + public array $wp_send_json_spies = []; + + public WP_Send_Json_Mock_Spy $wp_send_json_unexpected_spy; + + /** + * @before + */ + public function set_up_wp_send_json_mocks(): void { + $this->wp_send_json_spies = []; + $this->wp_send_json_unexpected_spy = new WP_Send_Json_Mock_Spy( 'wp_send_json' ); + $this->wp_send_json_unexpected_spy->should_not_be_called(); + $this->wp_send_json_spies[] = $this->wp_send_json_unexpected_spy; + $test_case = $this; + $log_unexpected = static function ( $response, $status_code = null, $flags = 0 ) use ( $test_case ) { + $test_case->wp_send_json_unexpected_spy->register_call( [ $response, $status_code, $flags ] ); + }; + $this->set_fn_return( "wp_send_json", $log_unexpected, true ); + + $this->set_fn_return( + 'check_ajax_referer', + static function ( $action = -1, $query_arg = false, $stop = true ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed + $nonce = ''; + // phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) ) { + $nonce = $_REQUEST[ $query_arg ]; + } elseif ( isset( $_REQUEST['_ajax_nonce'] ) ) { + $nonce = $_REQUEST['_ajax_nonce']; + } elseif ( isset( $_REQUEST['_wpnonce'] ) ) { + $nonce = $_REQUEST['_wpnonce']; + } + // phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + + $result = wp_verify_nonce( $nonce, $action ); + + if ( ! $result && $stop ) { + throw new Exception( 'check_ajax_referer failed and was called with stop = true' ); + } + + return $result; + }, + true + ); + } + + protected function mock_wp_send_json_error( $value = null, $status_code = null, $flags = 0 ): WP_Send_Json_Mock_Spy { + $spy = new WP_Send_Json_Mock_Spy( 'wp_send_json_error' ); + + $mock = static function ( $value = null, $status_code = null, $flags = 0 ) use ( $spy ) { + $spy->register_call( [ $value, $status_code, $flags ] ); + }; + + $this->set_fn_return( "wp_send_json_error", $mock, true ); + $this->wp_send_json_spies[] = $spy; + + return $spy; + } + + protected function mock_wp_send_json_success(): WP_Send_Json_Mock_Spy { + $spy = new WP_Send_Json_Mock_Spy( 'wp_send_json_success' ); + $mock = function ( $data = null, $status_code = null, $options = 0 ) use ( $spy ) { + $spy->register_call( [ $data, $status_code, $options ] ); + }; + + $this->set_fn_return( "wp_send_json_success", $mock, true ); + $this->wp_send_json_spies[] = $spy; + + return $spy; + } + + protected function reset_wp_send_json_mocks(): void { + $this->wp_send_json_spies = []; + uopz_unset_return( 'wp_send_json_error' ); + uopz_unset_return( 'wp_send_json_success' ); + } + + /** + * @after + */ + public function assert_wp_send_json_mocks_post_conditions(): void { + foreach ( $this->wp_send_json_spies as $spy ) { + if ( $spy->was_verified() ) { + continue; + } + + if ( $spy->expects_calls() ) { + $this->assertTrue( $spy->was_called(), + sprintf( + "The %s mock function was never called with expected arguments:\n%s\n\nUnexpected calls:\n%s\n\nwp_send_json calls:\n%s", + $spy->get_name(), + $spy->get_pretty_arguments(), + implode( "\n", $spy->get_pretty_calls() ) ?: 'none', + implode( "\n", $this->wp_send_json_unexpected_spy->get_pretty_calls() ) ?: 'none', + ) + ); + } else { + $this->assertFalse( $spy->was_called(), + sprintf( + "The %s mock function was unexpectedly called with:\n%s", + $spy->get_name(), + implode( "\n", $spy->get_pretty_calls() ) + ) + ); + } + } + + $this->wp_send_json_spies = []; + $this->wp_send_json_unexpected_spy = new WP_Send_Json_Mock_Spy( 'wp_send_json' ); + } +} diff --git a/tests/_support/Traits/With_Clock_Mock.php b/tests/_support/Traits/With_Clock_Mock.php new file mode 100644 index 0000000000..f3a58be387 --- /dev/null +++ b/tests/_support/Traits/With_Clock_Mock.php @@ -0,0 +1,71 @@ +clock_mock_frozen ) { + return; + } + + ClockMock::reset(); + } + + /** + * Using the clock mock library, set the current PHP time and date functions to a specific time. + * + * @since TBD + * + * @param \DateTimeInterface $datetime The datetime to freeze the clock to. + * + * @return void Time is frozen. + */ + protected function freeze_time( \DateTimeInterface $datetime ): void { + $this->clock_mock_frozen = true; + ClockMock::freeze( $datetime ); + } + + /** + * Unfreeze the time. + * + * @since TBD + * + * @return void Time is unfrozen. + */ + protected function unfreeze_time(): void { + if ( ! $this->clock_mock_frozen ) { + return; + } + + $this->clock_mock_frozen = false; + ClockMock::reset(); + } +} diff --git a/tests/_support/Traits/With_Uopz.php b/tests/_support/Traits/With_Uopz.php index 13967728da..436c78407a 100644 --- a/tests/_support/Traits/With_Uopz.php +++ b/tests/_support/Traits/With_Uopz.php @@ -2,6 +2,7 @@ namespace Tribe\Tests\Traits; +use Closure; use PHPUnit\Framework\Assert; trait With_Uopz { @@ -93,14 +94,19 @@ public function unset_uopz_functions() { * @param boolean $execute If true, and a Closure was provided as the value, * the Closure will be executed in place of the original function. * - * @return void + * @return Closure A Closure that will unset the return value when called. */ - private function set_fn_return( $fn, $value, $execute = false ) { + private function set_fn_return( $fn, $value, $execute = false ): Closure { if ( ! function_exists( 'uopz_set_return' ) ) { $this->markTestSkipped( 'uopz extension is not installed' ); } uopz_set_return( $fn, $value, $execute ); self::$uopz_set_returns[] = $fn; + + return static function () use ( $fn ) { + uopz_unset_return( $fn ); + self::$uopz_set_returns = array_values( array_diff( self::$uopz_set_returns, [ $fn ] ) ); + }; } private function set_const_value( $const, ...$args ) { @@ -146,7 +152,7 @@ private function set_const_value( $const, ...$args ) { Assert::assertEquals( $previous_value, constant( $class . '::' . $const ) ); }; } - uopz_redefine( $const, ...$args ); + uopz_redefine( $class, ...$args ); self::$uopz_redefines[] = $restore_callback; } @@ -204,9 +210,9 @@ public function undefine_uopz_class_fn() { /** * @param string $function - * @param \Closure $handler + * @param Closure $handler */ - private function add_fn( string $function, \Closure $handler ) { + private function add_fn( string $function, Closure $handler ) { if ( ! function_exists( 'uopz_add_function' ) ) { $this->markTestSkipped( 'uopz extension is not installed' ); } diff --git a/tests/eva_integration/Power_Automate/Triggers/AttendeesTest.php b/tests/eva_integration/Power_Automate/Triggers/AttendeesTest.php index 12f76590df..d1c142fbcb 100644 --- a/tests/eva_integration/Power_Automate/Triggers/AttendeesTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/AttendeesTest.php @@ -3,14 +3,14 @@ namespace Tribe\tests\eva_integration\Power_Automate\Triggers; use TEC\Event_Automator\Power_Automate\Triggers\Attendees; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use Tribe\Tests\Traits\With_Uopz; class AttendeesTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/CanceledEventTest.php b/tests/eva_integration/Power_Automate/Triggers/CanceledEventTest.php index cfbd4b89b4..f5dac86c84 100644 --- a/tests/eva_integration/Power_Automate/Triggers/CanceledEventTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/CanceledEventTest.php @@ -8,7 +8,7 @@ class CanceledEventTest extends \Codeception\TestCase\WPTestCase { - use Create_events; + use Create_Events; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/CheckinTest.php b/tests/eva_integration/Power_Automate/Triggers/CheckinTest.php index 94a5501e3c..651b0ecef5 100644 --- a/tests/eva_integration/Power_Automate/Triggers/CheckinTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/CheckinTest.php @@ -12,8 +12,8 @@ class CheckinTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/NewEventTest.php b/tests/eva_integration/Power_Automate/Triggers/NewEventTest.php index 60db47adbd..0b8c974d21 100644 --- a/tests/eva_integration/Power_Automate/Triggers/NewEventTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/NewEventTest.php @@ -8,7 +8,7 @@ class NewEventTest extends \Codeception\TestCase\WPTestCase { - use Create_events; + use Create_Events; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/OrdersTest.php b/tests/eva_integration/Power_Automate/Triggers/OrdersTest.php index 50a0317f3f..1c8c07106d 100644 --- a/tests/eva_integration/Power_Automate/Triggers/OrdersTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/OrdersTest.php @@ -9,8 +9,8 @@ class OrdersTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/RefundedOrdersTest.php b/tests/eva_integration/Power_Automate/Triggers/RefundedOrdersTest.php index bce311a27f..97eb48e304 100644 --- a/tests/eva_integration/Power_Automate/Triggers/RefundedOrdersTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/RefundedOrdersTest.php @@ -9,8 +9,8 @@ class RefundedOrdersTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/UpdatedAttendeesTest.php b/tests/eva_integration/Power_Automate/Triggers/UpdatedAttendeesTest.php index a6da6184d4..c503f4c515 100644 --- a/tests/eva_integration/Power_Automate/Triggers/UpdatedAttendeesTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/UpdatedAttendeesTest.php @@ -9,8 +9,8 @@ class UpdatedAttendeesTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Power_Automate/Triggers/UpdatedEventTest.php b/tests/eva_integration/Power_Automate/Triggers/UpdatedEventTest.php index 137422ef67..be06e9aef0 100644 --- a/tests/eva_integration/Power_Automate/Triggers/UpdatedEventTest.php +++ b/tests/eva_integration/Power_Automate/Triggers/UpdatedEventTest.php @@ -8,7 +8,7 @@ class UpdatedEventTest extends \Codeception\TestCase\WPTestCase { - use Create_events; + use Create_Events; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Traits/Maps/AttendeeTest.php b/tests/eva_integration/Traits/Maps/AttendeeTest.php index c814051976..34b181b27c 100644 --- a/tests/eva_integration/Traits/Maps/AttendeeTest.php +++ b/tests/eva_integration/Traits/Maps/AttendeeTest.php @@ -2,8 +2,8 @@ namespace Tribe\tests\eva_integration\Traits\Maps; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Traits\Maps\Attendees; use Tribe\Tests\Traits\With_Uopz; use Tribe\Test\PHPUnit\Traits\With_Post_Remapping; @@ -13,8 +13,8 @@ class AttendeeTest extends \Codeception\TestCase\WPTestCase { use SnapshotAssertions; use With_Post_Remapping; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; use Attendees; diff --git a/tests/eva_integration/Traits/Maps/Commerce/EDDTest.php b/tests/eva_integration/Traits/Maps/Commerce/EDDTest.php index dc73c94d4f..b3488630a6 100644 --- a/tests/eva_integration/Traits/Maps/Commerce/EDDTest.php +++ b/tests/eva_integration/Traits/Maps/Commerce/EDDTest.php @@ -2,8 +2,8 @@ namespace Tribe\tests\eva_integration\Traits\Maps\Commerce; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Traits\Maps\Commerce\EDD; use Tribe\Tests\Traits\With_Uopz; use Tribe\Test\PHPUnit\Traits\With_Post_Remapping; @@ -13,8 +13,8 @@ class EDDTest extends \Codeception\TestCase\WPTestCase { use SnapshotAssertions; use With_Post_Remapping; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; use EDD; diff --git a/tests/eva_integration/Traits/Maps/Commerce/TicketsCommerceTest.php b/tests/eva_integration/Traits/Maps/Commerce/TicketsCommerceTest.php index e9dcecc5a7..8fed75a873 100644 --- a/tests/eva_integration/Traits/Maps/Commerce/TicketsCommerceTest.php +++ b/tests/eva_integration/Traits/Maps/Commerce/TicketsCommerceTest.php @@ -2,8 +2,8 @@ namespace Tribe\tests\eva_integration\Traits\Maps\Commerce; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Traits\Maps\Commerce\Tickets_Commerce; use Tribe\Tests\Traits\With_Uopz; use Tribe\Test\PHPUnit\Traits\With_Post_Remapping; @@ -13,8 +13,8 @@ class TicketsCommerceTest extends \Codeception\TestCase\WPTestCase { use SnapshotAssertions; use With_Post_Remapping; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; use Tickets_Commerce; diff --git a/tests/eva_integration/Traits/Maps/Commerce/WooCommerceTest.php b/tests/eva_integration/Traits/Maps/Commerce/WooCommerceTest.php index 6617423710..ed53332e3d 100644 --- a/tests/eva_integration/Traits/Maps/Commerce/WooCommerceTest.php +++ b/tests/eva_integration/Traits/Maps/Commerce/WooCommerceTest.php @@ -2,8 +2,8 @@ namespace Tribe\tests\eva_integration\Traits\Maps\Commerce; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Traits\Maps\Commerce\WooCommerce; use Tribe\Tests\Traits\With_Uopz; use Tribe\Test\PHPUnit\Traits\With_Post_Remapping; @@ -13,8 +13,8 @@ class WooCommerceTest extends \Codeception\TestCase\WPTestCase { use SnapshotAssertions; use With_Post_Remapping; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; use WooCommerce; diff --git a/tests/eva_integration/Traits/Maps/EventTest.php b/tests/eva_integration/Traits/Maps/EventTest.php index 754f6a2a73..cea1ddc4e7 100644 --- a/tests/eva_integration/Traits/Maps/EventTest.php +++ b/tests/eva_integration/Traits/Maps/EventTest.php @@ -19,8 +19,8 @@ class EventTest extends \Codeception\TestCase\WPTestCase { use SnapshotAssertions; use With_Post_Remapping; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; use Event; diff --git a/tests/eva_integration/Traits/Maps/TicketsTest.php b/tests/eva_integration/Traits/Maps/TicketsTest.php index 0721156295..c10da57ee7 100644 --- a/tests/eva_integration/Traits/Maps/TicketsTest.php +++ b/tests/eva_integration/Traits/Maps/TicketsTest.php @@ -3,8 +3,8 @@ namespace Tribe\tests\eva_integration\Traits\Maps; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_attendees; -use TEC\Event_Automator\Tests\Traits\Create_events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; use TEC\Event_Automator\Traits\Maps\Ticket; use Tribe\Tests\Traits\With_Uopz; use Tribe\Test\PHPUnit\Traits\With_Post_Remapping; @@ -13,8 +13,8 @@ class TicketsTest extends \Codeception\TestCase\WPTestCase { use SnapshotAssertions; use With_Post_Remapping; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; use Ticket; diff --git a/tests/eva_integration/Zapier/Triggers/AttendeesTest.php b/tests/eva_integration/Zapier/Triggers/AttendeesTest.php index 0ebaa35134..9bd4d71bca 100644 --- a/tests/eva_integration/Zapier/Triggers/AttendeesTest.php +++ b/tests/eva_integration/Zapier/Triggers/AttendeesTest.php @@ -2,15 +2,15 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Zapier\Triggers\Attendees; use Tribe\Tests\Traits\With_Uopz; class AttendeesTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/CanceledEventTest.php b/tests/eva_integration/Zapier/Triggers/CanceledEventTest.php index 805a273679..83361cbbba 100644 --- a/tests/eva_integration/Zapier/Triggers/CanceledEventTest.php +++ b/tests/eva_integration/Zapier/Triggers/CanceledEventTest.php @@ -2,13 +2,13 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; +use TEC\Event_Automator\Tests\Traits\Create_Events; use TEC\Event_Automator\Zapier\Triggers\Canceled_Events; use Tribe\Tests\Traits\With_Uopz; class CanceledEventTest extends \Codeception\TestCase\WPTestCase { - use Create_events; + use Create_Events; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/CheckinTest.php b/tests/eva_integration/Zapier/Triggers/CheckinTest.php index f5a2c46dc0..eacf4b3553 100644 --- a/tests/eva_integration/Zapier/Triggers/CheckinTest.php +++ b/tests/eva_integration/Zapier/Triggers/CheckinTest.php @@ -2,8 +2,8 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Zapier\Triggers\Checkin; use Tribe\Tests\Traits\With_Uopz; use TEC\Tickets\Commerce\Module; @@ -12,8 +12,8 @@ class CheckinTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/NewEventTest.php b/tests/eva_integration/Zapier/Triggers/NewEventTest.php index 7a25c4ffa2..8175682187 100644 --- a/tests/eva_integration/Zapier/Triggers/NewEventTest.php +++ b/tests/eva_integration/Zapier/Triggers/NewEventTest.php @@ -2,13 +2,13 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; +use TEC\Event_Automator\Tests\Traits\Create_Events; use TEC\Event_Automator\Zapier\Triggers\New_Events; use Tribe\Tests\Traits\With_Uopz; class NewEventTest extends \Codeception\TestCase\WPTestCase { - use Create_events; + use Create_Events; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/OrdersTest.php b/tests/eva_integration/Zapier/Triggers/OrdersTest.php index a9ed552209..f47733a406 100644 --- a/tests/eva_integration/Zapier/Triggers/OrdersTest.php +++ b/tests/eva_integration/Zapier/Triggers/OrdersTest.php @@ -2,15 +2,15 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Zapier\Triggers\Orders; use Tribe\Tests\Traits\With_Uopz; class OrdersTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/RefundedOrdersTest.php b/tests/eva_integration/Zapier/Triggers/RefundedOrdersTest.php index 3f284c03fc..a3279bc6c0 100644 --- a/tests/eva_integration/Zapier/Triggers/RefundedOrdersTest.php +++ b/tests/eva_integration/Zapier/Triggers/RefundedOrdersTest.php @@ -2,15 +2,15 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Zapier\Triggers\Refunded_Orders; use Tribe\Tests\Traits\With_Uopz; class RefundedOrdersTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/UpdatedAttendeesTest.php b/tests/eva_integration/Zapier/Triggers/UpdatedAttendeesTest.php index 18b9b45954..901df6381a 100644 --- a/tests/eva_integration/Zapier/Triggers/UpdatedAttendeesTest.php +++ b/tests/eva_integration/Zapier/Triggers/UpdatedAttendeesTest.php @@ -2,15 +2,15 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; use TEC\Event_Automator\Zapier\Triggers\Updated_Attendees; use Tribe\Tests\Traits\With_Uopz; class UpdatedAttendeesTest extends \Codeception\TestCase\WPTestCase { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; use With_Uopz; public function setUp() { diff --git a/tests/eva_integration/Zapier/Triggers/UpdatedEventTest.php b/tests/eva_integration/Zapier/Triggers/UpdatedEventTest.php index 87e7850d2b..36c197e507 100644 --- a/tests/eva_integration/Zapier/Triggers/UpdatedEventTest.php +++ b/tests/eva_integration/Zapier/Triggers/UpdatedEventTest.php @@ -2,13 +2,13 @@ namespace Tribe\tests\eva_integration\Zapier\Triggers; -use TEC\Event_Automator\Tests\Traits\Create_events; +use TEC\Event_Automator\Tests\Traits\Create_Events; use TEC\Event_Automator\Zapier\Triggers\Updated_Events; use Tribe\Tests\Traits\With_Uopz; class UpdatedEventTest extends \Codeception\TestCase\WPTestCase { - use Create_events; + use Create_Events; use With_Uopz; public function setUp() { diff --git a/tests/integration/Tribe/PUE/Checker_Test.php b/tests/integration/Tribe/PUE/Checker_Test.php index e8aab9789a..9e4aaffe06 100644 --- a/tests/integration/Tribe/PUE/Checker_Test.php +++ b/tests/integration/Tribe/PUE/Checker_Test.php @@ -4,6 +4,9 @@ use TEC\Common\Tests\Licensing\PUE_Service_Mock; use Tribe__PUE__Checker as PUE_Checker; +use Tribe__Main; +use TEC\Common\StellarWP\Uplink\Register; +use function TEC\Common\StellarWP\Uplink\get_resource; class Checker_Test extends \Codeception\TestCase\WPTestCase { /** @@ -104,6 +107,28 @@ public function should_update_license_key_if_replacement_key_provided_and_key_pr $this->assertEquals( $replacement_key, $pue_instance->get_key() ); } + /** + * @test + */ + public function it_should_check_uplink_before_pue() { + Register::plugin( + 'test-plugin', + 'Test Plugin', + '1.0.0', + __DIR__, + tribe( Tribe__Main::class ) + ); + + $key = 'license-key-for-test-plugin'; + + $resource = get_resource( 'test-plugin' ); + $resource->set_license_key( $key, 'any' ); + + $pue_instance = new PUE_Checker( 'deprecated', 'test-plugin', [], 'test-plugin/test-plugin.php' ); + + $this->assertEquals( $key, $pue_instance->get_key() ); + } + public function test_replacemnt_key_update_in_multisite_context(): void { } diff --git a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/AttendeesCest.php b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/AttendeesCest.php index 6509102f3e..1524caddaf 100644 --- a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/AttendeesCest.php +++ b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/AttendeesCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETPowerAutomateCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class AttendeesCest extends BaseRestETPowerAutomateCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/CheckinCest.php b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/CheckinCest.php index 75ddebfb96..66cd74b21d 100644 --- a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/CheckinCest.php +++ b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/CheckinCest.php @@ -11,8 +11,8 @@ class CheckinCest extends BaseRestETPowerAutomateCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @test diff --git a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/OrdersCest.php b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/OrdersCest.php index 20d8e35f74..0a759ad2bc 100644 --- a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/OrdersCest.php +++ b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/OrdersCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETPowerAutomateCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class OrdersCest extends BaseRestETPowerAutomateCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @test diff --git a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/RefundedOrdersCest.php b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/RefundedOrdersCest.php index 158bc7e8b9..313663883d 100644 --- a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/RefundedOrdersCest.php +++ b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/RefundedOrdersCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETPowerAutomateCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class RefundedOrdersCest extends BaseRestETPowerAutomateCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/UpdatedAttendeeCest.php b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/UpdatedAttendeeCest.php index 173851143d..fb0d152738 100644 --- a/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/UpdatedAttendeeCest.php +++ b/tests/restv1_et/Event_Automator/Power_Automate/REST/V1/Endpoints/Queue/UpdatedAttendeeCest.php @@ -11,8 +11,8 @@ class UpdatedAttendeeCest extends BaseRestETPowerAutomateCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @test diff --git a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/Actions/FindTicketsCest.php b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/Actions/FindTicketsCest.php index 3bebb40eda..317739ae28 100644 --- a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/Actions/FindTicketsCest.php +++ b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/Actions/FindTicketsCest.php @@ -17,8 +17,8 @@ class FindTicketsCest extends BaseRestETCest { - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /* * Attendee meta values. diff --git a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/AttendeeCest.php b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/AttendeeCest.php index 1f70b5fe5a..3be124b4e2 100644 --- a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/AttendeeCest.php +++ b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/AttendeeCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class AttendeeCest extends BaseRestETCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/CheckinCest.php b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/CheckinCest.php index 6bee760d16..5259491b1c 100644 --- a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/CheckinCest.php +++ b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/CheckinCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class CheckinCest extends BaseRestETCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/OrdersCest.php b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/OrdersCest.php index 4ac1b2b572..b45309f0c0 100644 --- a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/OrdersCest.php +++ b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/OrdersCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class OrdersCest extends BaseRestETCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/RefundedOrdersCest.php b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/RefundedOrdersCest.php index 8b847a082e..b2693f3b1d 100644 --- a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/RefundedOrdersCest.php +++ b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/RefundedOrdersCest.php @@ -5,14 +5,14 @@ use TEC\Event_Automator\Tests\Testcases\REST\V1\BaseRestETCest; use Restv1_etTester; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; -use TEC\Event_Automator\Tests\Traits\Create_events; -use TEC\Event_Automator\Tests\Traits\Create_attendees; +use TEC\Event_Automator\Tests\Traits\Create_Events; +use TEC\Event_Automator\Tests\Traits\Create_Attendees; class RefundedOrdersCest extends BaseRestETCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/UpdatedAttendeeCest.php b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/UpdatedAttendeeCest.php index b1127c2783..51c38db71a 100644 --- a/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/UpdatedAttendeeCest.php +++ b/tests/restv1_et/Event_Automator/Zapier/REST/V1/Endpoints/UpdatedAttendeeCest.php @@ -11,8 +11,8 @@ class UpdatedAttendeeCest extends BaseRestETCest { use SnapshotAssertions; - use Create_events; - use Create_attendees; + use Create_Events; + use Create_Attendees; /** * @inheritdoc diff --git a/tests/snapshots/Views/Admin_Views/Stellar_SnapshotTest.php b/tests/snapshots/Views/Admin_Views/Stellar_SnapshotTest.php deleted file mode 100644 index 19b1e4409a..0000000000 --- a/tests/snapshots/Views/Admin_Views/Stellar_SnapshotTest.php +++ /dev/null @@ -1,66 +0,0 @@ -set_class_fn_return( Dates::class, 'build_date_object', static function ( $input ) use ( $year ) { - return $input === 'now' ? - new \DateTime( "2022-07-30 19:23:23" ) - : new \DateTime( $input ); - }, true ); - - // Mock a premium plugin installed. - $this->set_class_fn_return( Tribe__Dependency::class, 'has_active_premium_plugin', true ); - - $notice = tribe( Stellar_Sale::class ); - - $this->assertMatchesHtmlSnapshot( $notice->display_notice() ); - } - - - /** - * @test - */ - public function should_render_free() { - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - // Mock the `now` date to be this year on November 21st. - $year = date( 'Y' ); - $this->set_class_fn_return( Dates::class, 'build_date_object', static function ( $input ) use ( $year ) { - return $input === 'now' ? - new \DateTime( "2022-07-30 19:23:23" ) - : new \DateTime( $input ); - }, true ); - - // Mock a premium plugin installed. - $this->set_class_fn_return( Tribe__Dependency::class, 'has_active_premium_plugin', false ); - - $notice = tribe( Stellar_Sale::class ); - - $this->assertMatchesHtmlSnapshot( $notice->display_notice() ); - } -} diff --git a/tests/snapshots/__snapshots__/BaseSnapshotTest__should_correctly_test_a_string_snapshot__0.snapshot.txt b/tests/snapshots/__snapshots__/BaseSnapshotTest__should_correctly_test_a_string_snapshot__0.snapshot.txt deleted file mode 100644 index 1f8f6fdafa..0000000000 --- a/tests/snapshots/__snapshots__/BaseSnapshotTest__should_correctly_test_a_string_snapshot__0.snapshot.txt +++ /dev/null @@ -1 +0,0 @@ -test the date function can be mocked: 2019-12-31 00:00:00 \ No newline at end of file diff --git a/tests/wpunit/Common/Libraries/Uplink_Controller_Test.php b/tests/wpunit/Common/Libraries/Uplink_Controller_Test.php new file mode 100644 index 0000000000..ee036b1125 --- /dev/null +++ b/tests/wpunit/Common/Libraries/Uplink_Controller_Test.php @@ -0,0 +1,120 @@ +controller = tribe( Uplink_Controller::class ); + $this->controller->register_uplink(); + $this->register_plugin(); + } + + public function register_plugin() { + // Register the test plugin + Register::plugin( + 'common-test-slug', + 'common-test', + '1.0.0', + __DIR__, + tribe( Tribe__Main::class ) + ); + } + + /** + * @test + */ + public function it_should_setup_license_fields() { + // Retrieve the collection and the specific resource + $collection = Config::get_container()->get( Collection::class ); + $slug = 'common-test-slug'; + $resource = $collection->get( $slug ); + + // Update the license key to a known value + $option_name = $resource->get_license_object()->get_key_option_name(); + $license_key = 'license_key' . $slug; + update_option( $option_name, $license_key ); + + // Assert the license key was updated correctly + $option_value = get_option( $option_name ); + $this->assertEquals( $option_value, $license_key ); + + // Mock the wp_create_nonce function + $this->set_fn_return( 'wp_create_nonce', '123456789', false ); + + // Initialize fields array + $fields = [ + 'tribe-form-content-start' => [], + ]; + + // Register license fields and assert the HTML snapshot + $license_fields = $this->controller->register_license_fields( $fields ); + + $html = $license_fields['stellarwp-uplink_common-test-slug']['html']; + $html = str_replace( dirname( __DIR__, 5 ), '{__DIR__}', $html ); + + $this->assertMatchesHtmlSnapshot( $html ); + } + + /** + * @test + */ + public function it_should_add_actions_on_do_register_and_unregister() { + $this->controller->do_register(); + + // Assert actions were added + $this->assertNotFalse( has_action( 'init', [ $this->controller, 'register_uplink' ] ) ); + $this->assertNotFalse( has_filter( 'tribe_license_fields', [ $this->controller, 'register_license_fields' ] ) ); + + $this->controller->unregister(); // Then remove them + + // Assert actions were removed + $this->assertFalse( has_action( 'init', [ $this->controller, 'register_uplink' ] ) ); + $this->assertFalse( has_filter( 'tribe_license_fields', [ $this->controller, 'register_license_fields' ] ) ); + } + + /** + * @test + */ + public function it_should_handle_unregister_before_register() { + $this->controller->unregister(); // Call unregister before register + + // Assert actions were not added + $this->assertFalse( has_action( 'init', [ $this->controller, 'register_uplink' ] ) ); + $this->assertFalse( has_filter( 'tribe_license_fields', [ $this->controller, 'register_license_fields' ] ) ); + } + + /** + * @test + */ + public function it_should_modify_fields_with_filter() { + $fields = [ + 'tribe-form-content-start' => [], + ]; + + // Apply the filter + $modified_fields = apply_filters( 'tribe_license_fields', $fields ); + + // Assert that the filter modified the fields array + $this->assertNotEmpty( $modified_fields ); + $this->assertArrayHasKey( 'stellarwp-uplink_common-test-slug-heading', $modified_fields ); + $this->assertArrayHasKey( 'stellarwp-uplink_common-test-slug', $modified_fields ); + } +} diff --git a/tests/wpunit/Common/Libraries/__snapshots__/Controller_Test__it_should_setup_license_fields__0.snapshot.html b/tests/wpunit/Common/Libraries/__snapshots__/Controller_Test__it_should_setup_license_fields__0.snapshot.html new file mode 100644 index 0000000000..c19d8092de --- /dev/null +++ b/tests/wpunit/Common/Libraries/__snapshots__/Controller_Test__it_should_setup_license_fields__0.snapshot.html @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/tests/wpunit/Tribe/Notices/Black_FridayTest.php b/tests/wpunit/Tribe/Notices/Black_FridayTest.php deleted file mode 100644 index 09fd97bb6b..0000000000 --- a/tests/wpunit/Tribe/Notices/Black_FridayTest.php +++ /dev/null @@ -1,168 +0,0 @@ -set_const_value( 'TRIBE_HIDE_UPSELL', true ); - // Ensure we're on a good date. - add_filter( - 'tribe_black-friday_notice_start_date', - function ( $date ) { - // Set the start date to the past. - return Dates::build_date_object( '-7 days', 'UTC' ); - } - ); - - add_filter( - 'tribe_black-friday_notice_end_date', - function ( $date ) { - // Set the end date to the future. - return Dates::build_date_object( '+7 days', 'UTC' ); - } - ); - - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Black_Friday::class ); - - $this->assertFalse( $notice->should_display() ); - } - - /** - * Test ! should_display() when on wrong screen. - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_not_display_when_wrong_screen() { - // Ensure we're on a good date. - add_filter( - 'tribe_black-friday_notice_start_date', - function ( $date ) { - // Set the start date to the past. - return Dates::build_date_object( '-7 days', 'UTC' ); - } - ); - - add_filter( - 'tribe_black-friday_notice_end_date', - function ( $date ) { - // Set the end date to the future. - return Dates::build_date_object( '+7 days', 'UTC' ); - } - ); - - // Ensure we're on the WRONG screen. - set_current_screen( 'edit-post' ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Black_Friday::class ); - - $this->assertFalse( $notice->should_display() ); - } - - /** - * Test ! should_display() when date passed. - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_not_display_when_past() { - add_filter( - 'tribe_black-friday_notice_start_date', - function ( $date ) { - // Set the start date to the past. - return Dates::build_date_object( '-7 days', 'UTC' ); - }, 200 - ); - - add_filter( - 'tribe_black-friday_notice_end_date', - function ( $date ) { - // Set the end date to the past. - return Dates::build_date_object( '-5 days', 'UTC' ); - }, 200 - ); - - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Black_Friday::class ); - - $this->assertFalse( $notice->should_display() ); - } - - /** - * Test ! should_display() when date in future. - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_not_display_when_in_future() { - add_filter( - 'tribe_black-friday_notice_start_date', - function ( $date ) { - // Set the start date to the future. - return Dates::build_date_object( '+5 days', 'UTC' ); - }, 200 - ); - - add_filter( - 'tribe_black-friday_notice_end_date', - function ( $date ) { - // Set the end date to the future. - return Dates::build_date_object( '+7 days', 'UTC' ); - }, 200 - ); - - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Black_Friday::class ); - - $this->assertFalse( $notice->should_display() ); - } - - /** - * Test should_display() when the stars align (all conditions true). - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_display_when_stars_align() { - add_filter( - 'tribe_black-friday_notice_start_date', - function ( $date ) { - // Set the start date to the past. - return Dates::build_date_object( '-7 days', 'UTC' ); - }, 200 - ); - - add_filter( - 'tribe_black-friday_notice_end_date', - function ( $date ) { - // Set the end date to the future. - return Dates::build_date_object( '+7 days', 'UTC' ); - }, 200 - ); - - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Black_Friday::class ); - - codecept_debug( $notice ); - - $this->assertTrue( $notice->should_display() ); - } -} diff --git a/tests/wpunit/Tribe/Notices/Stellar_SaleTest.php b/tests/wpunit/Tribe/Notices/Stellar_SaleTest.php deleted file mode 100644 index 3529300702..0000000000 --- a/tests/wpunit/Tribe/Notices/Stellar_SaleTest.php +++ /dev/null @@ -1,152 +0,0 @@ -assertFalse( $notice->should_display() ); - - // So we don't muck up later tests. - remove_all_filters( 'tribe_stellar-sale-2024_notice_start_date' ); - uopz_undefine( 'TRIBE_HIDE_UPSELL' ); - } - - /** - * Test ! should_display() when on wrong screen. - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_not_display_when_wrong_screen() { - // Ensure we're on a good date. - add_filter( - 'tribe_stellar-sale-2024_notice_start_date', - function( $date ) { - // Set the start date to the past. - return Dates::build_date_object( '-7 days', 'UTC' ); - } - ); - - add_filter( - 'tribe_stellar-sale-2024_notice_end_date', - function( $date ) { - // Set the end date to the future. - return Dates::build_date_object( '+7 days', 'UTC' ); - } - ); - - // Ensure we're on the WRONG screen. - set_current_screen( 'edit-post' ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Stellar_Sale::class ); - - $this->assertFalse( $notice->should_display() ); - - // So we don't muck up later tests. - remove_all_filters( 'tribe_stellar-sale-2024_notice_start_date' ); - } - - /** - * Test ! should_display() when date passed. - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_not_display_when_past() { - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - // Mock the `now` date to be this year, in the past of the notice display date. - $year = date( 'Y' ); - $this->set_class_fn_return( Dates::class, 'build_date_object', static function ( $input ) use ( $year ) { - return $input === 'now' ? - new DateTime( "$year-02-23 09:23:23" ) - : new DateTime( $input ); - }, true ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Stellar_Sale::class ); - - $this->assertFalse( $notice->should_display() ); - } - - /** - * Test ! should_display() when date in future. - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_not_display_when_in_future() { - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - // Mock the `now` date to be this year, in the future of the notice display date. - $year = date( 'Y' ); - $this->set_class_fn_return( Dates::class, 'build_date_object', static function ( $input ) use ( $year ) { - return $input === 'now' ? - new DateTime( "$year-12-10 09:23:23" ) - : new DateTime( $input ); - }, true ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Stellar_Sale::class ); - - $this->assertFalse( $notice->should_display() ); - } - - /** - * Test should_display() when the stars align (all conditions true). - * Note this test assumes we have not set the constant in our testing environment. - * - * @test - */ - public function should_display_when_stars_align() { - // Ensure we're on a good screen. - set_current_screen( 'tribe_events_page_tribe-common' ); - - // Mock the `now` date to be this year on November 21st. - $year = date( 'Y' ); - $this->set_class_fn_return( Dates::class, 'build_date_object', static function ( $input ) use ( $year ) { - return $input === 'now' ? - new DateTime( '2024-07-26 19:23:23' ) - : new DateTime( $input ); - }, true ); - - $notice = tribe( Tribe\Admin\Notice\Marketing\Stellar_Sale::class ); - - $this->assertTrue( $notice->should_display() ); - } -} diff --git a/tribe-common.php b/tribe-common.php index 4788532bb9..d15259789e 100644 --- a/tribe-common.php +++ b/tribe-common.php @@ -2,7 +2,7 @@ /** * Plugin Name: Tribe Common * Description: An event settings framework for managing shared options. - * Version: 6.1.0 + * Version: 6.3.0 * Requires at least: 6.3 * Requires PHP: 7.4 * Author: The Events Calendar