Make WordPress Core

Opened 7 months ago

Closed 3 months ago

Last modified 3 weeks ago

#64238 closed task (blessed) (fixed)

PHPStan code quality improvements for 7.0

Reported by: sergeybiryukov's profile SergeyBiryukov Owned by:
Milestone: 7.0 Priority: normal
Severity: normal Version:
Component: General Keywords: has-patch has-unit-tests
Focuses: coding-standards Cc:

Description

This ticket is for various code quality issues and improvements surfaced via PHPStan.

Implementing PHPStan is tracked separately in #61175.

Previously:

Change History (130)

This ticket was mentioned in PR #7720 on WordPress/wordpress-develop by @justlevine.


7 months ago
#1

  • Keywords has-patch added

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This PR fixes an issue in get_taxonomy_labels(), where the template_name was accessed as an object property on $tax->labels instead of as an array property.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

This ticket was mentioned in PR #8860 on WordPress/wordpress-develop by @justlevine.


7 months ago
#2

This PR improves the type safety around WP_Screen in the following ways:

  • Correctly hint that WP_Screen::$_show_screen_options is null before instantiated.
  • Correctly hint that ::get_option(), get_help_tab() and get_screen_reader_text() can return null.
  • Ensure $this->columns is an int, by casting $this->get_option( 'layout_columns', 'default' ) from its numeric string.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8861 on WordPress/wordpress-develop by @justlevine.


7 months ago
#3

This PR fixes wp_create_category() to return an int as defined in the DocBlock, instead of the numeric-string returned by category_exists().

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8864 on WordPress/wordpress-develop by @justlevine.


7 months ago
#4

This PR removes an unnecessary empty( $old_user_data ) check from wp_insert_user(). The $old_user_data variable is defined alongside $update, so by checking for one, we've already narrowed the type for the other:

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8865 on WordPress/wordpress-develop by @justlevine.


7 months ago
#5

This PR fixes an issue in WP_REST_Attachments_Controller::update_item(), where the $schema['properties'] are checked for featured media, but is only defined in the parent method and not where it is currently used.

Follow up to: https://core.trac.wordpress.org/ticket/41692

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8866 on WordPress/wordpress-develop by @justlevine.


7 months ago
#6

This PR removes an unnecessary empty( $modes_str ) check from wpdb::set_sql_mode(), as the previous code block already checks and returns early:

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8872 on WordPress/wordpress-develop by @justlevine.


7 months ago
#7

This PR fixes two attempts to use the results of base_convert() in a binaryOp without first converting the results to an integer.

In

  • add_menu_page()
  • WP_Duotone::colord_parse_hex()

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8873 on WordPress/wordpress-develop by @justlevine.


7 months ago
#8

  • Keywords has-unit-tests added

This PR updates WP_REST_Comments_Controller::get_items() to cast the values of $total_comments and $max_pages to string types before they are set on the response headers.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8945 on WordPress/wordpress-develop by @justlevine.


7 months ago
#9

This PR fixes the return type on WP_HTML_Decoder::read_character_reference() to correctly indicate that it returns a _nullable_ string, and not string|false.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8946 on WordPress/wordpress-develop by @justlevine.


7 months ago
#10

This PR fixes the return type on WP_Speculation_Rules::jsonSerialize() to show that it returns an array<string, mixed[]> instead of the internal array having a string key. This is due to the method's use of array_values() to intentionally strip any keys.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8953 on WordPress/wordpress-develop by @justlevine.


7 months ago
#11

This PR updates various @var tags on class properties to correctly indicate that they props may be null|unset:

  • WP_Dependencies::$all_queued_deps is nullable by both ::enqueue() and ::dequeue.
  • WP_Duotone::$global_styles_presets and ::$global_styles_block_names start off unset and are only initialized by static classes.
  • WP_Query::init() and WP_Rewrite::init() are public methods that unset()s many class props.
  • WP_Theme::cache_delete() sets many props to null.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8955 on WordPress/wordpress-develop by @justlevine.


7 months ago
#12

This PR updates several functions to explicitly return null in accordance to their existing doc-types, instead of using a void return;.

Affected functions:

  • get_comment_reply_link()
  • get_page_of_comment()
  • get_edit_term_link()
  • get_preview_post_link()
  • get_edit_post_link()
  • wp_set_all_user_settings()
  • get_page_by_path()
  • save_mod_rewrite_rules()

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

This ticket was mentioned in PR #8956 on WordPress/wordpress-develop by @justlevine.


7 months ago
#13

This PR removes an unreachable break; from the 'allblogs' -> 'delete' case in wp-admin/network/sites.php, as the line before exits entirely.

While this issue was surfaced via PHPStan in https://github.com/WordPress/wordpress-develop/pull/7619 (trac: https://core.trac.wordpress.org/ticket/61175 ), it can be remediated independently of that ticket.

Trac ticket:
https://core.trac.wordpress.org/ticket/64238
https://core.trac.wordpress.org/ticket/63268

#14 @SergeyBiryukov
7 months ago

In 61243:

Coding Standards: Remove redundant check in wpdb::set_sql_mode().

This commit removes an unnecessary empty( $modes_str ) check, as the previous code block already checks the same value and returns early.

Follow-up to [30587], [56475].

Props justlevine.
See #64238.

@SergeyBiryukov commented on PR #8866:


7 months ago
#15

Thanks for the PR! Merged in r61243.

#16 @SergeyBiryukov
7 months ago

In 61247:

Coding Standards: Cast base_convert() to an integer before arithmetic operations.

Follow-up to [35477], [53104], [56101].

Props justlevine.
See #64238.

@SergeyBiryukov commented on PR #8872:


7 months ago
#17

Thanks for the PR! Merged in r61247.

#18 @westonruter
7 months ago

In 61280:

Docs: Fix phpdoc types for WP_Speculation_Rules members.

What was previously mixed is actually a speculation rule which can be more accurately be typed as array<string, mixed>. Additionally, the return value of jsonSerialize is fixed to indicate it returns an array of lists as opposed an array of associative arrays.

Developed in https://github.com/WordPress/wordpress-develop/pull/8946

Follow-up to [59837].

Props justlevine, johnbillion, westonruter.
See #64238, #63268, #62503.

@westonruter commented on PR #8946:


7 months ago
#19

Committed in r61280 (9e2d045)

#20 @westonruter
7 months ago

In 61281:

Docs: Explicitly return null when documented instead of void in link-template.php functions.

The phpdoc @return tags for these functions indicate they may return null. This also fixes "Missing return argument" warnings which an IDE may also complain about.

Developed in https://github.com/WordPress/wordpress-develop/pull/8955

Props justlevine.
See #64238.

@westonruter commented on PR #8955:


7 months ago
#21

Committed in r61281 (c9c6518)

#22 @westonruter
7 months ago

In 61282:

Docs: Cast header values to strings in WP_REST_Comments_Controller::get_items().

Follow-up to [38832].

Props justlevine, johnbillion.
See #64238.

#24 @westonruter
7 months ago

In 61283:

Docs: Fix return type for WP_HTML_Decoder::read_character_reference().

Developed in https://github.com/WordPress/wordpress-develop/pull/8945

Follow-up to [58281].

Props justlevine.
See #64238, #61072.

@westonruter commented on PR #8945:


7 months ago
#25

Committed in r61283 (e870c4a)

@westonruter commented on PR #8861:


7 months ago
#26

@justlevine I found that wp_create_category() was incorrectly saying that it could return WP_Error, when in fact it is supposed to always return an integer. In the case of failure, it returns zero, since wp_insert_category() isn't called with the $wp_error arg.

@westonruter commented on PR #8860:


7 months ago
#27

In trunk when I run:

phpstan analyze --memory-limit=2G --level=3 src/wp-admin/includes/class-wp-screen.php

I get:

