diff --git a/phpstan.neon.dist b/phpstan.neon.dist index d67d63bd45bc1..03b3e2ebd00a5 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -9,7 +9,6 @@ includes: - tests/phpstan/base.neon # The baseline file includes preexisting errors in the codebase that should be ignored. # https://phpstan.org/user-guide/baseline - - tests/phpstan/baseline/level-0.php - tests/phpstan/baseline/level-1.php - tests/phpstan/baseline/level-2.php - tests/phpstan/baseline/level-3.php @@ -26,6 +25,18 @@ parameters: - # Inner functions arent supported by PHPstan. message: '#Function wxr_[a-z_]+ not found#' path: src/wp-admin/includes/export.php + - + identifier: function.inner + path: src/wp-admin/includes/export.php + count: 13 + - + identifier: function.inner + path: src/wp-admin/includes/file.php + count: 1 + - + identifier: function.inner + path: src/wp-includes/canonical.php + count: 1 # Level 1: - # These are too noisy at the moment. diff --git a/src/wp-activate.php b/src/wp-activate.php index 0c3321f74618c..61851232e7d23 100644 --- a/src/wp-activate.php +++ b/src/wp-activate.php @@ -37,7 +37,8 @@ if ( $key ) { $redirect_url = remove_query_arg( 'key' ); - if ( remove_query_arg( false ) !== $redirect_url ) { + // If we still have query args, stash the key and redirect to handle them. + if ( remove_query_arg( '' ) !== $redirect_url ) { setcookie( $activate_cookie, $key, 0, $activate_path, COOKIE_DOMAIN, is_ssl(), true ); wp_safe_redirect( $redirect_url ); exit; diff --git a/src/wp-admin/about.php b/src/wp-admin/about.php index 455058a47cead..c52ec0456ce3a 100644 --- a/src/wp-admin/about.php +++ b/src/wp-admin/about.php @@ -298,9 +298,12 @@ : (int<1, max>|\WP_Error) ) */ function wp_insert_link( $linkdata, $wp_error = false ) { global $wpdb; @@ -295,7 +297,7 @@ function wp_set_link_cats( $link_id = 0, $link_categories = array() ) { * @since 2.0.0 * * @param array $linkdata Link data to update. See wp_insert_link() for accepted arguments. - * @return int|WP_Error Value 0 or WP_Error on failure. The updated link ID on success. + * @return int Value 0 on failure. The updated link ID on success. */ function wp_update_link( $linkdata ) { $link_id = (int) $linkdata['link_id']; diff --git a/src/wp-admin/includes/class-custom-image-header.php b/src/wp-admin/includes/class-custom-image-header.php index e8a16e47dc80a..c335d0e26b8f2 100644 --- a/src/wp-admin/includes/class-custom-image-header.php +++ b/src/wp-admin/includes/class-custom-image-header.php @@ -310,6 +310,8 @@ public function process_default_headers() { * * @param string $type The header type. One of 'default' (for the Uploaded Images control) * or 'uploaded' (for the Uploaded Images control). + * + * @phpstan-param 'default'|'uploaded' $type */ public function show_header_selector( $type = 'default' ) { if ( 'default' === $type ) { @@ -1169,6 +1171,8 @@ public function filter_upload_tabs( $tabs ) { * registered for that theme; and the key of an image uploaded for that theme * (the attachment ID of the image). Or an array of arguments: attachment_id, * url, width, height. All are required. + * + * @phpstan-param 'random-default-image'|'random-uploaded-image'|array{attachment_id: int<1, max>, url: string, width: int<0, max>, height: int<0, max>} $choice */ final public function set_header_image( $choice ) { if ( is_array( $choice ) || is_object( $choice ) ) { diff --git a/src/wp-admin/includes/class-wp-filesystem-ssh2.php b/src/wp-admin/includes/class-wp-filesystem-ssh2.php index 9e0cb885b0bcc..30bd38c3cf2f2 100644 --- a/src/wp-admin/includes/class-wp-filesystem-ssh2.php +++ b/src/wp-admin/includes/class-wp-filesystem-ssh2.php @@ -672,6 +672,7 @@ public function size( $file ) { * Default 0. */ public function touch( $file, $time = 0, $atime = 0 ) { + // @phpstan-ignore-next-line // Not implemented. } diff --git a/src/wp-admin/includes/class-wp-importer.php b/src/wp-admin/includes/class-wp-importer.php index 8489919f8a5e2..686108d73e9c9 100644 --- a/src/wp-admin/includes/class-wp-importer.php +++ b/src/wp-admin/includes/class-wp-importer.php @@ -131,7 +131,11 @@ public function get_imported_comments( $blog_id ) { /** * @param int $blog_id - * @return int|void + * @return int + * + * @phpstan-param int|string $blog_id + * + * @phpstan-return ( $blog_id is (int|numeric-string) ? int : (int|never) ) */ public function set_blog( $blog_id ) { if ( is_numeric( $blog_id ) ) { diff --git a/src/wp-admin/includes/class-wp-list-table.php b/src/wp-admin/includes/class-wp-list-table.php index 6568b1563bef4..d4bc6a2d650ad 100644 --- a/src/wp-admin/includes/class-wp-list-table.php +++ b/src/wp-admin/includes/class-wp-list-table.php @@ -307,6 +307,8 @@ public function prepare_items() { * @since 3.1.0 * * @param array|string $args Array or string of arguments with information about the pagination. + * + * @phpstan-param array{total_items?: int, total_pages?: int, per_page?: int} $args */ protected function set_pagination_args( $args ) { $args = wp_parse_args( diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index bc25dd0045a87..de0867eb16533 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -819,7 +819,7 @@ public function display_rows( $posts = array(), $level = 0 ) { * @param array $posts * @param int $level */ - private function _display_rows( $posts, $level = 0 ) { + private function _display_rows( $posts, $level = 0 ): void { $post_type = $this->screen->post_type; // Create array of post IDs. @@ -846,7 +846,7 @@ private function _display_rows( $posts, $level = 0 ) { * @param int $pagenum * @param int $per_page */ - private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) { + private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ): void { global $wpdb; $level = 0; @@ -956,7 +956,7 @@ private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 2 * @param int $per_page * @param array $to_display List of pages to be displayed. Passed by reference. */ - private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ) { + private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ): void { if ( ! isset( $children_pages[ $parent_page ] ) ) { return; } diff --git a/src/wp-admin/includes/class-wp-screen.php b/src/wp-admin/includes/class-wp-screen.php index 60a82476c1fd0..f13a703b2e2fb 100644 --- a/src/wp-admin/includes/class-wp-screen.php +++ b/src/wp-admin/includes/class-wp-screen.php @@ -175,8 +175,10 @@ final class WP_Screen { /** * Stores the result of the public show_screen_options function. * + * Set when calling ::show_screen_options() for the first time. + * * @since 3.3.0 - * @var bool + * @var ?bool */ private $_show_screen_options; @@ -407,7 +409,7 @@ public static function get( $hook_name = '' ) { * @global string $typenow The post type of the current screen. * @global string $taxnow The taxonomy of the current screen. */ - public function set_current_screen() { + public function set_current_screen(): void { global $current_screen, $taxnow, $typenow; $current_screen = $this; @@ -472,7 +474,7 @@ public function is_block_editor( $set = null ) { * @param WP_Screen $screen A screen object. * @param string $help Help text. */ - public static function add_old_compat_help( $screen, $help ) { + public static function add_old_compat_help( $screen, $help ): void { self::$_old_compat_help[ $screen->id ] = $help; } @@ -485,7 +487,7 @@ public static function add_old_compat_help( $screen, $help ) { * * @param string $parent_file The parent file of the screen. Typically the $parent_file global. */ - public function set_parentage( $parent_file ) { + public function set_parentage( $parent_file ): void { $this->parent_file = $parent_file; list( $this->parent_base ) = explode( '?', $parent_file ); $this->parent_base = str_replace( '.php', '', $this->parent_base ); @@ -502,7 +504,7 @@ public function set_parentage( $parent_file ) { * @param string $option Option ID. * @param mixed $args Option-dependent arguments. */ - public function add_option( $option, $args = array() ) { + public function add_option( $option, $args = array() ): void { $this->_options[ $option ] = $args; } @@ -513,7 +515,7 @@ public function add_option( $option, $args = array() ) { * * @param string $option Option ID. */ - public function remove_option( $option ) { + public function remove_option( $option ): void { unset( $this->_options[ $option ] ); } @@ -522,7 +524,7 @@ public function remove_option( $option ) { * * @since 3.8.0 */ - public function remove_options() { + public function remove_options(): void { $this->_options = array(); } @@ -545,7 +547,7 @@ public function get_options() { * @param string $option Option name. * @param string|false $key Optional. Specific array key for when the option is an array. * Default false. - * @return string The option value if set, null otherwise. + * @return ?string The option value if set, null otherwise. */ public function get_option( $option, $key = false ) { if ( ! isset( $this->_options[ $option ] ) ) { @@ -598,7 +600,7 @@ public function get_help_tabs() { * @since 3.4.0 * * @param string $id Help Tab ID. - * @return array Help tab arguments. + * @return ?array Help tab arguments. */ public function get_help_tab( $id ) { if ( ! isset( $this->_help_tabs[ $id ] ) ) { @@ -631,7 +633,7 @@ public function get_help_tab( $id ) { * @type int $priority Optional. The priority of the tab, used for ordering. Default 10. * } */ - public function add_help_tab( $args ) { + public function add_help_tab( $args ): void { $defaults = array( 'title' => false, 'id' => false, @@ -659,7 +661,7 @@ public function add_help_tab( $args ) { * * @param string $id The help tab ID. */ - public function remove_help_tab( $id ) { + public function remove_help_tab( $id ): void { unset( $this->_help_tabs[ $id ] ); } @@ -668,7 +670,7 @@ public function remove_help_tab( $id ) { * * @since 3.3.0 */ - public function remove_help_tabs() { + public function remove_help_tabs(): void { $this->_help_tabs = array(); } @@ -693,7 +695,7 @@ public function get_help_sidebar() { * * @param string $content Sidebar content in plain text or HTML. */ - public function set_help_sidebar( $content ) { + public function set_help_sidebar( $content ): void { $this->_help_sidebar = $content; } @@ -733,7 +735,7 @@ public function get_screen_reader_content() { * @since 4.4.0 * * @param string $key Screen reader text array named key. - * @return string Screen reader text string. + * @return ?string Screen reader text string. Null if no text is associated with the key. */ public function get_screen_reader_text( $key ) { if ( ! isset( $this->_screen_reader_content[ $key ] ) ) { @@ -787,7 +789,7 @@ public function remove_screen_reader_content() { * * @global string $screen_layout_columns */ - public function render_screen_meta() { + public function render_screen_meta(): void { /** * Filters the legacy contextual help list. @@ -950,7 +952,7 @@ public function render_screen_meta() { $this->columns = (int) get_user_option( "screen_layout_$this->id" ); if ( ! $this->columns && $this->get_option( 'layout_columns', 'default' ) ) { - $this->columns = $this->get_option( 'layout_columns', 'default' ); + $this->columns = (int) $this->get_option( 'layout_columns', 'default' ); } } $GLOBALS['screen_layout_columns'] = $this->columns; // Set the global for back-compat. @@ -1048,7 +1050,7 @@ public function show_screen_options() { * @type bool $wrap Whether the screen-options-wrap div will be included. Defaults to true. * } */ - public function render_screen_options( $options = array() ) { + public function render_screen_options( $options = array() ): void { $options = wp_parse_args( $options, array( @@ -1107,7 +1109,7 @@ public function render_screen_options( $options = array() ) { * * @global array $wp_meta_boxes Global meta box state. */ - public function render_meta_boxes_preferences() { + public function render_meta_boxes_preferences(): void { global $wp_meta_boxes; if ( ! isset( $wp_meta_boxes[ $this->id ] ) ) { @@ -1150,7 +1152,7 @@ public function render_meta_boxes_preferences() { * * @since 4.4.0 */ - public function render_list_table_columns_preferences() { + public function render_list_table_columns_preferences(): void { $columns = get_column_headers( $this ); $hidden = get_hidden_columns( $this ); @@ -1198,7 +1200,7 @@ public function render_list_table_columns_preferences() { * * @since 3.3.0 */ - public function render_screen_layout() { + public function render_screen_layout(): void { if ( ! $this->get_option( 'layout_columns' ) ) { return; } @@ -1230,7 +1232,7 @@ public function render_screen_layout() { * * @since 3.3.0 */ - public function render_per_page_options() { + public function render_per_page_options(): void { if ( null === $this->get_option( 'per_page' ) ) { return; } @@ -1296,7 +1298,7 @@ public function render_per_page_options() { * * @global string $mode List table view mode. */ - public function render_view_mode() { + public function render_view_mode(): void { global $mode; $screen = get_current_screen(); @@ -1351,7 +1353,7 @@ public function render_view_mode() { * @param string $key The screen reader text array named key. * @param string $tag Optional. The HTML tag to wrap the screen reader text. Default h2. */ - public function render_screen_reader_content( $key = '', $tag = 'h2' ) { + public function render_screen_reader_content( $key = '', $tag = 'h2' ): void { if ( ! isset( $this->_screen_reader_content[ $key ] ) ) { return; diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php index 0658662126a59..beb19227a9b8f 100644 --- a/src/wp-admin/includes/file.php +++ b/src/wp-admin/includes/file.php @@ -2193,7 +2193,7 @@ function WP_Filesystem( $args = false, $context = false, $allow_relaxed_file_own $abstraction_file = apply_filters( 'filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method ); if ( ! file_exists( $abstraction_file ) ) { - return; + return null; } require_once $abstraction_file; diff --git a/src/wp-admin/includes/list-table.php b/src/wp-admin/includes/list-table.php index 1e2c190c80fe9..d2c863a06ebe1 100644 --- a/src/wp-admin/includes/list-table.php +++ b/src/wp-admin/includes/list-table.php @@ -17,8 +17,14 @@ * @param string $class_name The type of the list table, which is the class name. * @param array $args Optional. Arguments to pass to the class. Accepts 'screen'. * @return WP_List_Table|false List table object on success, false if the class does not exist. + + * @phpstan-template T of WP_List_Table + * @phpstan-param class-string|string $class_name + * @phpstan-param array{screen?: string}&array $args + * @phpstan-return ( $class_name is class-string ? new : false ) */ function _get_list_table( $class_name, $args = array() ) { + /** @var array, mixed> */ $core_classes = array( // Site Admin. 'WP_Posts_List_Table' => 'posts', diff --git a/src/wp-admin/includes/plugin.php b/src/wp-admin/includes/plugin.php index 300edff42fb1f..73c31a0c8cfca 100644 --- a/src/wp-admin/includes/plugin.php +++ b/src/wp-admin/includes/plugin.php @@ -926,7 +926,7 @@ function delete_plugins( $plugins, $deprecated = '' ) { require_once ABSPATH . 'wp-admin/admin-footer.php'; exit; } - return; + return null; } if ( ! WP_Filesystem( $credentials ) ) { @@ -941,7 +941,7 @@ function delete_plugins( $plugins, $deprecated = '' ) { require_once ABSPATH . 'wp-admin/admin-footer.php'; exit; } - return; + return null; } if ( ! is_object( $wp_filesystem ) ) { @@ -1387,6 +1387,9 @@ function uninstall_plugin( $plugin ) { * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS. * @param int|float $position Optional. The position in the menu order this item should appear. * @return string The resulting page's hook_suffix. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable|callable-string */ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) { global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages; @@ -1427,7 +1430,7 @@ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $call if ( null === $position || ! is_numeric( $position ) ) { $menu[] = $new_menu; } elseif ( isset( $menu[ (string) $position ] ) ) { - $collision_avoider = base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) * 0.00001; + $collision_avoider = ( (int) base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) ) * 0.00001; $position = (string) ( $position + $collision_avoider ); $menu[ $position ] = $new_menu; } else { @@ -1482,6 +1485,9 @@ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $call * @param callable $callback Optional. The function to be called to output the content for this page. * @param int|float $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, @@ -1595,6 +1601,9 @@ function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1619,6 +1628,9 @@ function add_management_page( $page_title, $menu_title, $capability, $menu_slug, * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1643,6 +1655,9 @@ function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $c * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1667,6 +1682,9 @@ function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1691,6 +1709,9 @@ function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $c * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { if ( current_user_can( 'edit_users' ) ) { @@ -1720,6 +1741,9 @@ function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1744,6 +1768,9 @@ function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1768,6 +1795,9 @@ function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1792,6 +1822,9 @@ function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1816,6 +1849,9 @@ function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); @@ -1840,6 +1876,9 @@ function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $cal * @param callable $callback Optional. The function to be called to output the content for this page. * @param int $position Optional. The position in the menu order this item should appear. * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required. + * + * @phpstan-param callable|callable-string $callback + * @phpstan-return ''|callable-string|false */ function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position ); diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index 97345331de221..a61fa9ca8a472 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -986,7 +986,7 @@ function wp_write_post() { * * @since 2.0.0 * - * @return int|void Post ID on success, void on failure. + * @return int Post ID on success, dies on failure. */ function write_post() { $result = wp_write_post(); diff --git a/src/wp-admin/includes/taxonomy.php b/src/wp-admin/includes/taxonomy.php index 359cfafe2ffb5..f3bcbd9252715 100644 --- a/src/wp-admin/includes/taxonomy.php +++ b/src/wp-admin/includes/taxonomy.php @@ -55,7 +55,7 @@ function get_category_to_edit( $id ) { function wp_create_category( $cat_name, $category_parent = 0 ) { $id = category_exists( $cat_name, $category_parent ); if ( $id ) { - return $id; + return (int) $id; } return wp_insert_category( @@ -117,6 +117,8 @@ 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<0, max> : (int<1, max>|\WP_Error) ) */ function wp_insert_category( $catarr, $wp_error = false ) { $cat_defaults = array( @@ -218,6 +220,14 @@ 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-admin/includes/theme.php b/src/wp-admin/includes/theme.php index 8fc9c00f149db..4ae7d2936d8f8 100644 --- a/src/wp-admin/includes/theme.php +++ b/src/wp-admin/includes/theme.php @@ -40,7 +40,7 @@ function delete_theme( $stylesheet, $redirect = '' ) { require_once ABSPATH . 'wp-admin/admin-footer.php'; exit; } - return; + return null; } if ( ! WP_Filesystem( $credentials ) ) { @@ -55,7 +55,7 @@ function delete_theme( $stylesheet, $redirect = '' ) { require_once ABSPATH . 'wp-admin/admin-footer.php'; exit; } - return; + return null; } if ( ! is_object( $wp_filesystem ) ) { diff --git a/src/wp-admin/install.php b/src/wp-admin/install.php index 64cb4104c41ae..feebf1a726cd9 100644 --- a/src/wp-admin/install.php +++ b/src/wp-admin/install.php @@ -6,7 +6,7 @@ * @subpackage Administration */ -// Confidence check. +// @phpstan-ignore if.alwaysFalse (Confidence check) if ( false ) { ?> diff --git a/src/wp-admin/menu-header.php b/src/wp-admin/menu-header.php index dcdf58d6391ce..0502153ca3898 100644 --- a/src/wp-admin/menu-header.php +++ b/src/wp-admin/menu-header.php @@ -111,7 +111,7 @@ function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) { $class[] = esc_attr( $item[4] ); } - $class = $class ? ' class="' . implode( ' ', $class ) . '"' : ''; + $class = ' class="' . implode( ' ', $class ) . '"'; $id = ! empty( $item[5] ) ? ' id="' . preg_replace( '|[^a-zA-Z0-9_:.]|', '-', $item[5] ) . '"' : ''; $img = ''; $img_style = ''; diff --git a/src/wp-admin/network/sites.php b/src/wp-admin/network/sites.php index 17a072287d25b..b4d266f2b9050 100644 --- a/src/wp-admin/network/sites.php +++ b/src/wp-admin/network/sites.php @@ -240,7 +240,7 @@ html(); } elseif ( current_user_can( 'activate_plugins' ) ) { if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ) ) { diff --git a/src/wp-admin/upload.php b/src/wp-admin/upload.php index 1110f63ce8df5..264b01d4304be 100644 --- a/src/wp-admin/upload.php +++ b/src/wp-admin/upload.php @@ -421,7 +421,7 @@ function () { if ( current_user_can( 'upload_files' ) ) { ?> - $selector, 'declarations' => array( 'gap' => $gap_value ), @@ -526,7 +526,7 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false } $gap_value = trim( $combined_gap_value ); - if ( null !== $gap_value && ! $should_skip_gap_serialization ) { + if ( '' !== $gap_value && ! $should_skip_gap_serialization ) { $layout_styles[] = array( 'selector' => $selector, 'declarations' => array( 'gap' => $gap_value ), diff --git a/src/wp-includes/bookmark-template.php b/src/wp-includes/bookmark-template.php index 893494a7e92cd..fd04d21a8c51f 100644 --- a/src/wp-includes/bookmark-template.php +++ b/src/wp-includes/bookmark-template.php @@ -207,6 +207,8 @@ function _walk_bookmarks( $bookmarks, $args = '' ) { * Default 'ASC'. * } * @return void|string Void if 'echo' argument is true, HTML list of bookmarks if 'echo' is false. + * + * @phpstan-return ($args is array{echo: false|0}&array ? string : void) */ function wp_list_bookmarks( $args = '' ) { $defaults = array( diff --git a/src/wp-includes/bookmark.php b/src/wp-includes/bookmark.php index d4b597843820d..5c8f1816c9ad3 100644 --- a/src/wp-includes/bookmark.php +++ b/src/wp-includes/bookmark.php @@ -19,7 +19,11 @@ * correspond to an stdClass object, an associative array, or a numeric array, * 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/capabilities.php b/src/wp-includes/capabilities.php index 85f68985de511..f8e52d98379c6 100644 --- a/src/wp-includes/capabilities.php +++ b/src/wp-includes/capabilities.php @@ -909,6 +909,8 @@ function map_meta_cap( $cap, $user_id, ...$args ) { * @param mixed ...$args Optional further parameters, typically starting with an object ID. * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is * passed, whether the current user has the given meta capability for the given object. + * + * @phpstan-impure */ function current_user_can( $capability, ...$args ) { return user_can( wp_get_current_user(), $capability, ...$args ); @@ -935,6 +937,8 @@ function current_user_can( $capability, ...$args ) { * @param string $capability Capability name. * @param mixed ...$args Optional further parameters, typically starting with an object ID. * @return bool Whether the user has the given capability. + * + * @phpstan-impure */ function current_user_can_for_site( $site_id, $capability, ...$args ) { $switched = is_multisite() ? switch_to_blog( $site_id ) : false; diff --git a/src/wp-includes/category-template.php b/src/wp-includes/category-template.php index b2c88c9c25413..8d0821c76720a 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}&array ? (string|false) : (false|void) ) */ function wp_list_categories( $args = '' ) { $defaults = array( @@ -712,6 +714,8 @@ function wp_list_categories( $args = '' ) { * } * @return void|string|string[] Void if 'echo' argument is true, or on failure. Otherwise, tag cloud * as a string or an array, depending on 'format' argument. + * + * @phpstan-return ($args is array{format: 'array'}&array ? (array|void) : ($args is array{echo: false|0}&array ? (string|void) : void)) */ function wp_tag_cloud( $args = '' ) { $defaults = array( @@ -841,6 +845,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 ? 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 d1c43274d704b..992216aad75ab 100644 --- a/src/wp-includes/category.php +++ b/src/wp-includes/category.php @@ -22,6 +22,18 @@ * @type string $taxonomy Taxonomy to retrieve terms for. Default 'category'. * } * @return array List of category objects. + * + * @phpstan-return ( + * $args is array{fields: 'count'}&array ? list : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is array{fields: 'ids'|'tt_ids'}&array ? list : array + * ) + * ) + * ) + * ) + * ) */ function get_categories( $args = '' ) { $defaults = array( 'taxonomy' => 'category' ); @@ -88,11 +100,29 @@ 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 ( + * $category is object ? ( + * array|\WP_Term + * ) : ( + * array|\WP_Term|\WP_Error|null) & ( + * $output is 'ARRAY_A' ? + * ( array|\WP_Error|null ) + * : ( + * $output is 'ARRAY_N' ? + * ( array|\WP_Error|null) + * : ( \WP_Term|\WP_Error|null ) + * ) + * ) + * ) + * ) + * ) */ function get_category( $category, $output = OBJECT, $filter = 'raw' ) { $category = get_term( $category, 'category', $output, $filter ); - if ( is_wp_error( $category ) ) { + if ( null === $category || is_wp_error( $category ) ) { return $category; } @@ -120,7 +150,16 @@ function get_category( $category, $output = OBJECT, $filter = 'raw' ) { * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which * 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. + * + * @return WP_Term|array|WP_Error|null Category data. WP_Error if $category is empty, + * Returns 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' ? (array|\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 ) ); @@ -144,7 +183,7 @@ function get_category_by_path( $category_path, $full_match = true, $output = OBJ ); if ( empty( $categories ) ) { - return; + return null; } foreach ( $categories as $category ) { @@ -257,6 +296,10 @@ function cat_is_ancestor_of( $cat1, $cat2 ) { * @param object|array $category Category data. * @param string $context Optional. Default 'display'. * @return object|array Same type as $category with sanitized data for safe use. + * + * @phpstan-template T as object|array + * @phpstan-param T $category + * @phpstan-return T */ function sanitize_category( $category, $context = 'display' ) { return sanitize_term( $category, 'category', $context ); @@ -291,6 +334,18 @@ 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: 'count'}&array ? numeric-string : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is array{fields: 'ids'|'tt_ids'}&array ? list : array + * ) + * ) + * ) + * ) + * ) |\WP_Error */ function get_tags( $args = '' ) { $defaults = array( 'taxonomy' => 'post_tag' ); @@ -337,6 +392,8 @@ 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-return ($output is 'OBJECT' ? WP_Term : array)|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-bindings-registry.php b/src/wp-includes/class-wp-block-bindings-registry.php index 519453d22ba92..5e9418ceb2029 100644 --- a/src/wp-includes/class-wp-block-bindings-registry.php +++ b/src/wp-includes/class-wp-block-bindings-registry.php @@ -95,15 +95,6 @@ final class WP_Block_Bindings_Registry { * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. */ public function register( string $source_name, array $source_properties ) { - if ( ! is_string( $source_name ) ) { - _doing_it_wrong( - __METHOD__, - __( 'Block bindings source name must be a string.' ), - '6.5.0' - ); - return false; - } - if ( preg_match( '/[A-Z]+/', $source_name ) ) { _doing_it_wrong( __METHOD__, diff --git a/src/wp-includes/class-wp-block-processor.php b/src/wp-includes/class-wp-block-processor.php index 06dc4478e3874..43038b585dba6 100644 --- a/src/wp-includes/class-wp-block-processor.php +++ b/src/wp-includes/class-wp-block-processor.php @@ -1599,6 +1599,8 @@ public function opens_block( string ...$block_type ): bool { * @see self::is_non_whitespace_html() * * @return bool Whether the processor is matched on an HTML span. + * + * @phpstan-impure */ public function is_html(): bool { return self::HTML_SPAN === $this->state; diff --git a/src/wp-includes/class-wp-comment-query.php b/src/wp-includes/class-wp-comment-query.php index 6c813c7e1a7db..b8a57a48cea3b 100644 --- a/src/wp-includes/class-wp-comment-query.php +++ b/src/wp-includes/class-wp-comment-query.php @@ -359,7 +359,9 @@ public function parse_query( $query = '' ) { * @since 4.2.0 Moved parsing to WP_Comment_Query::parse_query(). * * @param string|array $query Array or URL query string of parameters. - * @return array|int List of comments, or number of comments when 'count' is passed as a query var. + * @return WP_Comment[]|int[]|int List of comments, or number of comments when 'count' is passed as a query var. + * + * @phpstan-return ( $query is array{count:true}&array ? int : (WP_Comment[]|int[]) ) */ public function query( $query ) { $this->query_vars = wp_parse_args( $query ); @@ -683,10 +685,8 @@ protected function get_comment_ids() { break; } - } - // Default to DESC. - if ( ! $comment_id_order ) { + // Default to DESC. $comment_id_order = 'DESC'; } diff --git a/src/wp-includes/class-wp-dependencies.php b/src/wp-includes/class-wp-dependencies.php index f0c1aaa371ed0..92c78f93dd6c2 100644 --- a/src/wp-includes/class-wp-dependencies.php +++ b/src/wp-includes/class-wp-dependencies.php @@ -91,7 +91,7 @@ class WP_Dependencies { * * @since 5.4.0 * - * @var array + * @var ?array */ private $all_queued_deps; diff --git a/src/wp-includes/class-wp-duotone.php b/src/wp-includes/class-wp-duotone.php index a22745d8950dd..afb4a9287f9fd 100644 --- a/src/wp-includes/class-wp-duotone.php +++ b/src/wp-includes/class-wp-duotone.php @@ -52,7 +52,7 @@ class WP_Duotone { * * @since 6.3.0 * - * @var array + * @var ?array */ private static $global_styles_block_names; @@ -76,7 +76,7 @@ class WP_Duotone { * * @since 6.3.0 * - * @var array + * @var ?array */ private static $global_styles_presets; @@ -246,7 +246,7 @@ private static function colord_parse_hex( $hex ) { 'r' => (int) base_convert( $hex[0] . $hex[0], 16, 10 ), 'g' => (int) base_convert( $hex[1] . $hex[1], 16, 10 ), 'b' => (int) base_convert( $hex[2] . $hex[2], 16, 10 ), - 'a' => 4 === strlen( $hex ) ? round( base_convert( $hex[3] . $hex[3], 16, 10 ) / 255, 2 ) : 1, + 'a' => 4 === strlen( $hex ) ? round( ( (int) base_convert( $hex[3] . $hex[3], 16, 10 ) ) / 255, 2 ) : 1, ); } diff --git a/src/wp-includes/class-wp-feed-cache-transient.php b/src/wp-includes/class-wp-feed-cache-transient.php index 2beeab69d2577..d7ee87d617d36 100644 --- a/src/wp-includes/class-wp-feed-cache-transient.php +++ b/src/wp-includes/class-wp-feed-cache-transient.php @@ -50,10 +50,10 @@ class WP_Feed_Cache_Transient implements SimplePie\Cache\Base { * @since 3.2.0 Updated to use a PHP5 constructor. * @since 6.7.0 Parameter names have been updated to be in line with the `SimplePie\Cache\Base` interface. * - * @param string $location URL location (scheme is used to determine handler). - * @param string $name Unique identifier for cache object. - * @param Base::TYPE_FEED|Base::TYPE_IMAGE $type Either `TYPE_FEED` ('spc') for SimplePie data, - * or `TYPE_IMAGE` ('spi') for image data. + * @param string $location URL location (scheme is used to determine handler). + * @param string $name Unique identifier for cache object. + * @param \SimplePie\Cache\Base::TYPE_FEED|\SimplePie\Cache\Base::TYPE_IMAGE $type Either `TYPE_FEED` ('spc') for SimplePie data, + * or `TYPE_IMAGE` ('spi') for image data. */ public function __construct( $location, $name, $type ) { $this->name = 'feed_' . $name; diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index ba7395f959af0..aab6fa93c40a5 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -22,7 +22,7 @@ class WP_Query { * Query vars set by the user. * * @since 1.5.0 - * @var array + * @var ?array */ public $query; @@ -72,7 +72,7 @@ class WP_Query { * The ID of the queried object. * * @since 1.5.0 - * @var int + * @var ?int */ public $queried_object_id; @@ -80,7 +80,7 @@ class WP_Query { * SQL for the database query. * * @since 2.0.1 - * @var string + * @var ?string */ public $request; @@ -88,7 +88,7 @@ class WP_Query { * Array of post objects or post IDs. * * @since 1.5.0 - * @var WP_Post[]|int[] + * @var WP_Post[]|int[]|null */ public $posts; @@ -139,7 +139,7 @@ class WP_Query { * The list of comments for current post. * * @since 2.2.0 - * @var WP_Comment[] + * @var ?WP_Comment[] */ public $comments; @@ -163,7 +163,7 @@ class WP_Query { * Current comment object. * * @since 2.2.0 - * @var WP_Comment + * @var ?WP_Comment */ public $comment; @@ -466,7 +466,7 @@ class WP_Query { * Cached list of search stopwords. * * @since 3.7.0 - * @var array + * @var ?array */ private $stopwords; @@ -3828,6 +3828,8 @@ function ( $carry, $post ) { * @since 1.5.0 * * @return bool True if posts are available, false if end of the loop. + * + * @phpstan-impure */ public function have_posts() { if ( $this->current_post + 1 < $this->post_count ) { diff --git a/src/wp-includes/class-wp-rewrite.php b/src/wp-includes/class-wp-rewrite.php index 99bc689705224..113da69e79804 100644 --- a/src/wp-includes/class-wp-rewrite.php +++ b/src/wp-includes/class-wp-rewrite.php @@ -52,7 +52,7 @@ class WP_Rewrite { * Permalink structure for author archives. * * @since 1.5.0 - * @var string + * @var ?string */ public $author_structure; @@ -60,7 +60,7 @@ class WP_Rewrite { * Permalink structure for date archives. * * @since 1.5.0 - * @var string + * @var ?string */ public $date_structure; @@ -68,7 +68,7 @@ class WP_Rewrite { * Permalink structure for pages. * * @since 1.5.0 - * @var string + * @var ?string */ public $page_structure; @@ -76,7 +76,7 @@ class WP_Rewrite { * Base of the search permalink structure (example.com/$search_base/query). * * @since 1.5.0 - * @var string + * @var ?string */ public $search_base = 'search'; @@ -84,7 +84,7 @@ class WP_Rewrite { * Permalink structure for searches. * * @since 1.5.0 - * @var string + * @var ?string */ public $search_structure; @@ -124,7 +124,7 @@ class WP_Rewrite { * Comments feed permalink structure. * * @since 1.5.0 - * @var string + * @var ?string */ public $comment_feed_structure; @@ -132,7 +132,7 @@ class WP_Rewrite { * Feed request permalink structure. * * @since 1.5.0 - * @var string + * @var ?string */ public $feed_structure; diff --git a/src/wp-includes/class-wp-script-modules.php b/src/wp-includes/class-wp-script-modules.php index 838c0eaf9cdf3..324c31aa94f31 100644 --- a/src/wp-includes/class-wp-script-modules.php +++ b/src/wp-includes/class-wp-script-modules.php @@ -546,6 +546,8 @@ private function get_import_map(): array { * @since 6.5.0 * * @return array Script modules marked for enqueue, keyed by script module identifier. + * + * @phpstan-ignore method.unused */ private function get_marked_for_enqueue(): array { return wp_array_slice_assoc( diff --git a/src/wp-includes/class-wp-speculation-rules.php b/src/wp-includes/class-wp-speculation-rules.php index 8d23eefe1207a..8931851618616 100644 --- a/src/wp-includes/class-wp-speculation-rules.php +++ b/src/wp-includes/class-wp-speculation-rules.php @@ -230,7 +230,7 @@ public function has_rule( string $mode, string $id ): bool { * * @since 6.8.0 * - * @return array> Speculation rules data. + * @return array> Speculation rules data. */ #[ReturnTypeWillChange] public function jsonSerialize() { diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index 598f3ba918536..1e91fd3c39876 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -3365,7 +3365,7 @@ public function get_svg_filters( $origins ) { * @param array $theme_json The theme.json like structure to inspect. * @param array $path Path to inspect. * @param bool|array $override Data to compute whether to override the preset. - * @return bool + * @return bool|null True if the preset should override the defaults, false if not. Null if the override parameter is invalid. */ protected static function should_override_preset( $theme_json, $path, $override ) { _deprecated_function( __METHOD__, '6.0.0', 'get_metadata_boolean' ); @@ -3400,6 +3400,8 @@ protected static function should_override_preset( $theme_json, $path, $override return true; } + + return null; } /** diff --git a/src/wp-includes/class-wp-theme.php b/src/wp-includes/class-wp-theme.php index 49020d5e969c4..613011ec3cd80 100644 --- a/src/wp-includes/class-wp-theme.php +++ b/src/wp-includes/class-wp-theme.php @@ -114,7 +114,7 @@ final class WP_Theme implements ArrayAccess { * Header data from the theme's style.css file after being sanitized. * * @since 3.4.0 - * @var array + * @var ?array */ private $headers_sanitized; @@ -122,7 +122,7 @@ final class WP_Theme implements ArrayAccess { * Is this theme a block theme. * * @since 6.2.0 - * @var bool + * @var ?bool */ private $block_theme; @@ -132,7 +132,7 @@ final class WP_Theme implements ArrayAccess { * Cached due to sorting functions running over the translated name. * * @since 3.4.0 - * @var string + * @var ?string */ private $name_translated; @@ -140,7 +140,7 @@ final class WP_Theme implements ArrayAccess { * Errors encountered when initializing the theme. * * @since 3.4.0 - * @var WP_Error + * @var ?WP_Error */ private $errors; @@ -162,7 +162,7 @@ final class WP_Theme implements ArrayAccess { * Otherwise, 'template' is the same as 'stylesheet'. * * @since 3.4.0 - * @var string + * @var ?string */ private $template; @@ -170,7 +170,7 @@ final class WP_Theme implements ArrayAccess { * A reference to the parent theme, in the case of a child theme. * * @since 3.4.0 - * @var WP_Theme + * @var ?WP_Theme */ private $parent; @@ -178,7 +178,7 @@ final class WP_Theme implements ArrayAccess { * URL to the theme root, usually an absolute URL to wp-content/themes * * @since 3.4.0 - * @var string + * @var ?string */ private $theme_root_uri; @@ -186,7 +186,7 @@ final class WP_Theme implements ArrayAccess { * Flag for whether the theme's textdomain is loaded. * * @since 3.4.0 - * @var bool + * @var ?bool */ private $textdomain_loaded; @@ -202,7 +202,7 @@ final class WP_Theme implements ArrayAccess { * Block template folders. * * @since 6.4.0 - * @var string[] + * @var ?string[] */ private $block_template_folders; diff --git a/src/wp-includes/class-wp-user.php b/src/wp-includes/class-wp-user.php index 8fd5e5cd211ac..cc07366928e95 100644 --- a/src/wp-includes/class-wp-user.php +++ b/src/wp-includes/class-wp-user.php @@ -196,6 +196,13 @@ public function init( $data, $site_id = 0 ) { * @param string $field The field to query against: Accepts 'id', 'ID', 'slug', 'email' or 'login'. * @param string|int $value The field value. * @return object|false Raw user object. + * + * @phpstan-param 'id'|'ID'|'slug'|'email'|'login' $field + * @phpstan-return ( + * $field is 'id'|'ID' ? ( + * $value is not numeric ? false : (object|false) + * ) : ( $value is non-empty-string ? (object|false) : false ) + * ) */ public static function get_data_by( $field, $value ) { global $wpdb; diff --git a/src/wp-includes/class-wp-widget-factory.php b/src/wp-includes/class-wp-widget-factory.php index ed719b9d4d7a1..8f9c9e3dbc08a 100644 --- a/src/wp-includes/class-wp-widget-factory.php +++ b/src/wp-includes/class-wp-widget-factory.php @@ -20,7 +20,7 @@ class WP_Widget_Factory { * Widgets array. * * @since 2.8.0 - * @var array + * @var array */ public $widgets = array(); @@ -54,6 +54,8 @@ public function WP_Widget_Factory() { * instead of simply a `WP_Widget` subclass name. * * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. + * + * @phpstan-param class-string|WP_Widget $widget */ public function register( $widget ) { if ( $widget instanceof WP_Widget ) { @@ -71,6 +73,8 @@ public function register( $widget ) { * instead of simply a `WP_Widget` subclass name. * * @param string|WP_Widget $widget Either the name of a `WP_Widget` subclass or an instance of a `WP_Widget` subclass. + * + * @phpstan-param class-string|WP_Widget $widget */ public function unregister( $widget ) { if ( $widget instanceof WP_Widget ) { diff --git a/src/wp-includes/class-wpdb.php b/src/wp-includes/class-wpdb.php index fefccb4bc8bdf..8489c9608d1cb 100644 --- a/src/wp-includes/class-wpdb.php +++ b/src/wp-includes/class-wpdb.php @@ -962,10 +962,6 @@ public function set_sql_mode( $modes = array() ) { $modes_str = $modes_array[0]; - if ( empty( $modes_str ) ) { - return; - } - $modes = explode( ',', $modes_str ); } @@ -1460,6 +1456,8 @@ private function _escape_identifier_value( $identifier ) { * @param mixed ...$args Further variables to substitute into the query's placeholders * if being called with individual arguments. * @return string|void Sanitized query string, if there is a query to prepare. + * + * @phpstan-param literal-string $query */ public function prepare( $query, ...$args ) { if ( is_null( $query ) ) { @@ -3063,6 +3061,10 @@ public function get_var( $query = null, $x = 0, $y = 0 ) { * respectively. Default OBJECT. * @param int $y Optional. Row to return. Indexed from 0. Default 0. * @return array|object|null|void Database query result in format specified by $output or null on failure. + * + * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output + * @phpstan-param int<0, max> $y + * @phpstan-return null|void|($output is 'ARRAY_A' ? array : ($output is 'ARRAY_N' ? list : \stdClass)) */ public function get_row( $query = null, $output = OBJECT, $y = 0 ) { $this->func_call = "\$db->get_row(\"$query\",$output,$y)"; @@ -3144,6 +3146,9 @@ public function get_col( $query = null, $x = 0 ) { * of each row's first column's value. Duplicate keys are discarded. * Default OBJECT. * @return array|object|null Database query results. + * + * @phpstan-param 'OBJECT'|'OBJECT_K'|'ARRAY_A'|'ARRAY_N' $output + * @phpstan-return null|($output is 'ARRAY_A' ? list> : ($output is 'ARRAY_N' ? list> : ($output is 'OBJECT_K' ? array : list<\stdClass>))) */ public function get_results( $query = null, $output = OBJECT ) { $this->func_call = "\$db->get_results(\"$query\", $output)"; diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php index 2499c255223da..2e6ab2b33baf2 100644 --- a/src/wp-includes/comment-template.php +++ b/src/wp-includes/comment-template.php @@ -489,6 +489,8 @@ function comment_author_url_link( $link_text = '', $before = '', $after = '', $c * @param bool $display Optional. Whether to print or return the output. * Default true. * @return void|string Void if `$display` argument is true, comment classes if `$display` is false. + * + * @phpstan-return ($display is true ? void : string) */ function comment_class( $css_class = '', $comment = null, $post = null, $display = true ) { // Separates classes with a single space, collates classes for comment DIV. @@ -834,7 +836,10 @@ function get_comment_link( $comment = null, $args = array() ) { if ( $cpage && get_option( 'page_comments' ) ) { if ( $wp_rewrite->using_permalinks() ) { + // We build the link first. $comment_link = trailingslashit( $comment_link ) . $wp_rewrite->comments_pagination_base . '-' . $cpage; + // Then, we filter & slash it. + $comment_link = user_trailingslashit( $comment_link, 'comment' ); } else { $comment_link = add_query_arg( 'cpage', $cpage, $comment_link ); } diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 9399889768e57..e4b8dfb44e75a 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -184,6 +184,8 @@ function check_comment( $author, $email, $url, $comment, $user_ip, $user_agent, * } * @return WP_Comment[]|int[]|int The approved comments, or number of comments if `$count` * argument is true. + * + * @phpstan-return ($args is array{count: true}&array ? int : ($args is array{fields: 'ids'}&array ? array : array)) */ function get_approved_comments( $post_id, $args = array() ) { if ( ! $post_id ) { @@ -216,7 +218,17 @@ function get_approved_comments( $post_id, $args = array() ) { * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which * correspond to a WP_Comment object, an associative array, or a numeric array, * respectively. Default OBJECT. + * * @return WP_Comment|array|null Depends on $output value. + * + * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output + * @phpstan-return ( + * $output is 'ARRAY_A' ? array : ( + * $output is 'ARRAY_N' ? array : ( + * $output is 'OBJECT' ? \WP_Comment : ( array|\WP_Comment ) + * ) + * ) + * )|null */ function get_comment( $comment = null, $output = OBJECT ) { if ( empty( $comment ) && isset( $GLOBALS['comment'] ) ) { @@ -2475,6 +2487,8 @@ function wp_new_comment_notify_postauthor( $comment_id ) { * @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; @@ -2549,6 +2563,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 ? (0|1|false) : (0|1|\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 5ada670278562..46750fb0326b9 100644 --- a/src/wp-includes/cron.php +++ b/src/wp-includes/cron.php @@ -35,6 +35,8 @@ * The array keys are ignored. 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 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. @@ -230,6 +232,8 @@ function wp_schedule_single_event( $timestamp, $hook, $args = array(), $wp_error * The array keys are ignored. 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 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. @@ -336,6 +340,8 @@ function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array(), $wp * The array keys are ignored. 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 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. @@ -458,6 +464,8 @@ function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array(), $ * 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. @@ -545,6 +553,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<0, max>|( $wp_error is false ? false : \WP_Error ) */ function wp_clear_scheduled_hook( $hook, $args = array(), $wp_error = false ) { /* @@ -650,6 +660,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 int<0, max>|($wp_error is false ? false : \WP_Error) */ function wp_unschedule_hook( $hook, $wp_error = false ) { /** diff --git a/src/wp-includes/customize/class-wp-customize-background-image-setting.php b/src/wp-includes/customize/class-wp-customize-background-image-setting.php index f56810e6aab4b..641540660c45d 100644 --- a/src/wp-includes/customize/class-wp-customize-background-image-setting.php +++ b/src/wp-includes/customize/class-wp-customize-background-image-setting.php @@ -28,6 +28,7 @@ final class WP_Customize_Background_Image_Setting extends WP_Customize_Setting { * @since 3.4.0 * * @param mixed $value The value to update. Not used. + * @return bool|void Nothing is returned. */ public function update( $value ) { remove_theme_mod( 'background_image_thumb' ); diff --git a/src/wp-includes/customize/class-wp-customize-filter-setting.php b/src/wp-includes/customize/class-wp-customize-filter-setting.php index ad70f4f853288..cf0ce2b2fb7ab 100644 --- a/src/wp-includes/customize/class-wp-customize-filter-setting.php +++ b/src/wp-includes/customize/class-wp-customize-filter-setting.php @@ -24,6 +24,7 @@ class WP_Customize_Filter_Setting extends WP_Customize_Setting { * @since 3.4.0 * * @param mixed $value The value to update. + * @return bool|void Nothing is returned. */ public function update( $value ) {} } diff --git a/src/wp-includes/customize/class-wp-customize-header-image-setting.php b/src/wp-includes/customize/class-wp-customize-header-image-setting.php index 80333a54128af..cdf5128322717 100644 --- a/src/wp-includes/customize/class-wp-customize-header-image-setting.php +++ b/src/wp-includes/customize/class-wp-customize-header-image-setting.php @@ -32,6 +32,7 @@ final class WP_Customize_Header_Image_Setting extends WP_Customize_Setting { * @global Custom_Image_Header $custom_image_header * * @param mixed $value The value to update. + * @return bool|void Nothing is returned. */ public function update( $value ) { global $custom_image_header; diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index 2569e5ad308c0..0ad72967f0685 100644 --- a/src/wp-includes/deprecated.php +++ b/src/wp-includes/deprecated.php @@ -2515,6 +2515,14 @@ 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()' ); diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 4f28e745751ff..24283066732c5 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -941,6 +941,8 @@ function seems_utf8( $str ) { * @param false|string $charset Optional. The character encoding of the string. Default false. * @param bool $double_encode Optional. Whether to encode existing HTML entities. Default false. * @return string The encoded text with HTML entities. + * + * @phpstan-param scalar $text */ function _wp_specialchars( $text, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { $text = (string) $text; @@ -1011,6 +1013,8 @@ function _wp_specialchars( $text, $quote_style = ENT_NOQUOTES, $charset = false, * double if set to 'double' or both if otherwise set. * Default is ENT_NOQUOTES. * @return string The decoded text without HTML entities. + * + * @phpstan-param scalar $text */ function wp_specialchars_decode( $text, $quote_style = ENT_NOQUOTES ) { $text = (string) $text; @@ -1123,6 +1127,8 @@ function wp_specialchars_decode( $text, $quote_style = ENT_NOQUOTES ) { * @param bool $strip Optional. Whether to replace invalid sequences of bytes with the Unicode replacement * character (U+FFFD `�`). Default `false` returns an empty string for invalid UTF-8 inputs. * @return string The checked text. + * + * @phpstan-param scalar $text */ function wp_check_invalid_utf8( $text, $strip = false ) { $text = (string) $text; @@ -2844,6 +2850,10 @@ function untrailingslashit( $value ) { * * @param string|array $gpc String or array of data to slash. * @return string|array Slashed `$gpc`. + * + * @phpstan-template T of string|array + * @phpstan-param T $gpc + * @phpstan-return T */ function addslashes_gpc( $gpc ) { return wp_slash( $gpc ); @@ -2856,6 +2866,10 @@ function addslashes_gpc( $gpc ) { * * @param mixed $value The value to be stripped. * @return mixed Stripped value. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function stripslashes_deep( $value ) { return map_deep( $value, 'stripslashes_from_strings_only' ); @@ -2868,6 +2882,10 @@ function stripslashes_deep( $value ) { * * @param mixed $value The array or string to be stripped. * @return mixed The stripped value. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function stripslashes_from_strings_only( $value ) { return is_string( $value ) ? stripslashes( $value ) : $value; @@ -2880,6 +2898,10 @@ function stripslashes_from_strings_only( $value ) { * * @param mixed $value The array or string to be encoded. * @return mixed The encoded value. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function urlencode_deep( $value ) { return map_deep( $value, 'urlencode' ); @@ -2892,6 +2914,10 @@ function urlencode_deep( $value ) { * * @param mixed $value The array or string to be encoded. * @return mixed The encoded value. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function rawurlencode_deep( $value ) { return map_deep( $value, 'rawurlencode' ); @@ -2904,6 +2930,10 @@ function rawurlencode_deep( $value ) { * * @param mixed $value The array or string to be decoded. * @return mixed The decoded value. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function urldecode_deep( $value ) { return map_deep( $value, 'urldecode' ); @@ -4653,6 +4683,8 @@ function htmlentities2( $text ) { * * @param string $text The text to be escaped. * @return string Escaped text. + * + * @phpstan-param scalar $text */ function esc_js( $text ) { $safe_text = wp_check_invalid_utf8( $text ); @@ -4681,6 +4713,8 @@ function esc_js( $text ) { * * @param string $text * @return string + * + * @phpstan-param scalar $text */ function esc_html( $text ) { $safe_text = wp_check_invalid_utf8( $text ); @@ -4704,8 +4738,10 @@ function esc_html( $text ) { * * @since 2.8.0 * - * @param string $text + * @param string $text . Non-string values will be cast to string. * @return string + * + * @phpstan-param scalar $text */ function esc_attr( $text ) { $safe_text = wp_check_invalid_utf8( $text ); @@ -4720,6 +4756,8 @@ function esc_attr( $text ) { * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. + * + * @phpstan-param scalar $text */ return apply_filters( 'attribute_escape', $safe_text, $text ); } @@ -4752,6 +4790,8 @@ function esc_textarea( $text ) { * * @param string $text Text to escape. * @return string Escaped text. + * + * @phpstan-param scalar $text */ function esc_xml( $text ) { $safe_text = wp_check_invalid_utf8( $text ); @@ -5782,6 +5822,10 @@ function sanitize_trackback_urls( $to_ping ) { * * @param string|array $value String or array of data to slash. * @return string|array Slashed `$value`, in the same type as supplied. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function wp_slash( $value ) { if ( is_array( $value ) ) { @@ -5805,6 +5849,10 @@ function wp_slash( $value ) { * * @param string|array $value String or array of data to unslash. * @return string|array Unslashed `$value`, in the same type as supplied. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-return T */ function wp_unslash( $value ) { return stripslashes_deep( $value ); diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index e99d13366ec99..79aa7d1f063b4 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 'G'|'U' ? int : 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. @@ -463,6 +467,8 @@ function number_format_i18n( $number, $decimals = 0 ) { * @param int|string $bytes Number of bytes. Note max integer size for integers. * @param int $decimals Optional. Precision of number of decimal places. Default 0. * @return string|false Number string on success, false on failure. + * + * @phpstan-return ( $bytes is not numeric ? false : ($bytes is int|'0' ? false : string)) */ function size_format( $bytes, $decimals = 0 ) { $quant = array( @@ -1014,6 +1020,8 @@ function wp_get_http_headers( $url, $deprecated = false ) { * @global string $previousday The day of the previous post in the loop. * * @return int 1 when new day, 0 if not a new day. + * + * @phpstan-return 0|1 */ function is_new_day() { global $currentday, $previousday; @@ -1587,6 +1595,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 ) ); @@ -1864,6 +1874,8 @@ function is_blog_installed() { * @param int|string $action Optional. Nonce action name. Default -1. * @param string $name Optional. Nonce name. Default '_wpnonce'. * @return string Escaped URL with nonce action added. + * + * @phpstan-param -1|string $action */ function wp_nonce_url( $actionurl, $action = -1, $name = '_wpnonce' ) { $actionurl = str_replace( '&', '&', $actionurl ); @@ -1895,6 +1907,8 @@ function wp_nonce_url( $actionurl, $action = -1, $name = '_wpnonce' ) { * @param bool $referer Optional. Whether to set the referer field for validation. Default true. * @param bool $display Optional. Whether to display or return hidden form field. Default true. * @return string Nonce field HTML markup. + * + * @phpstan-param -1|string $action */ function wp_nonce_field( $action = -1, $name = '_wpnonce', $referer = true, $display = true ) { $name = esc_attr( $name ); @@ -3765,6 +3779,8 @@ function wp_nonce_ays( $action ) { * is a WP_Error. * @type bool $exit Whether to exit the process after completion. Default true. * } + * + * @phpstan-return ($args is array{exit: false}&array ? void : never) */ function wp_die( $message = '', $title = '', $args = array() ) { global $wp_query; @@ -4381,6 +4397,9 @@ function _wp_die_process_input( $message, $title = '', $args = array() ) { * @param int $depth Optional. Maximum depth to walk through $value. Must be * greater than 0. Default 512. * @return string|false The JSON encoded string, or false if it cannot be encoded. + * + * @phpstan-param int<1,max> $depth + * @phpstan-return non-empty-string|false */ function wp_json_encode( $value, $flags = 0, $depth = 512 ) { $json = json_encode( $value, $flags, $depth ); @@ -4413,6 +4432,11 @@ function wp_json_encode( $value, $flags = 0, $depth = 512 ) { * @param mixed $value Variable (usually an array or object) to encode as JSON. * @param int $depth Maximum depth to walk through $value. Must be greater than 0. * @return mixed The sanitized data that shall be encoded to JSON. + * + * @phpstan-template T + * @phpstan-param T $value + * @phpstan-param int<1,max> $depth + * @phpstan-return T */ function _wp_json_sanity_check( $value, $depth ) { if ( $depth < 0 ) { @@ -4970,6 +4994,8 @@ function wp_parse_args( $args, $defaults = array() ) { * * @param array|string $input_list List of values. * @return array Array of values. + * + * @phpstan-return ($input_list is array ? array : list) */ function wp_parse_list( $input_list ) { if ( ! is_array( $input_list ) ) { @@ -5276,6 +5302,11 @@ function _wp_to_kebab_case( $input_string ) { * * @param mixed $data Variable to check. * @return bool Whether the variable is a list. + * + * @phpstan-template T + * @phpstan-param T $data + * @phpstan-return (T is array ? (key-of is int ? true : false) : false) + * @phpstan-assert-if-true (T is list ? T : array>) $data */ function wp_is_numeric_array( $data ) { if ( ! is_array( $data ) ) { @@ -6087,6 +6118,8 @@ function _doing_it_wrong( $function_name, $message, $version ) { * before passing to this function to avoid being stripped {@see wp_kses()}. * @param int $error_level Optional. The designated error type for this error. * Only works with E_USER family of constants. Default E_USER_NOTICE. + * + * @phpstan-param \E_USER_ERROR|\E_USER_WARNING|\E_USER_NOTICE|\E_USER_DEPRECATED $error_level */ function wp_trigger_error( $function_name, $message, $error_level = E_USER_NOTICE ) { @@ -6239,6 +6272,12 @@ 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 ) { @@ -6983,6 +7022,8 @@ function __return_false() { // phpcs:ignore WordPress.NamingConventions.ValidFun * @since 3.0.0 * * @return int 0. + * + * @phpstan-return 0 */ function __return_zero() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return 0; @@ -6996,6 +7037,8 @@ function __return_zero() { // phpcs:ignore WordPress.NamingConventions.ValidFunc * @since 3.0.0 * * @return array Empty array. + * + * @phpstan-return array{} */ function __return_empty_array() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return array(); @@ -7024,6 +7067,8 @@ function __return_null() { // phpcs:ignore WordPress.NamingConventions.ValidFunc * @see __return_null() * * @return string Empty string. + * + * @phpstan-return '' */ function __return_empty_string() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return ''; @@ -7237,6 +7282,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; @@ -8005,6 +8052,8 @@ function wp_is_uuid( $uuid, $version = null ) { * * @param string $prefix Prefix for the returned ID. * @return string Unique ID. + * + * @phpstan-return ($prefix is empty ? numeric-string : ($prefix is numeric ? numeric-string : string)) */ function wp_unique_id( $prefix = '' ) { static $id_counter = 0; diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 5f432c7a41e06..2f6d239b6782e 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -380,6 +380,8 @@ function get_search_form( $args = array() ) { * @param string $redirect Optional path to redirect to on login/logout. * @param bool $display Default to echo and not return the link. * @return void|string Void if `$display` argument is true, log in/out link if `$display` is false. + * + * @phpstan-return ($display is true ? void : string) */ function wp_loginout( $redirect = '', $display = true ) { if ( ! is_user_logged_in() ) { @@ -697,6 +699,8 @@ function wp_lostpassword_url( $redirect = '' ) { * @param bool $display Default to echo and not return the link. * @return void|string Void if `$display` argument is true, registration or admin link * if `$display` is false. + * + * @phpstan-return ($display is true ? void : string) */ function wp_register( $before = '
  • ', $after = '
  • ', $display = true ) { if ( ! is_user_logged_in() ) { @@ -1335,6 +1339,8 @@ function _wp_render_title_tag() { * @param bool $display Optional. Whether to display or retrieve title. Default true. * @param string $seplocation Optional. Location of the separator (either 'left' or 'right'). * @return string|void String when `$display` is false, nothing otherwise. + * + * @phpstan-return ($display is true ? void : string) */ function wp_title( $sep = '»', $display = true, $seplocation = '' ) { global $wp_locale; @@ -1480,6 +1486,8 @@ function wp_title( $sep = '»', $display = true, $seplocation = '' ) { * @param string $prefix Optional. What to display before the title. * @param bool $display Optional. Whether to display or retrieve title. Default true. * @return string|void Title when retrieving. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function single_post_title( $prefix = '', $display = true ) { $_post = get_queried_object(); @@ -1515,6 +1523,8 @@ function single_post_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|void Title when retrieving, null when displaying or failure. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function post_type_archive_title( $prefix = '', $display = true ) { if ( ! is_post_type_archive() ) { @@ -1557,9 +1567,11 @@ function post_type_archive_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|void Title when retrieving. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function single_cat_title( $prefix = '', $display = true ) { - return single_term_title( $prefix, $display ); + return single_term_title( $prefix, false ); } /** @@ -1574,6 +1586,8 @@ function single_cat_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|void Title when retrieving. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function single_tag_title( $prefix = '', $display = true ) { return single_term_title( $prefix, $display ); @@ -1591,6 +1605,8 @@ function single_tag_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|void Title when retrieving. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function single_term_title( $prefix = '', $display = true ) { $term = get_queried_object(); @@ -1656,6 +1672,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|void False if there's no valid title for the month. Title when retrieving. + * + * @phpstan-return ( $display is true ? void : string )|false */ function single_month_title( $prefix = '', $display = true ) { global $wp_locale; @@ -1992,6 +2010,8 @@ function get_archives_link( $url, $text, $format = 'html', $before = '', $after * @type string $w Week. Default current week. * } * @return void|string Void if 'echo' argument is true, archive links if 'echo' is false. + * + * @phpstan-return ( $args is array{echo: false|0}&array ? (string|void) : void ) */ function wp_get_archives( $args = '' ) { global $wpdb, $wp_locale; @@ -2251,6 +2271,8 @@ function calendar_week_mod( $num ) { * @type string $post_type Optional. Post type. Default 'post'. * } * @return void|string Void if `$display` argument is true, calendar HTML if `$display` is false. + * + * @phpstan-return ($args is array{display: false}&array ? string : void) */ function get_calendar( $args = array() ) { global $wpdb, $m, $monthnum, $year, $wp_locale, $posts; @@ -2665,6 +2687,8 @@ function the_date_xml() { * @param string $after Optional. Output after the date. Default empty. * @param bool $display Optional. Whether to echo the date or return it. Default true. * @return string|void String if retrieving. + * + * @phpstan-return ($display is true ? void : string) */ function the_date( $format = '', $before = '', $after = '', $display = true ) { global $currentday, $previousday; @@ -2740,6 +2764,8 @@ function get_the_date( $format = '', $post = null ) { * @param string $after Optional. Output after the date. Default empty. * @param bool $display Optional. Whether to echo the date or return it. Default true. * @return string|void String if retrieving. + * + * @phpstan-return ($display is true ? void : string) */ function the_modified_date( $format = '', $before = '', $after = '', $display = true ) { $the_modified_date = $before . get_the_modified_date( $format ) . $after; @@ -4632,6 +4658,8 @@ function language_attributes( $doctype = 'html' ) { * } * @return string|string[]|void String of page links or array of page links, depending on 'type' argument. * Void if total number of pages is less than 2. + * + * @phpstan-return ($args is array{total: int}&array ? void : ($args is array{type: 'array'}&array ? list : string)) */ function paginate_links( $args = '' ) { global $wp_query, $wp_rewrite; @@ -4762,7 +4790,7 @@ function paginate_links( $args = '' ) { ); $dots = true; - elseif ( $dots && ! $args['show_all'] ) : + elseif ( $dots ) : $page_links[] = '' . __( '…' ) . ''; $dots = false; diff --git a/src/wp-includes/html-api/class-wp-html-decoder.php b/src/wp-includes/html-api/class-wp-html-decoder.php index 6c1404beddcf1..bd62f311aef13 100644 --- a/src/wp-includes/html-api/class-wp-html-decoder.php +++ b/src/wp-includes/html-api/class-wp-html-decoder.php @@ -203,7 +203,7 @@ public static function decode( $context, $text ): string { * @param int $at Optional. Byte offset into text where span begins, defaults to the beginning (0). * @param int &$match_byte_length Optional. Set to byte-length of character reference if provided and if a match * is found, otherwise not set. Default null. - * @return string|false Decoded character reference in UTF-8 if found, otherwise `false`. + * @return ?string Decoded character reference in UTF-8 if found, otherwise null. */ public static function read_character_reference( $context, $text, $at = 0, &$match_byte_length = null ) { /** diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 55f955f2c1a9a..61473c7ed4c7a 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -139,6 +139,8 @@ * * @see WP_HTML_Tag_Processor * @see https://html.spec.whatwg.org/ + * + * @phpstan-consistent-constructor */ class WP_HTML_Processor extends WP_HTML_Tag_Processor { /** @@ -583,6 +585,8 @@ private function create_fragment_at_current_node( string $html ) { * @since 6.7.0 * * @param string $message Explains support is missing in order to parse the current node. + * + * @phpstan-return never */ private function bail( string $message ) { $here = $this->bookmarks[ $this->state->current_token->bookmark_name ]; @@ -5102,9 +5106,9 @@ private function step_in_foreign_content(): bool { * * @throws Exception When unable to allocate requested bookmark. * - * @return string|false Name of created bookmark, or false if unable to create. + * @return string Name of created bookmark */ - private function bookmark_token() { + private function bookmark_token(): string { if ( ! parent::set_bookmark( ++$this->bookmark_counter ) ) { $this->last_error = self::ERROR_EXCEEDED_MAX_BOOKMARKS; throw new Exception( 'could not allocate bookmark' ); diff --git a/src/wp-includes/interactivity-api/class-wp-interactivity-api.php b/src/wp-includes/interactivity-api/class-wp-interactivity-api.php index 1763142167211..7eeeca17fea83 100644 --- a/src/wp-includes/interactivity-api/class-wp-interactivity-api.php +++ b/src/wp-includes/interactivity-api/class-wp-interactivity-api.php @@ -204,12 +204,11 @@ public function config( string $store_namespace, array $config = array() ): arra if ( ! isset( $this->config_data[ $store_namespace ] ) ) { $this->config_data[ $store_namespace ] = array(); } - if ( is_array( $config ) ) { - $this->config_data[ $store_namespace ] = array_replace_recursive( - $this->config_data[ $store_namespace ], - $config - ); - } + + $this->config_data[ $store_namespace ] = array_replace_recursive( + $this->config_data[ $store_namespace ], + $config + ); return $this->config_data[ $store_namespace ]; } diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php index 40a5e14ade879..06e5479b371c6 100644 --- a/src/wp-includes/l10n.php +++ b/src/wp-includes/l10n.php @@ -1672,6 +1672,8 @@ function wp_get_l10n_php_file_data( $php_file ) { * instead of an empty value. Default false. * } * @return string HTML dropdown list of languages. + * + * @phpstan-return ( $args is array{id: null|''}&array ? void : ( $args is array{name: null|''}&array ? void : string ) ) */ function wp_dropdown_languages( $args = array() ) { diff --git a/src/wp-includes/l10n/class-wp-translations.php b/src/wp-includes/l10n/class-wp-translations.php index e919fea8b94b3..b158501b64e83 100644 --- a/src/wp-includes/l10n/class-wp-translations.php +++ b/src/wp-includes/l10n/class-wp-translations.php @@ -112,6 +112,11 @@ 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-param int $count + * @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 +140,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 525a9efe53eb8..c5ac4f262aae8 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; @@ -1082,13 +1088,13 @@ function edit_tag_link( $link = '', $before = '', $after = '', $tag = null ) { function get_edit_term_link( $term, $taxonomy = '', $object_type = '' ) { $term = get_term( $term, $taxonomy ); if ( ! $term || is_wp_error( $term ) ) { - return; + return null; } $tax = get_taxonomy( $term->taxonomy ); $term_id = $term->term_id; if ( ! $tax || ! current_user_can( 'edit_term', $term_id ) ) { - return; + return null; } $args = array( @@ -1132,6 +1138,8 @@ function get_edit_term_link( $term, $taxonomy = '', $object_type = '' ) { * @param int|WP_Term|null $term Optional. Term ID or object. If null, the queried object will be inspected. Default null. * @param bool $display Optional. Whether or not to echo the return. Default true. * @return string|void HTML content. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function edit_term_link( $link = '', $before = '', $after = '', $term = null, $display = true ) { if ( is_null( $term ) ) { @@ -1410,7 +1418,7 @@ function get_preview_post_link( $post = null, $query_args = array(), $preview_li $post = get_post( $post ); if ( ! $post ) { - return; + return null; } $post_type_object = get_post_type_object( $post->post_type ); @@ -1454,7 +1462,7 @@ function get_edit_post_link( $post = 0, $context = 'display' ) { $post = get_post( $post ); if ( ! $post ) { - return; + return null; } if ( 'revision' === $post->post_type ) { @@ -1468,11 +1476,11 @@ function get_edit_post_link( $post = 0, $context = 'display' ) { $post_type_object = get_post_type_object( $post->post_type ); if ( ! $post_type_object ) { - return; + return null; } if ( ! current_user_can( 'edit_post', $post->ID ) ) { - return; + return null; } $link = ''; @@ -2536,6 +2544,8 @@ function get_next_posts_page_link( $max_page = 0 ) { * @param int $max_page Optional. Max pages. Default 0. * @param bool $display Optional. Whether to echo the link. Default true. * @return string|void The link URL for next posts page if `$display = false`. + * + * @phpstan-return ($display is true ? void : string) */ function next_posts( $max_page = 0, $display = true ) { $link = get_next_posts_page_link( $max_page ); @@ -2642,6 +2652,8 @@ function get_previous_posts_page_link() { * * @param bool $display Optional. Whether to echo the link. Default true. * @return string|void The previous posts page link if `$display = false`. + * + * @phpstan-return ($display is true ? void : string) */ function previous_posts( $display = true ) { $output = esc_url( get_previous_posts_page_link() ); diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php index 095affd67747a..3fe8742437eca 100644 --- a/src/wp-includes/load.php +++ b/src/wp-includes/load.php @@ -860,6 +860,7 @@ function wp_start_object_cache() { if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { require_once WP_CONTENT_DIR . '/object-cache.php'; + // @phpstan-ignore if.alwaysFalse if ( function_exists( 'wp_cache_init' ) ) { wp_using_ext_object_cache( true ); } @@ -1464,6 +1465,22 @@ function is_multisite() { * * @param mixed $maybeint Data you wish to have converted to a non-negative integer. * @return int A non-negative integer. + * + * @phpstan-template T of int + * @phpstan-param T|scalar|array|resource|null $maybeint + * @phpstan-return ( + * $maybeint is T&int<0, max> ? T : ( + * $maybeint is int ? int<1, max> : ( + * $maybeint is empty ? 0 : ( + * $maybeint is numeric-string ? int<0, max> : ( + * $maybeint is string ? 0 : ( + * $maybeint is (true|non-empty-array) ? 1 : ( $maybeint is bool ? (0|1) : int<0, max> ) + * ) + * ) + * ) + * ) + * ) + * ) */ function absint( $maybeint ) { return abs( (int) $maybeint ); @@ -1477,6 +1494,8 @@ function absint( $maybeint ) { * @global int $blog_id * * @return int Site ID. + * + * @phpstan-return int<0, max> */ function get_current_blog_id() { global $blog_id; @@ -1798,6 +1817,12 @@ function wp_doing_cron() { * * @param mixed $thing The variable to check. * @return bool Whether the variable is an instance of WP_Error. + * + * @phpstan-template T + * @phpstan-param T|WP_Error $thing + * @phpstan-return ($thing is \WP_Error ? true : false) + * @phpstan-assert-if-true \WP_Error $thing + * @phpstan-assert-if-false !\WP_Error $thing */ function is_wp_error( $thing ) { $is_wp_error = ( $thing instanceof WP_Error ); diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index be41add6590b6..96b30077637a7 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -4022,6 +4022,8 @@ function adjacent_image_link( $prev = true, $size = 'thumbnail', $text = false ) * or 'objects' to return an array of taxonomy objects. * Default is 'names'. * @return string[]|WP_Taxonomy[] List of taxonomies or taxonomy names. Empty array on failure. + * + * @phpstan-return ($output is 'names' ? array : array) */ function get_attachment_taxonomies( $attachment, $output = 'names' ) { if ( is_int( $attachment ) ) { @@ -4084,6 +4086,8 @@ function get_attachment_taxonomies( $attachment, $output = 'names' ) { * @param string $output Optional. The type of taxonomy output to return. Accepts 'names' or 'objects'. * Default 'names'. * @return string[]|WP_Taxonomy[] Array of names or objects of registered taxonomies for attachments. + * + * @phpstan-return ($output is 'names' ? array : array) */ function get_taxonomies_for_attachments( $output = 'names' ) { $taxonomies = array(); @@ -4118,7 +4122,7 @@ function get_taxonomies_for_attachments( $output = 'names' ) { * false otherwise. */ function is_gd_image( $image ) { - if ( $image instanceof GdImage + if ( $image instanceof GdImage // @phpstan-ignore class.notFound (Only available with PHP8+.) || is_resource( $image ) && 'gd' === get_resource_type( $image ) ) { return true; diff --git a/src/wp-includes/ms-site.php b/src/wp-includes/ms-site.php index 0058d1a48200d..19bb3ec0b33a3 100644 --- a/src/wp-includes/ms-site.php +++ b/src/wp-includes/ms-site.php @@ -441,6 +441,8 @@ 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}&array ? int : ($args is array{fields: 'ids'}&array ? array : array)) */ function get_sites( $args = array() ) { $query = new WP_Site_Query(); @@ -598,9 +600,9 @@ function wp_validate_site_data( $errors, $data, $old_site = null ) { // Allow '0000-00-00 00:00:00', although it be stripped out at this point. if ( '0000-00-00 00:00:00' !== $data[ $date_field ] ) { - $month = substr( $data[ $date_field ], 5, 2 ); - $day = substr( $data[ $date_field ], 8, 2 ); - $year = substr( $data[ $date_field ], 0, 4 ); + $month = (int) substr( $data[ $date_field ], 5, 2 ); + $day = (int) substr( $data[ $date_field ], 8, 2 ); + $year = (int) substr( $data[ $date_field ], 0, 4 ); $valid_date = wp_checkdate( $month, $day, $year, $data[ $date_field ] ); if ( ! $valid_date ) { $errors->add( 'site_invalid_' . $date_field, __( 'Both registration and last updated dates must be valid dates.' ) ); @@ -1126,7 +1128,7 @@ function update_site_meta( $site_id, $meta_key, $meta_value, $prev_value = '' ) * @return bool Whether the site meta key was deleted from the database. */ function delete_site_meta_by_key( $meta_key ) { - return delete_metadata( 'blog', null, $meta_key, '', true ); + return delete_metadata( 'blog', 0, $meta_key, '', true ); } /** diff --git a/src/wp-includes/nav-menu.php b/src/wp-includes/nav-menu.php index d808c4e212d39..4042ca25e55ef 100644 --- a/src/wp-includes/nav-menu.php +++ b/src/wp-includes/nav-menu.php @@ -377,7 +377,7 @@ function wp_update_nav_menu_object( $menu_id = 0, $menu_data = array() ) { return (int) $_menu['term_id']; } - if ( ! $_menu || ! isset( $_menu->term_id ) ) { + if ( ! isset( $_menu->term_id ) ) { return 0; } diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php index 098024b083fae..e83436e186a2f 100644 --- a/src/wp-includes/pluggable.php +++ b/src/wp-includes/pluggable.php @@ -97,6 +97,13 @@ 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-param 'id'|'ID'|'slug'|'email'|'login' $field + * @phpstan-return ( + * $field is 'id'|'ID' ? ( + * $value is not numeric ? false : (\WP_User|false) + * ) : ( $value is non-empty-string ? (\WP_User|false) : false ) + * ) */ function get_user_by( $field, $value ) { $userdata = WP_User::get_data_by( $field, $value ); @@ -1353,6 +1360,9 @@ function auth_redirect() { * @return int|false 1 if the nonce is valid and generated between 0-12 hours ago, * 2 if the nonce is valid and generated between 12-24 hours ago. * False if the nonce is invalid. + * + * @phpstan-param -1|string $action + * @phpstan-return 1|2|false */ function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) { if ( -1 === $action ) { @@ -1398,6 +1408,9 @@ function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) { * @return int|false 1 if the nonce is valid and generated between 0-12 hours ago, * 2 if the nonce is valid and generated between 12-24 hours ago. * False if the nonce is invalid. + * + * @phpstan-param -1|string $action + * @phpstan-return 1|2|false */ function check_ajax_referer( $action = -1, $query_arg = false, $stop = true ) { if ( -1 === $action ) { @@ -2435,6 +2448,9 @@ function wp_nonce_tick( $action = -1 ) { * @return int|false 1 if the nonce is valid and generated between 0-12 hours ago, * 2 if the nonce is valid and generated between 12-24 hours ago. * False if the nonce is invalid. + * + * @phpstan-param -1|string $action + * @phpstan-return 1|2|false */ function wp_verify_nonce( $nonce, $action = -1 ) { $nonce = (string) $nonce; @@ -2498,6 +2514,8 @@ function wp_verify_nonce( $nonce, $action = -1 ) { * * @param string|int $action Scalar value to add context to the nonce. * @return string The token. + * + * @phpstan-param -1|string $action */ function wp_create_nonce( $action = -1 ) { $user = wp_get_current_user(); diff --git a/src/wp-includes/plugin.php b/src/wp-includes/plugin.php index 5b4079b0bdd81..755895eee9a0f 100644 --- a/src/wp-includes/plugin.php +++ b/src/wp-includes/plugin.php @@ -277,6 +277,8 @@ function apply_filters_ref_array( $hook_name, $args ) { * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has * anything registered. When checking a specific function, the priority * of that hook is returned, or false if the function is not attached. + * + * @phpstan-return ( $callback is false ? bool : (false|int) ) */ function has_filter( $hook_name, $callback = false ) { global $wp_filter; @@ -584,6 +586,8 @@ function do_action_ref_array( $hook_name, $args ) { * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has * anything registered. When checking a specific function, the priority * of that hook is returned, or false if the function is not attached. + * + * @phpstan-return ( $callback is false ? bool : (false|int) ) */ function has_action( $hook_name, $callback = false ) { return has_filter( $hook_name, $callback ); @@ -671,6 +675,8 @@ function doing_action( $hook_name = null ) { * * @param string $hook_name The name of the action hook. * @return int The number of times the action hook has been fired. + * + * @phpstan-return int<0, max> */ function did_action( $hook_name ) { global $wp_actions; diff --git a/src/wp-includes/post-template.php b/src/wp-includes/post-template.php index edcc1e0f035ec..17d94fc404599 100644 --- a/src/wp-includes/post-template.php +++ b/src/wp-includes/post-template.php @@ -39,6 +39,8 @@ function get_the_ID() { // phpcs:ignore WordPress.NamingConventions.ValidFunctio * @param bool $display Optional. Whether to echo or return the title. Default true for echo. * @return void|string Void if `$display` argument is true or the title is empty, * current post title if `$display` is false. + * + * @phpstan-return ( $display is true ? void : (string|void) ) */ function the_title( $before = '', $after = '', $display = true ) { $title = get_the_title(); @@ -1296,6 +1298,8 @@ function wp_dropdown_pages( $args = '' ) { * Walker_Page instance being used. * } * @return void|string Void if 'echo' argument is true, HTML list of pages if 'echo' is false. + * + * @phpstan-return ($args is array{echo: false}&array ? string : void) */ function wp_list_pages( $args = '' ) { $defaults = array( diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 3940519d4dc15..ac901663d378d 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -986,6 +986,9 @@ function _wp_relative_upload_path( $path ) { * correspond to a WP_Post object, an associative array, or a numeric array, * respectively. Default OBJECT. * @return WP_Post[]|array[]|int[] Array of post objects, arrays, or IDs, depending on `$output`. + * + * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output + * @phpstan-return ($output is 'OBJECT' ? WP_Post[] : array[])|int[] */ function get_children( $args = '', $output = OBJECT ) { $kids = array(); @@ -1108,8 +1111,16 @@ function get_extended( $post ) { * respectively. Default OBJECT. * @param string $filter Optional. Type of filter to apply. Accepts 'raw', 'edit', 'db', * or 'display'. Default 'raw'. - * @return WP_Post|array|null Type corresponding to $output on success or null on failure. - * When $output is OBJECT, a `WP_Post` instance is returned. + * @return WP_Post|array|null Post data on success, or null on failure. + * + * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output + * @phpstan-return ( + * $output is 'ARRAY_A' ? ( $post is \WP_Post ? array : (array|null) ) : ( + * $output is 'ARRAY_N' ? ( $post is \WP_Post ? array : (array|null) ) : ( + * $post is \WP_Post ? \WP_Post : (\WP_Post|null) + * ) + * ) + * ) */ function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) { if ( empty( $post ) && isset( $GLOBALS['post'] ) ) { @@ -1535,6 +1546,8 @@ function get_post_status_object( $post_status ) { * from the array needs to match; 'and' means all elements must match. * Default 'and'. * @return string[]|stdClass[] A list of post status names or objects. + * + * @phpstan-return ($output is 'names' ? array : array) */ function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_post_statuses; @@ -1640,6 +1653,8 @@ function get_post_type_object( $post_type ) { * element from the array needs to match; 'and' means all elements * must match; 'not' means no elements may match. Default 'and'. * @return string[]|WP_Post_Type[] An array of post type names or objects. + * + * @phpstan-return ($output is 'names' ? array : array) */ function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_post_types; @@ -2577,6 +2592,8 @@ function is_post_embeddable( $post = null ) { * @type bool $suppress_filters Whether to suppress filters. Default true. * } * @return WP_Post[]|int[] Array of post objects or post IDs. + * + * @phpstan-return ( $args is array{fields: 'id=>parent'|'ids'}&array ? array : array ) */ function get_posts( $args = null ) { $defaults = array( @@ -2912,6 +2929,10 @@ function is_sticky( $post_id = 0 ) { * 'attribute', or 'js'. Default 'display'. * @return object|WP_Post|array The now sanitized post object or array (will be the * same type as `$post`). + * + * @phpstan-template T of object|array|\WP_Post + * @phpstan-param T $post + * @phpstan-return T */ function sanitize_post( $post, $context = 'display' ) { if ( is_object( $post ) ) { @@ -4318,6 +4339,20 @@ function wp_untrash_post_comments( $post = null ) { * 'all_with_object_id', an array of WP_Term objects will be returned. If `$fields` * is 'ids', an array of category IDs. If `$fields` is 'names', an array of category names. * WP_Error object if 'category' taxonomy doesn't exist. + * + * @phpstan-return ( + * $post_id is empty ? array{} : ( + * $args is array{fields: 'count'}&array ? numeric-string : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is (array{}|(array{fields: 'ids'|'tt_ids'}&array)) ? list : array + * ) + * ) + * ) + * )|\WP_Error + * ) + * ) */ function wp_get_post_categories( $post_id = 0, $args = array() ) { $post_id = (int) $post_id; @@ -4344,6 +4379,19 @@ function wp_get_post_categories( $post_id = 0, $args = array() ) { * See WP_Term_Query::__construct() for supported arguments. * @return array|WP_Error Array of WP_Term objects on success or empty array if no tags were found. * WP_Error object if 'post_tag' taxonomy doesn't exist. + * @phpstan-return ( + * $post_id is empty ? array{} : ( + * $args is array{fields: 'count'}&array ? numeric-string : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is array{fields: 'ids'|'tt_ids'}&array ? list : array + * ) + * ) + * ) + * )|\WP_Error + * ) + * ) */ function wp_get_post_tags( $post_id = 0, $args = array() ) { return wp_get_post_terms( $post_id, 'post_tag', $args ); @@ -4365,6 +4413,20 @@ function wp_get_post_tags( $post_id = 0, $args = array() ) { * } * @return array|WP_Error Array of WP_Term objects on success or empty array if no terms were found. * WP_Error object if `$taxonomy` doesn't exist. + * + * @phpstan-return ( + * $post_id is empty ? array{} : ( + * $args is array{fields: 'count'}&array ? numeric-string : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is array{fields: 'ids'|'tt_ids'}&array ? list : array + * ) + * ) + * ) + * )|\WP_Error + * ) + * ) */ function wp_get_post_terms( $post_id = 0, $taxonomy = 'post_tag', $args = array() ) { $post_id = (int) $post_id; @@ -4395,7 +4457,7 @@ function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) { if ( is_numeric( $args ) ) { _deprecated_argument( __FUNCTION__, '3.1.0', __( 'Passing an integer number of posts is deprecated. Pass an array of arguments instead.' ) ); - $args = array( 'numberposts' => absint( $args ) ); + $args = array( 'numberposts' => absint( $args ) ); // @phpstan-ignore function.unresolvableReturnType } // Set default arguments. @@ -4497,6 +4559,8 @@ function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) { * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. * @param bool $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true. * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure. + * + * @phpstan-return ( $wp_error is false ? int<0, max> : (int<1, max>|\WP_Error) ) */ function wp_insert_post( $postarr, $wp_error = false, $fire_after_hooks = true ) { global $wpdb; @@ -5221,6 +5285,8 @@ function wp_insert_post( $postarr, $wp_error = false, $fire_after_hooks = true ) * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. * @param bool $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true. * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure. + * + * @phpstan-return ( $wp_error is false ? int<0, max> : (int<1, max>|\WP_Error) ) */ function wp_update_post( $postarr = array(), $wp_error = false, $fire_after_hooks = true ) { if ( is_object( $postarr ) ) { @@ -6122,6 +6188,15 @@ function get_all_page_ids() { * @param string $filter Optional. How the return value should be filtered. Accepts 'raw', * 'edit', 'db', 'display'. Default 'raw'. * @return WP_Post|array|null WP_Post or array on success, null on failure. + * + * @phpstan-param 'OBJECT'|'ARRAY_A'|'ARRAY_N' $output + * @phpstan-return ( + * $output is 'ARRAY_A' ? ( $page is \WP_Post ? array : (array|null) ) : ( + * $output is 'ARRAY_N' ? ( $page is \WP_Post ? array : (array|null) ) : ( + * $page is \WP_Post ? \WP_Post : (\WP_Post|null) + * ) + * ) + * ) */ function get_page( $page, $output = OBJECT, $filter = 'raw' ) { return get_post( $page, $output, $filter ); @@ -6139,7 +6214,15 @@ function get_page( $page, $output = OBJECT, $filter = 'raw' ) { * correspond to a WP_Post object, an associative array, or a numeric array, * 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' ? array : ( + * $output is 'ARRAY_N' ? array : \WP_Post + * ) + * )|null */ function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) { global $wpdb; @@ -6640,6 +6723,8 @@ function is_local_attachment( $url ) { * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. * @param bool $fire_after_hooks Optional. Whether to fire the after insert hooks. Default true. * @return int|WP_Error The attachment ID on success. The value 0 or WP_Error on failure. + * + * @phpstan-return ( $wp_error is false ? int<0, max> : (int<1, max>|\WP_Error) ) */ function wp_insert_attachment( $args, $file = false, $parent_post_id = 0, $wp_error = false, $fire_after_hooks = true ) { $defaults = array( diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 592e70e0290a3..65ea2b1a370ce 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -937,6 +937,8 @@ function is_main_query() { * @global WP_Query $wp_query WordPress Query object. * * @return bool True if posts are available, false if end of the loop. + * + * @phpstan-impure */ function have_posts() { global $wp_query; diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php index d23931a589eed..e3adcc7fdf137 100644 --- a/src/wp-includes/rest-api.php +++ b/src/wp-includes/rest-api.php @@ -740,6 +740,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 ) ) { diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php index faeb01c93904a..c6b7b81bdac5c 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php @@ -470,6 +470,7 @@ public function update_item( $request ) { } $attachment = get_post( $request['id'] ); + $schema = $this->get_item_schema(); if ( ! empty( $schema['properties']['featured_media'] ) && isset( $request['featured_media'] ) ) { $thumbnail_update = $this->handle_featured_media( $request['featured_media'], $attachment->ID ); @@ -777,7 +778,7 @@ public function edit_media_item( $request ) { $new_attachment_post->post_parent = $new_attachment_post->post_parent ?? 0; // Insert the new attachment post. - $new_attachment_id = wp_insert_attachment( wp_slash( $new_attachment_post ), $saved['path'], 0, true ); + $new_attachment_id = wp_insert_attachment( wp_slash( (array) $new_attachment_post ), $saved['path'], 0, true ); if ( is_wp_error( $new_attachment_id ) ) { if ( 'db_update_error' === $new_attachment_id->get_error_code() ) { diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php index f4f6bdd1f1a54..2ff97dccad84f 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php @@ -336,8 +336,8 @@ public function get_items( $request ) { } $response = $is_head_request ? new WP_REST_Response( array() ) : rest_ensure_response( $comments ); - $response->header( 'X-WP-Total', $total_comments ); - $response->header( 'X-WP-TotalPages', $max_pages ); + $response->header( 'X-WP-Total', (string) $total_comments ); + $response->header( 'X-WP-TotalPages', (string) $max_pages ); $base = add_query_arg( urlencode_deep( $request->get_query_params() ), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); diff --git a/src/wp-includes/revision.php b/src/wp-includes/revision.php index a2267fcbf8f60..8d0ce6584daf6 100644 --- a/src/wp-includes/revision.php +++ b/src/wp-includes/revision.php @@ -423,6 +423,13 @@ function wp_save_revisioned_meta_fields( $revision_id, $post_id ) { * respectively. Default OBJECT. * @param string $filter Optional sanitization filter. See sanitize_post(). Default 'raw'. * @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' ? array : ( + * $output is 'ARRAY_N' ? array : \WP_Post + * ) + * )|null */ function wp_get_post_revision( &$post, $output = OBJECT, $filter = 'raw' ) { $revision = get_post( $post, OBJECT, $filter ); @@ -463,7 +470,7 @@ function wp_restore_post_revision( $revision, $fields = null ) { $revision = wp_get_post_revision( $revision, ARRAY_A ); if ( ! $revision ) { - return $revision; + return null; } if ( ! is_array( $fields ) ) { @@ -938,7 +945,11 @@ function _wp_preview_terms_filter( $terms, $post_id, $taxonomy ) { * @param null|array|string $value The value to return - a single metadata value, or an array of values. * @param int $post_id Post ID. * @param string $meta_key Meta key. - * @return null|array The default return value or the post thumbnail meta array. + * @return null|array|string The default return value or the post thumbnail meta array. + * + * @template T + * @phpstan-param T $value + * @phpstan-return T|''|numeric-string */ function _wp_preview_post_thumbnail_filter( $value, $post_id, $meta_key ) { $post = get_post(); diff --git a/src/wp-includes/style-engine/class-wp-style-engine-css-rules-store.php b/src/wp-includes/style-engine/class-wp-style-engine-css-rules-store.php index 4a82f28b8a41e..220980c8dc6b6 100644 --- a/src/wp-includes/style-engine/class-wp-style-engine-css-rules-store.php +++ b/src/wp-includes/style-engine/class-wp-style-engine-css-rules-store.php @@ -13,6 +13,8 @@ * Holds, sanitizes, processes, and prints CSS declarations for the style engine. * * @since 6.1.0 + * + * @phpstan-consistent-constructor */ #[AllowDynamicProperties] class WP_Style_Engine_CSS_Rules_Store { diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 69f3fe7484c24..00779a6477ed7 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -278,6 +278,8 @@ function create_initial_taxonomies() { * one element from the array needs to match; 'and' means all elements must match. * Default 'and'. * @return string[]|WP_Taxonomy[] An array of taxonomy names or objects. + * + * @phpstan-return ($output is 'names' ? array : array) */ function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) { global $wp_taxonomies; @@ -307,6 +309,8 @@ function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) * @param string $output Optional. The type of output to return in the array. Accepts either * 'names' or 'objects'. Default 'names'. * @return string[]|WP_Taxonomy[] The names or objects of all taxonomies of `$object_type`. + * + * @phpstan-return ($output is 'names' ? array : array) */ function get_object_taxonomies( $object_type, $output = 'names' ) { global $wp_taxonomies; @@ -971,8 +975,12 @@ function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) { * correspond to a WP_Term object, an associative array, or a numeric array, * respectively. Default OBJECT. * @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. + * + * @return WP_Term|array|WP_Error|null Term data on success, 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 : ($output is 'ARRAY_N' ? array : \WP_Term) )|\WP_Error|null */ function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { if ( empty( $term ) ) { @@ -1093,8 +1101,15 @@ function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { * correspond to a WP_Term object, an associative array, or a numeric array, * respectively. Default OBJECT. * @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-return ( + * $output is 'ARRAY_A' ? array : ( + * $output is 'ARRAY_N' ? array : \WP_Term + * ) + * )|false */ function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { @@ -1245,7 +1260,9 @@ function get_term_field( $field, $term, $taxonomy = '', $context = 'display' ) { * * @param int|object $id Term ID or object. * @param string $taxonomy Taxonomy name. - * @return string|int|null|WP_Error Will return empty string if $term is not an object. + * @return string|WP_Term|WP_Error Will return empty string if $term is not an object. + * + * @phpstan-return ''|\WP_Error|\WP_Term|WP_Error */ function get_term_to_edit( $id, $taxonomy ) { $term = get_term( $id, $taxonomy ); @@ -1312,6 +1329,18 @@ function get_term_to_edit( $id, $taxonomy ) { * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string, * or WP_Error if any of the taxonomies do not exist. * See the function description for more information. + * + * @phpstan-return ( + * $args is array{fields: 'count'}&array ? numeric-string : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is array{fields: 'ids'|'tt_ids'}&array ? list : array + * ) + * ) + * ) + * ) + * )|\WP_Error */ function get_terms( $args = array(), $deprecated = '' ) { $term_query = new WP_Term_Query(); @@ -1588,6 +1617,14 @@ function unregister_term_meta( $taxonomy, $meta_key ) { * Returns the term ID if no taxonomy is specified and the term ID exists. * Returns an array of the term ID and the term taxonomy ID if the taxonomy is specified and the pairing exists. * Returns 0 if term ID 0 is passed to the function. + * + * @phpstan-return ( + * $term is 0 ? 0 : ( + * $term is '' ? null : ( + * $taxonomy is '' ? (string|null) : (array{term_id: string, term_taxonomy_id: string}|null) + * ) + * ) + * ) */ function term_exists( $term, $taxonomy = '', $parent_term = null ) { global $_wp_suspend_cache_invalidation; @@ -1711,12 +1748,16 @@ function term_is_ancestor_of( $term1, $term2, $taxonomy ) { * * @since 2.3.0 * - * @param array|object $term The term to check. + * @param array|object|WP_Term $term The term to check. * @param string $taxonomy The taxonomy name to use. * @param string $context Optional. Context in which to sanitize the term. * Accepts 'raw', 'edit', 'db', 'display', 'rss', * 'attribute', or 'js'. Default 'display'. - * @return array|object Term with all fields sanitized. + * @return array|object|WP_Term Term with all fields sanitized. + * + * @phpstan-template T of object|array|\WP_Term + * @phpstan-param T $term + * @phpstan-return T */ function sanitize_term( $term, $taxonomy, $context = 'display' ) { $fields = array( 'term_id', 'name', 'description', 'slug', 'count', 'parent', 'term_group', 'term_taxonomy_id', 'object_id' ); @@ -2267,6 +2308,22 @@ function wp_delete_category( $cat_id ) { * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string, * or WP_Error if any of the taxonomies do not exist. * See WP_Term_Query::get_terms() for more information. + * + * @phpstan-return ( + * $object_ids is empty ? array{} : ( + * $taxonomies is empty ? array{} : ( + * $args is array{fields: 'count'}&array ? numeric-string : ( + * $args is array{fields: 'names'|'slugs'}&array ? list : ( + * $args is array{fields: 'id=>name'|'id=>slug'}&array ? array : ( + * $args is array{fields: 'id=>parent'}&array ? array : ( + * $args is array{fields: 'ids'|'tt_ids'}&array ? list : array + * ) + * ) + * ) + * )|\WP_Error + * ) + * ) + * ) */ function wp_get_object_terms( $object_ids, $taxonomies, $args = array() ) { if ( empty( $object_ids ) || empty( $taxonomies ) ) { @@ -2595,7 +2652,7 @@ function wp_insert_term( $term, $taxonomy, $args = array() ) { // Seems unreachable. However, is used in the case that a term name is provided, which sanitizes to an empty string. if ( empty( $slug ) ) { - $slug = sanitize_title( $slug, $term_id ); + $slug = sanitize_title( $slug, (string) $term_id ); /** This action is documented in wp-includes/taxonomy.php */ do_action( 'edit_terms', $term_id, $taxonomy ); @@ -3368,7 +3425,7 @@ function wp_update_term( $term_id, $taxonomy, $args = array() ) { $wpdb->update( $wpdb->terms, $data, compact( 'term_id' ) ); if ( empty( $slug ) ) { - $slug = sanitize_title( $name, $term_id ); + $slug = sanitize_title( $name, (string) $term_id ); $wpdb->update( $wpdb->terms, compact( 'slug' ), compact( 'term_id' ) ); } @@ -3515,7 +3572,7 @@ function wp_defer_term_counting( $defer = null ) { $_defer = $defer; // Flush any deferred counts. if ( ! $defer ) { - wp_update_term_count( null, null, true ); + wp_update_term_count( 0, '', true ); } } diff --git a/src/wp-includes/template.php b/src/wp-includes/template.php index 1c127e7fdf40b..cc9888f64b601 100644 --- a/src/wp-includes/template.php +++ b/src/wp-includes/template.php @@ -796,7 +796,7 @@ function load_template( $_template_file, $load_once = true, $args = array() ) { } if ( isset( $s ) ) { - $s = esc_attr( $s ); + $s = esc_attr( $s ); // @phpstan-ignore variable.undefined (It's extracted from query vars.) } /** diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 10d8d4a21d136..439a1b5ffbf90 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -855,6 +855,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 ); @@ -908,7 +910,9 @@ function get_users( $args = array() ) { * @type string $exclude An array, comma-, or space-separated list of user IDs to exclude. Default empty. * @type string $include An array, comma-, or space-separated list of user IDs to include. Default empty. * } - * @return string|null The output if echo is false. Otherwise null. + * @return string|void The output if echo is false. Otherwise void. + * + * @phpstan-return ( $args is array{echo:false}&array ? string : void ) */ function wp_list_users( $args = array() ) { $defaults = array( @@ -2342,7 +2346,7 @@ function wp_insert_user( $userdata ) { * check if current email and new email are the same, and check `email_exists` * accordingly. */ - if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) ) + if ( ( ! $update || 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) && ! defined( 'WP_IMPORTING' ) && email_exists( $user_email ) ) { diff --git a/src/wp-includes/widgets.php b/src/wp-includes/widgets.php index 5bf9d16b31393..9d917aebd5919 100644 --- a/src/wp-includes/widgets.php +++ b/src/wp-includes/widgets.php @@ -392,6 +392,8 @@ function is_registered_sidebar( $sidebar_id ) { * Only available for WP_Widget based widgets. * } * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * + * @phpstan-param string|callable|callable-string $output_callback */ function wp_register_sidebar_widget( $id, $name, $output_callback, $options = array(), ...$params ) { global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates, $_wp_deprecated_widgets_callbacks; @@ -532,6 +534,8 @@ function wp_unregister_sidebar_widget( $id ) { * text widget. The widget ID will end up looking like `{$id_base}-{$unique_number}`. * } * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * + * @phpstan-param string|callable|callable-string $control_callback */ function wp_register_widget_control( $id, $name, $control_callback, $options = array(), ...$params ) { global $wp_registered_widget_controls, $wp_registered_widget_updates, $wp_registered_widgets, $_wp_deprecated_widgets_callbacks; @@ -598,6 +602,8 @@ function wp_register_widget_control( $id, $name, $control_callback, $options = a * @param array $options Optional. Widget control options. See wp_register_widget_control(). * Default empty array. * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * + * @phpstan-param string|callable|callable-string $update_callback */ function _register_widget_update_callback( $id_base, $update_callback, $options = array(), ...$params ) { global $wp_registered_widget_updates; @@ -633,8 +639,9 @@ function _register_widget_update_callback( $id_base, $update_callback, $options * @param array $options Optional. Widget control options. See wp_register_widget_control(). * Default empty array. * @param mixed ...$params Optional additional parameters to pass to the callback function when it's called. + * + * @phpstan-param string|callable|callable-string $form_callback */ - function _register_widget_form_callback( $id, $name, $form_callback, $options = array(), ...$params ) { global $wp_registered_widget_controls; diff --git a/src/wp-login.php b/src/wp-login.php index 4900834447eca..6d8698dbd606d 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -408,6 +408,7 @@ function login_footer( $input_id = '' ) { wp_dropdown_languages( apply_filters( 'login_language_dropdown_args', $args ) ); ?> + diff --git a/src/wp-signup.php b/src/wp-signup.php index 0508d01c50df5..8150cc937e3d1 100644 --- a/src/wp-signup.php +++ b/src/wp-signup.php @@ -26,7 +26,7 @@ * * @since MU (3.0.0) */ -function do_signup_header() { +function do_signup_header(): void { /** * Fires within the head section of the site sign-up screen. * @@ -61,7 +61,7 @@ function do_signup_header() { * * @since MU (3.0.0) */ -function wpmu_signup_stylesheet() { +function wpmu_signup_stylesheet(): void { ?>