diff --git a/.github/actions/prepare-source/action.yml b/.github/actions/prepare-source/action.yml index 03aa0e4337..57e281cbfc 100644 --- a/.github/actions/prepare-source/action.yml +++ b/.github/actions/prepare-source/action.yml @@ -4,7 +4,7 @@ runs: using: composite steps: - name: Check out mu-plugins-ext - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 with: repository: 'Automattic/vip-go-mu-plugins-ext' path: 'vip-go-mu-plugins-ext' diff --git a/.github/actions/run-wp-tests/action.yml b/.github/actions/run-wp-tests/action.yml index 5e7c270d10..a2acc5ea01 100644 --- a/.github/actions/run-wp-tests/action.yml +++ b/.github/actions/run-wp-tests/action.yml @@ -80,7 +80,7 @@ runs: uses: ramsey/composer-install@3.0.0 - name: Set up WordPress and WordPress Test Library - uses: sjinks/setup-wordpress-test-library@v2.1.1 + uses: sjinks/setup-wordpress-test-library@v2.1.2 with: version: ${{ inputs.wordpress }} @@ -122,7 +122,7 @@ runs: "${PHPUNIT}" ${OPTIONS} - name: Upload coverage report - uses: codecov/codecov-action@v4.6.0 + uses: codecov/codecov-action@v5.0.2 with: files: ${{ inputs.coverage-file }} flags: ${{ inputs.coverage-flags }} diff --git a/.github/workflows/changelog-summary-prod.yml b/.github/workflows/changelog-summary-prod.yml index 7025c84fa3..702dd978f9 100644 --- a/.github/workflows/changelog-summary-prod.yml +++ b/.github/workflows/changelog-summary-prod.yml @@ -50,7 +50,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: softprops/action-gh-release@v2.0.9 + - uses: softprops/action-gh-release@v2.1.0 with: generate_release_notes: true tag_name: ${{ steps.id-generator.outputs.id }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 340c2cb41f..18d31d75af 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,10 +32,10 @@ jobs: uses: actions/checkout@v4.2.2 - name: Initialize CodeQL - uses: github/codeql-action/init@v3.27.0 + uses: github/codeql-action/init@v3.27.4 with: languages: ${{ matrix.language }} config-file: ./.github/codeql-config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3.27.0 + uses: github/codeql-action/analyze@v3.27.4 diff --git a/.github/workflows/core-tests.yml b/.github/workflows/core-tests.yml index ab441d1dc5..ce8d987077 100644 --- a/.github/workflows/core-tests.yml +++ b/.github/workflows/core-tests.yml @@ -20,10 +20,13 @@ permissions: contents: read env: - LOCAL_PHP: "8.0-fpm" + LOCAL_PHP: "8.2-fpm" + LOCAL_PHP_XDEBUG: "false" + LOCAL_PHP_XDEBUG_MODE: "develop,debug" LOCAL_DB_TYPE: "mysql" - LOCAL_DB_VERSION: "8.0" + LOCAL_DB_VERSION: "8.3" LOCAL_PHP_MEMCACHED: "true" + LOCAL_WP_TESTS_DOMAIN: "example.org" PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" jobs: @@ -57,6 +60,7 @@ jobs: - name: Tweaks run: | echo "define( 'VIP_JETPACK_SKIP_LOAD', 'true' );" >> "wordpress/src/wp-content/mu-plugins/000-vip-init.php" + cp wordpress/.env.example wordpress/.env echo "GITHUB_EVENT_NAME=pull_request" >> "wordpress/.env" - name: Set up Node.js @@ -72,17 +76,10 @@ jobs: php-version: 8.0 coverage: none - # - name: Install Composer dependencies - # uses: ramsey/composer-install@83af392bf5f031813d25e6fe4cd626cdba9a2df6 # v2.2.0 - # with: - # working-directory: wordpress - name: Install Composer dependencies - run: composer install -n - working-directory: wordpress - - # - name: Downgrade PHPUnit - # run: composer require --dev -n phpunit/phpunit:^9 - # working-directory: wordpress + uses: ramsey/composer-install@3.0.0 + with: + working-directory: wordpress - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 3f4d6d545c..09fcc41244 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -25,4 +25,4 @@ jobs: uses: actions/checkout@v4.2.2 - name: Review dependencies - uses: actions/dependency-review-action@v4.3.4 + uses: actions/dependency-review-action@v4.4.0 diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 3fc35179b2..fa771d496c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -60,6 +60,7 @@ jobs: playwright.azureedge.net:443 production.cloudflare.docker.com:443 public-api.wordpress.com:443 + raw.githubusercontent.com:443 registry-1.docker.io:443 registry.npmjs.org:443 s.w.org:443 diff --git a/000-vip-init.php b/000-vip-init.php index e47492d3fa..dce6df9fa4 100644 --- a/000-vip-init.php +++ b/000-vip-init.php @@ -244,6 +244,7 @@ __DIR__ . '/telemetry/tracks/class-tracks-event-dto.php', __DIR__ . '/telemetry/tracks/class-tracks-event.php', __DIR__ . '/telemetry/tracks/class-tracks-client.php', + __DIR__ . '/telemetry/tracks/tracks-utils.php', ]; // If there is a missing file, the loop will break and the telemetry files will not be loaded at all diff --git a/__tests__/e2e/bin/setup-env.sh b/__tests__/e2e/bin/setup-env.sh index 0d363af1a2..96e832d078 100755 --- a/__tests__/e2e/bin/setup-env.sh +++ b/__tests__/e2e/bin/setup-env.sh @@ -22,14 +22,26 @@ if [ -z "${version}" ]; then version=${WORDPRESS_VERSION:-latest} fi +if [ "${version}" = "latest" ]; then + WPVER="$(wget https://github.com/Automattic/vip-container-images/raw/refs/heads/master/wordpress/versions.json -O - | jq -r '[.[] | select(.prerelease == false)] | max_by(.tag) | .tag')" +else + WPVER="$(wget https://github.com/Automattic/vip-container-images/raw/refs/heads/master/wordpress/versions.json -O - | jq -r --arg ref_value "${version}" '.[] | select(.ref == $ref_value) | .tag')" +fi + +if [ -z "${WPVER}" ]; then + WPVER=trunk +fi + # Destroy existing test site vip dev-env destroy --slug=e2e-test-site || true # Create and run test site -vip --slug=e2e-test-site dev-env create --title="E2E Testing site" --mu-plugins="${pluginPath}" --mailpit false --wordpress=trunk --multisite=false --app-code="${clientCodePath}" --php 8.2 --xdebug false --phpmyadmin false --elasticsearch true < /dev/null +vip --slug=e2e-test-site dev-env create --title="E2E Testing site" --mu-plugins="${pluginPath}" --mailpit false --wordpress="${WPVER}" --multisite=false --app-code="${clientCodePath}" --php 8.2 --xdebug false --phpmyadmin false --elasticsearch true < /dev/null vip dev-env start --slug e2e-test-site --skip-wp-versions-check -vip dev-env shell --root --slug e2e-test-site -- chown -R www-data:www-data /wp +vip dev-env shell --root --slug e2e-test-site -- chown -R www-data:www-data /wp/wp-content/plugins vip dev-env exec --slug e2e-test-site --quiet -- wp plugin install --activate classic-editor -vip dev-env exec --slug e2e-test-site --quiet -- wp core update --force --version="${version}" -vip dev-env exec --slug e2e-test-site --quiet -- wp core update-db +if [ "${WPVER}" = 'trunk' ]; then + vip dev-env exec --slug e2e-test-site --quiet -- wp core update --force --version="${version}" + vip dev-env exec --slug e2e-test-site --quiet -- wp core update-db +fi vip dev-env exec --slug e2e-test-site --quiet -- wp rewrite structure '/%postname%/' diff --git a/__tests__/e2e/package-lock.json b/__tests__/e2e/package-lock.json index bbe27a5fd5..5b15325c45 100644 --- a/__tests__/e2e/package-lock.json +++ b/__tests__/e2e/package-lock.json @@ -15,7 +15,7 @@ "asana-phrase": "^0.0.8", "eslint": "^8.51.0", "eslint-plugin-deprecation": "^3.0.0", - "eslint-plugin-playwright": "^1.0.1", + "eslint-plugin-playwright": "^2.0.1", "typescript": "^5.2.2" } }, @@ -213,9 +213,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", - "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true, "engines": { "node": ">=6.9.0" @@ -319,12 +319,12 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.7.tgz", - "integrity": "sha512-oXduHo642ZhstLVYTe2z2GSJIruU0c/W3/Ghr6A5yGMsVrvdnxO1z+3pbTcT7f3/Clnt+1z8D/w1r1f1SHaCHw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", + "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -685,12 +685,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", - "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", "dev": true, "dependencies": { - "playwright": "1.48.1" + "playwright": "1.48.2" }, "bin": { "playwright": "cli.js" @@ -714,12 +714,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", - "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -2200,9 +2200,9 @@ } }, "node_modules/eslint-plugin-playwright": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-1.8.1.tgz", - "integrity": "sha512-wzT8rUFOXN6ztRVHSAZI0QpQnxY7bbvcu2z+C/giy3zrkL8WlsFQCv7NillgLBhWnr7oZjC5Pax/GMAJmZlWHA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.0.1.tgz", + "integrity": "sha512-f4a73xgCOK5Ug/5dtC82BVvND62lLqlMqgGkZn42teyvk6ccSyybHZXRHkpE7vKZSCjV57bnbR+3ucwItOhXlA==", "dev": true, "dependencies": { "globals": "^13.23.0" @@ -2211,13 +2211,7 @@ "node": ">=16.6.0" }, "peerDependencies": { - "eslint": ">=8.40.0", - "eslint-plugin-jest": ">=25" - }, - "peerDependenciesMeta": { - "eslint-plugin-jest": { - "optional": true - } + "eslint": ">=8.40.0" } }, "node_modules/eslint-plugin-prettier": { @@ -4199,12 +4193,12 @@ } }, "node_modules/playwright": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", - "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", "dev": true, "dependencies": { - "playwright-core": "1.48.1" + "playwright-core": "1.48.2" }, "bin": { "playwright": "cli.js" @@ -4217,9 +4211,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", - "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", "dev": true, "bin": { "playwright-core": "cli.js" diff --git a/__tests__/e2e/package.json b/__tests__/e2e/package.json index 053fecd01e..e7d2304f1c 100644 --- a/__tests__/e2e/package.json +++ b/__tests__/e2e/package.json @@ -18,7 +18,7 @@ "asana-phrase": "^0.0.8", "eslint": "^8.51.0", "eslint-plugin-deprecation": "^3.0.0", - "eslint-plugin-playwright": "^1.0.1", + "eslint-plugin-playwright": "^2.0.1", "typescript": "^5.2.2" } } diff --git a/composer.json b/composer.json index 0522fa5515..eb5bfc3e68 100644 --- a/composer.json +++ b/composer.json @@ -6,8 +6,8 @@ "erusev/parsedown": "1.7.4", "dms/phpunit-arraysubset-asserts": "0.5.0", "yoast/phpunit-polyfills": "3.0.0", - "johnpbloch/wordpress-core": "6.6.2", - "wp-phpunit/wp-phpunit": "6.6.2", + "johnpbloch/wordpress-core": "6.7.0", + "wp-phpunit/wp-phpunit": "6.7.0", "wp-cli/wp-cli": "2.11.0" }, "config": { diff --git a/composer.lock b/composer.lock index 301a40ad91..927e957f49 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": "119b018f33e17ffb6fc4259fa2203394", + "content-hash": "30e2e5b09ea0da76cc3f82731deba148", "packages": [], "packages-dev": [ { @@ -305,16 +305,16 @@ }, { "name": "johnpbloch/wordpress-core", - "version": "6.6.2", + "version": "6.7.0", "source": { "type": "git", "url": "https://github.com/johnpbloch/wordpress-core.git", - "reference": "dbb5f96e78905e26cbfb4c4796d9d5b92c451a81" + "reference": "3b6bdf11cf72ecb3777914259604dda961798ce2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/dbb5f96e78905e26cbfb4c4796d9d5b92c451a81", - "reference": "dbb5f96e78905e26cbfb4c4796d9d5b92c451a81", + "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/3b6bdf11cf72ecb3777914259604dda961798ce2", + "reference": "3b6bdf11cf72ecb3777914259604dda961798ce2", "shasum": "" }, "require": { @@ -322,7 +322,7 @@ "php": ">=7.2.24" }, "provide": { - "wordpress/core-implementation": "6.6.2" + "wordpress/core-implementation": "6.7.0" }, "type": "wordpress-core", "notification-url": "https://packagist.org/downloads/", @@ -349,7 +349,7 @@ "source": "https://core.trac.wordpress.org/browser", "wiki": "https://codex.wordpress.org/" }, - "time": "2024-09-10T15:26:41+00:00" + "time": "2024-11-14T16:46:24+00:00" }, { "name": "mustache/mustache", @@ -3042,16 +3042,16 @@ }, { "name": "wp-phpunit/wp-phpunit", - "version": "6.6.2", + "version": "6.7.0", "source": { "type": "git", "url": "https://github.com/wp-phpunit/wp-phpunit.git", - "reference": "7a1d3a2150033a3d3e19de40aa5b2ef2fee36bc3" + "reference": "2ed55b450c10f6850c44531bed7d86aceba2f842" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/7a1d3a2150033a3d3e19de40aa5b2ef2fee36bc3", - "reference": "7a1d3a2150033a3d3e19de40aa5b2ef2fee36bc3", + "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/2ed55b450c10f6850c44531bed7d86aceba2f842", + "reference": "2ed55b450c10f6850c44531bed7d86aceba2f842", "shasum": "" }, "type": "library", @@ -3086,7 +3086,7 @@ "issues": "https://github.com/wp-phpunit/issues", "source": "https://github.com/wp-phpunit/wp-phpunit" }, - "time": "2024-07-17T01:13:44+00:00" + "time": "2024-11-13T01:22:47+00:00" }, { "name": "yoast/phpunit-polyfills", diff --git a/package-lock.json b/package-lock.json index 05ca835122..df1a081d7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23386,9 +23386,9 @@ } }, "node_modules/react-select": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.1.tgz", - "integrity": "sha512-RT1CJmuc+ejqm5MPgzyZujqDskdvB9a9ZqrdnVLsvAHjJ3Tj0hELnLeVPQlmYdVKCdCpxanepl6z7R5KhXhWzg==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.3.tgz", + "integrity": "sha512-lVswnIq8/iTj1db7XCG74M/3fbGB6ZaluCzvwPGT5ZOjCdL/k0CLWhEK0vCBLuU5bHTEf6Gj8jtSvi+3v+tO1w==", "dependencies": { "@babel/runtime": "^7.12.0", "@emotion/cache": "^11.4.0", diff --git a/search/search-dev-tools/package-lock.json b/search/search-dev-tools/package-lock.json index 6ab96337dc..fe04ca5c0b 100644 --- a/search/search-dev-tools/package-lock.json +++ b/search/search-dev-tools/package-lock.json @@ -4183,11 +4183,10 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6108,9 +6107,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -6118,7 +6117,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", diff --git a/telemetry/tracks/class-tracks-event-dto.php b/telemetry/tracks/class-tracks-event-dto.php index 4520abe7b1..e5dad8253f 100644 --- a/telemetry/tracks/class-tracks-event-dto.php +++ b/telemetry/tracks/class-tracks-event-dto.php @@ -10,10 +10,6 @@ namespace Automattic\VIP\Telemetry\Tracks; use AllowDynamicProperties; -use stdClass; -use WP_Error; -use Automattic\VIP\Support_User\User as Support_User; -use function Automattic\VIP\Logstash\log2logstash; /** * Class that holds necessary properties of Tracks events. diff --git a/telemetry/tracks/class-tracks-event.php b/telemetry/tracks/class-tracks-event.php index 8d49c93740..160d0a1281 100644 --- a/telemetry/tracks/class-tracks-event.php +++ b/telemetry/tracks/class-tracks-event.php @@ -11,7 +11,6 @@ use Automattic\VIP\Telemetry\Telemetry_Event; use WP_Error; -use Automattic\VIP\Support_User\User as Support_User; use function Automattic\VIP\Logstash\log2logstash; /** @@ -153,24 +152,19 @@ protected function process_properties( unset( $event->_via_ip ); } - // Set VIP environment if it exists. - if ( defined( 'VIP_GO_APP_ENVIRONMENT' ) ) { - $app_environment = constant( 'VIP_GO_APP_ENVIRONMENT' ); - if ( is_string( $app_environment ) && '' !== $app_environment ) { - $event->vipgo_env = $app_environment; - } + $base_props = get_base_properties_of_track_event(); + + if ( isset( $base_props['vipgo_env'] ) ) { + $event->vipgo_env = $base_props['vipgo_env']; } - // Set VIP organization if it exists. - if ( defined( 'VIP_ORG_ID' ) ) { - $org_id = constant( 'VIP_ORG_ID' ); - if ( is_integer( $org_id ) && $org_id > 0 ) { - $event->vipgo_org = $org_id; - } + if ( isset( $base_props['vipgo_org'] ) ) { + $event->vipgo_org = $base_props['vipgo_org']; } - // Check if the user is a VIP user. - $event->is_vip_user = Support_User::user_has_vip_support_role( get_current_user_id() ); + if ( isset( $base_props['is_vip_user'] ) ) { + $event->is_vip_user = $base_props['is_vip_user']; + } return $event; } @@ -183,44 +177,16 @@ protected function process_properties( * @return Tracks_Event_DTO The new event object including identity information. */ protected static function set_user_properties( Tracks_Event_DTO $event ): Tracks_Event_DTO { - $wp_user = wp_get_current_user(); - - // Only track logged-in users. - if ( 0 === $wp_user->ID ) { - return $event; - } + $base_props = get_base_properties_of_track_user(); - // Set anonymized event user ID; it should be consistent across environments. - // VIP_TELEMETRY_SALT is a private constant shared across the platform. - if ( defined( 'VIP_TELEMETRY_SALT' ) ) { - $salt = constant( 'VIP_TELEMETRY_SALT' ); - $tracks_user_id = hash_hmac( 'sha256', $wp_user->user_email, $salt ); - - $event->_ui = $tracks_user_id; - $event->_ut = 'vip:user_email'; - - return $event; + if ( isset( $base_props['_ui'] ) ) { + $event->_ui = $base_props['_ui']; } - // Users in the VIP environment. - if ( defined( 'VIP_GO_APP_ID' ) ) { - $app_id = constant( 'VIP_GO_APP_ID' ); - if ( is_integer( $app_id ) && $app_id > 0 ) { - $event->_ui = sprintf( '%s_%s', $app_id, $wp_user->ID ); - $event->_ut = 'vip_go_app_wp_user'; - - return $event; - } + if ( isset( $base_props['_ut'] ) ) { + $event->_ut = $base_props['_ut']; } - // All other environments. - $event->_ui = wp_hash( sprintf( '%s|%s', get_option( 'home' ), $wp_user->ID ) ); - - /** - * @see \Automattic\VIP\Parsely\Telemetry\Tracks_Event::annotate_with_id_and_type() - */ - $event->_ut = 'anon'; // Same as the default value in the original code. - return $event; } diff --git a/telemetry/tracks/tracks-utils.php b/telemetry/tracks/tracks-utils.php new file mode 100644 index 0000000000..5f7ec1200e --- /dev/null +++ b/telemetry/tracks/tracks-utils.php @@ -0,0 +1,128 @@ + The base properties. + */ +function get_base_properties_of_track_event(): array { + $props = [ + 'hosting_provider' => get_hosting_provider(), + 'is_vip_user' => Support_User::user_has_vip_support_role( get_current_user_id() ), + 'is_multisite' => is_multisite(), + 'wp_version' => get_bloginfo( 'version' ), + ]; + + // Set VIP environment if it exists. + if ( defined( 'VIP_GO_APP_ENVIRONMENT' ) ) { + $app_environment = constant( 'VIP_GO_APP_ENVIRONMENT' ); + if ( is_string( $app_environment ) && '' !== $app_environment ) { + $props['vipgo_env'] = $app_environment; + } + } + + // Set VIP organization if it exists. + if ( defined( 'VIP_ORG_ID' ) ) { + $org_id = constant( 'VIP_ORG_ID' ); + if ( is_integer( $org_id ) && $org_id > 0 ) { + $props['vipgo_org'] = $org_id; + } + } + + return $props; +} + +/** + * Check if the site is hosted on VIP. + */ +function is_wpvip_site(): bool { + if ( is_wpvip_sandbox() ) { + return false; + } + + return defined( 'WPCOM_IS_VIP_ENV' ) && constant( 'WPCOM_IS_VIP_ENV' ) === true; +} + +/** + * Check if the site is hosted on VIP sandbox. + */ +function is_wpvip_sandbox(): bool { + return defined( 'WPCOM_SANDBOXED' ) && constant( 'WPCOM_SANDBOXED' ) === true; +} + +/** + * Get the hosting provider. + */ +function get_hosting_provider(): string { + if ( is_wpvip_sandbox() ) { + return 'wpvip_sandbox'; + } + + if ( is_wpvip_site() ) { + return 'wpvip'; + } + + return 'other'; +} + +/** + * Returns the base properties for a track user. + * + * @return array The base properties. + */ +function get_base_properties_of_track_user(): array { + $props = []; + + // Only track logged-in users. + $wp_user = wp_get_current_user(); + if ( 0 === $wp_user->ID ) { + return $props; + } + + // Set anonymized event user ID; it should be consistent across environments. + // VIP_TELEMETRY_SALT is a private constant shared across the platform. + if ( defined( 'VIP_TELEMETRY_SALT' ) ) { + $salt = constant( 'VIP_TELEMETRY_SALT' ); + $tracks_user_id = hash_hmac( 'sha256', $wp_user->user_email, $salt ); + + $props['_ui'] = $tracks_user_id; + $props['_ut'] = 'vip:user_email'; + } elseif ( defined( 'VIP_GO_APP_ID' ) ) { + // Users in the VIP environment. + $app_id = constant( 'VIP_GO_APP_ID' ); + if ( is_integer( $app_id ) && $app_id > 0 ) { + $props['_ui'] = sprintf( '%s_%s', $app_id, $wp_user->ID ); + $props['_ut'] = 'vip_go_app_wp_user'; + } + } else { + // All other environments. + $props['_ui'] = wp_hash( sprintf( '%s|%s', get_option( 'home' ), $wp_user->ID ) ); + + /** + * @see \Automattic\VIP\Parsely\Telemetry\Tracks_Event::annotate_with_id_and_type() + */ + $props['_ut'] = 'anon'; // Same as the default value in the original code. + } + + return $props; +} + +/** + * Get the core properties for a Tracks event. + * + * @return array The core properties. + */ +function get_tracks_core_properties(): array { + return array_merge( get_base_properties_of_track_event(), get_base_properties_of_track_user() ); +} diff --git a/tests/telemetry/test-class-tracks.php b/tests/telemetry/test-class-tracks.php index 8fe36475da..ea7a521f3e 100644 --- a/tests/telemetry/test-class-tracks.php +++ b/tests/telemetry/test-class-tracks.php @@ -5,6 +5,7 @@ namespace Automattic\VIP\Telemetry; use Automattic\VIP\Telemetry\Tracks\Tracks_Event; +use PHPUnit\Framework\MockObject\MockObject; use WP_UnitTestCase; class Tracks_Test extends WP_UnitTestCase { @@ -12,6 +13,7 @@ public function test_event_queued() { $user = $this->factory()->user->create_and_get(); wp_set_current_user( $user->ID ); + /** @var MockObject|Telemetry_Event_Queue */ $queue = $this->getMockBuilder( Telemetry_Event_Queue::class ) ->disableOriginalConstructor() ->getMock(); @@ -28,6 +30,7 @@ public function test_event_queued() { ->willReturn( true ); $tracks = new Tracks( 'test_', [], $queue ); + $this->assertTrue( $tracks->record_event( 'cool_event', [ 'foo' => 'bar' ] ) ); } diff --git a/tests/telemetry/test-tracks-utils.php b/tests/telemetry/test-tracks-utils.php new file mode 100644 index 0000000000..6f3d3d4c12 --- /dev/null +++ b/tests/telemetry/test-tracks-utils.php @@ -0,0 +1,84 @@ +assertEquals( false, is_wpvip_site() ); + } + + public function test_is_wpvip_site_returns_false_on_sandbox(): void { + Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', true ); + Constant_Mocker::define( 'WPCOM_SANDBOXED', true ); + + $this->assertEquals( false, is_wpvip_site() ); + } + + public function test_is_wpvip_site_returns_true(): void { + Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', true ); + Constant_Mocker::define( 'WPCOM_SANDBOXED', false ); + + $this->assertEquals( true, is_wpvip_site() ); + } + + public function test_is_wpvip_sandbox_returns_true(): void { + Constant_Mocker::define( 'WPCOM_SANDBOXED', true ); + + $this->assertEquals( true, is_wpvip_sandbox() ); + } + + public function test_is_wpvip_sandbox_returns_false(): void { + Constant_Mocker::define( 'WPCOM_SANDBOXED', false ); + + $this->assertEquals( false, is_wpvip_sandbox() ); + } + + public function test_get_hosting_provider_returns_wpvip_on_VIP_hosting(): void { + Constant_Mocker::define( 'WPCOM_IS_VIP_ENV', true ); + Constant_Mocker::define( 'WPCOM_SANDBOXED', false ); + + $this->assertEquals( 'wpvip', get_hosting_provider() ); + } + + public function test_get_hosting_provider_returns_wpvip_sandbox_on_sandbox(): void { + Constant_Mocker::define( 'WPCOM_SANDBOXED', true ); + + $this->assertEquals( 'wpvip_sandbox', get_hosting_provider() ); + } + + public function test_get_hosting_provider_returns_other_on_non_VIP_hosting(): void { + $this->assertEquals( 'other', get_hosting_provider() ); + } + + public function test_track_core_properties(): void { + wp_set_current_user( 1 ); + $output = get_tracks_core_properties(); + + $props = [ + 'hosting_provider' => 'other', + 'is_vip_user' => false, + 'is_multisite' => is_multisite(), + 'wp_version' => get_bloginfo( 'version' ), + '_ut' => 'anon', + '_ui' => wp_hash( sprintf( '%s|%s', get_option( 'home' ), 1 ) ), + ]; + $this->assertEquals( $props, $output ); + } +} diff --git a/vip-support/class-vip-support-user.php b/vip-support/class-vip-support-user.php index 1173eadbb1..cffeb36dbe 100644 --- a/vip-support/class-vip-support-user.php +++ b/vip-support/class-vip-support-user.php @@ -190,7 +190,12 @@ public function __construct() { * user edit and profile screens. */ public function action_admin_head() { - if ( in_array( get_current_screen()->base, array( 'user-edit', 'profile' ) ) ) { + $current_screen = get_current_screen(); + if ( ! $current_screen ) { + return; + } + + if ( in_array( $current_screen->base, array( 'user-edit', 'profile' ) ) ) { ?>