Note: Using configuration file /Users/westonruter/repos/wordpress-develop/phpstan.neon.
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ ----------------------------------------------------------------------------------- 
  Line   class-wp-screen.php                                                                
 ------ ----------------------------------------------------------------------------------- 
  306    Variable $post_id might not be defined.                                            
         🪪  variable.undefined                                                             
         at src/wp-admin/includes/class-wp-screen.php:306                                   
  552    Method WP_Screen::get_option() should return string but returns null.              
         🪪  return.type                                                                    
         at src/wp-admin/includes/class-wp-screen.php:552                                   
  558    Method WP_Screen::get_option() should return string but returns null.              
         🪪  return.type                                                                    
         at src/wp-admin/includes/class-wp-screen.php:558                                   
  605    Method WP_Screen::get_help_tab() should return array but returns null.             
         🪪  return.type                                                                    
         at src/wp-admin/includes/class-wp-screen.php:605                                   
  740    Method WP_Screen::get_screen_reader_text() should return string but returns null.  
         🪪  return.type                                                                    
         at src/wp-admin/includes/class-wp-screen.php:740                                   
  953    Property WP_Screen::$columns (int) does not accept string.                         
         🪪  assign.propertyType                                                            
         at src/wp-admin/includes/class-wp-screen.php:953      

In this branch, the last five are eliminated.

@westonruter commented on PR #8865:


7 months ago
#28

I guess the bug here has never been noticed before because no where in core is the REST API used to set the featured image for an attachment?

We should add a unit test for this.

@westonruter commented on PR #8865:


7 months ago
#29

@justlevine ok, I found the issue, and I've fixed it in 720512a. The issue is that with fixing the $schema here, it's allowing handle_featured_media() to be called by \WP_REST_Attachments_Controller::update_item() when the this method is also calling parent::update_item() in which case it calls \WP_REST_Posts_Controller::update_item() which _also_ calls the handle_featured_media() method. The handle_featured_media() method wasn't accounting for the case where an attempt is made to update a featured media to be the same as the featured media currently set.

This appears to have been introduced in r57603 (54d72c5deee2c5cfa2dadef4409b7beb1cefea38) to fix Core-41692 (as noted above).

The idempotency issue is only noticed for updating attachments because it short-circuits with an error when handle_featured_media() returns false:

https://github.com/WordPress/wordpress-develop/blob/ba4d80d346eb2f71e1ccc122af466451759d84ba/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php#L224-L230

This doesn't happen when updating posts:

https://github.com/WordPress/wordpress-develop/blob/ba4d80d346eb2f71e1ccc122af466451759d84ba/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L817-L819

So while the tests have been fixed, it's clear that test coverage is not complete, because this code is never run:

https://github.com/WordPress/wordpress-develop/blob/ba4d80d346eb2f71e1ccc122af466451759d84ba/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php#L227-L229

So we need to make sure that the error scenario is tested.

@westonruter commented on PR #8865:


7 months ago
#30

So we need to make sure that the error scenario is tested.

OK, added in e6c6c68

@westonruter commented on PR #8865:


7 months ago
#31

Summarized in comment on original ticket: https://core.trac.wordpress.org/ticket/41692#comment:44

#32 @westonruter
7 months ago

In 61298:

Docs: Update typing for wp_create_category().

  • Ensure that wp_create_category() returns int as opposed to numeric-string.
  • Rename $cat_name to $category_name to avoid abbreviating variables.
  • Update docblock to remove erroneous int for $category_name param when only string is intended.
  • Add missing tests for wp_create_category().

Developed in https://github.com/WordPress/wordpress-develop/pull/8861

Props justlevine, westonruter.
See #64238, #64226.

@westonruter commented on PR #8861:


7 months ago
#33

Committed in r61298 (2cf0f3d)

#34 @westonruter
7 months ago

In 61299:

Docs: Update various class @var tags to indicate nullability.

This updates various @var tags on class properties to correctly indicate that the props may be null or unset:

  • WP_Dependencies::$all_queued_deps is nullable by both ::enqueue() and ::dequeue. Also, the types of the keys and values are specified.
  • WP_Duotone::$global_styles_presets and ::$global_styles_block_names start off unset and are only initialized by static classes.
  • WP_Query::init() and WP_Rewrite::init() are public methods that unset()s many class props.
  • WP_Theme::cache_delete() sets many props to null.

Developed in https://github.com/WordPress/wordpress-develop/pull/8953

Props justlevine, westonruter.
See #64238, #64224.

@westonruter commented on PR #8953:


7 months ago
#35

Committed in r61299 (0d33b5c)

#36 @westonruter
7 months ago

In 61300:

Docs: Improve docblocks and types for WP_Screen properties.

  • Correctly hint that WP_Screen::$_show_screen_options is null before being instantiated.
  • Correctly hint that ::get_option(), get_help_tab() and get_screen_reader_text() can return null.
  • Ensure $this->columns is an int, by casting $this->get_option( 'layout_columns', 'default' ) from its numeric string.

Developed in https://github.com/WordPress/wordpress-develop/pull/8860

Props justlevine, peterwilsoncc, westonruter.
See #64238, #64224.

@westonruter commented on PR #8860:


7 months ago
#37

Committed in r61300 (2898ab5).

#38 @westonruter
7 months ago

In 61303:

Coding Standards: Remove unreachable break statement after exit in switch.

This resolves static analysis warnings about an unreachable statement.

Developed in https://github.com/WordPress/wordpress-develop/pull/8956

Follow-up to [41131].

Props justlevine, johnbillion.
See #64238.

@westonruter commented on PR #8956:


7 months ago
#39

Committed in r61303 (6bea530)

This ticket was mentioned in PR #10607 on WordPress/wordpress-develop by @westonruter.


6 months ago
#40

Trac ticket: https://core.trac.wordpress.org/ticket/64238

Running this PHPStan command:

phpstan analyze --memory-limit=4G --level=8 src/wp-includes/class-wp-scripts.php src/wp-includes/class-wp-styles.php src/wp-includes/class-wp-dependencies.php src/wp-includes/class-wp-dependency.php

Results in the following report for trunk:

 ------ ------------------------------------------------------------------------------------------------------------ 
  Line   class-wp-dependencies.php                                                                                   
 ------ ------------------------------------------------------------------------------------------------------------ 
  65     Property WP_Dependencies::$args type has no value type specified in iterable type array.                    
         🪪  missingType.iterableValue                                                                               
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                  
         at src/wp-includes/class-wp-dependencies.php:65                                                             
  105    Property WP_Dependencies::$queued_before_register type has no value type specified in iterable type array.  
         🪪  missingType.iterableValue                                                                               
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                  
         at src/wp-includes/class-wp-dependencies.php:105                                                            
 ------ ------------------------------------------------------------------------------------------------------------ 

 ------ -------------------------------------------------------------------------------------------- 
  Line   class-wp-dependency.php                                                                     
 ------ -------------------------------------------------------------------------------------------- 
  71     Property _WP_Dependency::$extra type has no value type specified in iterable type array.    
         🪪  missingType.iterableValue                                                               
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type  
         at src/wp-includes/class-wp-dependency.php:71                                               
 ------ -------------------------------------------------------------------------------------------- 

 ------ -------------------------------------------------------------------------------------------------------- 
  Line   class-wp-scripts.php                                                                                    
 ------ -------------------------------------------------------------------------------------------------------- 
  51     Property WP_Scripts::$in_footer type has no value type specified in iterable type array.                
         🪪  missingType.iterableValue                                                                           
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type              
         at src/wp-includes/class-wp-scripts.php:51                                                              
  123    Property WP_Scripts::$default_dirs type has no value type specified in iterable type array.             
         🪪  missingType.iterableValue                                                                           
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type              
         at src/wp-includes/class-wp-scripts.php:123                                                             
  597    Method WP_Scripts::localize() has parameter $l10n with no value type specified in iterable type array.  
         🪪  missingType.iterableValue                                                                           
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type              
         at src/wp-includes/class-wp-scripts.php:597                                                             
  724    Property _WP_Dependency::$translations_path (string) in isset() is not nullable.                        
         🪪  isset.property                                                                                      
         at src/wp-includes/class-wp-scripts.php:724                                                             
 ------ -------------------------------------------------------------------------------------------------------- 

 ------ --------------------------------------------------------------------------------------------- 
  Line   class-wp-styles.php                                                                          
 ------ --------------------------------------------------------------------------------------------- 
  101    Property WP_Styles::$default_dirs type has no value type specified in iterable type array.   
         🪪  missingType.iterableValue                                                                
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type   
         at src/wp-includes/class-wp-styles.php:101                                                   
  186    Parameter #1 $src of method WP_Styles::in_default_dir() expects string, string|false given.  
         🪪  argument.type                                                                            
         at src/wp-includes/class-wp-styles.php:186                                                   
 ------ --------------------------------------------------------------------------------------------- 

 [ERROR] Found 9 errors                                                                                                 

