WordPress Version: 6.1
/**
* Retrieves an array of pages (or hierarchical post type items).
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @since 1.5.0
*
* @param array|string $args {
* Optional. Array or string of arguments to retrieve pages.
*
* @type int $child_of Page ID to return child and grandchild pages of. Note: The value
* of `$hierarchical` has no bearing on whether `$child_of` returns
* hierarchical results. Default 0, or no restriction.
* @type string $sort_order How to sort retrieved pages. Accepts 'ASC', 'DESC'. Default 'ASC'.
* @type string $sort_column What columns to sort pages by, comma-separated. Accepts 'post_author',
* 'post_date', 'post_title', 'post_name', 'post_modified', 'menu_order',
* 'post_modified_gmt', 'post_parent', 'ID', 'rand', 'comment_count'.
* 'post_' can be omitted for any values that start with it.
* Default 'post_title'.
* @type bool $hierarchical Whether to return pages hierarchically. If false in conjunction with
* `$child_of` also being false, both arguments will be disregarded.
* Default true.
* @type int[] $exclude Array of page IDs to exclude. Default empty array.
* @type int[] $include Array of page IDs to include. Cannot be used with `$child_of`,
* `$parent`, `$exclude`, `$meta_key`, `$meta_value`, or `$hierarchical`.
* Default empty array.
* @type string $meta_key Only include pages with this meta key. Default empty.
* @type string $meta_value Only include pages with this meta value. Requires `$meta_key`.
* Default empty.
* @type string $authors A comma-separated list of author IDs. Default empty.
* @type int $parent Page ID to return direct children of. Default -1, or no restriction.
* @type string|int[] $exclude_tree Comma-separated string or array of page IDs to exclude.
* Default empty array.
* @type int $number The number of pages to return. Default 0, or all pages.
* @type int $offset The number of pages to skip before returning. Requires `$number`.
* Default 0.
* @type string $post_type The post type to query. Default 'page'.
* @type string|array $post_status A comma-separated list or array of post statuses to include.
* Default 'publish'.
* }
* @return WP_Post[]|false Array of pages (or hierarchical post type items). Boolean false if the
* specified post type is not hierarchical or the specified status is not
* supported by the post type.
*/
function get_pages($args = array())
{
global $wpdb;
$defaults = array('child_of' => 0, 'sort_order' => 'ASC', 'sort_column' => 'post_title', 'hierarchical' => 1, 'exclude' => array(), 'include' => array(), 'meta_key' => '', 'meta_value' => '', 'authors' => '', 'parent' => -1, 'exclude_tree' => array(), 'number' => '', 'offset' => 0, 'post_type' => 'page', 'post_status' => 'publish');
$parsed_args = wp_parse_args($args, $defaults);
$number = (int) $parsed_args['number'];
$offset = (int) $parsed_args['offset'];
$child_of = (int) $parsed_args['child_of'];
$hierarchical = $parsed_args['hierarchical'];
$exclude = $parsed_args['exclude'];
$meta_key = $parsed_args['meta_key'];
$meta_value = $parsed_args['meta_value'];
$parent = $parsed_args['parent'];
$post_status = $parsed_args['post_status'];
// Make sure the post type is hierarchical.
$hierarchical_post_types = get_post_types(array('hierarchical' => true));
if (!in_array($parsed_args['post_type'], $hierarchical_post_types, true)) {
return false;
}
if ($parent > 0 && !$child_of) {
$hierarchical = false;
}
// Make sure we have a valid post status.
if (!is_array($post_status)) {
$post_status = explode(',', $post_status);
}
if (array_diff($post_status, get_post_stati())) {
return false;
}
// $args can be whatever, only use the args defined in defaults to compute the key.
$key = md5(serialize(wp_array_slice_assoc($parsed_args, array_keys($defaults))));
$last_changed = wp_cache_get_last_changed('posts');
$cache_key = "get_pages:{$key}:{$last_changed}";
$cache = wp_cache_get($cache_key, 'posts');
if (false !== $cache) {
_prime_post_caches($cache, false, false);
// Convert to WP_Post instances.
$pages = array_map('get_post', $cache);
/** This filter is documented in wp-includes/post.php */
$pages = apply_filters('get_pages', $pages, $parsed_args);
return $pages;
}
$inclusions = '';
if (!empty($parsed_args['include'])) {
$child_of = 0;
// Ignore child_of, parent, exclude, meta_key, and meta_value params if using include.
$parent = -1;
$exclude = '';
$meta_key = '';
$meta_value = '';
$hierarchical = false;
$incpages = wp_parse_id_list($parsed_args['include']);
if (!empty($incpages)) {
$inclusions = ' AND ID IN (' . implode(',', $incpages) . ')';
}
}
$exclusions = '';
if (!empty($exclude)) {
$expages = wp_parse_id_list($exclude);
if (!empty($expages)) {
$exclusions = ' AND ID NOT IN (' . implode(',', $expages) . ')';
}
}
$author_query = '';
if (!empty($parsed_args['authors'])) {
$post_authors = wp_parse_list($parsed_args['authors']);
if (!empty($post_authors)) {
foreach ($post_authors as $post_author) {
// Do we have an author id or an author login?
if (0 == (int) $post_author) {
$post_author = get_user_by('login', $post_author);
if (empty($post_author)) {
continue;
}
if (empty($post_author->ID)) {
continue;
}
$post_author = $post_author->ID;
}
if ('' === $author_query) {
$author_query = $wpdb->prepare(' post_author = %d ', $post_author);
} else {
$author_query .= $wpdb->prepare(' OR post_author = %d ', $post_author);
}
}
if ('' !== $author_query) {
$author_query = " AND ({$author_query})";
}
}
}
$join = '';
$where = "{$exclusions} {$inclusions} ";
if ('' !== $meta_key || '' !== $meta_value) {
$join = " LEFT JOIN {$wpdb->postmeta} ON ( {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id )";
// meta_key and meta_value might be slashed.
$meta_key = wp_unslash($meta_key);
$meta_value = wp_unslash($meta_value);
if ('' !== $meta_key) {
$where .= $wpdb->prepare(" AND {$wpdb->postmeta}.meta_key = %s", $meta_key);
}
if ('' !== $meta_value) {
$where .= $wpdb->prepare(" AND {$wpdb->postmeta}.meta_value = %s", $meta_value);
}
}
if (is_array($parent)) {
$post_parent__in = implode(',', array_map('absint', (array) $parent));
if (!empty($post_parent__in)) {
$where .= " AND post_parent IN ({$post_parent__in})";
}
} elseif ($parent >= 0) {
$where .= $wpdb->prepare(' AND post_parent = %d ', $parent);
}
if (1 === count($post_status)) {
$where_post_type = $wpdb->prepare('post_type = %s AND post_status = %s', $parsed_args['post_type'], reset($post_status));
} else {
$post_status = implode("', '", $post_status);
$where_post_type = $wpdb->prepare("post_type = %s AND post_status IN ('{$post_status}')", $parsed_args['post_type']);
}
$orderby_array = array();
$allowed_keys = array('author', 'post_author', 'date', 'post_date', 'title', 'post_title', 'name', 'post_name', 'modified', 'post_modified', 'modified_gmt', 'post_modified_gmt', 'menu_order', 'parent', 'post_parent', 'ID', 'rand', 'comment_count');
foreach (explode(',', $parsed_args['sort_column']) as $orderby) {
$orderby = trim($orderby);
if (!in_array($orderby, $allowed_keys, true)) {
continue;
}
switch ($orderby) {
case 'menu_order':
break;
case 'ID':
$orderby = "{$wpdb->posts}.ID";
break;
case 'rand':
$orderby = 'RAND()';
break;
case 'comment_count':
$orderby = "{$wpdb->posts}.comment_count";
break;
default:
if (0 === strpos($orderby, 'post_')) {
$orderby = "{$wpdb->posts}." . $orderby;
} else {
$orderby = "{$wpdb->posts}.post_" . $orderby;
}
}
$orderby_array[] = $orderby;
}
$sort_column = (!empty($orderby_array)) ? implode(',', $orderby_array) : "{$wpdb->posts}.post_title";
$sort_order = strtoupper($parsed_args['sort_order']);
if ('' !== $sort_order && !in_array($sort_order, array('ASC', 'DESC'), true)) {
$sort_order = 'ASC';
}
$query = "SELECT * FROM {$wpdb->posts} {$join} WHERE ({$where_post_type}) {$where} ";
$query .= $author_query;
$query .= ' ORDER BY ' . $sort_column . ' ' . $sort_order;
if (!empty($number)) {
$query .= ' LIMIT ' . $offset . ',' . $number;
}
$pages = $wpdb->get_results($query);
if (empty($pages)) {
wp_cache_set($cache_key, array(), 'posts');
/** This filter is documented in wp-includes/post.php */
$pages = apply_filters('get_pages', array(), $parsed_args);
return $pages;
}
// Sanitize before caching so it'll only get done once.
$num_pages = count($pages);
for ($i = 0; $i < $num_pages; $i++) {
$pages[$i] = sanitize_post($pages[$i], 'raw');
}
// Update cache.
update_post_cache($pages);
if ($child_of || $hierarchical) {
$pages = get_page_children($child_of, $pages);
}
if (!empty($parsed_args['exclude_tree'])) {
$exclude = wp_parse_id_list($parsed_args['exclude_tree']);
foreach ($exclude as $id) {
$children = get_page_children($id, $pages);
foreach ($children as $child) {
$exclude[] = $child->ID;
}
}
$num_pages = count($pages);
for ($i = 0; $i < $num_pages; $i++) {
if (in_array($pages[$i]->ID, $exclude, true)) {
unset($pages[$i]);
}
}
}
$page_structure = array();
foreach ($pages as $page) {
$page_structure[] = $page->ID;
}
wp_cache_set($cache_key, $page_structure, 'posts');
// Convert to WP_Post instances.
$pages = array_map('get_post', $pages);
/**
* Filters the retrieved list of pages.
*
* @since 2.1.0
*
* @param WP_Post[] $pages Array of page objects.
* @param array $parsed_args Array of get_pages() arguments.
*/
return apply_filters('get_pages', $pages, $parsed_args);
}