Skip to content

Commit beab576

Browse files
authored
Merge branch 'trunk' into fix/adv-templates-twentytwentyfive
2 parents 96d0bf8 + 7924b71 commit beab576

216 files changed

Lines changed: 24674 additions & 200 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: PHPStan Static Analysis
2+
3+
on:
4+
# PHPStan testing was introduced in 7.0.0.
5+
push:
6+
branches:
7+
- trunk
8+
- '[7-9].[0-9]'
9+
tags:
10+
- '[7-9].[0-9]'
11+
- '[7-9]+.[0-9].[0-9]+'
12+
pull_request:
13+
branches:
14+
- trunk
15+
- '[7-9].[0-9]'
16+
paths:
17+
# This workflow only scans PHP files.
18+
- '**.php'
19+
# These files configure Composer. Changes could affect the outcome.
20+
- 'composer.*'
21+
# These files configure PHPStan. Changes could affect the outcome.
22+
- 'phpstan.neon.dist'
23+
- 'tests/phpstan/base.neon'
24+
- 'tests/phpstan/baseline.php'
25+
# Confirm any changes to relevant workflow files.
26+
- '.github/workflows/phpstan-static-analysis.yml'
27+
- '.github/workflows/reusable-phpstan-static-analysis.yml'
28+
workflow_dispatch:
29+
30+
# Cancels all previous workflow runs for pull requests that have not completed.
31+
concurrency:
32+
# The concurrency group contains the workflow name and the branch name for pull requests
33+
# or the commit hash for any other events.
34+
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
35+
cancel-in-progress: true
36+
37+
# Disable permissions for all available scopes by default.
38+
# Any needed permissions should be configured at the job level.
39+
permissions: {}
40+
41+
jobs:
42+
# Runs PHPStan Static Analysis.
43+
phpstan:
44+
name: PHP static analysis
45+
uses: ./.github/workflows/reusable-phpstan-static-analysis.yml
46+
permissions:
47+
contents: read
48+
if: ${{ github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' ) }}
49+
50+
slack-notifications:
51+
name: Slack Notifications
52+
uses: ./.github/workflows/slack-notifications.yml
53+
permissions:
54+
actions: read
55+
contents: read
56+
needs: [ phpstan ]
57+
if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
58+
with:
59+
calling_status: ${{ contains( needs.*.result, 'cancelled' ) && 'cancelled' || contains( needs.*.result, 'failure' ) && 'failure' || 'success' }}
60+
secrets:
61+
SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }}
62+
SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }}
63+
SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }}
64+
SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }}
65+
66+
failed-workflow:
67+
name: Failed workflow tasks
68+
runs-on: ubuntu-24.04
69+
permissions:
70+
actions: write
71+
needs: [ slack-notifications ]
72+
if: |
73+
always() &&
74+
github.repository == 'WordPress/wordpress-develop' &&
75+
github.event_name != 'pull_request' &&
76+
github.run_attempt < 2 &&
77+
(
78+
contains( needs.*.result, 'cancelled' ) ||
79+
contains( needs.*.result, 'failure' )
80+
)
81+
82+
steps:
83+
- name: Dispatch workflow run
84+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
85+
with:
86+
retries: 2
87+
retry-exempt-status-codes: 418
88+
script: |
89+
github.rest.actions.createWorkflowDispatch({
90+
owner: context.repo.owner,
91+
repo: context.repo.repo,
92+
workflow_id: 'failed-workflow.yml',
93+
ref: 'trunk',
94+
inputs: {
95+
run_id: `${context.runId}`,
96+
}
97+
});
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
##
2+
# A reusable workflow that runs PHP Static Analysis tests.
3+
##
4+
name: PHP Static Analysis
5+
6+
on:
7+
workflow_call:
8+
inputs:
9+
php-version:
10+
description: 'The PHP version to use.'
11+
required: false
12+
type: 'string'
13+
default: 'latest'
14+
15+
# Disable permissions for all available scopes by default.
16+
# Any needed permissions should be configured at the job level.
17+
permissions: {}
18+
19+
jobs:
20+
# Runs PHP static analysis tests.
21+
#
22+
# Violations are reported inline with annotations.
23+
#
24+
# Performs the following steps:
25+
# - Checks out the repository.
26+
# - Sets up PHP.
27+
# - Logs debug information.
28+
# - Installs Composer dependencies.
29+
# - Configures caching for PHP static analysis scans.
30+
# - Make Composer packages available globally.
31+
# - Runs PHPStan static analysis (with Pull Request annotations).
32+
# - Saves the PHPStan result cache.
33+
# - Ensures version-controlled files are not modified or deleted.
34+
phpstan:
35+
name: Run PHP static analysis
36+
runs-on: ubuntu-24.04
37+
permissions:
38+
contents: read
39+
timeout-minutes: 20
40+
41+
steps:
42+
- name: Checkout repository
43+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
44+
with:
45+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
46+
persist-credentials: false
47+
48+
- name: Set up Node.js
49+
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
50+
with:
51+
node-version-file: '.nvmrc'
52+
cache: npm
53+
54+
- name: Set up PHP
55+
uses: shivammathur/setup-php@20529878ed81ef8e78ddf08b480401e6101a850f # v2.35.3
56+
with:
57+
php-version: ${{ inputs.php-version }}
58+
coverage: none
59+
tools: cs2pr
60+
61+
# This date is used to ensure that the Composer cache is cleared at least once every week.
62+
# http://man7.org/linux/man-pages/man1/date.1.html
63+
- name: "Get last Monday's date"
64+
id: get-date
65+
run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> "$GITHUB_OUTPUT"
66+
67+
- name: General debug information
68+
run: |
69+
npm --version
70+
node --version
71+
composer --version
72+
73+
# Since Composer dependencies are installed using `composer update` and no lock file is in version control,
74+
# passing a custom cache suffix ensures that the cache is flushed at least once per week.
75+
- name: Install Composer dependencies
76+
uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1
77+
with:
78+
custom-cache-suffix: ${{ steps.get-date.outputs.date }}
79+
80+
- name: Make Composer packages available globally
81+
run: echo "${PWD}/vendor/bin" >> "$GITHUB_PATH"
82+
83+
- name: Install npm dependencies
84+
run: npm ci --ignore-scripts
85+
86+
- name: Build WordPress
87+
run: npm run build:dev
88+
89+
- name: Cache PHP Static Analysis scan cache
90+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
91+
with:
92+
path: .cache # This is defined in the base.neon file.
93+
key: "phpstan-result-cache-${{ github.run_id }}"
94+
restore-keys: |
95+
phpstan-result-cache-
96+
97+
- name: Run PHP static analysis tests
98+
id: phpstan
99+
run: composer run phpstan -- -vvv --error-format=checkstyle | cs2pr --errors-as-warnings --graceful-warnings
100+
101+
- name: "Save result cache"
102+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
103+
if: ${{ !cancelled() }}
104+
with:
105+
path: .cache
106+
key: "phpstan-result-cache-${{ github.run_id }}"
107+
108+
- name: Ensure version-controlled files are not modified or deleted
109+
run: git diff --exit-code

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ wp-tests-config.php
2323
/gutenberg
2424
/tests/phpunit/build
2525
/wp-cli.local.yml
26+
/phpstan.neon
2627
/jsdoc
2728
/composer.lock
2829
/vendor