With this PR, the issues are fixed.

#41 @westonruter
6 months ago

In 61358:

Docs: Improve accuracy for types in phpdoc for WP_Dependencies, _WP_Dependency, WP_Scripts, and WP_Styles.

This increases these classes to PHPStan level 8.

Developed in https://github.com/WordPress/wordpress-develop/pull/10607

See #64238.

@westonruter commented on PR #10607:


6 months ago
#42

Committed in r61358.

This ticket was mentioned in PR #10614 on WordPress/wordpress-develop by @westonruter.


6 months ago
#43

This addresses the following PHPStan level 6 issues:

 ------ --------------------------------------------------------------------------------------------------------------- 
  Line   class-wp-script-modules.php                                                                                    
 ------ --------------------------------------------------------------------------------------------------------------- 
  122    Method WP_Script_Modules::register() has parameter $args with no value type specified in iterable type array.       
         🪪  missingType.iterableValue                                                                                       
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                          
         at src/wp-includes/class-wp-script-modules.php:122                                                                  
  294    Method WP_Script_Modules::enqueue() has parameter $args with no value type specified in iterable type array.        
         🪪  missingType.iterableValue                                                                                       
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                          
         at src/wp-includes/class-wp-script-modules.php:294                                                                  
  540    Method WP_Script_Modules::get_import_map() return type has no value type specified in iterable type array.          
         🪪  missingType.iterableValue                                                                                       
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                          
         at src/wp-includes/class-wp-script-modules.php:540                                                                  
  561    Method WP_Script_Modules::get_marked_for_enqueue() return type has no value type specified in iterable type array.  
         🪪  missingType.iterableValue                                                                                       
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                          
         at src/wp-includes/class-wp-script-modules.php:561                                                                  
  582    Method WP_Script_Modules::get_dependencies() return type has no value type specified in iterable type array.        
         🪪  missingType.iterableValue                                                                                       
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                          
         at src/wp-includes/class-wp-script-modules.php:582   

Trac ticket: https://core.trac.wordpress.org/ticket/64238

#44 @westonruter
6 months ago

In 61362:

Docs: Improve specificity of types in WP_Script_Modules and script-modules.php functions.

Developed in https://github.com/WordPress/wordpress-develop/pull/10614

Follow-up to [61358].

See #64238.

@westonruter commented on PR #10614:


6 months ago
#45

Committed in r61362.

This ticket was mentioned in PR #10627 on WordPress/wordpress-develop by @westonruter.


6 months ago
#46

Trac ticket: https://core.trac.wordpress.org/ticket/64238

This fixes the following PHPStan issues:

 ------ -------------------------------------------------------------------------------------------------------- 
  Line   functions.wp-scripts.php                                                                                
 ------ -------------------------------------------------------------------------------------------------------- 
  144    Parameter #1 $string of function trim expects string, string|null given.                                
         🪪  argument.type                                                                                       
         at src/wp-includes/functions.wp-scripts.php:144                                                         
  181    Function wp_register_script() has parameter $args with no value type specified in iterable type array.  
         🪪  missingType.iterableValue                                                                           
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type              
         at src/wp-includes/functions.wp-scripts.php:181                                                         
  230    Function wp_localize_script() has parameter $l10n with no value type specified in iterable type array.  
         🪪  missingType.iterableValue                                                                           
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type              
         at src/wp-includes/functions.wp-scripts.php:230                                                         
  366    Function wp_enqueue_script() has parameter $args with no value type specified in iterable type array.   
         🪪  missingType.iterableValue                                                                           
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type              
         at src/wp-includes/functions.wp-scripts.php:366                                                         
 ------ -------------------------------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------------------------------------------------ 
  Line   functions.wp-styles.php                                                                                                             
 ------ ------------------------------------------------------------------------------------------------------------------------------------ 
  44     Function wp_print_styles() has parameter $handles with no value type specified in iterable type array.                              
         🪪  missingType.iterableValue                                                                                                       
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                          
         at src/wp-includes/functions.wp-styles.php:44                                                                                       
  68     Parameter #1 $handles of method WP_Dependencies::do_items() expects array<string>|string|false, array|bool|non-empty-string given.  
         🪪  argument.type                                                                                                                   
         at src/wp-includes/functions.wp-styles.php:68                                                                                       
  101    Parameter #1 $string of function trim expects string, string|null given.                                                            
         🪪  argument.type                                                                                                                   
         at src/wp-includes/functions.wp-styles.php:101                                                                                      
 ------ ------------------------------------------------------------------------------------------------------------------------------------ 

 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
  Line   script-loader.php                                                                                                                                                             
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
  133    Offset                                                                                                                                                                        
         0|1|2|3|4|5|6|7|8|9|10|11|12|'lodash'|'moment'|'react'|'react-dom'|'react-jsx-runtime'|'regenerator-runtime'|'wp-polyfill'|'wp-polyfill-dom-rect'|'wp-polyfill-element…'|'wp  
         -polyfill-fetch'|'wp-polyfill-formdata'|'wp-polyfill-inert'|'wp-polyfill-node…'|'wp-polyfill-object…'|'wp-polyfill-url' might not exist on array{react: '18.3.1.1',           
         react-dom: '18.3.1.1', react-jsx-runtime: '18.3.1', regenerator-runtime: '0.14.1', moment: '2.30.1', lodash: '4.17.21', wp-polyfill-fetch: '3.6.20', wp-polyfill-formdata:    
         '4.0.10', ...}.                                                                                                                                                               
         🪪  offsetAccess.notFound                                                                                                                                                     
         at src/wp-includes/script-loader.php:133                                                                                                                                      
  135    Parameter #1 $handle of method WP_Dependencies::add() expects string, int|string given.                                                                                       
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:135                                                                                                                                      
  191    Parameter #1 $haystack of function str_starts_with expects string, string|false given.                                                                                        
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:191                                                                                                                                      
  191    Parameter #2 $subject of function preg_match expects string, string|false given.                                                                                              
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:191                                                                                                                                      
  700    Variable $wp_version might not be defined.                                                                                                                                    
         🪪  variable.undefined                                                                                                                                                        
         at src/wp-includes/script-loader.php:700                                                                                                                                      
  1089   Parameter #1 $string of function strtolower expects string, string|false given.                                                                                               
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:1089                                                                                                                                     
  1564   Variable $wp_version might not be defined.                                                                                                                                    
         🪪  variable.undefined                                                                                                                                                        
         at src/wp-includes/script-loader.php:1564                                                                                                                                     
  1608   Parameter #2 $src of method WP_Dependencies::add() expects string|false, true given.                                                                                          
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:1608                                                                                                                                     
  1907   Parameter #2 $offset of function array_splice expects int, int|string given.                                                                                                  
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:1907                                                                                                                                     
  2083   Function wp_style_loader_src() should return string|false but returns string|null.                                                                                            
         🪪  return.type                                                                                                                                                               
         at src/wp-includes/script-loader.php:2083                                                                                                                                     
  2357   Function print_late_styles() return type has no value type specified in iterable type array.                                                                                  
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2357                                                                                                                                     
  2514   Function wp_filter_out_block_nodes() has parameter $nodes with no value type specified in iterable type array.                                                                
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2514                                                                                                                                     
  2514   Function wp_filter_out_block_nodes() return type has no value type specified in iterable type array.                                                                          
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2514                                                                                                                                     
  2875   Function wp_sanitize_script_attributes() has parameter $attributes with no value type specified in iterable type array.                                                       
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2875                                                                                                                                     
  2907   Function wp_get_script_tag() has parameter $attributes with no value type specified in iterable type array.                                                                   
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2907                                                                                                                                     
  2939   Function wp_print_script_tag() has parameter $attributes with no value type specified in iterable type array.                                                                 
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2939                                                                                                                                     
  2955   Function wp_get_inline_script_tag() has parameter $attributes with no value type specified in iterable type array.                                                            
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:2955                                                                                                                                     
  3043   Function wp_print_inline_script_tag() has parameter $attributes with no value type specified in iterable type array.                                                          
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:3043                                                                                                                                     
  3081   Call to an undefined method object::get_data().                                                                                                                               
         🪪  method.notFound                                                                                                                                                           
         at src/wp-includes/script-loader.php:3081                                                                                                                                     
  3099   Parameter #1 $array of function usort contains unresolvable type.                                                                                                             
         🪪  argument.unresolvableType                                                                                                                                                 
         at src/wp-includes/script-loader.php:3099                                                                                                                                     
  3100   Parameter #2 $callback of function usort contains unresolvable type.                                                                                                          
         🪪  argument.unresolvableType                                                                                                                                                 
         at src/wp-includes/script-loader.php:3100                                                                                                                                     
  3128   Parameter #1 $css of function _wp_normalize_relative_css_links expects string, string|false given.                                                                            
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:3128                                                                                                                                     
  3158   Function _wp_normalize_relative_css_links() should return string but returns string|null.                                                                                     
         🪪  return.type                                                                                                                                                               
         at src/wp-includes/script-loader.php:3158                                                                                                                                     
  3244   Function wp_enqueue_stored_styles() has parameter $options with no value type specified in iterable type array.                                                               
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:3244                                                                                                                                     
  3318   Function wp_enqueue_block_style() has parameter $args with no value type specified in iterable type array.                                                                    
         🪪  missingType.iterableValue                                                                                                                                                 
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type                                                                                    
         at src/wp-includes/script-loader.php:3318                                                                                                                                     
  3756   Parameter #3 $priority of function remove_action expects int, int|true given.                                                                                                 
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:3756                                                                                                                                     
  3763   Parameter #3 $priority of function add_action expects int, int|true given.                                                                                                    
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:3763                                                                                                                                     
  3846   Parameter #1 $text of method WP_HTML_Tag_Processor@anonymous/script-loader.php:3773::insert_after() expects string, string|false given.                                       
         🪪  argument.type                                                                                                                                                             
         at src/wp-includes/script-loader.php:3846                                                                                                                                     
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 

 [ERROR] Found 35 errors                                                                                                

