Better Includes and Excludes for wp_list_pages
The wp_list_pages() template tag forms the navigation core of most WordPress-powered websites, but it has a few issues:
- The exclude_tree parameter doesn’t work. If you include a list of page ID numbers after “exclude_tree=” in your wp_list_pages() tag, all of those pages (and all of their child pages) are supposed to be excluded from the page list. However, only the first page ID actually works this way; the others are ignored.
- There’s no such thing as an include_tree parameter.
That second one really became a pain working on a non-profit site recently. After I turn the site over, I want the director to be able to add and move pages whenever he wants without it breaking the nice drop-down menus I worked so hard styling for him.
The Function
That’s where this handy little function comes in. It adds an include_tree parameter and solves the exclude_tree problem by taking the list of page IDs in your exclude- and include_tree parameters, finding all of the child pages (to the depth you specify), then adding those parent and child IDs to your exclude and include parameters before passing everything on to the wp_list_pages function.
function md_list_pages( $args ) {
$defaults = array(
'depth' => 0, 'show_date' => '',
'child_of' => 0, 'exclude' => '',
'title_li' => __('Pages'), 'echo' => 1,
'authors' => '', 'sort_column' => 'menu_order, post_title',
'link_before' => '', 'link_after' => '',
'include' => '', 'include_tree' => '',
'exclude_tree' => '',
);
$r = wp_parse_args( $args, $defaults );
$exclude = list_pages_tree( $r[ 'exclude' ], $r[ 'exclude_tree' ],
$r[ 'depth' ] );
$include = list_pages_tree( $r[ 'include' ], $r[ 'include_tree' ],
$r[ 'depth' ] );
$pages = wp_list_pages( 'depth=' . $r[ 'depth' ] . '&show_date='
. $r[ 'show_date' ] . '&child_of=' . $r[ 'child_of' ]
. '&exclude=' . $exclude . '&title_li='
. $r[ 'title_li' ] . '&echo=0&authors='
. $r[ 'authors' ] . '&sort_column='
. $r[ 'sort_column' ] . '&link_before='
. $r[ 'link_before' ] . '&link_after='
. $r[ 'link_after' ] . '&include=' . $include );
if($r['echo']){
echo $pages;
} else {
return $pages;
}
}
function list_pages_tree( $param, $tree, $depth ) {
// get the parent pages of the tree
$parent_pages = get_pages( 'include=' . $tree );
foreach ( $parent_pages as $parent ) {
if (!empty( $param ) ) {
$param .= ",";
}
$param .= $parent->ID;
// get the child pages of the tree
$child_pages = get_pages ( 'child_of=' . $parent->ID
. '&depth=' . $depth );
foreach ( $child_pages as $child ) {
$param .= "," . $child->ID;
}
}
return $param;
}
How to Use It
Copy and paste the above functions into your functions.php file. Then replace all instances of wp_list_pages() in your template with md_list_pages(). The parameters are the same as the wp_list_pages parameters, with the addition of the include_tree parameter.
For example, I replaced this call on the non-profit site:
<?php wp_list_pages( 'depth=2&sort_column=menu_order&title_li= &include=5,9,11,14,2,16' ); ?>
…which only returns the included pages, with this call:
<?php md_list_pages( 'depth=2&sort_column=menu_order&title_li= &include_tree=5,9,11,14,2,16' ); ?>
…which returns the included pages and all of their child pages (for the drop-down menu on the site).
I realize that this method results in the template tag parameters being parsed twice, but I decided to keep wp_list_pages in the mix rather than bypass it completely because some plugins (including some on the aforementioned non-profit site) function by adding or removing actions to that template tag.
Hope this is helpful to someone else out there — I’ll be using it myself more in the future (unless WP3.0 eliminates my need for a workaround).
Update: Wow, over 350 pingbacks, and all of them spam. Thank goodness for Akismet…
Update 23 July 2011: I thought the new menu system in WordPress 3.0 pretty much killed the need for this workaround, but I guess there are still reasons to use wp_list_pages(). I’d love to hear how people are still using the function (wp_list_pages(), not my md_list_pages()) and whether they prefer it to wp_nav_menu() or not. Depending on response, I may have to rework my solution a bit to reduce the processing overhead and to weed out the bugs.
WordPress Wednesday: How to Use paginate_comments_links Only When You Really Mean It
I was pretty happy when WordPress added paginate_comments_links because now I didn’t have to write a custom function to break blog comments into separate pages and give them a nice navigation (instead of just “next” and “previous”). However, I like to put my navigation in a div, and I like to style that div…and it can look pretty bad when my styled div shows up with no navigation (depending on my design).
The solution is pretty simple (as most of my solutions are): I wrote a simple function that only echoes my div and pagination links if the comments are paginated:
function comment_pagination() {
//read the page links but do not echo
$comment_page = paginate_comments_links('echo=0');
//if there are page links, echo the navigation div and the page links
if (!empty($comment_page)) {
echo "<div class=\"navigation\">\n";
echo $comment_page;
echo "\n</div>\n";
}
}
All that’s left at this point is styling the pagination links. The above code will give you a markup along these lines:
<div class="navigation"> <a class='prev page-numbers'>« Previous</a> <a class='page-numbers'>1</a> <span class='page-numbers current'>2</span> <a class='page-numbers'>3</a> <a class='next page-numbers'>Next »</a> </div>
Hopefully I’ll learn more about paginate_comments_links in the future and be able to better customize the output. We’ll see.
What Health Insurance Is and Isn’t
I’m not going to use this blog to stump for any particular side of the health care debate, but I want to clear up a misconception that’s been bothering me since the debate began.
Many of the arguments made for reform include comments about insurance companies denying coverage to individuals with pre-existing conditions. This has been represented as a greedy and heartless practice by insurance companies to avoid having to pay claims. This argument is being made by many who (in my opinion) do not understand the basic concept of what insurance is.
Insurance is the management of risk. Each of us lives in risk of suffering harm or illness at any point in our lives; health insurance helps us manage that risk by allowing us to pay (comparatively) small amounts of money over our lifetimes with the promise that funds will be provided for our care should such harm or illness befall us. We enter into this agreement with an insurance company knowing full well that we may never need those funds — we may pay out our entire lives and never get back. On the other hand, we may end up needing far more than we ever pay in. Several people doing the same allow the risks of these outcomes to be spread out over a larger group so that no one person bears the entire burden.
Insurance is not a discount program. It is not a way to get medical services for less than their market value. The money for insurance coverage has to come from somewhere, and there has to be enough of it available to cover any needs that may arise.
A person with a pre-existing medical condition who has to see a doctor or have procedures performed regularly will draw out more than he or she puts in. They are not managing risk, but receiving discounted care. They are denied coverage because there is no chance that their premium payments will ever equal or exceed the benefits they receive, so there is no risk to manage.
To borrow an analogy from a popular (if misinformed) YouTube video, imagine that maintaining a fire department was not one of the normally responsibilities of government. Instead, imagine that you had to pay $6,000 each time a fire needed to be put out at your home. You may never need fire service during your lifetime, or you may need it several times.
To help manage the risk, you and 9 other people in your neighborhood decide to pool your resources. You research statistics on home fires and determine that it is likely that one of your homes will catch fire in any 10-year period1. To manage this risk, each of will pay $5 per month (10 people × $5 per month × 120 months = $6,000). Your expectation is that any one of you may need to draw out this money at any time in a 10-year period. You may go 10 years with no fires, or there may be 2 fires, but at least this way the risk (and the charge) are spread out among the 10 of you so no one bears the burden by themselves.
One day a neighbor comes to you who is not part of your pool. His house is on fire and he wants to pay his $5 to become part of your pool. There is no risk to spread out here; you know that if he enters the pool you will have to immediately pay out the $6,000 to cover his bill, for which he will pay only $5. He is under no obligation to continue in your pool after he receives his money. This is what it is like when someone who has a pre-existing condition is applying for health insurance. He is asking you to pay his costs — which is not insurance, it is a subsidy.
Now I’m not saying that we shouldn’t have ways for everyone to have affordable access to health care. I’m not defending any other practices that insurance companies may or may not engage in. I am simply saying let’s stop using coverage denials due to pre-existing conditions to demonize insurers. Insurance is not a subsidy or discount program, it is risk management. If there is not a chance that you may not need your benefits, then it defeats the entire purpose and function of insurance.
Now let’s get back to debating.
1. This is of course not a real statistic and is only being used for illustrative purposes.
