Commit 6d8c6e5559 for wordpress.org

commit 6d8c6e5559e8ee637f9f4dc5bc199d131feecdd3
Author: westonruter <westonruter@1a063a9b-81f0-0310-95a4-ce76da25c4cd>
Date:   Sat Nov 14 05:15:02 2026 +0000

    Posts, Post Types: Accept an array `exclude` in `wp_list_pages()`.

    Passing an array of page IDs as the `exclude` argument caused a fatal `TypeError` on PHP 8, since the value was sanitized with `preg_replace()` and split with `explode()`. It is now parsed with `wp_parse_id_list()`, which also accepts the comma-separated string that remains supported for back-compat. The same fix is applied to `wp_page_menu()`, which appended the static front page to `exclude` by string concatenation. The `wp_list_pages_excludes` filter still receives a list of numeric strings, as before.

    The `exclude` and `include` arguments are now documented as `int[]`, matching `get_pages()` which receives them. The `include` argument had been typed as an array but described as a comma-separated list. Documenting the array form steers callers toward input that static analysis can check, even though a string is still accepted.

    Developed in https://github.com/WordPress/wordpress-develop/pull/13922.
    Follow-up to r10115, r10121.

    Props sabbir345, westonruter, marian1, irozum, wprashed, therssoftware.
    Fixes #66052.

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


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

diff --git a/wp-includes/post-template.php b/wp-includes/post-template.php
index 0c2e25112f..9f6559e648 100644
--- a/wp-includes/post-template.php
+++ b/wp-includes/post-template.php
@@ -1274,6 +1274,7 @@ function wp_dropdown_pages( $args = '' ) {
  *
  * @since 1.5.0
  * @since 4.7.0 Added the `item_spacing` argument.
+ * @since 7.2.0 The `exclude` argument now accepts an array of page IDs (a comma-separated list string of IDs remains supported).
  *
  * @see get_pages()
  *
@@ -1290,8 +1291,8 @@ function wp_dropdown_pages( $args = '' ) {
  *                                           Accepts -1 (any depth), 0 (all pages), 1 (top-level pages only), and n (pages to
  *                                           the given n depth). Default 0.
  *     @type bool              $echo         Whether or not to echo the list of pages. Default true.
- *     @type string            $exclude      Comma-separated list of page IDs to exclude. Default empty.
- *     @type array             $include      Comma-separated list of page IDs to include. Default empty.
+ *     @type int[]             $exclude      Array of page IDs to exclude. Default empty array.
+ *     @type int[]             $include      Array of page IDs to include. Default empty array.
  *     @type string            $link_after   Text or HTML to follow the page link label. Default null.
  *     @type string            $link_before  Text or HTML to precede the page link label. Default null.
  *     @type string            $post_type    Post type to query for. Default 'page'.
@@ -1321,7 +1322,7 @@ function wp_list_pages( $args = '' ) {
 		'show_date'    => '',
 		'date_format'  => get_option( 'date_format' ),
 		'child_of'     => 0,
-		'exclude'      => '',
+		'exclude'      => array(),
 		'title_li'     => __( 'Pages' ),
 		'echo'         => 1,
 		'authors'      => '',
@@ -1342,11 +1343,8 @@ function wp_list_pages( $args = '' ) {
 	$output       = '';
 	$current_page = 0;

-	// Sanitize, mostly to keep spaces out.
-	$parsed_args['exclude'] = preg_replace( '/[^0-9,]/', '', $parsed_args['exclude'] );
-
-	// Allow plugins to filter an array of excluded pages (but don't put a nullstring into the array).
-	$exclude_array = ( $parsed_args['exclude'] ) ? explode( ',', $parsed_args['exclude'] ) : array();
+	// Allow plugins to filter a list of excluded page IDs, cast to strings for back-compat with the filter's original input.
+	$exclude_array = array_map( 'strval', array_values( array_filter( wp_parse_id_list( $parsed_args['exclude'] ) ) ) );

 	/**
 	 * Filters the array of pages to exclude from the pages list.
@@ -1354,6 +1352,7 @@ function wp_list_pages( $args = '' ) {
 	 * @since 2.1.0
 	 *
 	 * @param string[] $exclude_array An array of page IDs to exclude.
+	 * @phpstan-param list<numeric-string> $exclude_array
 	 */
 	$parsed_args['exclude'] = implode( ',', apply_filters( 'wp_list_pages_excludes', $exclude_array ) );

@@ -1414,6 +1413,7 @@ function wp_list_pages( $args = '' ) {
  * @since 2.7.0
  * @since 4.4.0 Added `menu_id`, `container`, `before`, `after`, and `walker` arguments.
  * @since 4.7.0 Added the `item_spacing` argument.
+ * @since 7.2.0 The `exclude` argument now accepts an array of page IDs (a comma-separated list string of IDs remains supported).
  *
  * @param array|string $args {
  *     Optional. Array or string of arguments to generate a page menu. See wp_list_pages() for additional arguments.
@@ -1502,12 +1502,8 @@ function wp_page_menu( $args = array() ) {
 		$menu .= '<li ' . $class . '><a href="' . esc_url( home_url( '/' ) ) . '">' . $args['link_before'] . $text . $args['link_after'] . '</a></li>';
 		// If the front page is a page, add it to the exclude list.
 		if ( 'page' === get_option( 'show_on_front' ) ) {
-			if ( ! empty( $list_args['exclude'] ) ) {
-				$list_args['exclude'] .= ',';
-			} else {
-				$list_args['exclude'] = '';
-			}
-			$list_args['exclude'] .= get_option( 'page_on_front' );
+			$list_args['exclude']   = wp_parse_id_list( $list_args['exclude'] ?? array() );
+			$list_args['exclude'][] = (int) get_option( 'page_on_front' );
 		}
 	}

diff --git a/wp-includes/version.php b/wp-includes/version.php
index aaf3efbc3b..4c198a1ac6 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-beta5-65526';
+$wp_version = '7.2-beta5-65527';

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