#47 @westonruter
6 months ago

In 61397:

Script Loader: Fix adding default version to script/style URL when args are supplied via enqueued handle.

Also fixes phpdoc for some member variables of WP_Scripts and WP_Styles.

Developed in https://github.com/WordPress/wordpress-develop/pull/10608

Follow-up to [61358].

Props westonruter, peterwilsoncc.
See #64224, #64238.
Fixes #64372.

This ticket was mentioned in PR #10652 on WordPress/wordpress-develop by @westonruter.


6 months ago
#48

This PR addresses the following issues PHPStan level 8 issues:

phpstan analyze --memory-limit=4G --level=8 src/wp-includes/functions.wp-styles.php src/wp-includes/functions.wp-scripts.php

Before:

Note: Using configuration file /Users/westonruter/repos/wordpress-develop/phpstan.neon.
 2/2 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ --------------------------------------------------------------------------------------------------------
  Line   functions.wp-scripts.php
 ------ --------------------------------------------------------------------------------------------------------
  144    Parameter #1 $string of function trim expects string, string|null given.
         🪪  argument.type
  181    Function wp_register_script() has parameter $args with no value type specified in iterable type array.
         🪪  missingType.iterableValue
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type
  230    Function wp_localize_script() has parameter $l10n with no value type specified in iterable type array.
         🪪  missingType.iterableValue
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type
  366    Function wp_enqueue_script() has parameter $args with no value type specified in iterable type array.
         🪪  missingType.iterableValue
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type
 ------ --------------------------------------------------------------------------------------------------------

 ------ ------------------------------------------------------------------------------------------------------------------------------------
  Line   functions.wp-styles.php
 ------ ------------------------------------------------------------------------------------------------------------------------------------
  44     Function wp_print_styles() has parameter $handles with no value type specified in iterable type array.
         🪪  missingType.iterableValue
         💡  See: https://phpstan.org/blog/solving-phpstan-no-value-type-specified-in-iterable-type
  68     Parameter #1 $handles of method WP_Dependencies::do_items() expects array<string>|string|false, array|bool|non-empty-string given.
         🪪  argument.type
  101    Parameter #1 $string of function trim expects string, string|null given.
         🪪  argument.type
 ------ ------------------------------------------------------------------------------------------------------------------------------------

After:

[OK] No errors

Trac ticket: https://core.trac.wordpress.org/ticket/64238

#49 @westonruter
6 months ago

In 61402:

Docs: Improve specificity of PHP types in functions.wp-scripts.php and functions.wp-styles.php.

These files now adhere to PHPStan level 8.

Developed in https://github.com/WordPress/wordpress-develop/pull/10652

Follow-up to [61362], [61358].

See #64238.

@westonruter commented on PR #10652:


6 months ago
#50

Committed in r61402

#51 @westonruter
5 months ago

In 61425:

Script Loader: Simplify data structure in wp_default_packages_vendor() to facilitate static analysis.

This resolves two PHPStan level 7 issues: offsetAccess.notFound and argument.type.

Follow-up to [44114].

See #64238, #45065.

#52 @westonruter
5 months ago

In 61426:

Script Loader: Add types for arrays in phpdoc.

This resolves 10 missingType.iterableValue issues in PHPStan.

Follow-up to [61402], [61362], [61358].

See #64224, #64238.

This ticket was mentioned in Slack in #core by mukeshpanchal27. View the logs.


4 months ago

#54 @westonruter
4 months ago

In 61642:

Code Quality: Remove unused WP_Block_Bindings_Registry::$supported_blocks private member variable.

Developed in https://github.com/WordPress/wordpress-develop/pull/10912

Follow-up to [59080], [57641].

Props soean.
See #64238, #61642.
Fixes #64633.

This ticket was mentioned in PR #10951 on WordPress/wordpress-develop by @westonruter.


4 months ago
#55

The commits in this PR were cherry-picked from https://github.com/WordPress/wordpress-develop/pull/10419 for Core-61175.

Trac ticket: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools

n/a

@westonruter commented on PR #10951:


4 months ago
#56

@sabernhardt Would you review when you get a chance?

This ticket was mentioned in PR #10952 on WordPress/wordpress-develop by @westonruter.


4 months ago
#57

The changes in this PR were cherry-picked (e.g. 2f724070eca10d8503c6453732cbc9131d7da010 and 22370b6a9783ed0bd56c9b1b731617b8b9cedcbf) from https://github.com/WordPress/wordpress-develop/pull/10419 for Core-61175.

Trac ticket: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools

n/a

This ticket was mentioned in PR #10953 on WordPress/wordpress-develop by @westonruter.


4 months ago
#58

The commits in this PR were cherry-picked from https://github.com/WordPress/wordpress-develop/pull/10419 for Core-61175.

See https://github.com/WordPress/wordpress-develop/pull/10419#issuecomment-3911582777:

I also got to the bottom of the issue with wp_insert_user() causing PHPStan to hang. Or at least, I think I did. The issue is that PHPStan couldn't figure out what $userdata's type was. So in 77d9403...512e368 I've ensured that $userdata always is a string, and I went the extra mile to ensure back-compat for passing in unexpected values to that function.

Trac ticket: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools

n/a

@westonruter commented on PR #10953:


4 months ago
#59

