Commit ef93d4d54f for wordpress.org

commit ef93d4d54fe8db5fa81dbdd9bc81d2ebe505cf1c
Author: westonruter <westonruter@git.wordpress.org>
Date:   Wed Oct 7 00:06:50 2026 +0000

    Docs: Improve list table documentation and types.

    Adds missing summaries, `@since` tags, and descriptions for parameters, return values, globals, and properties in `WP_MS_Users_List_Table` and `WP_Plugin_Install_List_Table`, and corrects several existing `@since` versions. Array descriptions now state what their keys and values are, such as column titles keyed by column name.

    Types are also made more precise for static analysis. Where a narrower type conflicted with one documented elsewhere, it was corrected at its source rather than loosened, which extends the change to `WP_List_Table` and several other list tables.

    Developed in https://github.com/WordPress/wordpress-develop/pull/11023.
    Follow-up to r29225, r30679, r32642, r32654, r42631, r54215.

    Props noruzzaman, huzaifaalmesbah, westonruter.
    See #65817, #65860.

    Built from https://develop.svn.wordpress.org/trunk@64222


    git-svn-id: http://core.svn.wordpress.org/trunk@63373 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-admin/includes/class-wp-application-passwords-list-table.php b/wp-admin/includes/class-wp-application-passwords-list-table.php
