Skip to content
mgburns edited this page Feb 24, 2013 · 18 revisions

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

Using the navigation library

For example, let's consider the following page hierarchy:

  • About
    • Our staff
      • John Smith
      • Jane Doe
    • Contact Us
    • Our Mission

Assuming that the post ID for the "About" page is 5, 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( 5, $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 that make up the requested section. This section information is then passed to bu_navigation_get_pages, where it is used to selectively retrieve posts in the "About" section.

Note that despite the function name, bu_navigation_get_pages() fully supports custom post types.

Filters

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()

Example Usage

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" metabox.

<?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 use case from the navigation plugin - removing posts that have been marked as hidden from navigation lists by unchecking the "Display page in navigation lists" checkbox.

<?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' );
Clone this wiki locally