@peterwilsoncc Hey! I'm requesting your review because this appears to have been related to your commit in r60650.

@westonruter commented on PR #10953:


4 months ago
#60

@peterwilsoncc thank you. My guess is that 99.99999% of the time, a array|stdClass|WP_User is passed in. But I can imagine someone wanting to pass in an array-like object for the sake of lazy-loading. So I wanted to be sure this didn't break anything.

It's also true that PHPStan probably shouldn't be struggling so hard here. But I still think this is an overall improvement since it improves type safety, ensuring that down the road the function is guaranteed to always be working with an array as it expects to be.

@westonruter commented on PR #10952:


4 months ago
#61

@justlevine Would you give this a review for me?

#62 @westonruter
4 months ago

In 61656:

Users: Ensure user data supplied to wp_insert_user() is normalized to an array.

This fixes an issue where PHPStan hangs when analyzing the containing users.php file.

Developed in https://github.com/WordPress/wordpress-develop/pull/10953

Follow-up to [60650].

Props westonruter, justlevine, peterwilsoncc.
See #64238, #61175.

@westonruter commented on PR #10953:


4 months ago
#63

Committed in r61656 (297771e887699386de70ed087147c2bf3b42bd28).

@westonruter commented on PR #10951:


4 months ago
#64

@sabernhardt anything else you'd like revised?

#65 @westonruter
4 months ago

In 61670:

Customize: Ensure WP_Customize_Setting::update() and subclass overrides return consistent types.

This addresses PHPStan type check issues.

Developed in https://github.com/WordPress/wordpress-develop/pull/10952

Props westonruter, peterwilsoncc, justlevine.
See #64238, #61175.

@westonruter commented on PR #10952:


4 months ago
#66

Committed in r61670 (ff7564a)

#67 @westonruter
4 months ago

