-
Notifications
You must be signed in to change notification settings - Fork 7
Navigation Library
The navigation library provides several low-level functions for querying large amounts of posts hierarchically.
Two functions in particuar are used through the navigation plugin to selectively fetch posts in specific "sections" (any post with at least one child is considered to be a section).
-
bu_navigation_gather_sections()
- Load ancestors or descendants of a specific post -
bu_navigation_get_pages()
- Alternative to WP_Query, allows you to get posts in specific sections
For example, let's consider the following page hierarchy:
- About
- Our staff
- John Smith
- Jane Doe
- Contact Us
- Our Mission
- Our staff
Assuming that the post ID for the "About" page is 4, the following lines of code would fetch all pages in the "About" section:
<?php
$section_args = array(
'post_types' => 'page',
'direction' => 'down'
);
$sections = bu_navigation_gather_sections( 4, $section_args );
$pages = bu_navigation_get_pages( array( 'sections' => $sections, 'post_types' => 'page' ) );
$pages_by_parent = bu_navigation_pages_by_parent( $pages );
Breaking this example down -- the call to bu_navigation_gather_sections()
will return an array of post ID's, one for each section below post ID 4. This information is then passed to bu_navigation_get_pages()
using the "section" key; this call builds the query accordingly and returns a flat list of posts contained in the requested sections. The last call to bu_navigation_pages_by_parent()
structures the results in to a more useful format - an associative array of posts, grouped in to sections by parent ID:
array (size=2)
4 =>
array (size=3)
0 =>
object(stdClass)[270]
public 'ID' => string '5' (length=1)
public 'post_date' => string '2013-02-24 18:48:40' (length=19)
public 'post_title' => string 'Our Staff' (length=9)
public 'post_excerpt' => string '' (length=0)
public 'post_name' => string 'our-staff' (length=9)
public 'post_parent' => string '4' (length=1)
public 'guid' => string 'http://buwp.dev/github/?page_id=5' (length=33)
public 'menu_order' => string '1' (length=1)
public 'post_type' => string 'page' (length=4)
public 'post_status' => string 'publish' (length=7)
public 'post_password' => string '' (length=0)
public 'post_content' => string '' (length=0)
public 'url' => string 'http://buwp.dev/github/our-staff/' (length=33)
public 'navigation_label' => string 'Our Staff' (length=9)
1 =>
object(stdClass)[265]
public 'ID' => string '11' (length=2)
public 'post_date' => string '2013-02-24 18:56:21' (length=19)
public 'post_title' => string 'Contact Us' (length=10)
public 'post_excerpt' => string '' (length=0)
public 'post_name' => string 'contact-us' (length=10)
public 'post_parent' => string '4' (length=1)
public 'guid' => string 'http://buwp.dev/github/?page_id=11' (length=34)
public 'menu_order' => string '2' (length=1)
public 'post_type' => string 'page' (length=4)
public 'post_status' => string 'publish' (length=7)
public 'post_password' => string '' (length=0)
public 'post_content' => string '' (length=0)
public 'url' => string 'http://buwp.dev/github/contact-us/' (length=34)
2 =>
object(stdClass)[266]
public 'ID' => string '12' (length=2)
public 'post_date' => string '2013-02-24 18:56:41' (length=19)
public 'post_title' => string 'Our Mission' (length=11)
public 'post_excerpt' => string '' (length=0)
public 'post_name' => string 'our-mission' (length=11)
public 'post_parent' => string '4' (length=1)
public 'guid' => string 'http://buwp.dev/github/?page_id=12' (length=34)
public 'menu_order' => string '3' (length=1)
public 'post_type' => string 'page' (length=4)
public 'post_status' => string 'publish' (length=7)
public 'post_password' => string '' (length=0)
public 'post_content' => string '' (length=0)
public 'url' => string 'http://buwp.dev/github/our-mission/' (length=35)
5 =>
array (size=2)
0 =>
object(stdClass)[271]
public 'ID' => string '9' (length=1)
public 'post_date' => string '2013-02-24 18:55:52' (length=19)
public 'post_title' => string 'Jane Doe' (length=8)
public 'post_excerpt' => string '' (length=0)
public 'post_name' => string 'jane-doe' (length=8)
public 'post_parent' => string '5' (length=1)
public 'guid' => string 'http://buwp.dev/github/?page_id=9' (length=33)
public 'menu_order' => string '1' (length=1)
public 'post_type' => string 'page' (length=4)
public 'post_status' => string 'publish' (length=7)
public 'post_password' => string '' (length=0)
public 'post_content' => string '' (length=0)
public 'url' => string 'http://buwp.dev/github/our-staff/jane-doe/' (length=42)
public 'navigation_label' => string 'Jane Doe' (length=8)
1 =>
object(stdClass)[272]
public 'ID' => string '7' (length=1)
public 'post_date' => string '2013-02-24 18:50:20' (length=19)
public 'post_title' => string 'John Smith' (length=10)
public 'post_excerpt' => string '' (length=0)
public 'post_name' => string 'john-smith' (length=10)
public 'post_parent' => string '5' (length=1)
public 'guid' => string 'http://buwp.dev/github/?page_id=7' (length=33)
public 'menu_order' => string '2' (length=1)
public 'post_type' => string 'page' (length=4)
public 'post_status' => string 'publish' (length=7)
public 'post_password' => string '' (length=0)
public 'post_content' => string '' (length=0)
public 'url' => string 'http://buwp.dev/github/our-staff/john-smith/' (length=44)
public 'navigation_label' => string 'John Smith' (length=10)
Note that despite the function name, bu_navigation_get_pages()
fully supports custom post types.
One of the more powerful features of using WP_Query is that you get post meta and other post-related meta data (such as taxonomy) for free. Since the navigation library was designed to be a leaner alternative in order to work with large page counts, it is up to clients of the navigation library to fetch any additionally required data.
The navigation library provides several filters which can be used to modify the results returned by library function calls.
- bu_navigation_filter_fields - Modify which columns will be returned for posts returned by
bu_navigation_get_posts()
- bu_navigation_filter_pages - Modify array of post objects returned by
bu_navigation_get_pages()
The following example, taken from the navigation plugin, uses the bu_navigation_filter_pages
filter to fetch multiple custom post meta values in one query and append the results to each post object. In this example the meta data is the custom navigation label, entered using the text field in the "Placement in Navigation" meta box.
<?php
// Name of meta_key used to hold navigation labels
define('BU_NAV_META_PAGE_LABEL', '_bu_cms_navigation_page_label');
function bu_navigation_filter_pages_navlabels( $pages ) {
global $wpdb;
$filtered = array();
if ( is_array( $pages ) && count( $pages ) > 0 ) {
$ids = array_keys( $pages );
$query = sprintf( "SELECT post_id, meta_value FROM %s WHERE meta_key = '%s' AND post_id IN (%s) AND meta_value != ''",
$wpdb->postmeta,
BU_NAV_META_PAGE_LABEL,
implode( ',', $ids )
);
$labels = $wpdb->get_results( $query, OBJECT_K );
if ( is_array( $labels ) && count( $labels ) > 0 ) {
foreach ( $pages as $page ) {
if ( array_key_exists( $page->ID, $labels ) ) {
$label = $labels[ $page->ID ];
$page->navigation_label = $label->meta_value;
}
$filtered[ $page->ID ] = $page;
}
} else {
$filtered = $pages;
}
}
return $filtered;
}
add_filter( 'bu_navigation_filter_pages', 'bu_navigation_filter_pages_navlabels' );
Adding this filter before a call to bu_navigation_get_posts()
will result in posts being returned with navigation labels appended to the post objects themselves (in the navigation_label
object property).
Another example uses the same filter to remove posts entirely that have been marked as hidden from navigation lists. (By unchecking the "Display page in navigation lists" checkbox in the "Placement in Navigation" meta box).
<?php
// Name of meta_key used to exclude pages from navigation
define( 'BU_NAV_META_PAGE_EXCLUDE', '_bu_cms_navigation_exclude' );
function bu_navigation_filter_pages_exclude( $pages ) {
global $wpdb;
$filtered = array();
if ( is_array( $pages ) && count( $pages ) > 0 ) {
$ids = array_keys( $pages );
$query = sprintf( "SELECT post_id, meta_value FROM %s WHERE meta_key = '%s' AND post_id IN (%s) AND meta_value != '0'",
$wpdb->postmeta,
BU_NAV_META_PAGE_EXCLUDE,
implode( ',', $ids )
);
$exclusions = $wpdb->get_results( $query, OBJECT_K );
if ( is_array( $exclusions ) && count( $exclusions ) > 0 ) {
foreach ( $pages as $page ) {
if ( ! array_key_exists( $page->ID, $exclusions ) ) {
$filtered[ $page->ID ] = $page;
}
}
} else {
$filtered = $pages;
}
}
return $filtered;
}
add_filter( 'bu_navigation_filter_pages', 'bu_navigation_filter_pages_exclude' );