WordPress at a glance

How to change the SQL query for the get_pages() function

Suppose we need to change the request parameters of the get_pages() function to change results of drop-down list on the admin panel "Reading" page.

We need to show the first level pages only.

The problem of doing so is that there is no any hooks to change parameters for wp_dropdown_pages(). And no hooks to change parameters for get_pages() functions, based on which the dropdown functions works. Tested for WP 5.7.

The only variant to change the request is the query hook, which allow to change the SQL query itself just before the query will be executed.

add_filter( 'query', 'get_pages__change_sql_for_admin_pane' );

/**
 * Change SQL query for get_pages() function.
 *
 * @param string $query
 *
 * @return string mixed
 */
function get_pages__change_sql_for_admin_pane( $query ){

	if(
		/* start render admin page HTML */
		! ( did_action( 'in_admin_header' ) || did_action( 'customize_controls_head' ) )
		/* get_pages() function only */
		|| in_array( 'get_pages', wp_list_pluck( debug_backtrace(), 'function' ), 1 )
		//|| ! in_array( get_current_screen()->id, [ 'options-reading', 'options-privacy', 'edit-page', 'page', 'customize' ], 1 )
	)
		return $query;

	// the query to change:
	// SELECT * FROM wp_posts WHERE (post_type = 'page' AND post_status IN ('draft', 'publish')) ORDER BY wp_posts.post_title ASC
	// SELECT * FROM wp_posts  WHERE (post_type = 'page' AND post_status = 'publish')     ORDER BY wp_posts.post_title ASC
	$split = preg_split( '/(WHERE|ORDER BY)/', $query, -1, PREG_SPLIT_DELIM_CAPTURE );
	$WHERE = $split[2];

	// do our replace!
	if(
		/* for 'page' post type only */
		strpos( $WHERE, "post_type = 'page'" )
		/* check what we want to add in the query */
		&& ! strpos( $WHERE, 'post_parent' )
	){

		$grip = "post_type = 'page'";
		$add = 'AND post_parent = 0';

		$query = str_replace( $grip, "$grip $add", $query );
	}

	return $query;
}

As a result we get:

IMPORTANT! get_pages() use the object cache to cache the result, so if you have an object caching plugin installed (it saves the results between pages generations), the hook may not work or it may affect the result of the same request for some other page!

No comments
    Log In