Commit bae737caf0 for wordpress.org
commit bae737caf0eb1d6ebe194ed169953b27341cac08
Author: westonruter <westonruter@git.wordpress.org>
Date: Sat Sep 26 02:44:50 2026 +0000
Code Quality: Add conditional return types across core.
Declare PHPStan conditional return types on 86 functions and methods whose return type is selected by one of their arguments, in each case a selection their `@return` descriptions already spelled out in prose. They fall into these groups, alongside about thirty more of the same shape:
* An `$output` argument choosing an object or an array form: `get_term()`, `get_term_by()`, `get_category()`, `get_tag()`, `get_bookmark()`, `get_page_by_title()` and others.
* The `count` and `fields` arguments reshaping a query result: `WP_Comment_Query::query()`, `get_sites()`, `get_networks()`, `get_users()`, `get_categories()` and `get_tags()`.
* A `'U'` or `'G'` date format returning a timestamp rather than a string: `current_time()`, `mysql2date()` and the `get_the_date()` family.
* A `$wp_error` flag deciding how failure is reported: the cron scheduling functions, `wp_set_comment_status()`, `wp_update_comment()`, `wp_insert_category()` and `wp_insert_link()`.
* A display flag returning markup instead of printing it: `single_month_title()`, `wp_list_categories()`, `wp_generate_tag_cloud()` and `paginate_links()`.
* The `WP_Theme` header pipeline, from `sanitize_header()` through `display()`.
* The `$callback` and `$priority` arguments of `has_filter()`, `has_action()` and `WP_Hook::has_filter()` deciding between a bool and a priority.
With only the flat unions, a caller asking for an array was checked against a type that included an object, and the reverse. Likewise, a priority read back from `has_filter()` and passed on to `remove_filter()` was never narrowed to an integer.
Many of the annotations are adopted from the function map of the `php-stubs/wordpress-stubs` package, where they were developed and have long been relied on by plugin and theme authors. Each one was then checked against the body of the function it describes, and those claiming more than the code delivers were corrected. For instance:
* User IDs from `get_users()` are typed as the numeric strings the query actually returns.
* A `null` from `paginate_links()` is allowed when `total` is left to the main query, which may have only a single page.
* No conditional is declared for `wp_allow_comment()`, since the `pre_comment_approved` filter has been allowed to return a `WP_Error` regardless of `$wp_error` as of r41980.
The `@return` descriptions of `wp_allow_comment()`, `wp_set_comment_status()`, `wp_get_link_cats()`, `get_link()` and the network query methods are corrected to match the code as well.
Two small code changes accompany the annotations. In `wp_get_link_cats()`, the `WP_Error` from `wp_get_object_terms()` is now returned rather than passed to `array_unique()`, and in `wp_filter_oembed_result()` the `WP_Site::$blog_id` numeric string is cast before being passed to `switch_to_blog()`, as the comparison on the line above already did.
The PHPStan baselines are regenerated, resolving eleven errors and adding five. Three of the additions are existing errors reworded by a narrower type. The other two record a pre-existing issue that the narrower `get_post_time()` type exposes, where `the_weekday()` and `the_weekday_date()` pass a value that may be `false` to `WP_Locale::get_weekday()`.
Developed in https://github.com/WordPress/wordpress-develop/pull/13614.
Follow-up to r41980, r44154, r62680, r62822, r63358, r63441, r63488.
Props marian1, johnbillion, swissspidy, szepeviktor, mat-lipe, peter8nss, apermo, westonruter.
See #65817.
Built from https://develop.svn.wordpress.org/trunk@63941
git-svn-id: http://core.svn.wordpress.org/trunk@63107 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-admin/includes/bookmark.php b/wp-admin/includes/bookmark.php
index c64bac144c..aae87b9abc 100644
--- a/wp-admin/includes/bookmark.php
+++ b/wp-admin/includes/bookmark.php
@@ -121,10 +121,13 @@ function wp_delete_link( $link_id ) {
* @since 2.1.0
*
* @param int $link_id Link ID to look up.
- * @return int[] The IDs of the requested link's categories.
+ * @return int[]|WP_Error The IDs of the requested link's categories, or else a WP_Error if the `link_category` taxonomy was unregistered.
*/
function wp_get_link_cats( $link_id = 0 ) {
$cats = wp_get_object_terms( $link_id, 'link_category', array( 'fields' => 'ids' ) );
+ if ( is_wp_error( $cats ) ) {
+ return $cats;
+ }
return array_unique( $cats );
}
@@ -170,6 +173,8 @@ function get_link_to_edit( $link ) {
* }
* @param bool $wp_error Optional. Whether to return a WP_Error object on failure. Default false.
* @return int|WP_Error The link ID on success. The value 0 or WP_Error on failure.
+ *
+ * @phpstan-return ( $wp_error is false ? int : int|WP_Error )
*/
function wp_insert_link( $linkdata, $wp_error = false ) {
global $wpdb;
diff --git a/wp-admin/includes/menu.php b/wp-admin/includes/menu.php
index a95cf9e339..f1c2985e93 100644
--- a/wp-admin/includes/menu.php
+++ b/wp-admin/includes/menu.php
@@ -208,6 +208,10 @@ unset( $id, $data, $subs, $first_sub );
* @param string $class_to_add The CSS class to add.
* @param string $classes The string to add the CSS class to.
* @return string The string with the CSS class added.
+ *
+ * @phpstan-template T of string
+ * @phpstan-param T $class_to_add
+ * @phpstan-return ( $classes is empty ? T : non-empty-string )
*/
function add_cssclass( $class_to_add, $classes ) {
if ( empty( $classes ) ) {
diff --git a/wp-admin/includes/plugin.php b/wp-admin/includes/plugin.php
index 53d933d07e..a34d473bca 100644
--- a/wp-admin/includes/plugin.php
+++ b/wp-admin/includes/plugin.php
@@ -906,6 +906,8 @@ function activate_plugins( $plugins, $redirect = '', $network_wide = false, $sil
* @param string $deprecated Not used.
* @return bool|null|WP_Error True on success, false if `$plugins` is empty, `WP_Error` on failure.
* `null` if filesystem credentials are required to proceed.
+ *
+ * @phpstan-return ( $plugins is empty ? false : true|null|WP_Error )
*/
function delete_plugins( $plugins, $deprecated = '' ) {
global $wp_filesystem;
@@ -1111,6 +1113,8 @@ function validate_active_plugins() {
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
* @return int|WP_Error 0 on success, WP_Error on failure.
+ *
+ * @phpstan-return ( $plugin is empty ? WP_Error : 0|WP_Error )
*/
function validate_plugin( $plugin ) {
if ( validate_file( $plugin ) ) {
diff --git a/wp-admin/includes/taxonomy.php b/wp-admin/includes/taxonomy.php
index 470d36d55f..dbdab1af4f 100644
--- a/wp-admin/includes/taxonomy.php
+++ b/wp-admin/includes/taxonomy.php
@@ -117,6 +117,10 @@ function wp_create_categories( $categories, $post_id = 0 ) {
* @param bool $wp_error Optional. Default false.
* @return int|WP_Error The ID number of the new or updated Category on success. Zero or a WP_Error on failure,
* depending on param `$wp_error`.
+ *
+ * @phpstan-return (
+ * $wp_error is false ? int : int|WP_Error
+ * )
*/
function wp_insert_category( $catarr, $wp_error = false ) {
$cat_defaults = array(
@@ -218,6 +222,12 @@ function wp_update_category( $catarr ) {
* @return mixed Returns null if the term does not exist.
* Returns an array of the term ID and the term taxonomy ID if the pairing exists.
* Returns 0 if term ID 0 is passed to the function.
+ *
+ * @phpstan-return (
+ * $tag_name is 0
+ * ? 0
+ * : ( $tag_name is '' ? null : array{ term_id: string, term_taxonomy_id: string }|null )
+ * )
*/
function tag_exists( $tag_name ) {
return term_exists( $tag_name, 'post_tag' );
diff --git a/wp-includes/block-template-utils.php b/wp-includes/block-template-utils.php
index 96d2372694..78cd1bbdc1 100644
--- a/wp-includes/block-template-utils.php
+++ b/wp-includes/block-template-utils.php
@@ -319,8 +319,8 @@ function _get_block_templates_paths( $base_directory ) {
* @param string $template_type Template type. Either 'wp_template' or 'wp_template_part'.
* @param string $slug Template slug.
* @return array|null {
- * Array with template metadata if $template_type is one of 'wp_template' or 'wp_template_part',
- * null otherwise.
+ * Array with template metadata, or null if `$template_type` is neither 'wp_template' nor
+ * 'wp_template_part', or if the theme has no template file for `$slug`.
*
* @type string $slug Template slug.
* @type string $path Template file path.
@@ -392,6 +392,10 @@ function _get_block_template_file( $template_type, $slug ) {
* }
*
* @return array|null Template files on success, null if `$template_type` is not matched.
+ *
+ * @phpstan-return (
+ * $template_type is 'wp_template'|'wp_template_part' ? list<array<array-key, mixed>> : null
+ * )
*/
function _get_block_templates_files( $template_type, $query = array() ) {
if ( 'wp_template' !== $template_type && 'wp_template_part' !== $template_type ) {
diff --git a/wp-includes/blocks.php b/wp-includes/blocks.php
index 487c2765ac..beaf08d402 100644
--- a/wp-includes/blocks.php
+++ b/wp-includes/blocks.php
@@ -2682,6 +2682,8 @@ function _wp_apply_block_content_filters( $content, $context = '', &$seen_ids =
*
* @param string $content Content to test.
* @return int The block format version is 1 if the content contains one or more blocks, 0 otherwise.
+ *
+ * @phpstan-return ( $content is '' ? 0 : 0|1 )
*/
function block_version( $content ) {
return has_blocks( $content ) ? 1 : 0;
diff --git a/wp-includes/bookmark.php b/wp-includes/bookmark.php
index 9e44d78190..e1c8a6e522 100644
--- a/wp-includes/bookmark.php
+++ b/wp-includes/bookmark.php
@@ -20,6 +20,13 @@
* respectively. Default OBJECT.
* @param string $filter Optional. How to sanitize bookmark fields. Default 'raw'.
* @return array|object|null Type returned depends on $output value.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return null|(
+ * $output is 'ARRAY_A' ? array<string, mixed> : (
+ * $output is 'ARRAY_N' ? array<int, mixed> : stdClass
+ * )
+ * )
*/
function get_bookmark( $bookmark, $output = OBJECT, $filter = 'raw' ) {
global $wpdb;
diff --git a/wp-includes/category-template.php b/wp-includes/category-template.php
index f268f93cbc..1d456f309d 100644
--- a/wp-includes/category-template.php
+++ b/wp-includes/category-template.php
@@ -534,6 +534,8 @@ function wp_dropdown_categories( $args = '' ) {
* }
* @return void|string|false Void if 'echo' argument is true, HTML list of categories if 'echo' is false.
* False if the taxonomy does not exist.
+ *
+ * @phpstan-return ( $args is array{ echo: false|0, ... } ? string|false : false|void )
*/
function wp_list_categories( $args = '' ) {
$defaults = array(
@@ -849,6 +851,8 @@ function default_topic_count_scale( $count ) {
* 0, 1, or their bool equivalents.
* }
* @return string|string[] Tag cloud as a string or an array, depending on 'format' argument.
+ *
+ * @phpstan-return ( $args is array{ format: 'array', ... } ? array<int, string> : string )
*/
function wp_generate_tag_cloud( $tags, $args = '' ) {
$defaults = array(
diff --git a/wp-includes/category.php b/wp-includes/category.php
index dbb48d630b..e6085418e2 100644
--- a/wp-includes/category.php
+++ b/wp-includes/category.php
@@ -22,6 +22,24 @@
* @type string $taxonomy Taxonomy to retrieve terms for. Default 'category'.
* }
* @return array List of category objects.
+ *
+ * @phpstan-return (
+ * $args is array{ fields: 'count', ... }
+ * ? list<0|numeric-string>
+ * : (
+ * $args is array{ fields: 'names'|'slugs', ... }
+ * ? list<string>
+ * : (
+ * $args is array{ fields: 'id=>name'|'id=>slug', ... }
+ * ? array<int, string>
+ * : (
+ * $args is array{ fields: 'id=>parent', ... }
+ * ? array<int, int>
+ * : ( $args is array{ fields: 'ids'|'tt_ids', ... } ? list<int> : array<int, WP_Term> )
+ * )
+ * )
+ * )
+ * )
*/
function get_categories( $args = '' ) {
$defaults = array( 'taxonomy' => 'category' );
@@ -88,6 +106,13 @@ function get_categories( $args = '' ) {
* @return WP_Term|array|WP_Error|null Category data in type defined by $output parameter.
* Returns a WP_Term object with backwards compatible property aliases filled in.
* WP_Error if $category is empty, null if it does not exist.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return (
+ * $output is 'ARRAY_A' ? array<string, mixed>|WP_Error|null : (
+ * $output is 'ARRAY_N' ? list<mixed>|WP_Error|null : WP_Term|WP_Error|null
+ * )
+ * )
*/
function get_category( $category, $output = OBJECT, $filter = 'raw' ) {
$category = get_term( $category, 'category', $output, $filter );
@@ -121,6 +146,13 @@ function get_category( $category, $output = OBJECT, $filter = 'raw' ) {
* correspond to a WP_Term object, an associative array, or a numeric array,
* respectively. Default OBJECT.
* @return WP_Term|array|WP_Error|null Type is based on $output value.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return (
+ * $output is 'ARRAY_A' ? array<string, mixed>|WP_Error|null : (
+ * $output is 'ARRAY_N' ? list<mixed>|WP_Error|null : WP_Term|WP_Error|null
+ * )
+ * )
*/
function get_category_by_path( $category_path, $full_match = true, $output = OBJECT ) {
$category_path = rawurlencode( urldecode( $category_path ) );
@@ -293,6 +325,20 @@ function sanitize_category_field( $field, $value, $cat_id, $context ) {
* }
* @return WP_Term[]|int|WP_Error Array of 'post_tag' term objects, a count thereof,
* or WP_Error if any of the taxonomies do not exist.
+ *
+ * @phpstan-return (
+ * $args is array{ fields: 'names'|'slugs', ... }
+ * ? list<string>
+ * : (
+ * $args is array{ fields: 'id=>name'|'id=>slug', ... }
+ * ? array<int, string>
+ * : (
+ * $args is array{ fields: 'id=>parent', ... }
+ * ? array<int, int>
+ * : ( $args is array{ fields: 'ids'|'tt_ids', ... } ? list<int> : array<int, WP_Term> )
+ * )
+ * )
+ * )|WP_Error
*/
function get_tags( $args = '' ) {
$defaults = array( 'taxonomy' => 'post_tag' );
@@ -339,6 +385,13 @@ function get_tags( $args = '' ) {
* @param string $filter Optional. How to sanitize tag fields. Default 'raw'.
* @return WP_Term|array|WP_Error|null Tag data in type defined by $output parameter.
* WP_Error if $tag is empty, null if it does not exist.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return (
+ * $output is 'ARRAY_A' ? array<string, mixed>|WP_Error|null : (
+ * $output is 'ARRAY_N' ? list<mixed>|WP_Error|null : WP_Term|WP_Error|null
+ * )
+ * )
*/
function get_tag( $tag, $output = OBJECT, $filter = 'raw' ) {
return get_term( $tag, 'post_tag', $output, $filter );
diff --git a/wp-includes/class-wp-comment-query.php b/wp-includes/class-wp-comment-query.php
index 1147446bb7..8b5f1f276c 100644
--- a/wp-includes/class-wp-comment-query.php
+++ b/wp-includes/class-wp-comment-query.php
@@ -365,7 +365,12 @@ class WP_Comment_Query {
*
* @param string|array $query Array or URL query string of parameters.
* @return WP_Comment[]|int[]|int List of comments, or number of comments when 'count' is passed as a query var.
- * @phpstan-return array<int, WP_Comment>|non-negative-int[]|non-negative-int
+ *
+ * @phpstan-return (
+ * $query is array{ count: true, ... } ? non-negative-int : (
+ * $query is array{ fields: 'ids', ... } ? non-negative-int[] : array<int, WP_Comment>
+ * )
+ * )
*/
public function query( $query ) {
$this->query_vars = wp_parse_args( $query );
diff --git a/wp-includes/class-wp-dependencies.php b/wp-includes/class-wp-dependencies.php
index c2daba389b..80559201dd 100644
--- a/wp-includes/class-wp-dependencies.php
+++ b/wp-includes/class-wp-dependencies.php
@@ -472,6 +472,16 @@ class WP_Dependencies {
* @param string $handle Name of the item. Should be unique.
* @param string $status Optional. Status of the item to query. Default 'registered'.
* @return bool|_WP_Dependency Found, or object Item data.
+ *
+ * @phpstan-return (
+ * $handle is not non-empty-string
+ * ? false
+ * : (
+ * $status is not 'registered'|'scripts'|'enqueued'|'queue'|'to_do'|'to_print'|'done'|'printed'
+ * ? false
+ * : ( $status is 'registered'|'scripts' ? _WP_Dependency|false : bool )
+ * )
+ * )
*/
public function query( $handle, $status = 'registered' ) {
switch ( $status ) {
diff --git a/wp-includes/class-wp-hook.php b/wp-includes/class-wp-hook.php
index 1718878308..9a4d4a2c5e 100644
--- a/wp-includes/class-wp-hook.php
+++ b/wp-includes/class-wp-hook.php
@@ -250,6 +250,13 @@ final class WP_Hook implements Iterator, ArrayAccess {
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
* @phpstan-param Maybe_Callable|false $callback
+ * @phpstan-return (
+ * $callback is false
+ * ? bool
+ * : ( $priority is int
+ * ? bool
+ * : false|int )
+ * )
*/
public function has_filter( $hook_name = '', $callback = false, $priority = false ) {
if ( false === $callback ) {
diff --git a/wp-includes/class-wp-network-query.php b/wp-includes/class-wp-network-query.php
index 7a5e9e7f41..a7c747798f 100644
--- a/wp-includes/class-wp-network-query.php
+++ b/wp-includes/class-wp-network-query.php
@@ -179,8 +179,14 @@ class WP_Network_Query {
* @since 4.6.0
*
* @param string|array $query Array or URL query string of parameters.
- * @return array|int List of WP_Network objects, a list of network IDs when 'fields' is set to 'ids',
- * or the number of networks when 'count' is passed as a query var.
+ * @return WP_Network[]|int[]|int List of WP_Network objects, a list of network IDs when 'fields' is set
+ * to 'ids', or the number of networks when 'count' is passed as a query var.
+ *
+ * @phpstan-return (
+ * $query is array{ count: true, ... } ? int : (
+ * $query is array{ fields: 'ids', ... } ? int[] : array<int, WP_Network>
+ * )
+ * )
*/
public function query( $query ) {
$this->query_vars = wp_parse_args( $query );
@@ -192,8 +198,8 @@ class WP_Network_Query {
*
* @since 4.6.0
*
- * @return array|int List of WP_Network objects, a list of network IDs when 'fields' is set to 'ids',
- * or the number of networks when 'count' is passed as a query var.
+ * @return WP_Network[]|int[]|int List of WP_Network objects, a list of network IDs when 'fields' is set
+ * to 'ids', or the number of networks when 'count' is passed as a query var.
*/
public function get_networks() {
$this->parse_query();
@@ -234,10 +240,11 @@ class WP_Network_Query {
* @since 5.6.0 The returned array of network data is assigned to the `networks` property
* of the current WP_Network_Query instance.
*
- * @param array|int|null $network_data Return an array of network data to short-circuit WP's network query,
- * the network count as an integer if `$this->query_vars['count']` is set,
- * or null to allow WP to run its normal queries.
- * @param WP_Network_Query $query The WP_Network_Query instance, passed by reference.
+ * @param WP_Network[]|int[]|int|null $network_data Return an array of network data to short-circuit WP's
+ * network query, the network count as an integer if
+ * `$this->query_vars['count']` is set, or null to allow WP
+ * to run its normal queries.
+ * @param WP_Network_Query $query The WP_Network_Query instance, passed by reference.
*/
$network_data = apply_filters_ref_array( 'networks_pre_query', array( $network_data, &$this ) );
diff --git a/wp-includes/class-wp-site-query.php b/wp-includes/class-wp-site-query.php
index 52ae228d90..aab8b511fc 100644
--- a/wp-includes/class-wp-site-query.php
+++ b/wp-includes/class-wp-site-query.php
@@ -265,6 +265,12 @@ class WP_Site_Query {
* @param string|array $query Array or URL query string of parameters.
* @return WP_Site[]|int[]|int List of WP_Site objects, a list of site IDs when 'fields' is set to 'ids',
* or the number of sites when 'count' is passed as a query var.
+ *
+ * @phpstan-return (
+ * $query is array{ count: true, ... } ? int : (
+ * $query is array{ fields: 'ids', ... } ? int[] : array<int, WP_Site>
+ * )
+ * )
*/
public function query( $query ) {
$this->query_vars = wp_parse_args( $query );
diff --git a/wp-includes/class-wp-term.php b/wp-includes/class-wp-term.php
index 33547e4cbe..a9a58da875 100644
--- a/wp-includes/class-wp-term.php
+++ b/wp-includes/class-wp-term.php
@@ -225,7 +225,7 @@ final class WP_Term {
*
* @since 4.4.0
*
- * @return array Object as array.
+ * @return array<string, mixed> Object as array.
*/
public function to_array() {
return get_object_vars( $this );
diff --git a/wp-includes/class-wp-theme.php b/wp-includes/class-wp-theme.php
index 87399e399a..87fcd7eec7 100644
--- a/wp-includes/class-wp-theme.php
+++ b/wp-includes/class-wp-theme.php
@@ -5,6 +5,8 @@
* @package WordPress
* @subpackage Theme
* @since 3.4.0
+ *
+ * @phpstan-type Theme_Key 'Name'|'Version'|'Status'|'Title'|'Author'|'Author Name'|'Author URI'|'Description'|'Template'|'Stylesheet'|'Template Files'|'Stylesheet Files'|'Template Dir'|'Stylesheet Dir'|'Screenshot'|'Tags'|'Theme Root'|'Theme Root URI'|'Parent Theme'
*/
#[AllowDynamicProperties]
final class WP_Theme implements ArrayAccess {
@@ -654,6 +656,8 @@ final class WP_Theme implements ArrayAccess {
*
* @param mixed $offset
* @return bool
+ *
+ * @phpstan-return ( $offset is Theme_Key ? true : false )
*/
#[ReturnTypeWillChange]
public function offsetExists( $offset ) {
@@ -696,6 +700,8 @@ final class WP_Theme implements ArrayAccess {
*
* @param mixed $offset
* @return mixed
+ *
+ * @phpstan-return ( $offset is Theme_Key ? mixed : null )
*/
#[ReturnTypeWillChange]
public function offsetGet( $offset ) {
@@ -916,6 +922,14 @@ final class WP_Theme implements ArrayAccess {
* @param bool $translate Optional. Whether to translate the header. Defaults to true.
* @return string|array|false Processed header. An array for Tags if `$markup` is false, string otherwise.
* False on failure.
+ *
+ * @phpstan-return (
+ * $markup is false
+ * ? ( $header is 'Tags'
+ * ? string[]|false
+ * : string|false )
+ * : string|false
+ * )
*/
public function display( $header, $markup = true, $translate = true ) {
$value = $this->get( $header );
@@ -949,7 +963,9 @@ final class WP_Theme implements ArrayAccess {
* 'ThemeURI', 'AuthorURI', 'Status', 'Tags', 'RequiresWP', 'RequiresPHP',
* 'UpdateURI'.
* @param string $value Value to sanitize.
- * @return string|array An array for Tags header, string otherwise.
+ * @return string|string[] An array for Tags header, string otherwise.
+ *
+ * @phpstan-return ( $header is 'Tags' ? string[] : string )
*/
private function sanitize_header( $header, $value ) {
switch ( $header ) {
@@ -1053,9 +1069,11 @@ final class WP_Theme implements ArrayAccess {
*
* @since 3.4.0
*
- * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
- * @param string|array $value Value to translate. An array for Tags header, string otherwise.
- * @return string|array Translated value. An array for Tags header, string otherwise.
+ * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
+ * @param string|string[] $value Value to translate. An array for Tags header, string otherwise.
+ * @return string|string[] Translated value. An array for Tags header, string otherwise.
+ *
+ * @phpstan-return ( $value is string ? string : string[] )
*/
private function translate_header( $header, $value ) {
switch ( $header ) {
diff --git a/wp-includes/class-wp-user-query.php b/wp-includes/class-wp-user-query.php
index 3815023924..61fc3edbc8 100644
--- a/wp-includes/class-wp-user-query.php
+++ b/wp-includes/class-wp-user-query.php
@@ -962,7 +962,8 @@ class WP_User_Query {
*
* @since 3.1.0
*
- * @return array Array of results.
+ * @return array<int, mixed> Array of results. Contains WP_User objects unless the 'fields' query var
+ * requested specific fields, in which case it contains the requested values.
*/
public function get_results() {
return $this->results;
diff --git a/wp-includes/comment.php b/wp-includes/comment.php
index ae4b8efbbc..9ad18180b7 100644
--- a/wp-includes/comment.php
+++ b/wp-includes/comment.php
@@ -761,7 +761,8 @@ function sanitize_comment_cookies() {
* returning a WP_Error object, rather than executing wp_die().
* Default false.
* @return int|string|WP_Error Allowed comments return the approval status (0|1|'spam'|'trash').
- * If `$wp_error` is true, disallowed comments return a WP_Error.
+ * WP_Error if the comment is a duplicate or a flood and `$wp_error`
+ * is true, or if the {@see 'pre_comment_approved'} filter returns one.
*/
function wp_allow_comment( $commentdata, $wp_error = false ) {
global $wpdb;
@@ -2795,7 +2796,7 @@ function wp_send_note_notification( WP_User $user, WP_Comment $comment, ?WP_Post
* Sets the status of a comment.
*
* The {@see 'wp_set_comment_status'} action is called after the comment is handled.
- * If the comment status is not in the list, then false is returned.
+ * If the comment status is not in the list, then false is returned, even when `$wp_error` is true.
*
* @since 1.0.0
*
@@ -2804,7 +2805,14 @@ function wp_send_note_notification( WP_User $user, WP_Comment $comment, ?WP_Post
* @param int|WP_Comment $comment_id Comment ID or WP_Comment object.
* @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.
* @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default false.
- * @return bool|WP_Error True on success, false or WP_Error on failure.
+ * @return bool|WP_Error True on success, false or WP_Error on failure. False for an invalid
+ * `$comment_status` regardless of `$wp_error`.
+ *
+ * @phpstan-return (
+ * $wp_error is false
+ * ? bool
+ * : ( $comment_status is 'hold'|'0'|'approve'|'1'|'spam'|'trash' ? true|WP_Error : bool|WP_Error )
+ * )
*/
function wp_set_comment_status( $comment_id, $comment_status, $wp_error = false ) {
global $wpdb;
@@ -2879,6 +2887,8 @@ function wp_set_comment_status( $comment_id, $comment_status, $wp_error = false
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return int|false|WP_Error The value 1 if the comment was updated, 0 if not updated.
* False or a WP_Error object on failure.
+ *
+ * @phpstan-return ( $wp_error is false ? int|false : int|WP_Error )
*/
function wp_update_comment( $commentarr, $wp_error = false ) {
global $wpdb;
diff --git a/wp-includes/cron.php b/wp-includes/cron.php
index 1070ae4680..743b37b326 100644
--- a/wp-includes/cron.php
+++ b/wp-includes/cron.php
@@ -44,6 +44,8 @@
* database performance issues.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure.
+ *
+ * @phpstan-return ( $wp_error is false ? bool : true|WP_Error )
*/
function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
@@ -248,6 +250,8 @@ function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error
* database performance issues.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully scheduled. False or WP_Error on failure.
+ *
+ * @phpstan-return ( $wp_error is false ? bool : true|WP_Error )
*/
function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
@@ -363,6 +367,8 @@ function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp
* database performance issues.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully rescheduled. False or WP_Error on failure.
+ *
+ * @phpstan-return ( $wp_error is false ? bool : true|WP_Error )
*/
function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
@@ -485,6 +491,8 @@ function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array(), $
* arguments do not match exactly, the event will not be found. Default empty array.
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return bool|WP_Error True if event successfully unscheduled. False or WP_Error on failure.
+ *
+ * @phpstan-return ( $wp_error is false ? bool : true|WP_Error )
*/
function wp_unschedule_event( $timestamp, $hook, $args = array(), $wp_error = false ) {
// Make sure timestamp is a positive integer.
@@ -572,6 +580,8 @@ function wp_unschedule_event( $timestamp, $hook, $args = array(), $wp_error = fa
* @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
* events were registered with the hook and arguments combination), false or WP_Error
* if unscheduling one or more events fail.
+ *
+ * @phpstan-return ( int|( $wp_error is false ? false : WP_Error ) )
*/
function wp_clear_scheduled_hook( $hook, $args = array(), $wp_error = false ) {
/*
@@ -677,6 +687,8 @@ function wp_clear_scheduled_hook( $hook, $args = array(), $wp_error = false ) {
* @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false.
* @return int|false|WP_Error On success an integer indicating number of events unscheduled (0 indicates no
* events were registered on the hook), false or WP_Error if unscheduling fails.
+ *
+ * @phpstan-return ( $wp_error is false ? int|false : int|WP_Error )
*/
function wp_unschedule_hook( $hook, $wp_error = false ) {
/**
diff --git a/wp-includes/deprecated.php b/wp-includes/deprecated.php
index d2b987ec18..76d3971085 100644
--- a/wp-includes/deprecated.php
+++ b/wp-includes/deprecated.php
@@ -2021,7 +2021,15 @@ function get_attachment_innerHTML($id = 0, $fullsize = false, $max_dims = false)
* Default OBJECT.
* @param string $filter Optional. How to filter the link for output. Accepts 'raw', 'edit',
* 'attribute', 'js', 'db', or 'display'. Default 'raw'.
- * @return object|array Bookmark object or array, depending on the type specified by `$output`.
+ * @return object|array|null Bookmark object or array, depending on the type specified by `$output`.
+ * Null if the bookmark does not exist.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return null|(
+ * $output is 'ARRAY_A' ? array<string, mixed> : (
+ * $output is 'ARRAY_N' ? array<int, mixed> : stdClass
+ * )
+ * )
*/
function get_link( $bookmark_id, $output = OBJECT, $filter = 'raw' ) {
_deprecated_function( __FUNCTION__, '2.1.0', 'get_bookmark()' );
@@ -2518,6 +2526,16 @@ function is_taxonomy( $taxonomy ) {
* @param string $taxonomy The taxonomy name to use
* @param int $parent ID of parent term under which to confine the exists search.
* @return mixed Get the term ID or term object, if exists.
+ *
+ * @phpstan-return (
+ * $term is 0
+ * ? 0
+ * : (
+ * $term is ''
+ * ? null
+ * : ( $taxonomy is '' ? string|null : array{ term_id: string, term_taxonomy_id: string }|null )
+ * )
+ * )
*/
function is_term( $term, $taxonomy = '', $parent = 0 ) {
_deprecated_function( __FUNCTION__, '3.0.0', 'term_exists()' );
@@ -4569,6 +4587,13 @@ function _filter_query_attachment_filenames( $clauses ) {
* respectively. Default OBJECT.
* @param string|array $post_type Optional. Post type or array of post types. Default 'page'.
* @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return (
+ * $output is 'ARRAY_A' ? non-empty-array<string, mixed>|null : (
+ * $output is 'ARRAY_N' ? non-empty-array<int, mixed>|null : WP_Post|null
+ * )
+ * )
*/
function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) {
_deprecated_function( __FUNCTION__, '6.2.0', 'WP_Query' );
@@ -6498,6 +6523,8 @@ function wp_print_auto_sizes_contain_css_fix() {
*
* @param string|array $gpc String or array of data to slash.
* @return string|array Slashed `$gpc`.
+ *
+ * @phpstan-return ( $gpc is string ? string : array )
*/
function addslashes_gpc( $gpc ) {
_deprecated_function( __FUNCTION__, '7.0.0', 'wp_slash()' );
diff --git a/wp-includes/embed.php b/wp-includes/embed.php
index e87cf4ec57..6a7501027a 100644
--- a/wp-includes/embed.php
+++ b/wp-includes/embed.php
@@ -676,7 +676,7 @@ function get_oembed_response_data_for_url( $url, $args ) {
}
if ( $site && get_current_blog_id() !== (int) $site->blog_id ) {
- switch_to_blog( $site->blog_id );
+ switch_to_blog( (int) $site->blog_id );
$switched_blog = true;
}
}
diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php
index faa94c6f6b..c39beaf7b1 100644
--- a/wp-includes/formatting.php
+++ b/wp-includes/formatting.php
@@ -2440,6 +2440,10 @@ function wp_truncate_slug( $slug, $length = 200 ) {
*
* @param string $orderby Order by clause to be validated.
* @return string|false Returns $orderby if valid, false otherwise.
+ *
+ * @phpstan-template T of string
+ * @phpstan-param T $orderby
+ * @phpstan-return ( T is non-empty-string ? T|false : false )
*/
function sanitize_sql_orderby( $orderby ) {
if ( preg_match( '/^\s*(([a-z0-9_]+|`[a-z0-9_]+`)(\s+(ASC|DESC))?\s*(,\s*(?=[a-z0-9_`])|$))+$/i', $orderby ) || preg_match( '/^\s*RAND\(\s*\)\s*$/i', $orderby ) ) {
@@ -2816,6 +2820,16 @@ function format_to_edit( $content, $rich_text = false ) {
* @param int $number Number to append zeros to if not greater than threshold.
* @param int $threshold Digit places number needs to be to not have zeros added.
* @return string Adds leading zeros to number if needed.
+ *
+ * @phpstan-return (
+ * $threshold is 0
+ * ? lowercase-string&non-empty-string&numeric-string
+ * : (
+ * $number is int<0, max>
+ * ? lowercase-string&non-empty-string&numeric-string
+ * : lowercase-string&non-empty-string
+ * )
+ * )
*/
function zeroise( $number, $threshold ) {
return sprintf( '%0' . $threshold . 's', $number );
diff --git a/wp-includes/functions.php b/wp-includes/functions.php
index 89d27f75e9..393f50a3aa 100644
--- a/wp-includes/functions.php
+++ b/wp-includes/functions.php
@@ -31,6 +31,8 @@ require ABSPATH . WPINC . '/option.php';
* @param bool $translate Whether the return date should be translated. Default true.
* @return string|int|false Integer if `$format` is 'U' or 'G', string otherwise.
* False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function mysql2date( $format, $date, $translate = true ) {
if ( empty( $date ) ) {
@@ -74,6 +76,8 @@ function mysql2date( $format, $date, $translate = true ) {
* or PHP date format string (e.g. 'Y-m-d').
* @param bool $gmt Optional. Whether to use GMT timezone. Default false.
* @return int|string Integer if `$type` is 'timestamp' or 'U', string otherwise.
+ *
+ * @phpstan-return ( $type is 'timestamp'|'U' ? int : string )
*/
function current_time( $type, $gmt = false ) {
// Don't use non-GMT timestamp, unless you know the difference and really need to.
@@ -465,6 +469,8 @@ function number_format_i18n( $number, $decimals = 0 ) {
* @return string|false Number string on success, false on failure.
*
* @phpstan-param int|float|numeric-string $bytes
+ *
+ * @phpstan-return ( $bytes is int<0, max> ? string : string|false )
*/
function size_format( $bytes, $decimals = 0 ) {
if ( ! is_numeric( $bytes ) ) {
@@ -632,6 +638,10 @@ function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
*
* @param string|array|object $data Data that might be serialized.
* @return mixed A scalar data.
+ *
+ * @phpstan-template T of mixed
+ * @phpstan-param T $data
+ * @phpstan-return ( T is array|object|string ? string : T )
*/
function maybe_serialize( $data ) {
if ( is_array( $data ) || is_object( $data ) ) {
@@ -840,6 +850,8 @@ function xmlrpc_removepostdata( $content ) {
*
* @param string $content Content to extract URLs from.
* @return string[] Array of URLs found in passed string.
+ *
+ * @phpstan-return ( $content is empty ? array{} : list<string> )
*/
function wp_extract_urls( $content ) {
preg_match_all(
@@ -1600,6 +1612,8 @@ function get_num_queries() {
*
* @param string $yn Character string containing either 'y' (yes) or 'n' (no).
* @return bool True if 'y', false on anything else.
+ *
+ * @phpstan-return ( $yn is 'y'|'Y' ? true : false )
*/
function bool_from_yn( $yn ) {
return ( 'y' === strtolower( $yn ) );
@@ -2131,6 +2145,8 @@ function wp_mkdir_p( $target ) {
*
* @param string $path File path.
* @return bool True if path is absolute, false is not absolute.
+ *
+ * @phpstan-return ( $path is non-falsy-string ? bool : false )
*/
function path_is_absolute( $path ) {
/*
@@ -5416,6 +5432,8 @@ function _wp_to_kebab_case( $input_string ) {
* @return bool Whether the variable is a list.
*
* @phpstan-assert-if-true array<int, mixed> $data
+ *
+ * @phpstan-return ( $data is array<int, mixed> ? true : false )
*/
function wp_is_numeric_array( $data ): bool {
if ( ! is_array( $data ) ) {
@@ -6416,6 +6434,8 @@ function iis7_supports_permalinks() {
* @param string $file File path.
* @param string[] $allowed_files Optional. Array of allowed files. Default empty array.
* @return int 0 means nothing is wrong, greater than 0 means something was wrong.
+ *
+ * @phpstan-return ( $file is '' ? 0 : ( $allowed_files is empty ? 0|1|2 : 0|1|2|3 ) )
*/
function validate_file( $file, $allowed_files = array() ) {
if ( ! is_scalar( $file ) || '' === $file ) {
@@ -7298,7 +7318,11 @@ function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_arg
* to true if you already know the given $start is part of a loop (otherwise
* the returned array might include branches). Default false.
* @return mixed Scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if
- * $_return_loop
+ * $_return_loop. False if no loop was found.
+ *
+ * @phpstan-return (
+ * $_return_loop is true ? array<array-key, true>|false : mixed
+ * )
*/
function wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override = array(), $callback_args = array(), $_return_loop = false ) {
$tortoise = $start;
@@ -7426,6 +7450,8 @@ function wp_allowed_protocols() {
* the raw array returned. Default true.
* @return string|array Either a string containing a reversed comma separated trace or an array
* of individual calls.
+ *
+ * @phpstan-return ( $pretty is true ? string : list<string> )
*/
function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
static $truncate_paths;
@@ -7735,6 +7761,8 @@ function wp_auth_check( $response ) {
*
* @param string $tag An HTML tag name. Example: 'video'.
* @return string Tag RegEx.
+ *
+ * @phpstan-return ( $tag is ''|'0' ? '' : non-falsy-string )
*/
function get_tag_regex( $tag ) {
if ( empty( $tag ) ) {
@@ -8181,6 +8209,8 @@ function wp_generate_uuid4() {
* @param int $version Specify which version of UUID to check against. Default is none,
* to accept any UUID version. Otherwise, only version allowed is `4`.
* @return bool The string is a valid UUID or false on failure.
+ *
+ * @phpstan-return ( $version is 4|null ? bool : false )
*/
function wp_is_uuid( $uuid, $version = null ) {
@@ -8213,6 +8243,12 @@ function wp_is_uuid( $uuid, $version = null ) {
*
* @param string $prefix Prefix for the returned ID.
* @return string Unique ID.
+ *
+ * @phpstan-return (
+ * ( $prefix is ''|numeric-string ? numeric-string : string )
+ * & non-falsy-string
+ * & ( $prefix is lowercase-string ? lowercase-string : string )
+ * )
*/
function wp_unique_id( $prefix = '' ) {
static $id_counter = 0;
@@ -8232,6 +8268,12 @@ function wp_unique_id( $prefix = '' ) {
*
* @param string $prefix Optional. Prefix for the returned ID. Default empty string.
* @return string Incremental ID per prefix.
+ *
+ * @phpstan-return (
+ * ( $prefix is ''|numeric-string ? numeric-string : string )
+ * & non-falsy-string
+ * & ( $prefix is lowercase-string ? lowercase-string : string )
+ * )
*/
function wp_unique_prefixed_id( $prefix = '' ) {
static $id_counters = array();
@@ -8265,6 +8307,8 @@ function wp_unique_prefixed_id( $prefix = '' ) {
* @param array $data The input array to generate an ID from.
* @param string $prefix Optional. A prefix to prepend to the generated ID. Default empty string.
* @return string The generated unique ID for the array.
+ *
+ * @phpstan-return ( $prefix is lowercase-string ? lowercase-string&non-falsy-string : non-falsy-string )
*/
function wp_unique_id_from_values( array $data, string $prefix = '' ): string {
if ( empty( $data ) ) {
diff --git a/wp-includes/general-template.php b/wp-includes/general-template.php
index 6df509fbf5..73178b9eca 100644
--- a/wp-includes/general-template.php
+++ b/wp-includes/general-template.php
@@ -1929,6 +1929,8 @@ function single_term_title( $prefix = '', $display = true ) {
* @param string $prefix Optional. What to display before the title.
* @param bool $display Optional. Whether to display or retrieve title. Default true.
* @return string|false|null False if there's no valid title for the month. Title when retrieving.
+ *
+ * @phpstan-return ( $display is true ? false|null : string|false )
*/
function single_month_title( $prefix = '', $display = true ) {
global $wp_locale;
@@ -3005,6 +3007,8 @@ function the_date( $format = '', $before = '', $after = '', $display = true ) {
* @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
* @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default current post.
* @return string|int|false Date the current post was written. False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function get_the_date( $format = '', $post = null ) {
$post = get_post( $post );
@@ -3072,6 +3076,8 @@ function the_modified_date( $format = '', $before = '', $after = '', $display =
* @param string $format Optional. PHP date format. Defaults to the 'date_format' option.
* @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default current post.
* @return string|int|false Date the current post was modified. False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function get_the_modified_date( $format = '', $post = null ) {
$post = get_post( $post );
@@ -3131,6 +3137,8 @@ function the_time( $format = '' ) {
* @param int|WP_Post|null $post Post ID or post object. Default is global `$post` object.
* @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
* False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function get_the_time( $format = '', $post = null ) {
$post = get_post( $post );
@@ -3168,6 +3176,8 @@ function get_the_time( $format = '', $post = null ) {
* @param bool $translate Whether to translate the time string. Default false.
* @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
* False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function get_post_time( $format = 'U', $gmt = false, $post = null, $translate = false ) {
$post = get_post( $post );
@@ -3318,6 +3328,8 @@ function the_modified_time( $format = '' ) {
* Defaults to the 'time_format' option.
* @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default current post.
* @return string|int|false Formatted date string or Unix timestamp. False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function get_the_modified_time( $format = '', $post = null ) {
$post = get_post( $post );
@@ -3357,6 +3369,8 @@ function get_the_modified_time( $format = '', $post = null ) {
* @param bool $translate Whether to translate the time string. Default false.
* @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
* False on failure.
+ *
+ * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
*/
function get_post_modified_time( $format = 'U', $gmt = false, $post = null, $translate = false ) {
$post = get_post( $post );
@@ -4947,6 +4961,16 @@ function language_attributes( $doctype = 'html' ) {
* }
* @return string|string[]|null String of page links or array of page links, depending on 'type' argument.
* Null if total number of pages is less than 2.
+ *
+ * @phpstan-return (
+ * $args is array{ total: int<min, 1>, ... }
+ * ? null
+ * : (
+ * $args is array{ total: int<2, max>, ... }
+ * ? ( $args is array{ type: 'array', ... } ? list<string> : string )
+ * : ( $args is array{ type: 'array', ... } ? list<string> : string )|null
+ * )
+ * )
*/
function paginate_links( $args = '' ) {
global $wp_query, $wp_rewrite;
diff --git a/wp-includes/http.php b/wp-includes/http.php
index c2855a8d8d..1a189a2613 100644
--- a/wp-includes/http.php
+++ b/wp-includes/http.php
@@ -555,6 +555,8 @@ function send_origin_headers() {
*
* @param string $url Request URL.
* @return string|false Returns false if the URL is not safe, or the original URL if it is safe.
+ *
+ * @phpstan-return ( $url is numeric|'' ? false : string|false )
*/
function wp_http_validate_url( $url ) {
if ( ! is_string( $url ) || '' === $url || is_numeric( $url ) ) {
diff --git a/wp-includes/l10n/class-wp-translations.php b/wp-includes/l10n/class-wp-translations.php
index e919fea8b9..2cccf542d8 100644
--- a/wp-includes/l10n/class-wp-translations.php
+++ b/wp-includes/l10n/class-wp-translations.php
@@ -112,6 +112,10 @@ class WP_Translations {
* @param int|float $count Count. Should be an integer, but some plugins pass floats.
* @param string|null $context Context.
* @return string|null Translation if it exists, or the unchanged singular string.
+ *
+ * @phpstan-template T of string|null
+ * @phpstan-param T $singular
+ * @phpstan-return ( $singular is null ? null : ( $plural is null ? T : string ) )
*/
public function translate_plural( $singular, $plural, $count = 1, $context = '' ) {
if ( null === $singular || null === $plural ) {
@@ -135,6 +139,8 @@ class WP_Translations {
* @param string|null $singular Singular string.
* @param string|null $context Context.
* @return string|null Translation if it exists, or the unchanged singular string
+ *
+ * @phpstan-return ( $singular is null ? null : string )
*/
public function translate( $singular, $context = '' ) {
if ( null === $singular ) {
diff --git a/wp-includes/link-template.php b/wp-includes/link-template.php
index 10bda68115..3d4ffc23b8 100644
--- a/wp-includes/link-template.php
+++ b/wp-includes/link-template.php
@@ -153,6 +153,8 @@ function wp_force_plain_post_permalink( $post = null, $sample = null ) {
* @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`.
* @param bool $leavename Optional. Whether to keep post name or page name. Default false.
* @return string|false The permalink URL. False if the post does not exist.
+ *
+ * @phpstan-return ( $post is WP_Post ? string : string|false )
*/
function get_the_permalink( $post = 0, $leavename = false ) {
return get_permalink( $post, $leavename );
@@ -166,6 +168,8 @@ function get_the_permalink( $post = 0, $leavename = false ) {
* @param int|WP_Post $post Optional. Post ID or post object. Default is the global `$post`.
* @param bool $leavename Optional. Whether to keep post name or page name. Default false.
* @return string|false The permalink URL. False if the post does not exist.
+ *
+ * @phpstan-return ( $post is WP_Post ? string : string|false )
*/
function get_permalink( $post = 0, $leavename = false ) {
$rewritecode = array(
@@ -320,6 +324,8 @@ function get_permalink( $post = 0, $leavename = false ) {
* @param bool $leavename Optional. Whether to keep post name. Default false.
* @param bool $sample Optional. Is it a sample permalink. Default false.
* @return string|false The post permalink URL. False if the post does not exist.
+ *
+ * @phpstan-return ( $post is WP_Post ? string : string|false )
*/
function get_post_permalink( $post = 0, $leavename = false, $sample = false ) {
global $wp_rewrite;
diff --git a/wp-includes/load.php b/wp-includes/load.php
index 061754e8b4..1558a44189 100644
--- a/wp-includes/load.php
+++ b/wp-includes/load.php
@@ -1832,6 +1832,8 @@ function wp_doing_cron() {
* @return bool Whether the variable is an instance of WP_Error.
*
* @phpstan-assert-if-true WP_Error $thing
+ *
+ * @phpstan-return ( $thing is WP_Error ? true : false )
*/
function is_wp_error( $thing ) {
$is_wp_error = ( $thing instanceof WP_Error );
diff --git a/wp-includes/ms-network.php b/wp-includes/ms-network.php
index 8ab8819e26..35cc6bfc06 100644
--- a/wp-includes/ms-network.php
+++ b/wp-includes/ms-network.php
@@ -57,8 +57,14 @@ function get_network( $network = null ) {
*
* @param string|array $args Optional. Array or string of arguments. See WP_Network_Query::parse_query()
* for information on accepted arguments. Default empty array.
- * @return array|int List of WP_Network objects, a list of network IDs when 'fields' is set to 'ids',
- * or the number of networks when 'count' is passed as a query var.
+ * @return WP_Network[]|int[]|int List of WP_Network objects, a list of network IDs when 'fields' is set
+ * to 'ids', or the number of networks when 'count' is passed as a query var.
+ *
+ * @phpstan-return (
+ * $args is array{ count: true, ... } ? int : (
+ * $args is array{ fields: 'ids', ... } ? int[] : array<int, WP_Network>
+ * )
+ * )
*/
function get_networks( $args = array() ) {
$query = new WP_Network_Query();
diff --git a/wp-includes/ms-site.php b/wp-includes/ms-site.php
index f18189c30d..342058156b 100644
--- a/wp-includes/ms-site.php
+++ b/wp-includes/ms-site.php
@@ -441,6 +441,12 @@ function update_sitemeta_cache( $site_ids ) {
* for information on accepted arguments. Default empty array.
* @return WP_Site[]|int[]|int List of WP_Site objects, a list of site IDs when 'fields' is set to 'ids',
* or the number of sites when 'count' is passed as a query var.
+ *
+ * @phpstan-return (
+ * $args is array{ count: true, ... } ? int : (
+ * $args is array{ fields: 'ids', ... } ? int[] : array<int, WP_Site>
+ * )
+ * )
*/
function get_sites( $args = array() ) {
$query = new WP_Site_Query();
diff --git a/wp-includes/pluggable.php b/wp-includes/pluggable.php
index aa39c31d78..ff5a4d5da5 100644
--- a/wp-includes/pluggable.php
+++ b/wp-includes/pluggable.php
@@ -97,6 +97,12 @@ if ( ! function_exists( 'get_user_by' ) ) :
* @param string $field The field to retrieve the user with. id | ID | slug | email | login.
* @param int|string $value A value for $field. A user ID, slug, email address, or login name.
* @return WP_User|false WP_User object on success, false on failure.
+ *
+ * @phpstan-return (
+ * $field is 'id'|'ID'
+ * ? ( $value is int<min, 0> ? false : WP_User|false )
+ * : WP_User|false
+ * )
*/
function get_user_by( $field, $value ) {
$userdata = WP_User::get_data_by( $field, $value );
diff --git a/wp-includes/plugin.php b/wp-includes/plugin.php
index 38e88aa96b..a3e9afacdb 100644
--- a/wp-includes/plugin.php
+++ b/wp-includes/plugin.php
@@ -285,6 +285,13 @@ function apply_filters_ref_array( $hook_name, $args ) {
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
* @phpstan-param Maybe_Callable|false $callback
+ * @phpstan-return (
+ * $callback is false
+ * ? bool
+ * : ( $priority is int
+ * ? bool
+ * : false|int )
+ * )
*/
function has_filter( $hook_name, $callback = false, $priority = false ) {
global $wp_filter;
@@ -600,6 +607,13 @@ function do_action_ref_array( $hook_name, $args ) {
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
* @phpstan-param Maybe_Callable|false $callback
+ * @phpstan-return (
+ * $callback is false
+ * ? bool
+ * : ( $priority is int
+ * ? bool
+ * : false|int )
+ * )
*/
function has_action( $hook_name, $callback = false, $priority = false ) {
return has_filter( $hook_name, $callback, $priority );
diff --git a/wp-includes/rest-api.php b/wp-includes/rest-api.php
index c146289021..36b5b23de9 100644
--- a/wp-includes/rest-api.php
+++ b/wp-includes/rest-api.php
@@ -694,6 +694,8 @@ function rest_ensure_request( $request ) {
* @return WP_REST_Response|WP_Error If response generated an error, WP_Error, if response
* is already an instance, WP_REST_Response, otherwise
* returns a new WP_REST_Response instance.
+ *
+ * @phpstan-return ( $response is WP_Error ? WP_Error : WP_REST_Response )
*/
function rest_ensure_response( $response ) {
if ( is_wp_error( $response ) ) {
@@ -1531,6 +1533,12 @@ function rest_is_ip_address( $ip ) {
*
* @param bool|string|int $value The value being evaluated.
* @return bool Returns the proper associated boolean value.
+ *
+ * @phpstan-return (
+ * $value is false|''|'0'|0|'false'|'False'|'FALSE'
+ * ? false
+ * : ( $value is true|int|lowercase-string ? true : bool )
+ * )
*/
function rest_sanitize_boolean( $value ) {
// String values are translated to `true`; make sure 'false' is false.
diff --git a/wp-includes/revision.php b/wp-includes/revision.php
index 6e27fad4fa..31bbceeb4e 100644
--- a/wp-includes/revision.php
+++ b/wp-includes/revision.php
@@ -307,6 +307,8 @@ function wp_get_post_autosave( $post_id, $user_id = 0 ) {
*
* @param int|WP_Post $post Post ID or post object.
* @return int|false ID of revision's parent on success, false if not a revision.
+ *
+ * @phpstan-return ( $post is int<min, -1> ? false : false|int<0, max> )
*/
function wp_is_post_revision( $post ) {
$post = wp_get_post_revision( $post );
diff --git a/wp-includes/shortcodes.php b/wp-includes/shortcodes.php
index 01fed7244e..2727a992fa 100644
--- a/wp-includes/shortcodes.php
+++ b/wp-includes/shortcodes.php
@@ -145,6 +145,8 @@ function shortcode_exists( $tag ) {
* @param string $content Content to search for shortcodes.
* @param string $tag Shortcode tag to check.
* @return bool Whether the passed content contains the given shortcode.
+ *
+ * @phpstan-return ( $tag is '' ? false : ( $content is empty ? false : bool ) )
*/
function has_shortcode( $content, $tag ) {
if ( ! str_contains( $content, '[' ) ) {
diff --git a/wp-includes/taxonomy.php b/wp-includes/taxonomy.php
index ff90651e6b..1159ca64e6 100644
--- a/wp-includes/taxonomy.php
+++ b/wp-includes/taxonomy.php
@@ -374,6 +374,8 @@ function get_taxonomy( $taxonomy ) {
*
* @param string $taxonomy Name of taxonomy object.
* @return bool Whether the taxonomy exists.
+ *
+ * @phpstan-return ( $taxonomy is non-falsy-string ? bool : false )
*/
function taxonomy_exists( $taxonomy ) {
global $wp_taxonomies;
@@ -979,6 +981,13 @@ function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) {
* @param string $filter Optional. How to sanitize term fields. Default 'raw'.
* @return WP_Term|array|WP_Error|null WP_Term instance (or array) on success, depending on the `$output` value.
* WP_Error if `$taxonomy` does not exist. Null for miscellaneous failure.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return (
+ * $output is 'ARRAY_A' ? array<string, mixed>|WP_Error|null : (
+ * $output is 'ARRAY_N' ? list<mixed>|WP_Error|null : WP_Term|WP_Error|null
+ * )
+ * )
*/
function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
if ( empty( $term ) ) {
@@ -1101,6 +1110,13 @@ function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
* @param string $filter Optional. How to sanitize term fields. Default 'raw'.
* @return WP_Term|array|false WP_Term instance (or array) on success, depending on the `$output` value.
* False if `$taxonomy` does not exist or `$term` was not found.
+ *
+ * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output
+ * @phpstan-return (
+ * $output is 'ARRAY_A' ? array<string, mixed>|false : (
+ * $output is 'ARRAY_N' ? list<mixed>|false : WP_Term|false
+ * )
+ * )
*/
function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
@@ -1822,6 +1838,14 @@ function sanitize_term( $term, $taxonomy, $context = 'display' ) {
* Accepts 'raw', 'edit', 'db', 'display', 'rss',
* 'attribute', or 'js'.
* @return mixed Sanitized field.
+ *
+ * @phpstan-template T of string
+ * @phpstan-param T $value
+ * @phpstan-return (
+ * $field is 'parent'|'term_id'|'count'|'term_group'|'term_taxonomy_id'|'object_id'
+ * ? ( $context is 'raw' ? int<0, max> : int )
+ * : ( $context is 'raw' ? T : ( $context is 'attribute'|'edit'|'js' ? string : mixed ) )
+ * )
*/
function sanitize_term_field( $field, $value, $term_id, $taxonomy, $context ) {
$int_fields = array( 'parent', 'term_id', 'count', 'term_group', 'term_taxonomy_id', 'object_id' );
diff --git a/wp-includes/user.php b/wp-includes/user.php
index 8eab615269..92d0911655 100644
--- a/wp-includes/user.php
+++ b/wp-includes/user.php
@@ -854,6 +854,8 @@ function delete_user_option( $user_id, $option_name, $is_global = false ) {
*
* @param int $user_id User ID.
* @return WP_User|false WP_User object on success, false on failure.
+ *
+ * @phpstan-return ( $user_id is int<min, 0> ? false : WP_User|false )
*/
function get_user( $user_id ) {
return get_user_by( 'id', $user_id );
@@ -869,6 +871,14 @@ function get_user( $user_id ) {
* @param array $args Optional. Arguments to retrieve users. See WP_User_Query::prepare_query()
* for more information on accepted arguments.
* @return array List of users.
+ *
+ * @phpstan-return (
+ * $args is array{ fields: 'all'|'all_with_meta', ... } ? array<int, WP_User> : (
+ * $args is array{ fields: 'ID'|'id', ... } ? list<numeric-string> : (
+ * $args is array{ fields: non-empty-string|non-empty-array<array-key, string>, ... } ? array<int, mixed> : array<int, WP_User>
+ * )
+ * )
+ * )
*/
function get_users( $args = array() ) {
diff --git a/wp-includes/version.php b/wp-includes/version.php
index eb9cdb16c1..3b9bd6fdd0 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-63940';
+$wp_version = '7.2-alpha-63941';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.