Gruntfile.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,7 @@ module.exports = function(grunt) {
15601560
] );
15611561

15621562
grunt.registerTask( 'precommit:php', [
1563+
'phpstan',
15631564
'phpunit'
15641565
] );
15651566

@@ -2001,6 +2002,18 @@ module.exports = function(grunt) {
20012002

20022003
grunt.registerTask( 'test', 'Runs all QUnit and PHPUnit tasks.', ['qunit:compiled', 'phpunit'] );
20032004

2005+
grunt.registerTask( 'phpstan', 'Runs PHPStan on the entire codebase.', function() {
2006+
var done = this.async();
2007+
2008+
grunt.util.spawn( {
2009+
cmd: 'composer',
2010+
args: [ 'phpstan' ],
2011+
opts: { stdio: 'inherit' }
2012+
}, function( error ) {
2013+
done( ! error );
2014+
} );
2015+
} );
2016+
20042017
grunt.registerTask( 'format:php', 'Runs the code formatter on changed files.', function() {
20052018
var done = this.async();
20062019
var flags = this.flags;

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"squizlabs/php_codesniffer": "3.13.5",
2424
"wp-coding-standards/wpcs": "~3.3.0",
2525
"phpcompatibility/phpcompatibility-wp": "~2.1.3",
26+
"phpstan/phpstan": "2.1.39",
2627
"yoast/phpunit-polyfills": "^1.1.0"
2728
},
2829
"config": {
@@ -32,6 +33,7 @@
3233
"lock": false
3334
},
3435
"scripts": {
36+
"phpstan": "@php ./vendor/bin/phpstan analyse --memory-limit=2G",
3537
"compat": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcompat.xml.dist --report=summary,source",
3638
"format": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf --report=summary,source",
3739
"lint": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --report=summary,source",

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://develop.svn.wordpress.org/trunk"
88
},
99
"gutenberg": {
10-
"ref": "7a11a53377a95cba4d3786d71cadd4c2f0c5ac52"
10+
"ref": "23b566c72e9c4a36219ef5d6e62890f05551f6cb"
1111
},
1212
"engines": {
1313
"node": ">=20.10.0",
@@ -130,6 +130,7 @@
130130
"test:coverage": "npm run test:php -- --coverage-html ./coverage/html/ --coverage-php ./coverage/php/report.php --coverage-text=./coverage/text/report.txt",
131131
"test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js",
132132
"test:visual": "wp-scripts test-playwright --config tests/visual-regression/playwright.config.js",
133+
"typecheck:php": "node ./tools/local-env/scripts/docker.js run --rm php composer phpstan",
133134
"gutenberg:checkout": "node tools/gutenberg/checkout-gutenberg.js",
134135
"gutenberg:build": "node tools/gutenberg/build-gutenberg.js",
135136
"gutenberg:copy": "node tools/gutenberg/copy-gutenberg-build.js",

phpcs.xml.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
<exclude-pattern>/src/wp-includes/js/*</exclude-pattern>
7474
<exclude-pattern>/src/wp-includes/PHPMailer/*</exclude-pattern>
7575
<exclude-pattern>/src/wp-includes/Requests/*</exclude-pattern>
76+
<exclude-pattern>/src/wp-includes/php-ai-client/*</exclude-pattern>
7677
<exclude-pattern>/src/wp-includes/SimplePie/*</exclude-pattern>
7778
<exclude-pattern>/src/wp-includes/sodium_compat/*</exclude-pattern>
7879
<exclude-pattern>/src/wp-includes/Text/*</exclude-pattern>
@@ -81,6 +82,9 @@
8182
<exclude-pattern>/tests/phpunit/build*</exclude-pattern>
8283
<exclude-pattern>/tests/phpunit/data/*</exclude-pattern>
8384

85+
<!-- PHPStan bootstrap, stubs, and baseline. -->
86+
<exclude-pattern>/tests/phpstan/*</exclude-pattern>
87+
8488
<exclude-pattern>/tools/*</exclude-pattern>
8589

8690
<!-- Drop-in plugins. -->

phpstan.neon.dist

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# PHPStan configuration for WordPress Core.
2+
#
3+
# To overload this configuration, copy this file to phpstan.neon and adjust as needed.
4+
#
5+
# https://phpstan.org/config-reference
6+
7+
includes:
8+
# The base configuration file for using PHPStan with the WordPress core codebase.
9+
- tests/phpstan/base.neon
10+
11+
# The baseline file includes preexisting errors in the codebase that should be ignored.
12+
# https://phpstan.org/user-guide/baseline
13+
- tests/phpstan/baseline.php
14+
15+
parameters:
16+
# https://phpstan.org/user-guide/rule-levels
17+
level: 0
18+
reportUnmatchedIgnoredErrors: true
19+
20+
ignoreErrors:
21+
# Level 0:
22+
- # Inner functions aren't supported by PHPStan.
23+
message: '#Function wxr_[a-z_]+ not found#'
24+
path: src/wp-admin/includes/export.php
25+
-
26+
identifier: function.inner
27+
path: src/wp-admin/includes/export.php
28+
count: 13
29+
-
30+
identifier: function.inner
31+
path: src/wp-admin/includes/file.php
32+
count: 1
33+
-
34+
identifier: function.inner
35+
path: src/wp-includes/canonical.php
36+
count: 1

phpunit.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<directory suffix=".php">src/wp-includes/IXR</directory>
4848
<directory suffix=".php">src/wp-includes/PHPMailer</directory>
4949
<directory suffix=".php">src/wp-includes/Requests</directory>
50+
<directory suffix=".php">src/wp-includes/php-ai-client</directory>
5051
<directory suffix=".php">src/wp-includes/SimplePie</directory>
5152
<directory suffix=".php">src/wp-includes/sodium_compat</directory>
5253
<directory suffix=".php">src/wp-includes/Text</directory>

src/wp-admin/edit-form-blocks.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ static function ( $classes ) {
9292
'description',
9393
'gmt_offset',
9494
'home',
95+
'image_sizes',
96+
'image_size_threshold',
97+
'image_output_formats',
98+
'jpeg_interlaced',
99+
'png_interlaced',
100+
'gif_interlaced',
95101
'name',
96102
'site_icon',
97103
'site_icon_url',

0 commit comments

Comments
 (0)