index b3dccaf478..a5e143e30e 100644
--- a/wp-admin/includes/class-wp-application-passwords-list-table.php
+++ b/wp-admin/includes/class-wp-application-passwords-list-table.php
@@ -147,6 +147,8 @@ class WP_Application_Passwords_List_Table extends WP_List_Table {
 	 * @since 5.6.0
 	 *
 	 * @param string $which The location of the bulk actions: Either 'top' or 'bottom'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	protected function display_tablenav( $which ) {
 		?>
diff --git a/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php
index 2792b4b3ec..a63719d1d3 100644
--- a/wp-admin/includes/class-wp-list-table.php
+++ b/wp-admin/includes/class-wp-list-table.php
@@ -30,6 +30,13 @@ class WP_List_Table {
 	 * @since 3.1.0
 	 *
 	 * @var array<string, mixed>
+	 * @phpstan-var array{
+	 *     plural: string,
+	 *     singular: string,
+	 *     ajax: bool,
+	 *     screen: string|WP_Screen|null,
+	 *     ...
+	 * }
 	 */
 	protected $_args;

@@ -146,6 +153,14 @@ class WP_List_Table {
 	 *                                           screen, or a `WP_Screen` instance. If left null, the current
 	 *                                           screen will be automatically set. Default null.
 	 * }
+	 *
+	 * @phpstan-param array{
+	 *     plural?: string,
+	 *     singular?: string,
+	 *     ajax?: bool,
+	 *     screen?: string|WP_Screen|null,
+	 *     ...
+	 * }|string $args
 	 */
 	public function __construct( $args = array() ) {
 		$args = wp_parse_args(
@@ -438,6 +453,10 @@ class WP_List_Table {
 	 *     }
 	 * }
 	 * @return string[] An array of link markup. Keys match the `$link_data` input array.
+	 *
+	 * @phpstan-template TKey of array-key
+	 * @phpstan-param array<TKey, array{ url: string, label: string, current?: bool }>|string $link_data
+	 * @phpstan-return ($link_data is array ? array<TKey, string> : array{ 0: '' })
 	 */
 	protected function get_views_links( $link_data = array() ) {
 		if ( ! is_array( $link_data ) ) {
@@ -1030,6 +1049,8 @@ class WP_List_Table {
 	 * @since 3.1.0
 	 *
 	 * @param string $which The location of the pagination: Either 'top' or 'bottom'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	protected function pagination( $which ) {
 		if ( empty( $this->_pagination_args['total_items'] ) ) {
@@ -1665,6 +1686,8 @@ class WP_List_Table {
 	 * @since 3.1.0
 	 *
 	 * @return string[] Array of CSS classes for the table tag.
+	 *
+	 * @phpstan-return non-empty-list<string>
 	 */
 	protected function get_table_classes() {
 		$mode = get_user_setting( 'posts_list_mode', 'list' );
@@ -1680,6 +1703,8 @@ class WP_List_Table {
 	 * @since 3.1.0
 	 *
 	 * @param string $which The location of the navigation: Either 'top' or 'bottom'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	protected function display_tablenav( $which ) {
 		if ( 'bottom' === $which && ! $this->has_items() ) {
diff --git a/wp-admin/includes/class-wp-ms-sites-list-table.php b/wp-admin/includes/class-wp-ms-sites-list-table.php
index 1ffa24ea24..a12954827e 100644
--- a/wp-admin/includes/class-wp-ms-sites-list-table.php
+++ b/wp-admin/includes/class-wp-ms-sites-list-table.php
@@ -318,6 +318,8 @@ class WP_MS_Sites_List_Table extends WP_List_Table {
 	 * @global string $mode List table view mode.
 	 *
 	 * @param string $which The location of the pagination nav markup: Either 'top' or 'bottom'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	protected function pagination( $which ) {
 		global $mode;
diff --git a/wp-admin/includes/class-wp-ms-themes-list-table.php b/wp-admin/includes/class-wp-ms-themes-list-table.php
index eb49de1551..0ecacb8f27 100644
--- a/wp-admin/includes/class-wp-ms-themes-list-table.php
+++ b/wp-admin/includes/class-wp-ms-themes-list-table.php
@@ -73,6 +73,8 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
 	 * Gets the list of CSS classes for the table tag.
 	 *
 	 * @return string[] The list of CSS classes.
+	 *
+	 * @phpstan-return non-empty-list<string>
 	 */
 	protected function get_table_classes() {
 		// @todo Remove and add CSS for .themes.
diff --git a/wp-admin/includes/class-wp-ms-users-list-table.php b/wp-admin/includes/class-wp-ms-users-list-table.php
index 145299bcc2..adead723ab 100644
--- a/wp-admin/includes/class-wp-ms-users-list-table.php
+++ b/wp-admin/includes/class-wp-ms-users-list-table.php
@@ -16,16 +16,24 @@
  */
 class WP_MS_Users_List_Table extends WP_List_Table {
 	/**
-	 * @return bool
+	 * Checks if the current user has permissions to perform an Ajax action.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return bool Whether the current user can perform an Ajax action.
 	 */
 	public function ajax_user_can() {
 		return current_user_can( 'manage_network_users' );
 	}

 	/**
+	 * Prepares the users list for display.
+	 *
+	 * @since 3.1.0
+	 *
 	 * @global string $mode       List table view mode.
-	 * @global string $usersearch
-	 * @global string $role
+	 * @global string $usersearch User search query.
+	 * @global string $role       The user role to filter by. Only 'super' (super admins) is supported.
 	 */
 	public function prepare_items() {
 		global $mode, $usersearch, $role;
@@ -106,7 +114,11 @@ class WP_MS_Users_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @return array
+	 * Gets the available bulk actions for the users list table.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return array<string, string> Bulk action labels keyed by action name.
 	 */
 	protected function get_bulk_actions() {
 		$actions = array();
@@ -120,14 +132,22 @@ class WP_MS_Users_List_Table extends WP_List_Table {
 	}

 	/**
+	 * Displays a message when there are no items.
+	 *
+	 * @since 3.1.0
 	 */
 	public function no_items() {
 		_e( 'No users found.' );
 	}

 	/**
-	 * @global string $role
-	 * @return array
+	 * Gets the list of views (all, super admin) available for the users list table.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @global string $role The user role to filter by. Only 'super' (super admins) is supported.
+	 *
+	 * @return array<string, string> View link markup keyed by view name ('all' or 'super').
 	 */
 	protected function get_views() {
 		global $role;
@@ -170,9 +190,15 @@ class WP_MS_Users_List_Table extends WP_List_Table {
 	}

 	/**
+	 * Generates the list table pagination.
+	 *
+	 * @since 3.1.0
+	 *
 	 * @global string $mode List table view mode.
 	 *
-	 * @param string $which
+	 * @param string $which The location of the pagination: Either 'top' or 'bottom'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	protected function pagination( $which ) {
 		global $mode;
@@ -185,7 +211,11 @@ class WP_MS_Users_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @return string[] Array of column titles keyed by their column name.
+	 * Gets the list of columns for the users list table.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return array<string, string> Array of column titles keyed by their column name.
 	 */
 	public function get_columns() {
 		$users_columns = array(
@@ -201,14 +231,20 @@ class WP_MS_Users_List_Table extends WP_List_Table {
 		 *
 		 * @since MU (3.0.0)
 		 *
-		 * @param string[] $users_columns An array of user columns. Default 'cb', 'username',
-		 *                                'name', 'email', 'registered', 'blogs'.
+		 * @param array<string, string> $users_columns Column titles keyed by column name. Default keys are 'cb',
+		 *                                             'username', 'name', 'email', 'registered', and 'blogs'.
 		 */
 		return apply_filters( 'wpmu_users_columns', $users_columns );
 	}

 	/**
-	 * @return array
+	 * Gets the list of sortable columns for the users list table.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return array<string, array<int, string|bool>> Sortable columns.
+	 *
+	 * @phpstan-return array<string, array{0: string, 1: bool, 2: string, 3: string, 4?: 'asc'|'desc'}>
 	 */
 	protected function get_sortable_columns() {
 		return array(
@@ -349,12 +385,14 @@ class WP_MS_Users_List_Table extends WP_List_Table {
 	}

 	/**
+	 * Outputs the sites column content.
+	 *
 	 * @since 4.3.0
 	 *
-	 * @param WP_User $user
-	 * @param string  $classes
-	 * @param string  $data
-	 * @param string  $primary
+	 * @param WP_User $user    The current WP_User object.
+	 * @param string  $classes CSS classes for the cell.
+	 * @param string  $data    Custom data attributes for the cell.
+	 * @param string  $primary The primary column name.
 	 */
 	protected function _column_blogs( $user, $classes, $data, $primary ) {
 		echo '<td class="', $classes, ' has-row-actions" ', $data, '>';
diff --git a/wp-admin/includes/class-wp-plugin-install-list-table.php b/wp-admin/includes/class-wp-plugin-install-list-table.php
index 7c54aefca1..3f6d2a104d 100644
--- a/wp-admin/includes/class-wp-plugin-install-list-table.php
+++ b/wp-admin/includes/class-wp-plugin-install-list-table.php
@@ -16,14 +16,54 @@
  */
 class WP_Plugin_Install_List_Table extends WP_List_Table {

-	public $order   = 'ASC';
+	/**
+	 * Sort order of the plugins list: Either 'ASC' or 'DESC'.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @var string
+	 * @phpstan-var 'ASC'|'DESC'
+	 */
+	public $order = 'ASC';
+
+	/**
+	 * Plugin field to sort the list by, or null to keep the API's order.
+	 *
+	 * Not set by core. Sorting only applies when the plugins are objects, since
+	 * {@see self::order_callback()} reads object properties, whereas the plugins
+	 * returned by the API have been arrays since WordPress 5.1.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @var string|null
+	 */
 	public $orderby = null;
-	public $groups  = array();

+	/**
+	 * Plugin group names keyed by group slug, as returned by the Plugin Installation API.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @var array<string, string>
+	 */
+	public $groups = array();
+
+	/**
+	 * Error returned by the Plugin Installation API, if any.
+	 *
+	 * @since 4.0.0
+	 * @since 4.2.0 Declared as a private property.
+	 *
+	 * @var WP_Error|null
+	 */
 	private $error;

 	/**
-	 * @return bool
+	 * Checks if the current user has permissions to perform an Ajax action.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return bool Whether the current user can perform an Ajax action.
 	 */
 	public function ajax_user_can() {
 		return current_user_can( 'install_plugins' );
@@ -80,11 +120,15 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @global array  $tabs
-	 * @global string $tab
-	 * @global int    $paged
-	 * @global string $type
-	 * @global string $term
+	 * Prepares the plugins list for display.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @global array<string, string> $tabs  Labels of the tabs shown on the Add Plugins screen, keyed by tab slug.
+	 * @global string                $tab   The current active tab.
+	 * @global int                   $paged The current page number.
+	 * @global string                $type  The type of search being performed.
+	 * @global string                $term  The search term.
 	 */
 	public function prepare_items() {
 		require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
@@ -128,8 +172,9 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 		 *
 		 * @since 2.7.0
 		 *
-		 * @param string[] $tabs The tabs shown on the Add Plugins screen. Defaults include
-		 *                       'featured', 'popular', 'recommended', 'favorites', and 'upload'.
+		 * @param array<string, string> $tabs Labels of the tabs shown on the Add Plugins screen, keyed by tab
+		 *                                    slug. Default keys include 'featured', 'popular', 'recommended',
+		 *                                    'favorites', and 'upload'.
 		 */
 		$tabs = apply_filters( 'install_plugins_tabs', $tabs );

@@ -287,6 +332,9 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 	}

 	/**
+	 * Outputs the message when no plugins are found.
+	 *
+	 * @since 3.1.0
 	 */
 	public function no_items() {
 		if ( isset( $this->error ) ) {
@@ -307,10 +355,14 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @global array $tabs
-	 * @global string $tab
+	 * Gets the list of views (tabs) available for the plugins list table.
 	 *
-	 * @return array
+	 * @since 3.1.0
+	 *
+	 * @global array<string, string> $tabs Labels of the tabs shown on the Add Plugins screen, keyed by tab slug.
+	 * @global string                $tab  The current active tab.
+	 *
+	 * @return array<string, string> View link markup keyed by view ID ('plugin-install-' followed by the tab slug).
 	 */
 	protected function get_views() {
 		global $tabs, $tab;
@@ -332,6 +384,8 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 	/**
 	 * Overrides parent views so we can use the filter bar display.
 	 *
+	 * @since 4.0.0
+	 *
 	 * @global string $tab The current tab.
 	 */
 	public function views() {
@@ -403,9 +457,15 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @global string $tab
+	 * Generates the table navigation.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @global string $tab The current active tab.
 	 *
-	 * @param string $which
+	 * @param string $which The location of the navigation: Either 'top' or 'bottom'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	protected function display_tablenav( $which ) {
 		if ( 'featured' === $GLOBALS['tab'] ) {
@@ -439,23 +499,39 @@ class WP_Plugin_Install_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @return array
+	 * Gets a list of CSS classes for the list table container element.
+	 *
+	 * Unlike in the parent class, these are applied to a `div` element rather than a `table` element.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return string[] Array of CSS classes for the container element.
+	 *
+	 * @phpstan-return non-empty-list<string>
 	 */
 	protected function get_table_classes() {
 		return array( 'widefat', $this->_args['plural'] );
 	}

 	/**
-	 * @return string[] Array of column titles keyed by their column name.
+	 * Gets the list of columns for the plugins list table.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return array<string, string> Array of column titles keyed by their column name.
 	 */
 	public function get_columns() {
 		return array();
 	}

 	/**
-	 * @param object $plugin_a
-	 * @param object $plugin_b
-	 * @return int
+	 * Callback for sorting plugins.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @param array<string, mixed>|object $plugin_a The first plugin data.
+	 * @param array<string, mixed>|object $plugin_b The second plugin data.
+	 * @return int Comparison result.
 	 */
 	private function order_callback( $plugin_a, $plugin_b ) {
 		$orderby = $this->orderby;
diff --git a/wp-admin/includes/class-wp-plugins-list-table.php b/wp-admin/includes/class-wp-plugins-list-table.php
index d8945e1030..c63a37992b 100644
--- a/wp-admin/includes/class-wp-plugins-list-table.php
+++ b/wp-admin/includes/class-wp-plugins-list-table.php
@@ -68,6 +68,8 @@ class WP_Plugins_List_Table extends WP_List_Table {
 	 * @since 3.1.0
 	 *
 	 * @return string[] Array of CSS classes for the table tag.
+	 *
+	 * @phpstan-return non-empty-list<string>
 	 */
 	protected function get_table_classes() {
 		return array( 'widefat', $this->_args['plural'] );
diff --git a/wp-admin/includes/class-wp-post-comments-list-table.php b/wp-admin/includes/class-wp-post-comments-list-table.php
index 4454a77fe7..936f9a05ac 100644
--- a/wp-admin/includes/class-wp-post-comments-list-table.php
+++ b/wp-admin/includes/class-wp-post-comments-list-table.php
@@ -32,7 +32,13 @@ class WP_Post_Comments_List_Table extends WP_Comments_List_Table {
 	}

 	/**
-	 * @return array
+	 * Gets a list of CSS classes for the WP_List_Table table tag.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @return string[] Array of CSS classes for the table tag.
+	 *
+	 * @phpstan-return non-empty-list<string>
 	 */
 	protected function get_table_classes() {
 		$classes   = parent::get_table_classes();
diff --git a/wp-admin/includes/class-wp-posts-list-table.php b/wp-admin/includes/class-wp-posts-list-table.php
index d3d631b9b4..00edeed1ac 100644
--- a/wp-admin/includes/class-wp-posts-list-table.php
+++ b/wp-admin/includes/class-wp-posts-list-table.php
@@ -631,9 +631,15 @@ class WP_Posts_List_Table extends WP_List_Table {
 	}

 	/**
+	 * Gets a list of CSS classes for the WP_List_Table table tag.
+	 *
+	 * @since 3.1.0
+	 *
 	 * @global string $mode List table view mode.
 	 *
-	 * @return array
+	 * @return string[] Array of CSS classes for the table tag.
+	 *
+	 * @phpstan-return non-empty-list<string>
 	 */
 	protected function get_table_classes() {
 		global $mode;
diff --git a/wp-admin/includes/class-wp-themes-list-table.php b/wp-admin/includes/class-wp-themes-list-table.php
index 518b786f62..3a8f11aba2 100644
--- a/wp-admin/includes/class-wp-themes-list-table.php
+++ b/wp-admin/includes/class-wp-themes-list-table.php
@@ -134,7 +134,14 @@ class WP_Themes_List_Table extends WP_List_Table {
 	}

 	/**
-	 * @param string $which
+	 * Displays the table navigation, including the pagination.
+	 *
+	 * @since 3.1.0
+	 *
+	 * @param string $which Optional. The location of the navigation: Either 'top' or 'bottom'.
+	 *                      Default 'top'.
+	 *
+	 * @phpstan-param 'top'|'bottom' $which
 	 */
 	public function tablenav( $which = 'top' ) {
 		if ( $this->get_pagination_arg( 'total_pages' ) <= 1 ) {
diff --git a/wp-includes/version.php b/wp-includes/version.php
index d95b9411e0..1e6a567913 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-alpha-64163';
+$wp_version = '7.2-alpha-64222';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.