Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d540759
[PHPStan]: Apply `@phpstan-` typehints
justlevine Jun 10, 2025
1086aab
[PHPStan]: restore scanning WP_HTML_Processor with PHPStan
justlevine Jun 10, 2025
5e8f772
[PHPStan]: Add more typehints
justlevine Oct 24, 2025
ec66ce3
chore: improve doctypes /type safety for `WP_Screen` properties
justlevine May 31, 2025
f666a1d
fix: ensure wp_create_category() returns `int`
justlevine Jun 28, 2025
5bab037
code quality: remove unnecessary empty() check in wp_insert_user()
justlevine Jun 28, 2025
b10749a
fix: define `$schema` in `WP_REST_Attachments_Controller::update_item()`
justlevine Jun 28, 2025
cb0aa65
chore: remove needly `empty( )` check in `wpdb::set_sql_mode()`
justlevine Jun 28, 2025
7b5d9c8
fix: cast `base_convert()` to `int` before binaryOp
justlevine Oct 24, 2025
d876553
chore: cast headers to string in `WP_REST_Comments_Controller::get_it…
justlevine Oct 24, 2025
e6bee7f
docs: fix return type for WP_HTML_Decoder::read_character_reference()
justlevine Jun 10, 2025
dbf49bc
docs: fix return type for WP_Speculation_Rules::jsonSerialize to arra…
justlevine Oct 24, 2025
5334655
docs: Fix misc `@var` tags on nullable class props
justlevine Oct 24, 2025
52d14fb
code quality: explicitly return `null` when documented
justlevine Oct 24, 2025
b02c44a
code quality: remove unreachable `break;` from `allsites` case in `ne…
justlevine Oct 24, 2025
fc8803b
code quality: add explicit `: void` to method signatures in wp-signup…
justlevine Oct 24, 2025
7f4795d
code quality: remove needless $cpage checks from `get_comment_link()`
justlevine Jun 18, 2025
48db9b2
code quality: remove always-true ternary from _wp_menu_object()
justlevine Jun 18, 2025
7d1db07
fix: correctly check for trimmed value in wp_get_layout_style()
justlevine Jun 18, 2025
524710f
code quality: remove unreachable _doing_it_wrong from WP_Block_Bindin…
justlevine Jun 18, 2025
1935e92
chore: remove always-true if() from WP_Interactvity_API::config()
justlevine Jun 18, 2025
b34bda0
code quality: fix usage of `remove_query_arg()` in wp-activate.php
justlevine Jun 23, 2025
1584939
code quality: explicitly return null instead of coercing `void`
justlevine Jul 19, 2025
a691d01
code quality: remove always-true negated bools
justlevine Jul 19, 2025
c8daca9
chore: fix invalid argument types in `ms-site.php`
justlevine Jul 19, 2025
775f05f
chore: fix invalid argument types in `taxonomy.php`
justlevine Jul 19, 2025
edabf22
phpstan: regenerate baselines
justlevine Oct 24, 2025
00e9f54
phpstan: annotations
justlevine Oct 24, 2025
b295ab0
phpstan: update excludePaths
justlevine Oct 24, 2025
3dab380
fix: cast `$new_attachment_id` to array before `wp_slash()` ing in WP…
justlevine Oct 24, 2025
f9aa2bf
chore: regenerate baselines
justlevine Oct 24, 2025
3ca3dbf
code quality: explicitly return null in `WP_Theme_JSON::should_overri…
justlevine Oct 25, 2025
704b3f6
docs: add missing return hints to `WP_Customize_*Setting::update()`
justlevine Oct 25, 2025
e51a575
chore(phpstan): add phpstan level 0 annotations to code
justlevine Oct 25, 2025
cc2252a
chore: phpstan level 0 complete 🚀
justlevine Oct 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ includes:
- tests/phpstan/base.neon
# The baseline file includes preexisting errors in the codebase that should be ignored.
# https://phpstan.org/user-guide/baseline
- tests/phpstan/baseline/level-0.php
- tests/phpstan/baseline/level-1.php
- tests/phpstan/baseline/level-2.php
- tests/phpstan/baseline/level-3.php
Expand All @@ -26,6 +25,18 @@ parameters:
- # Inner functions arent supported by PHPstan.
message: '#Function wxr_[a-z_]+ not found#'
path: src/wp-admin/includes/export.php
-
identifier: function.inner
path: src/wp-admin/includes/export.php
count: 13
-
identifier: function.inner
path: src/wp-admin/includes/file.php
count: 1
-
identifier: function.inner
path: src/wp-includes/canonical.php
count: 1

# Level 1:
- # These are too noisy at the moment.
Expand Down
3 changes: 2 additions & 1 deletion src/wp-activate.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
if ( $key ) {
$redirect_url = remove_query_arg( 'key' );

if ( remove_query_arg( false ) !== $redirect_url ) {
// If we still have query args, stash the key and redirect to handle them.
if ( remove_query_arg( '' ) !== $redirect_url ) {
setcookie( $activate_cookie, $key, 0, $activate_path, COOKIE_DOMAIN, is_ssl(), true );
wp_safe_redirect( $redirect_url );
exit;
Expand Down
5 changes: 4 additions & 1 deletion src/wp-admin/about.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,12 @@

<?php

// These are strings we may use to describe maintenance/security releases, where we aim for no new strings.
return;

/**
* These are strings we may use to describe maintenance/security releases, where we aim for no new strings.
* @phpstan-ignore deadCode.unreachable
*/
__( 'Maintenance Release' );
__( 'Maintenance Releases' );

Expand Down
5 changes: 4 additions & 1 deletion src/wp-admin/credits.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@

return;

// These are strings returned by the API that we want to be translatable.
/**
* These are strings returned by the API that we want to be translatable.
* @phpstan-ignore deadCode.unreachable
*/
__( 'Project Leaders' );
/* translators: %s: The current WordPress version number. */
__( 'Core Contributors to WordPress %s' );
Expand Down
4 changes: 3 additions & 1 deletion src/wp-admin/includes/bookmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ function get_link_to_edit( $link ) {
* }
* @param bool $wp_error Optional. Whether to return a WP_Error object on failure. Default false.
* @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success.
*
* @phpstan-return ( $wp_error is false ? int<0, max> : (int<1, max>|\WP_Error) )
*/
function wp_insert_link( $linkdata, $wp_error = false ) {
global $wpdb;
Expand Down Expand Up @@ -295,7 +297,7 @@ function wp_set_link_cats( $link_id = 0, $link_categories = array() ) {
* @since 2.0.0
*
* @param array $linkdata Link data to update. See wp_insert_link() for accepted arguments.
* @return int|WP_Error Value 0 or WP_Error on failure. The updated link ID on success.
* @return int Value 0 on failure. The updated link ID on success.
*/
function wp_update_link( $linkdata ) {
$link_id = (int) $linkdata['link_id'];
Expand Down
4 changes: 4 additions & 0 deletions src/wp-admin/includes/class-custom-image-header.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ public function process_default_headers() {
*
* @param string $type The header type. One of 'default' (for the Uploaded Images control)
* or 'uploaded' (for the Uploaded Images control).
*
* @phpstan-param 'default'|'uploaded' $type
*/
public function show_header_selector( $type = 'default' ) {
if ( 'default' === $type ) {
Expand Down Expand Up @@ -1169,6 +1171,8 @@ public function filter_upload_tabs( $tabs ) {
* registered for that theme; and the key of an image uploaded for that theme
* (the attachment ID of the image). Or an array of arguments: attachment_id,
* url, width, height. All are required.
*
* @phpstan-param 'random-default-image'|'random-uploaded-image'|array{attachment_id: int<1, max>, url: string, width: int<0, max>, height: int<0, max>} $choice
*/
final public function set_header_image( $choice ) {
if ( is_array( $choice ) || is_object( $choice ) ) {
Expand Down
1 change: 1 addition & 0 deletions src/wp-admin/includes/class-wp-filesystem-ssh2.php
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ public function size( $file ) {
* Default 0.
*/
public function touch( $file, $time = 0, $atime = 0 ) {
// @phpstan-ignore-next-line
// Not implemented.
}

Expand Down
6 changes: 5 additions & 1 deletion src/wp-admin/includes/class-wp-importer.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ public function get_imported_comments( $blog_id ) {

/**
* @param int $blog_id
* @return int|void
* @return int
*
* @phpstan-param int|string $blog_id
*
* @phpstan-return ( $blog_id is (int|numeric-string) ? int : (int|never) )
*/
public function set_blog( $blog_id ) {
if ( is_numeric( $blog_id ) ) {
Expand Down
2 changes: 2 additions & 0 deletions src/wp-admin/includes/class-wp-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ public function prepare_items() {
* @since 3.1.0
*
* @param array|string $args Array or string of arguments with information about the pagination.
*
* @phpstan-param array{total_items?: int, total_pages?: int, per_page?: int} $args
*/
protected function set_pagination_args( $args ) {
$args = wp_parse_args(
Expand Down
6 changes: 3 additions & 3 deletions src/wp-admin/includes/class-wp-posts-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ public function display_rows( $posts = array(), $level = 0 ) {
* @param array $posts
* @param int $level
*/
private function _display_rows( $posts, $level = 0 ) {
private function _display_rows( $posts, $level = 0 ): void {
$post_type = $this->screen->post_type;

// Create array of post IDs.
Expand All @@ -846,7 +846,7 @@ private function _display_rows( $posts, $level = 0 ) {
* @param int $pagenum
* @param int $per_page
*/
private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) {
private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ): void {
global $wpdb;

$level = 0;
Expand Down Expand Up @@ -956,7 +956,7 @@ private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 2
* @param int $per_page
* @param array $to_display List of pages to be displayed. Passed by reference.
*/
private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ) {
private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ): void {
if ( ! isset( $children_pages[ $parent_page ] ) ) {
return;
}
Expand Down
48 changes: 25 additions & 23 deletions src/wp-admin/includes/class-wp-screen.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,10 @@ final class WP_Screen {
/**
* Stores the result of the public show_screen_options function.
*
* Set when calling ::show_screen_options() for the first time.
*
* @since 3.3.0
* @var bool
* @var ?bool
*/
private $_show_screen_options;

Expand Down Expand Up @@ -407,7 +409,7 @@ public static function get( $hook_name = '' ) {
* @global string $typenow The post type of the current screen.
* @global string $taxnow The taxonomy of the current screen.
*/
public function set_current_screen() {
public function set_current_screen(): void {
global $current_screen, $taxnow, $typenow;

$current_screen = $this;
Expand Down Expand Up @@ -472,7 +474,7 @@ public function is_block_editor( $set = null ) {
* @param WP_Screen $screen A screen object.
* @param string $help Help text.
*/
public static function add_old_compat_help( $screen, $help ) {
public static function add_old_compat_help( $screen, $help ): void {
self::$_old_compat_help[ $screen->id ] = $help;
}

Expand All @@ -485,7 +487,7 @@ public static function add_old_compat_help( $screen, $help ) {
*
* @param string $parent_file The parent file of the screen. Typically the $parent_file global.
*/
public function set_parentage( $parent_file ) {
public function set_parentage( $parent_file ): void {
$this->parent_file = $parent_file;
list( $this->parent_base ) = explode( '?', $parent_file );
$this->parent_base = str_replace( '.php', '', $this->parent_base );
Expand All @@ -502,7 +504,7 @@ public function set_parentage( $parent_file ) {
* @param string $option Option ID.
* @param mixed $args Option-dependent arguments.
*/
public function add_option( $option, $args = array() ) {
public function add_option( $option, $args = array() ): void {
$this->_options[ $option ] = $args;
}

Expand All @@ -513,7 +515,7 @@ public function add_option( $option, $args = array() ) {
*
* @param string $option Option ID.
*/
public function remove_option( $option ) {
public function remove_option( $option ): void {
unset( $this->_options[ $option ] );
}

Expand All @@ -522,7 +524,7 @@ public function remove_option( $option ) {
*
* @since 3.8.0
*/
public function remove_options() {
public function remove_options(): void {
$this->_options = array();
}

Expand All @@ -545,7 +547,7 @@ public function get_options() {
* @param string $option Option name.
* @param string|false $key Optional. Specific array key for when the option is an array.
* Default false.
* @return string The option value if set, null otherwise.
* @return ?string The option value if set, null otherwise.
*/
public function get_option( $option, $key = false ) {
if ( ! isset( $this->_options[ $option ] ) ) {
Expand Down Expand Up @@ -598,7 +600,7 @@ public function get_help_tabs() {
* @since 3.4.0
*
* @param string $id Help Tab ID.
* @return array Help tab arguments.
* @return ?array Help tab arguments.
*/
public function get_help_tab( $id ) {
if ( ! isset( $this->_help_tabs[ $id ] ) ) {
Expand Down Expand Up @@ -631,7 +633,7 @@ public function get_help_tab( $id ) {
* @type int $priority Optional. The priority of the tab, used for ordering. Default 10.
* }
*/
public function add_help_tab( $args ) {
public function add_help_tab( $args ): void {
$defaults = array(
'title' => false,
'id' => false,
Expand Down Expand Up @@ -659,7 +661,7 @@ public function add_help_tab( $args ) {
*
* @param string $id The help tab ID.
*/
public function remove_help_tab( $id ) {
public function remove_help_tab( $id ): void {
unset( $this->_help_tabs[ $id ] );
}

Expand All @@ -668,7 +670,7 @@ public function remove_help_tab( $id ) {
*
* @since 3.3.0
*/
public function remove_help_tabs() {
public function remove_help_tabs(): void {
$this->_help_tabs = array();
}

Expand All @@ -693,7 +695,7 @@ public function get_help_sidebar() {
*
* @param string $content Sidebar content in plain text or HTML.
*/
public function set_help_sidebar( $content ) {
public function set_help_sidebar( $content ): void {
$this->_help_sidebar = $content;
}

Expand Down Expand Up @@ -733,7 +735,7 @@ public function get_screen_reader_content() {
* @since 4.4.0
*
* @param string $key Screen reader text array named key.
* @return string Screen reader text string.
* @return ?string Screen reader text string. Null if no text is associated with the key.
*/
public function get_screen_reader_text( $key ) {
if ( ! isset( $this->_screen_reader_content[ $key ] ) ) {
Expand Down Expand Up @@ -787,7 +789,7 @@ public function remove_screen_reader_content() {
*
* @global string $screen_layout_columns
*/
public function render_screen_meta() {
public function render_screen_meta(): void {

/**
* Filters the legacy contextual help list.
Expand Down Expand Up @@ -950,7 +952,7 @@ public function render_screen_meta() {
$this->columns = (int) get_user_option( "screen_layout_$this->id" );

if ( ! $this->columns && $this->get_option( 'layout_columns', 'default' ) ) {
$this->columns = $this->get_option( 'layout_columns', 'default' );
$this->columns = (int) $this->get_option( 'layout_columns', 'default' );
}
}
$GLOBALS['screen_layout_columns'] = $this->columns; // Set the global for back-compat.
Expand Down Expand Up @@ -1048,7 +1050,7 @@ public function show_screen_options() {
* @type bool $wrap Whether the screen-options-wrap div will be included. Defaults to true.
* }
*/
public function render_screen_options( $options = array() ) {
public function render_screen_options( $options = array() ): void {
$options = wp_parse_args(
$options,
array(
Expand Down Expand Up @@ -1107,7 +1109,7 @@ public function render_screen_options( $options = array() ) {
*
* @global array $wp_meta_boxes Global meta box state.
*/
public function render_meta_boxes_preferences() {
public function render_meta_boxes_preferences(): void {
global $wp_meta_boxes;

if ( ! isset( $wp_meta_boxes[ $this->id ] ) ) {
Expand Down Expand Up @@ -1150,7 +1152,7 @@ public function render_meta_boxes_preferences() {
*
* @since 4.4.0
*/
public function render_list_table_columns_preferences() {
public function render_list_table_columns_preferences(): void {

$columns = get_column_headers( $this );
$hidden = get_hidden_columns( $this );
Expand Down Expand Up @@ -1198,7 +1200,7 @@ public function render_list_table_columns_preferences() {
*
* @since 3.3.0
*/
public function render_screen_layout() {
public function render_screen_layout(): void {
if ( ! $this->get_option( 'layout_columns' ) ) {
return;
}
Expand Down Expand Up @@ -1230,7 +1232,7 @@ public function render_screen_layout() {
*
* @since 3.3.0
*/
public function render_per_page_options() {
public function render_per_page_options(): void {
if ( null === $this->get_option( 'per_page' ) ) {
return;
}
Expand Down Expand Up @@ -1296,7 +1298,7 @@ public function render_per_page_options() {
*
* @global string $mode List table view mode.
*/
public function render_view_mode() {
public function render_view_mode(): void {
global $mode;

$screen = get_current_screen();
Expand Down Expand Up @@ -1351,7 +1353,7 @@ public function render_view_mode() {
* @param string $key The screen reader text array named key.
* @param string $tag Optional. The HTML tag to wrap the screen reader text. Default h2.
*/
public function render_screen_reader_content( $key = '', $tag = 'h2' ) {
public function render_screen_reader_content( $key = '', $tag = 'h2' ): void {

if ( ! isset( $this->_screen_reader_content[ $key ] ) ) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/wp-admin/includes/file.php
Original file line number Diff line number Diff line change
Expand Up @@ -2193,7 +2193,7 @@ function WP_Filesystem( $args = false, $context = false, $allow_relaxed_file_own
$abstraction_file = apply_filters( 'filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method );

if ( ! file_exists( $abstraction_file ) ) {
return;
return null;
}

require_once $abstraction_file;
Expand Down
6 changes: 6 additions & 0 deletions src/wp-admin/includes/list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@
* @param string $class_name The type of the list table, which is the class name.
* @param array $args Optional. Arguments to pass to the class. Accepts 'screen'.
* @return WP_List_Table|false List table object on success, false if the class does not exist.

* @phpstan-template T of WP_List_Table
* @phpstan-param class-string<T>|string $class_name
* @phpstan-param array{screen?: string}&array<string, mixed> $args
* @phpstan-return ( $class_name is class-string<T> ? new<T> : false )
*/
function _get_list_table( $class_name, $args = array() ) {
/** @var array<class-string<WP_List_Table>, mixed> */
$core_classes = array(
// Site Admin.
'WP_Posts_List_Table' => 'posts',
Expand Down
Loading