diff --git a/src/wp-admin/includes/bookmark.php b/src/wp-admin/includes/bookmark.php index c64bac144c588..eefb05df464de 100644 --- a/src/wp-admin/includes/bookmark.php +++ b/src/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<0, max> : int<0, max>|WP_Error ) */ function wp_insert_link( $linkdata, $wp_error = false ) { global $wpdb; diff --git a/src/wp-admin/includes/menu.php b/src/wp-admin/includes/menu.php index a95cf9e33956e..f1c2985e93e8e 100644 --- a/src/wp-admin/includes/menu.php +++ b/src/wp-admin/includes/menu.php @@ -208,6 +208,10 @@ * @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/src/wp-admin/includes/plugin.php b/src/wp-admin/includes/plugin.php index 53d933d07e4d8..a34d473bca650 100644 --- a/src/wp-admin/includes/plugin.php +++ b/src/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/src/wp-admin/includes/taxonomy.php b/src/wp-admin/includes/taxonomy.php index 470d36d55ffb1..dbdab1af4fab8 100644 --- a/src/wp-admin/includes/taxonomy.php +++ b/src/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/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index 96d2372694200..78cd1bbdc15f5 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/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> : null + * ) */ function _get_block_templates_files( $template_type, $query = array() ) { if ( 'wp_template' !== $template_type && 'wp_template_part' !== $template_type ) { diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php index 487c2765ac249..beaf08d4022c6 100644 --- a/src/wp-includes/blocks.php +++ b/src/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/src/wp-includes/bookmark.php b/src/wp-includes/bookmark.php index 9e44d781909ed..e1c8a6e522a00 100644 --- a/src/wp-includes/bookmark.php +++ b/src/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 : ( + * $output is 'ARRAY_N' ? array : stdClass + * ) + * ) */ function get_bookmark( $bookmark, $output = OBJECT, $filter = 'raw' ) { global $wpdb; diff --git a/src/wp-includes/category-template.php b/src/wp-includes/category-template.php index f268f93cbc461..1d456f309de3d 100644 --- a/src/wp-includes/category-template.php +++ b/src/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 : string ) */ function wp_generate_tag_cloud( $tags, $args = '' ) { $defaults = array( diff --git a/src/wp-includes/category.php b/src/wp-includes/category.php index dbb48d630b076..6f35c5db0bbf4 100644 --- a/src/wp-includes/category.php +++ b/src/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 + * : ( + * $args is array{ fields: 'names'|'slugs', ... } + * ? list + * : ( + * $args is array{ fields: 'id=>name'|'id=>slug', ... } + * ? array + * : ( + * $args is array{ fields: 'id=>parent', ... } + * ? array + * : ( $args is array{ fields: 'ids'|'tt_ids', ... } ? list : array ) + * ) + * ) + * ) + * ) */ 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|WP_Error|null : ( + * $output is 'ARRAY_N' ? list|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|WP_Error|null : ( + * $output is 'ARRAY_N' ? list|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 + * : ( + * $args is array{ fields: 'id=>name'|'id=>slug', ... } + * ? array + * : ( + * $args is array{ fields: 'id=>parent', ... } + * ? array + * : ( $args is array{ fields: 'ids'|'tt_ids', ... } ? list : array ) + * ) + * ) + * )|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|WP_Error|null : ( + * $output is 'ARRAY_N' ? list|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/src/wp-includes/class-wp-block-supports.php b/src/wp-includes/class-wp-block-supports.php index cf2d84f3b6756..c065cd911de04 100644 --- a/src/wp-includes/class-wp-block-supports.php +++ b/src/wp-includes/class-wp-block-supports.php @@ -197,6 +197,8 @@ private function register_attributes() { * * @param string[] $extra_attributes Optional. Array of extra attributes to render on the block wrapper. * @return string String of HTML attributes. + * + * @phpstan-return ( $extra_attributes is empty ? string : non-falsy-string ) */ function get_block_wrapper_attributes( $extra_attributes = array() ) { $new_attributes = WP_Block_Supports::get_instance()->apply_block_supports(); diff --git a/src/wp-includes/class-wp-comment-query.php b/src/wp-includes/class-wp-comment-query.php index f80864d31c8bc..a82cd5cd22372 100644 --- a/src/wp-includes/class-wp-comment-query.php +++ b/src/wp-includes/class-wp-comment-query.php @@ -365,7 +365,12 @@ public function parse_query( $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|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 + * ) + * ) */ public function query( $query ) { $this->query_vars = wp_parse_args( $query ); diff --git a/src/wp-includes/class-wp-dependencies.php b/src/wp-includes/class-wp-dependencies.php index c2daba389bd75..167dfd692ef70 100644 --- a/src/wp-includes/class-wp-dependencies.php +++ b/src/wp-includes/class-wp-dependencies.php @@ -472,6 +472,16 @@ protected function recurse_deps( $queue, $handle ) { * @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'|'queued'|'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/src/wp-includes/class-wp-hook.php b/src/wp-includes/class-wp-hook.php index 1718878308300..9a4d4a2c5eeca 100644 --- a/src/wp-includes/class-wp-hook.php +++ b/src/wp-includes/class-wp-hook.php @@ -250,6 +250,13 @@ public function remove_filter( $hook_name, $callback, $priority ) { * 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/src/wp-includes/class-wp-network-query.php b/src/wp-includes/class-wp-network-query.php index 7a5e9e7f41ffc..a7c747798f930 100644 --- a/src/wp-includes/class-wp-network-query.php +++ b/src/wp-includes/class-wp-network-query.php @@ -179,8 +179,14 @@ public function parse_query( $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 + * ) + * ) */ public function query( $query ) { $this->query_vars = wp_parse_args( $query ); @@ -192,8 +198,8 @@ public function query( $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 @@ public function get_networks() { * @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/src/wp-includes/class-wp-site-query.php b/src/wp-includes/class-wp-site-query.php index 52ae228d90af0..aab8b511fcf83 100644 --- a/src/wp-includes/class-wp-site-query.php +++ b/src/wp-includes/class-wp-site-query.php @@ -265,6 +265,12 @@ public function parse_query( $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 + * ) + * ) */ public function query( $query ) { $this->query_vars = wp_parse_args( $query ); diff --git a/src/wp-includes/class-wp-term.php b/src/wp-includes/class-wp-term.php index 33547e4cbef98..a9a58da875e4a 100644 --- a/src/wp-includes/class-wp-term.php +++ b/src/wp-includes/class-wp-term.php @@ -225,7 +225,7 @@ public function filter( $filter ) { * * @since 4.4.0 * - * @return array Object as array. + * @return array Object as array. */ public function to_array() { return get_object_vars( $this ); diff --git a/src/wp-includes/class-wp-theme.php b/src/wp-includes/class-wp-theme.php index 87399e399a198..87fcd7eec72b4 100644 --- a/src/wp-includes/class-wp-theme.php +++ b/src/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 @@ public function offsetUnset( $offset ) {} * * @param mixed $offset * @return bool + * + * @phpstan-return ( $offset is Theme_Key ? true : false ) */ #[ReturnTypeWillChange] public function offsetExists( $offset ) { @@ -696,6 +700,8 @@ public function offsetExists( $offset ) { * * @param mixed $offset * @return mixed + * + * @phpstan-return ( $offset is Theme_Key ? mixed : null ) */ #[ReturnTypeWillChange] public function offsetGet( $offset ) { @@ -916,6 +922,14 @@ public function get( $header ) { * @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 @@ public function display( $header, $markup = true, $translate = true ) { * '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 @@ private function markup_header( $header, $value, $translate ) { * * @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/src/wp-includes/class-wp-user-query.php b/src/wp-includes/class-wp-user-query.php index 3815023924489..61fc3edbc8ef9 100644 --- a/src/wp-includes/class-wp-user-query.php +++ b/src/wp-includes/class-wp-user-query.php @@ -962,7 +962,8 @@ protected function get_search_sql( $search, $columns, $wild = false ) { * * @since 3.1.0 * - * @return array Array of results. + * @return array 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/src/wp-includes/comment.php b/src/wp-includes/comment.php index 03511ee4db709..239435dc308a3 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -762,6 +762,10 @@ function sanitize_comment_cookies() { * 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. + * + * @phpstan-return ( + * $wp_error is false ? int|string : int|string|WP_Error + * ) */ function wp_allow_comment( $commentdata, $wp_error = false ) { global $wpdb; @@ -2805,6 +2809,8 @@ function wp_send_note_notification( WP_User $user, WP_Comment $comment, ?WP_Post * @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. + * + * @phpstan-return ( $wp_error is false ? bool : true|WP_Error ) */ function wp_set_comment_status( $comment_id, $comment_status, $wp_error = false ) { global $wpdb; @@ -2879,6 +2885,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/src/wp-includes/cron.php b/src/wp-includes/cron.php index 1070ae4680b91..743b37b326b25 100644 --- a/src/wp-includes/cron.php +++ b/src/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/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index 3b78d1610fdad..75d064c414ee2 100644 --- a/src/wp-includes/deprecated.php +++ b/src/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 : ( + * $output is 'ARRAY_N' ? array : 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|null : ( + * $output is 'ARRAY_N' ? non-empty-array|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/src/wp-includes/embed.php b/src/wp-includes/embed.php index e87cf4ec57989..6a7501027a978 100644 --- a/src/wp-includes/embed.php +++ b/src/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/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 5bf001c430a49..123885663ba85 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -2412,6 +2412,10 @@ function sanitize_title_with_dashes( $title, $raw_title = '', $context = 'displa * * @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 ) ) { @@ -2788,6 +2792,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/src/wp-includes/functions.php b/src/wp-includes/functions.php index 89d27f75e9f58..e8932d383b503 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -31,6 +31,8 @@ * @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 ) */ 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' ? 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 $data + * + * @phpstan-return ( $data is array ? 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|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 ) */ 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/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 2f37fbae50bbf..71c234df6612d 100644 --- a/src/wp-includes/general-template.php +++ b/src/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; @@ -3002,6 +3004,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 ); @@ -3069,6 +3073,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 ); @@ -3128,6 +3134,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 ); @@ -3165,6 +3173,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 ); @@ -3315,6 +3325,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 ); @@ -3354,6 +3366,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 ); @@ -4944,6 +4958,12 @@ 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, ... } + * ? null + * : ( $args is array{ type: 'array', ... } ? list : string ) + * ) */ function paginate_links( $args = '' ) { global $wp_query, $wp_rewrite; diff --git a/src/wp-includes/http.php b/src/wp-includes/http.php index c2855a8d8d9c1..1a189a261306b 100644 --- a/src/wp-includes/http.php +++ b/src/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/src/wp-includes/l10n/class-wp-translations.php b/src/wp-includes/l10n/class-wp-translations.php index e919fea8b94b3..2cccf542d8b3b 100644 --- a/src/wp-includes/l10n/class-wp-translations.php +++ b/src/wp-includes/l10n/class-wp-translations.php @@ -112,6 +112,10 @@ private function make_entry( $original, $translations ): Translation_Entry { * @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 @@ public function translate_plural( $singular, $plural, $count = 1, $context = '' * @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/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index 10bda681154f9..3d4ffc23b8f62 100644 --- a/src/wp-includes/link-template.php +++ b/src/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/src/wp-includes/load.php b/src/wp-includes/load.php index 061754e8b4e52..1558a44189226 100644 --- a/src/wp-includes/load.php +++ b/src/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/src/wp-includes/ms-network.php b/src/wp-includes/ms-network.php index 8ab8819e268f2..35cc6bfc06dd7 100644 --- a/src/wp-includes/ms-network.php +++ b/src/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 + * ) + * ) */ function get_networks( $args = array() ) { $query = new WP_Network_Query(); diff --git a/src/wp-includes/ms-site.php b/src/wp-includes/ms-site.php index f18189c30d5a3..342058156be01 100644 --- a/src/wp-includes/ms-site.php +++ b/src/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 + * ) + * ) */ function get_sites( $args = array() ) { $query = new WP_Site_Query(); diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php index aa39c31d78ce5..ff5a4d5da5621 100644 --- a/src/wp-includes/pluggable.php +++ b/src/wp-includes/pluggable.php @@ -97,6 +97,12 @@ function get_userdata( $user_id ) { * @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 ? false : WP_User|false ) + * : WP_User|false + * ) */ function get_user_by( $field, $value ) { $userdata = WP_User::get_data_by( $field, $value ); diff --git a/src/wp-includes/plugin.php b/src/wp-includes/plugin.php index 38e88aa96bb00..a3e9afacdb8dc 100644 --- a/src/wp-includes/plugin.php +++ b/src/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/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index c1462890213e5..5bc3c53c365c5 100644 --- a/src/wp-includes/rest-api.php +++ b/src/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,8 @@ 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 bool ? bool : ( $value is ''|'false'|'FALSE'|'0'|0 ? false : true ) ) */ function rest_sanitize_boolean( $value ) { // String values are translated to `true`; make sure 'false' is false. diff --git a/src/wp-includes/revision.php b/src/wp-includes/revision.php index 6e27fad4fa0a4..e562cd0cd5167 100644 --- a/src/wp-includes/revision.php +++ b/src/wp-includes/revision.php @@ -307,6 +307,12 @@ 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 WP_Post + * ? false|int<0, max> + * : ( $post is int ? false : false|int<0, max> ) + * ) */ function wp_is_post_revision( $post ) { $post = wp_get_post_revision( $post ); diff --git a/src/wp-includes/shortcodes.php b/src/wp-includes/shortcodes.php index 01fed7244e548..1ba655b176733 100644 --- a/src/wp-includes/shortcodes.php +++ b/src/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 empty ? false : ( $content is empty ? false : bool ) ) */ function has_shortcode( $content, $tag ) { if ( ! str_contains( $content, '[' ) ) { diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index d13a11e65581c..ec24ca2ca496b 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/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|WP_Error|null : ( + * $output is 'ARRAY_N' ? list|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|false : ( + * $output is 'ARRAY_N' ? list|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' + * ? int<0, max> + * : ( $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/src/wp-includes/user.php b/src/wp-includes/user.php index b4ab594038174..2cea28357b0d1 100644 --- a/src/wp-includes/user.php +++ b/src/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 ? 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 : ( + * $args is array{ fields: 'ID'|'id', ... } ? array : ( + * $args is array{ fields: non-empty-string|non-empty-array, ... } ? array : array + * ) + * ) + * ) */ function get_users( $args = array() ) { diff --git a/tests/phpstan/baselines/argument.type.neon b/tests/phpstan/baselines/argument.type.neon index 80844ad48e5ac..925f5cc743e04 100644 --- a/tests/phpstan/baselines/argument.type.neon +++ b/tests/phpstan/baselines/argument.type.neon @@ -729,7 +729,7 @@ parameters: count: 1 path: ../../../src/wp-includes/class-wp-customize-manager.php - - message: '#^Parameter \#1 \$postarr of function wp_insert_post expects array\{ID\?\: int, post_author\?\: int, post_date\?\: string, post_date_gmt\?\: string, post_content\?\: string, post_content_filtered\?\: string, post_title\?\: string, post_excerpt\?\: string, \.\.\., \.\.\.\}, array\ given\.$#' + message: '#^Parameter \#1 \$postarr of function wp_insert_post expects array\{ID\?\: int, post_author\?\: int, post_date\?\: string, post_date_gmt\?\: string, post_content\?\: string, post_content_filtered\?\: string, post_title\?\: string, post_excerpt\?\: string, \.\.\., \.\.\.\}, array\\|int\<1, max\>\|string\|false\> given\.$#' identifier: argument.type count: 1 path: ../../../src/wp-includes/class-wp-customize-manager.php @@ -849,7 +849,7 @@ parameters: count: 1 path: ../../../src/wp-includes/class-wp-widget.php - - message: '#^Parameter \#1 \$postarr of function wp_insert_post expects array\{ID\?\: int, post_author\?\: int, post_date\?\: string, post_date_gmt\?\: string, post_content\?\: string, post_content_filtered\?\: string, post_title\?\: string, post_excerpt\?\: string, \.\.\., \.\.\.\}, array\{post_author\: int, post_date\: int\|string, post_date_gmt\: int\|string, post_content\: string, post_title\: string, post_category\: array\\|string, post_status\: ''draft''\|''publish''\} given\.$#' + message: '#^Parameter \#1 \$postarr of function wp_insert_post expects array\{ID\?\: int, post_author\?\: int, post_date\?\: string, post_date_gmt\?\: string, post_content\?\: string, post_content_filtered\?\: string, post_title\?\: string, post_excerpt\?\: string, \.\.\., \.\.\.\}, array\{post_author\: int, post_date\: string, post_date_gmt\: string, post_content\: string, post_title\: string, post_category\: array\\|string, post_status\: ''draft''\|''publish''\} given\.$#' identifier: argument.type count: 1 path: ../../../src/wp-includes/class-wp-xmlrpc-server.php @@ -993,6 +993,11 @@ parameters: identifier: argument.type count: 2 path: ../../../src/wp-includes/general-template.php + - + message: '#^Parameter \#1 \$weekday_number of method WP_Locale\:\:get_weekday\(\) expects int, string\|false given\.$#' + identifier: argument.type + count: 2 + path: ../../../src/wp-includes/general-template.php - message: '#^Parameter \#2 \$replace of function str_replace expects array\\|string, int\<1, max\> given\.$#' identifier: argument.type diff --git a/tests/phpstan/baselines/if.alwaysFalse.neon b/tests/phpstan/baselines/if.alwaysFalse.neon index 6e33ed2a5365c..cc72813ceafbc 100644 --- a/tests/phpstan/baselines/if.alwaysFalse.neon +++ b/tests/phpstan/baselines/if.alwaysFalse.neon @@ -28,11 +28,6 @@ parameters: identifier: if.alwaysFalse count: 2 path: ../../../src/wp-includes/class-wp-block-processor.php - - - message: '#^If condition is always false\.$#' - identifier: if.alwaysFalse - count: 1 - path: ../../../src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php - message: '#^If condition is always false\.$#' identifier: if.alwaysFalse diff --git a/tests/phpstan/baselines/isset.property.neon b/tests/phpstan/baselines/isset.property.neon index ab7d839e22002..f5e272b598f34 100644 --- a/tests/phpstan/baselines/isset.property.neon +++ b/tests/phpstan/baselines/isset.property.neon @@ -186,7 +186,7 @@ parameters: - message: '#^Property WP_Term\:\:\$term_id \(int\) in isset\(\) is not nullable\.$#' identifier: isset.property - count: 1 + count: 2 path: ../../../src/wp-includes/nav-menu.php - message: '#^Property WP_Post\:\:\$post_name \(string\) in isset\(\) is not nullable\.$#' diff --git a/tests/phpstan/baselines/property.nonObject.neon b/tests/phpstan/baselines/property.nonObject.neon index d242b9373685b..895c9e3656d3d 100644 --- a/tests/phpstan/baselines/property.nonObject.neon +++ b/tests/phpstan/baselines/property.nonObject.neon @@ -183,21 +183,11 @@ parameters: identifier: property.nonObject count: 1 path: ../../../src/wp-includes/class-wp-customize-manager.php - - - message: '#^Cannot access property \$object_id on array\|WP_Error\|WP_Term\.$#' - identifier: property.nonObject - count: 1 - path: ../../../src/wp-includes/class-wp-term-query.php - message: '#^Cannot access property \$term_id on string\|WP_Customize_Setting\.$#' identifier: property.nonObject count: 1 path: ../../../src/wp-includes/customize/class-wp-customize-nav-menu-control.php - - - message: '#^Cannot access property \$link_id on array\|object\.$#' - identifier: property.nonObject - count: 3 - path: ../../../src/wp-includes/link-template.php - message: '#^Cannot access property \$plugins on array\|object\.$#' identifier: property.nonObject @@ -218,18 +208,8 @@ parameters: identifier: property.nonObject count: 1 path: ../../../src/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php - - - message: '#^Cannot access property \$parent on array\|object\.$#' - identifier: property.nonObject - count: 1 - path: ../../../src/wp-includes/taxonomy.php - message: '#^Cannot access property \$template_name on array\.$#' identifier: property.nonObject count: 1 path: ../../../src/wp-includes/taxonomy.php - - - message: '#^Cannot access property \$term_id on array\|object\.$#' - identifier: property.nonObject - count: 4 - path: ../../../src/wp-includes/taxonomy.php diff --git a/tests/phpstan/baselines/property.notFound.neon b/tests/phpstan/baselines/property.notFound.neon index c7d60d13061d2..460a5082ab0b8 100644 --- a/tests/phpstan/baselines/property.notFound.neon +++ b/tests/phpstan/baselines/property.notFound.neon @@ -293,6 +293,11 @@ parameters: identifier: property.notFound count: 2 path: ../../../src/wp-includes/class-walker-nav-menu.php + - + message: '#^Access to an undefined property WP_Error\|WP_Term\:\:\$object_id\.$#' + identifier: property.notFound + count: 1 + path: ../../../src/wp-includes/class-wp-term-query.php - message: '#^Access to an undefined property WP_Query\:\:\$comments_by_type\.$#' identifier: property.notFound