Once #61175 is closed with PHPStan support in core, we should follow up with the following change for is_wp_error():

  • src/wp-includes/load.php

    a b function wp_doing_cron() { 
    17961796 *
    17971797 * @since 2.1.0
    17981798 *
     1799 * @phpstan-assert-if-true WP_Error $thing
     1800 *
    17991801 * @param mixed $thing The variable to check.
    18001802 * @return bool Whether the variable is an instance of WP_Error.
    18011803 */

This ensures conditionals are understood correctly by PHPStan. For example, it fixes an error in this function:

<?php
function wp_remote_retrieve_headers( $response ) {
        if ( is_wp_error( $response ) || ! isset( $response['headers'] ) ) {
                return array();
        }

        return $response['headers'];
}

phpstan: Cannot access offset 'headers' on array|WP_Error.

@sabernhardt commented on PR #10951:


4 months ago
#68

I have nothing further.

#69 @westonruter
4 months ago

In 61676:

Themes: Fix type issues in core themes and remove PHPStan suppression comments.

Developed in https://github.com/WordPress/wordpress-develop/pull/10951

Props westonruter, sabernhardt, justlevine.
See #64238, #61175.

@westonruter commented on PR #10951:


4 months ago
#70

Committed in r61676 (265fbb4c71e5d07ce26ae051d55601e94626cc1f)

#71 @westonruter
4 months ago

Another patch we should land to improve static analysis:

  • src/wp-includes/comment.php

    diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php
    index 70d78ed33c..5951b1906c 100644
    a b function get_approved_comments( $post_id, $args = array() ) { 
    217217 *                                       correspond to a WP_Comment object, an associative array, or a numeric array,
    218218 *                                       respectively. Default OBJECT.
    219219 * @return WP_Comment|array|null Depends on $output value.
     220 * @phpstan-return (
     221 *     $output is 'ARRAY_A' ? non-empty-array<string, mixed>
     222 *                          : ( $output is 'ARRAY_N' ? non-empty-array<int, mixed>
     223 *                                                   : WP_Comment|null ) )
    220224 */
    221225function get_comment( $comment = null, $output = OBJECT ) {
    222226        if ( empty( $comment ) && isset( $GLOBALS['comment'] ) ) {
  • src/wp-includes/post.php

    diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php
    index 1b36ad58fc..50130770a3 100644
    a b function get_post_type_object( $post_type ) { 
    16401640 *                               element from the array needs to match; 'and' means all elements
    16411641 *                               must match; 'not' means no elements may match. Default 'and'.
    16421642 * @return string[]|WP_Post_Type[] An array of post type names or objects.
     1643 * @phpstan-return ( $output is 'names' ? string[] : WP_Post_Type[] )
    16431644 */
    16441645function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) {
    16451646        global $wp_post_types;

That first change is for get_comment() and a similar change could be made for get_post().

#72 @westonruter
4 months ago

In 61699:

Build/Test Tools: Integrate PHPStan into the core development workflow.

This change introduces PHPStan static analysis configured at rule level 0, which includes: "basic checks, unknown classes, unknown functions, unknown methods called on $this, wrong number of arguments passed to those methods and functions, always undefined variables". Contributors may elect for a higher PHPStan rule level by creating a phpstan.neon which overrides phpstan.neon.dist.

  • Fix various PHPStan level 0 errors by adding @phpstan-ignore comments, updating PHPDoc types, and adding missing return values.
  • Remove existing @phpstan-ignore comments that are now obsolete or inapplicable for level 0.
  • Add a new GitHub Actions workflow for PHPStan Static Analysis. Reports are currently provided as warnings with inline annotations in pull requests and do not fail the build.
  • Add a phpstan Grunt task and include it in the precommit:php task to run before phpunit.
  • Introduce a typecheck:php npm script and a composer phpstan script to run analysis in local development environments.
  • Add documentation for PHPStan usage in tests/phpstan/README.md.

Developed in https://github.com/WordPress/wordpress-develop/pull/10419

Props justlevine, westonruter, johnbillion, desrosj, SirLouen, dmsnell, oglekler, joehoyle, jorbin.
See #64238, #63268, #52217, #51423.
Fixes #61175.

@westonruter commented on PR #8864:


4 months ago
#73

This was _not_ committed yet.

@westonruter commented on PR #8865:


4 months ago
#74

This was _not_ committed yet.

This ticket was mentioned in PR #10995 on WordPress/wordpress-develop by @huzaifaalmesbah.


4 months ago
#75

The @return tags for these functions indicate they may return null.
This fixes "Missing return argument" warnings that PHPStan (level 1) and IDEs report when a bare return; is used in a function documented to return a typed value including null.

## Affected Functions and Files

  • WP_Filesystem() in wp-admin/includes/file.php
  • delete_plugins() in wp-admin/includes/plugin.php (2 occurrences)
  • delete_theme() in wp-admin/includes/theme.php (2 occurrences)
  • get_category_by_path() in wp-includes/category.php

## Details

In each case, the function's @return tag already documents null as a possible return value (e.g. @return bool|null|WP_Error), but the early exit paths used a bare return;, which implicitly returns void.

Related: Trac #64238

@noruzzaman commented on PR #10995:


4 months ago
#77

LGTM

@westonruter commented on PR #10995:


4 months ago
#78

Note: These fix PHPStan rule level 3 issues.

#79 @westonruter
4 months ago

In 61716:

Code Quality: Explicitly return null when documented instead of void.

This fixes a PHPStan rule level 3 error: return.empty.

Developed in https://github.com/WordPress/wordpress-develop/pull/10995

Props huzaifaalmesbah, westonruter, shailu25, mukesh27, noruzzaman.
See #64238.

@westonruter commented on PR #10995:


4 months ago
#80

Committed in r61716 (954c187)

#81 @westonruter
4 months ago

In 61719:

Code Quality: Return null instead of void in paginate_links().

Developed in https://github.com/WordPress/wordpress-develop/pull/10999

Follow-up to r32598.

Props apermo, mukesh27, westonruter
See #64238.
Fixes #64694.

This ticket was mentioned in PR #11014 on WordPress/wordpress-develop by @huzaifaalmesbah.


4 months ago
#82

This fixes a few PHPStan "variable might not be defined" warnings..
Changes:

  • src/wp-admin/includes/menu.php: Added the global declaration for $menu, $submenu, and $compat.
  • src/wp-admin/includes/network.php: Initialized the $message and $message_class variables to prevent them from being undefined when the condition isn't met.

Trac: https://core.trac.wordpress.org/ticket/64238

This ticket was mentioned in PR #11017 on WordPress/wordpress-develop by @huzaifaalmesbah.


4 months ago
#83

This PR addresses strict type return.empty violations reported by PHPStan, ensuring methods return their declared or documented types rather than relying on an empty return;.

Details

  • src/wp-includes/class-wp-query.php (WP_Query::setup_postdata):
    • Updated the PHPDoc to reflect that the method can return both true (success) and false (failure).
    • Replaced the early empty return; bail-outs with return false; when the post object is invalid or when generate_postdata() fails.
  • src/wp-includes/theme.php (_remove_theme_support):
    • Replaced an empty return; inside the custom-header-uploads backward compatibility fallback with return true;. This matches the documented bool return type to indicate the feature support was successfully removed.
    Why this is needed

Using empty return; statements in methods/functions that have a declared or documented non-void return type causes static analysis tooling (like PHPStan) to flag them as errors. Returning explicit boolean values improves strict typing constraints and code clarity.

Trac ticket: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools
Use For PR Content.

#84 @SergeyBiryukov
3 months ago

In 61721:

Code Quality: Correct return statement in _remove_theme_support().

This matches the documented bool return type to indicate the feature support was successfully removed.

Follow-up to [20212].

Props huzaifaalmesbah.
See #64238.

#85 @SergeyBiryukov
3 months ago

In 61727:

Code Quality: Correct return statement in WP_Query::setup_postdata().

This reflects that the method can return both true (success) and false (failure).

Follow-up to [32620], [34089], [44941].

Props huzaifaalmesbah, westonruter.
See #64238.

@SergeyBiryukov commented on PR #11017:


3 months ago
#86

Thanks for the PR! Merged in r61721 and r61727.

#87 @SergeyBiryukov
3 months ago

In 61753:

Code Quality: Initialize $message and $message_class in network_step1().

This prevents the variables from being undefined when the condition isn't met.

Follow-up to [56599].

Props huzaifaalmesbah, noruzzaman.
See #64238.

#88 @westonruter
3 months ago

In 61766:

Code Quality: Replace void with null in union return types in link-template.php.

Developed in https://github.com/WordPress/wordpress-develop/pull/11004

Follow-up to r61719, r61716, r32598.

Props apermo, xate, westonruter, noruzzaman.
See #64694, #64238.
Fixes #64699.

#89 @westonruter
3 months ago

In 61767:

Code Quality: Replace void with null in union return types in Customizer classes.

Developed in https://github.com/WordPress/wordpress-develop/pull/11006

Follow-up to r61766, r61719, r61716.

Props apermo, xate, mukesh27.
See #64238.
Fixes #64701.

#90 @westonruter
3 months ago

In 61768:

Code Quality: Replace void with null in union return types in general-template.php.

Developed in https://github.com/WordPress/wordpress-develop/pull/11005

Follow-up to r61767, r61766, r61719, r61716, r53300, r32598.

Props apermo, xate, mukesh27.
See #64238.
Fixes #64700.

This ticket was mentioned in PR #11095 on WordPress/wordpress-develop by @westonruter.


3 months ago
#91

This reduces the number of PHPStan errors at level 7 from 14,271 to 13,233 (-1,038 or -7.27%). See error report diff.

Trac ticket: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools

n/a

#92 @westonruter
3 months ago

In 61774:

Code Quality: Add @phpstan-assert-if-true to is_wp_error().

This ensures PHPStan is aware that passing a WP_Error instance to is_wp_error() will cause the function to return true. This reduces the total number of PHPStan errors at rule level 7 from 14,271 to 13,233 (-1,038 or -7.27%).

Developed in https://github.com/WordPress/wordpress-develop/pull/11095

See #64238.

@westonruter commented on PR #11095:


3 months ago
#93

Committed in r61774 (b00dde1)

This ticket was mentioned in PR #11096 on WordPress/wordpress-develop by @westonruter.


3 months ago
#94

Trac ticket: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools

n/a

#95 @rahultank
3 months ago

Reviewed ticket #64238 — PHPStan code quality improvements for WP 7.0 (March 2026).

This is a tracked aggregate ticket for PHPStan-surfaced issues. It has 30+ commits already merged. Reviewed scope of remaining work:

  • The ticket targets various type safety issues, null handling, and union type corrections across Core files
  • PHPStan analysis surfaced issues in: taxonomy, screen handling, REST API, and general WordPress functions
  • Unit tests are included with each fix (has-unit-tests keyword)

Latest PR: https://github.com/WordPress/wordpress-develop/pull/11096
PR scope:

Code quality improvements of this kind reduce PHP 8.x deprecation notices and improve static analysis confidence. The pattern of changes (fixing void return types, null coalescing, and union return types) is consistent across all sub-fixes.

This approach aligns with the PHP 8.5 compatibility goals also tracked for 7.0. Confirming the pattern of fixes is sound and follows WordPress coding standards.

Last edited 3 months ago by rahultank (previous) (diff)

#96 @westonruter
3 months ago

In 61789:

Code Quality: Normalize object as type being supplied as comment, post, site, term, and user.

When constructing these objects, the specific instance type is redundantly used in a union with a generic object. A generic object can be passed directly from database row result. This also hardens get_post() to account for passing an object that lacks an ID property. Similarly, sanitize_term() is hardened to account for an object lacking a term_id property. Comprehensive unit tests are added for get_post() and sanitize_term().

Developed in https://github.com/WordPress/wordpress-develop/pull/11096

Props westonruter, apermo.
See #64238, #64225.

@westonruter commented on PR #11096:


3 months ago
#97

Committed in r61789 (f997e86)

#98 @SergeyBiryukov
3 months ago

In 61853:

Code Quality: Explicitly globalize admin menu variables to avoid PHPStan warnings.

Follow-up to [15481].

Props huzaifaalmesbah, noruzzaman.
See #64238.

@SergeyBiryukov commented on PR #11014:


3 months ago
#99

Thanks for the PR! Merged in r61753 and r61853.

This ticket was mentioned in PR #11189 on WordPress/wordpress-develop by @huzaifaalmesbah.


3 months ago
#100

## Summary

Fixes PHPStan level 3 errors for undefined variables in:

  • wp-admin/comment.php - Added @global int $comment_id PHPDoc
  • wp-settings.php - Added @global array $wp_filter and @global string $table_prefix PHPDoc

## Testing

  • Run ./vendor/bin/phpstan analyse --level=3 src/wp-admin/comment.php src/wp-settings.php
  • Before: 6 errors
  • After: 0 errors

Trac: https://core.trac.wordpress.org/ticket/64238

## Use of AI Tools
Used AI tools for research and assistance in preparing the commit.

@westonruter commented on PR #11189:


3 months ago
#101

Thanks for the PR. Are these issues only at level 3 or do they also occur at level 1? I have https://github.com/WordPress/wordpress-develop/pull/11151 as well which is for fixing issues at rule level 1. I wonder if we could consolidate fixes rather than fix them one-by-one which will add a lot of overhead for committing.

@westonruter commented on PR #11189:


3 months ago
#102

I've updated https://github.com/WordPress/wordpress-develop/pull/11151 to now use an allow-list for unknown globals. This PR _almost_ allows us to eliminate the three variables referenced in this PR.

@huzaifaalmesbah commented on PR #11189:


3 months ago
#103

I've updated #11151 to now use an allow-list for unknown globals. This PR _almost_ allows us to eliminate the three variables referenced in that PR.

@westonruter Sounds good. should I close this as redundant since #11151 already handles these via baseline, or would you like me to also fix $table_prefix in wp-includes/ms-settings.php?

#104 @SergeyBiryukov
3 months ago

In 61859:

Code Quality: Make sure $comment_id is defined in wp-admin/comment.php.

This avoids a variable.undefined warning at PHPStan level 3.

Follow-up to [48958].

Props huzaifaalmesbah, westonruter, SergeyBiryukov.
See #64238.

@westonruter commented on PR #11189:


3 months ago
#105

It seems @SergeyBiryukov found an alternative fix for the issue with $comment_id in r61859 (ce40cd363aac41babfc1456fc24be67206738b00).

So if you want to revert your change to src/wp-admin/comment.php and then follow up with fixing wp-includes/ms-settings.php, then we can commit this PR.

@huzaifaalmesbah commented on PR #11189:


3 months ago
#106

@westonruter Thank you for the thorough review and the detailed suggestions!
I've updated both files to remove the @global declarations and applied your suggestions .
PHPStan level 3 passes locally with zero errors!

This ticket was mentioned in PR #11206 on WordPress/wordpress-develop by @huzaifaalmesbah.


3 months ago
#107

## Description
Fixes type casting issues found by PHPStan:

  • admin-header.php: Change (float) to (string) cast for version to preserve full format (e.g., "7.0-beta3")
  • customize.php: Add (string) cast for $active in aria-pressed attribute

## Trac Ticket
https://core.trac.wordpress.org/ticket/64238

## Testing

  1. Admin body class shows full version (e.g., branch-7-0-beta3)
  2. Customizer device buttons have proper aria-pressed string values

@apermo commented on PR #11206:


3 months ago
#108

One issue here is that admin-header.php is 15+ year old spaghetti code. Maybe it should be considered to modernize the file. Due to the nature of the file, this can't be unit tested. A function wp_get_admin_body_class() that wrapps all the logic would allow proper unit testing here.

cc @westonruter

@westonruter commented on PR #11206:


3 months ago
#109

One issue here is that admin-header.php is 15+ year old spaghetti code. Maybe it should be considered to modernize the file. Due to the nature of the file, this can't be unit tested. A function wp_get_admin_body_class() that wrapps all the logic would allow proper unit testing here.

Yeah, we should avoid refactoring this file or making substantial logic changes. If we do end up doing a deeper admin redesign, this would be part of that effort. But otherwise, we should avoid making changes unless we absolutely have to due to the extreme legacy nature and potential for back-compat breakage.

@westonruter commented on PR #11206:


3 months ago
#110

Fixes type casting issues found by PHPStan:

@huzaifaalmesbah How did you identify these two files alone to be included in this PR? Were they the only files with type casting issues, or what?

@siliconforks commented on PR #11189:


3 months ago
#111

Is it really a good idea to insert additional if statements (for conditions which can never happen in practice) just to make PHPStan be quiet? That will make the code more complicated and increase the cyclomatic complexity for no reason other than just to keep the tool happy...

I'm not an expert in PHPStan, but I'm wondering if there's a better way to do this? Could assert() perhaps be used here?

@westonruter commented on PR #11189:


3 months ago
#112

@siliconforks That would also address the PHPStan errors. So instead of wrapping logic in if ( isset( $wpdb ) ){} and if ( isset( $table_prefix ) ) {} the following two lines could be added instead:

assert( isset( $wpdb ) );
assert( isset( $table_prefix ) );

Core doesn't use assert() statements except in third-party libraries, however. But that doesn't mean we can't start to use them.

@huzaifaalmesbah commented on PR #11206:


3 months ago
#113

@huzaifaalmesbah How did you identify these two files alone to be included in this PR? Were they the only files with type casting issues, or what?

@westonruter I ran PHPStan at level 5:

  • Level 5: Found 2 errors
  1. admin-header.php:194 - str_replace() expects string but gets float from (float) get_bloginfo('version')
  2. customize.php:291 - esc_attr() expects string but gets bool from $active

These were the type casting issues I identified for this PR.

#114 @westonruter
3 months ago

In 62028:

Cache API: Address code quality issues with wp_cache_switch_to_blog().

This addresses 3 PHPStan errors at rule level 8:

  • arguments.count: Function wp_cache_switch_to_blog_fallback() invoked with 1 parameter, 0 required.
  • method.nonObject: Cannot call method switch_to_blog() on class-string|object.
  • missingType.return: Function wp_cache_switch_to_blog() has no return type specified.

Developed as subset of https://github.com/WordPress/wordpress-develop/pull/11151

Follow-up to r61760.

Props westonruter, johnjamesjacoby.
See #23290, #64238.

#115 @desrosj
3 months ago

  • Resolution set to fixed
  • Status changed from new to closed

Opened #64898 for the 7.1 release cycle. With 7.0 RC1 due out today, going to close this out. This can be reopened or referenced if there are more changes needed related to this during 7.0.

This ticket was mentioned in PR #11302 on WordPress/wordpress-develop by @Soean.


3 months ago
#116

This pull request makes a small change to the check_import_new_users function, simplifying its logic to directly return the result of the permission check.

Trac ticket: https://core.trac.wordpress.org/ticket/64238

#117 @SergeyBiryukov
3 months ago

In 62086:

Code Quality: Simplify user permission check for importing new users.

This removes a redundant conditional in the check_import_new_users() function, simplifying its logic to directly return the result of the permission check.

Follow-up to mu:1829, [39945].

Props Soean.
See #64238.

@SergeyBiryukov commented on PR #11302:


3 months ago
#118

Thanks for the PR! Merged in r62086.

This ticket was mentioned in PR #11329 on WordPress/wordpress-develop by @Soean.


3 months ago
#119

We don't need to initialize $post_counts as an empty array, since it will be overwritten directly by the filter value in line 502

Trac ticket: https://core.trac.wordpress.org/ticket/64238

#120 @SergeyBiryukov
3 months ago

In 62091:

Code Quality: Remove redundant variable assignment in wp_list_authors().

There is no need to initialize $post_counts as an empty array, since it will be overwritten directly by the filter value in the next line.

Follow-up to [54262].

Props Soean.
See #64238.

@SergeyBiryukov commented on PR #11329:


3 months ago
#121

Thanks for the PR! Merged in r62091.

#122 @westonruter
3 months ago

To be continued in #64898.

#123 @westonruter
6 weeks ago

In 62278:

I18N: Add translation support for script modules.

Add automatic translation loading for script modules (ES modules), so strings using __() and friends from @wordpress/i18n can be translated at runtime. This brings classic script i18n parity to script modules registered via wp_register_script_module(), which previously had no way to load translation data, leaving strings untranslated on screens like Connectors and Fonts that are built as script modules.

At the admin_print_footer_scripts and wp_footer actions, every enqueued script module and its dependencies are walked, the translation chunk is loaded for each, and an inline <script> calls wp.i18n.setLocaleData() so translations are available before deferred modules execute. Note there is currently a runtime dependency on the wp-i18n classic script, which is printed just-in-time if not already enqueued. This coupling is to be removed in a future release.

Public API:

  • WP_Script_Modules::set_translations() stores the text domain (and optional path) per registered module to override the text domain and path. A global wp_set_script_module_translations() function is added as a wrapper around wp_script_modules()->set_translations().
  • WP_Script_Modules::get_registered() obtains a registered module's data. See #60597.
  • WP_Script_Modules::print_script_module_translations() emits inline wp.i18n.setLocaleData() calls after classic scripts load but before modules execute.
  • load_script_module_textdomain() loads the translation data for a given script module ID and text domain.
  • The existing load_script_textdomain_relative_path filter gains a third $is_module parameter so callers can distinguish classic-script and script-module lookups when resolving translation paths.

PHPStan types are also added in WP_Script_Modules. See #64238.

Developed in https://github.com/WordPress/wordpress-develop/pull/11543

Props manzoorwanijk, westonruter, jsnajdr, jonsurrell, mukesh27, peterwilsoncc, 369work, desrosj, sabernhardt, nilambar, jorgefilipecosta, malayladu.
See #64238, #60597.
Fixes #65015.

#124 @peterwilsoncc
6 weeks ago

In 62286:

I18N: Add translation support for script modules.

Add automatic translation loading for script modules (ES modules), so strings using __() and friends from @wordpress/i18n can be translated at runtime. This brings classic script i18n parity to script modules registered via wp_register_script_module(), which previously had no way to load translation data, leaving strings untranslated on screens like Connectors and Fonts that are built as script modules.

At the admin_print_footer_scripts and wp_footer actions, every enqueued script module and its dependencies are walked, the translation chunk is loaded for each, and an inline <script> calls wp.i18n.setLocaleData() so translations are available before deferred modules execute. Note there is currently a runtime dependency on the wp-i18n classic script, which is printed just-in-time if not already enqueued. This coupling is to be removed in a future release.

Public API:

  • WP_Script_Modules::set_translations() stores the text domain (and optional path) per registered module to override the text domain and path. A global wp_set_script_module_translations() function is added as a wrapper around wp_script_modules()->set_translations().
  • WP_Script_Modules::get_registered() obtains a registered module's data. See #60597.
  • WP_Script_Modules::print_script_module_translations() emits inline wp.i18n.setLocaleData() calls after classic scripts load but before modules execute.
  • load_script_module_textdomain() loads the translation data for a given script module ID and text domain.
  • The existing load_script_textdomain_relative_path filter gains a third $is_module parameter so callers can distinguish classic-script and script-module lookups when resolving translation paths.

PHPStan types are also added in WP_Script_Modules. See #64238.

Developed in https://github.com/WordPress/wordpress-develop/pull/11543

Reviewed by audrasjb.
Merges r62278 to the 7.0 branch.

Props manzoorwanijk, westonruter, jsnajdr, jonsurrell, mukesh27, peterwilsoncc, 369work, desrosj, sabernhardt, nilambar, jorgefilipecosta, malayladu.
See #64238, #60597.
Fixes #65015.

#125 @westonruter
5 weeks ago

In 62293:

I18N: Harden against undefined index in _load_script_textdomain_from_src().

This guards against an undefined index warning being raised when a script or script module is registered with a URL that lacks a path component.

This also adds full PHPStan type definitions for wp_parse_url(), ensuring that the _load_script_textdomain_from_src() function has no PHPStan errors at rule level 10.

Developed in https://github.com/WordPress/wordpress-develop/pull/11690

Follow-up to r62278.

Props westonruter, manzoorwanijk, mukesh27.
See #65015, #64238.

#126 @jorbin
5 weeks ago

In 62325:

I18N: Harden against undefined index in _load_script_textdomain_from_src().

This guards against an undefined index warning being raised when a script or script module is registered with a URL that lacks a path component.

This also adds full PHPStan type definitions for wp_parse_url(), ensuring that the _load_script_textdomain_from_src() function has no PHPStan errors at rule level 10.

Developed in https://github.com/WordPress/wordpress-develop/pull/11690

Follow-up to r62278.

Reviewed by desrosj, jorbin.
Merges [62293] to the 7.0 branch.

Props westonruter, manzoorwanijk, mukesh27.
See #65015, #64238.

#127 @westonruter
4 weeks ago

In 62359:

Block Supports: Improve performance and hardening of block-level custom CSS rendering.

Short-circuits the custom CSS support filter before the more expensive lookups so blocks without custom CSS return faster.

Replaces the regex class name parsing in wp_render_custom_css_class_name() with a cheap str_contains() guard followed by an HTML spec-compliant strtok() walk over the className tokens. This avoids the regex engine for the common case where no wp-custom-css- class is present, and correctly handles tab/form-feed/CR/LF separators as well as classes such as my-wp-custom-css-* that merely contain the prefix as a substring after a hyphen.

Also hardens both functions against malformed parsed blocks (non-string className, missing keys), tightens @phpstan-param array shapes, and corrects the block_has_support() @param to allow WP_Block_Type|null. Lastly, a @return Generator<int, non-empty-string> phpdoc tag is added to WP_HTML_Tag_Processor::class_list().

Developed in https://github.com/WordPress/wordpress-develop/pull/11686 and https://github.com/WordPress/gutenberg/pull/78217

Follow-up to r61678.

Props mukesh27, westonruter, ramonopoly, jonsurrell.
See #64544, #64238.

#128 @westonruter
3 weeks ago

In 62368:

Script Loader: Warn when classic scripts with module dependencies lack footer/defer.

A classic script with module_dependencies may be evaluated before the script modules import map is printed if it loads blocking in the document head, causing a "Failed to resolve module specifier" error on dynamic imports.

  • Trigger _doing_it_wrong() from _wp_scripts_add_args_data() when a classic script provides module_dependencies without setting in_footer to true or using a defer loading strategy, and document this requirement in the wp_register_script() and wp_enqueue_script() docblocks.
  • Remove the module_dependencies arg from the wp-codemirror script registration in favor of passing the espree module URL directly through wp_get_code_editor_settings(). This avoids registering espree as a publicly-available script module when it is only ever used internally as a private implementation detail of the code editor.
  • Add a console.warn() in wp.codeEditor.initialize() when invoked before DOMContentLoaded, so developers are alerted if the function is called too early for the import map to have been parsed.
  • Add PHPStan types which were missing when module_dependencies were initially introduced.
  • Harden WP_Scripts::add_data() against non-string strategy values being passed to sprintf().

Developed in https://github.com/WordPress/wordpress-develop/pull/11788

Follow-up to r61587.

Props khokansardar, westonruter, jonsurrell, jorbin.
See #61500, #64238.
Fixes #65165.

#129 @ellatrix
3 weeks ago

In 62376:

Block Supports: Improve performance and hardening of block-level custom CSS rendering.

Short-circuits the custom CSS support filter before the more expensive lookups so blocks without custom CSS return faster.

Replaces the regex class name parsing in wp_render_custom_css_class_name() with a cheap str_contains() guard followed by an HTML spec-compliant strtok() walk over the className tokens. This avoids the regex engine for the common case where no wp-custom-css- class is present, and correctly handles tab/form-feed/CR/LF separators as well as classes such as my-wp-custom-css-* that merely contain the prefix as a substring after a hyphen.

Also hardens both functions against malformed parsed blocks (non-string className, missing keys), tightens @phpstan-param array shapes, and corrects the block_has_support() @param to allow WP_Block_Type|null. Lastly, a @return Generator<int, non-empty-string> phpdoc tag is added to WP_HTML_Tag_Processor::class_list().

Developed in https://github.com/WordPress/wordpress-develop/pull/11686 and https://github.com/WordPress/gutenberg/pull/78217

Follow-up to r61678.

Reviewed by ellatrix.
Merges [62359] to the 7.0 branch.
Props mukesh27, westonruter, ramonopoly, jonsurrell.
See #64544, #64238.

#130 @ellatrix
3 weeks ago

In 62379:

Script Loader: Warn when classic scripts with module dependencies lack footer/defer.

A classic script with module_dependencies may be evaluated before the script modules import map is printed if it loads blocking in the document head, causing a "Failed to resolve module specifier" error on dynamic imports.

  • Trigger _doing_it_wrong() from _wp_scripts_add_args_data() when a classic script provides module_dependencies without setting in_footer to true or using a defer loading strategy, and document this requirement in the wp_register_script() and wp_enqueue_script() docblocks.
  • Remove the module_dependencies arg from the wp-codemirror script registration in favor of passing the espree module URL directly through wp_get_code_editor_settings(). This avoids registering espree as a publicly-available script module when it is only ever used internally as a private implementation detail of the code editor.
  • Add a console.warn() in wp.codeEditor.initialize() when invoked before DOMContentLoaded, so developers are alerted if the function is called too early for the import map to have been parsed.
  • Add PHPStan types which were missing when module_dependencies were initially introduced.
  • Harden WP_Scripts::add_data() against non-string strategy values being passed to sprintf().

Developed in https://github.com/WordPress/wordpress-develop/pull/11788

Follow-up to r61587.

Reviewed by jonsurrell.
Merges [62368] to the 7.0 branch.
Props khokansardar, westonruter, jonsurrell, jorbin.
See #61500, #64238.
Fixes #65165.

Note: See TracTickets for help on using tickets.