scriptygoddess

17 Jan, 2008

Using WordPress (with some modifications) as a CMS

Posted by: Jennifer In: WordPress|WordPress Hacks

For a long time one of the things I've liked about WordPress is it's flexibility. I recently did a project for Savvydog Design for one of their clients: the National WASP WWII Museum – that involved doing some customizations to WordPress. They wanted most of the pages on the site to be editable (I used WordPress' pages functionality here), they also wanted to be able to enter in news items (these would be standard blog posts with a category of "news"), as well as be able to enter in events (these would also be standard blog posts with a category of "events"). They wanted the home page of the site to show some (editable) content at the top, and then list the last 3 news or event items. On the side bar, they wanted to be able to list the next 3 upcoming events. Here is how I put it all together:

*Please note – some of the customizations take a few things as assumptions – (for example how you have your permalinks set up, etc.) So if you use any of this, do so at your own risk (most especially the part about editing a core WordPress file – I'm sure I'll get heat for that from SOMEONE.) Your mileage may vary, and I don't guarantee this will work with your setup, yadda yadda yadda…

1) Home Page
So we set this up as a page. The page had a custom template.

By the way, to make a custom template for the page – all you need to do is create the template – which will probably look similar to your index.php, except with any modifications you want to make – and then at the top, above any other code, have the following code so that WordPress knows it's a custom page template:
<?php
/*
Template Name:CustomHomePage
*/
?>

So in this case – I wanted the top portion to be editable as a page… So where the content belonged I had this:
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><?php the_title(); ?></h1>
<?php the_content('<p class="serif">Read the rest of this page »</p>'); ?>
<?php endwhile; endif; ?>
<?php edit_post_link('Edit this entry.', '<p>', '</p>'); ?>

Now to list news and events – I wanted to allow them the ability to post news and event items that didn't have to show up on the home page. So I created a third category called "Show on home page". So they could enter an event or a news item in – indicate if it was a news or event item by selecting the appropriate category – and then if they wanted to have it show up on the home page, they would also indicate it as being in the "show on home page" category… To display that list of "posts" I had this:
<?php
$pageposts = $wpdb->get_results ("SELECT * FROM wp_posts, wp_term_relationships WHERE wp_term_relationships.object_id = wp_posts.ID && wp_term_relationships.term_taxonomy_id = '4' && wp_posts.post_status = 'publish' && wp_posts.post_category = '0' && wp_posts.post_type = 'post' order by post_date desc limit 3");
foreach ($pageposts as $post):
setup_postdata($post);
?>
<h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2>
<small><?php the_time('F jS, Y') ?></small>
<?php the_content('Read the rest of this entry »'); ?>
<?php endforeach; ?>

So that's doing a custom query to the database. It so happens that "show on home page" category has an id of 4 (you can see each category's ID by looking at the manage->categories page.) So you put that "4" in where I have it in bold and red in the code…

This file gets uploaded to your theme directory. Then, to create a page using this template, create a new page (or "Write Page") – and on the right hand side, you'll see a box "Page Template" – your template should be in the list by what you named it at the top (in this example it would be "CustomHomePage"). The title for the page is what the page will be named.

Then, to get THAT page to show up as the "home" page – go to Options -> Reading – and where you see Front page displays: select "static page" – and for "front page" select the page you created.

2) Sidebar
So there were a few tricky things with the events. I wanted the user to be able to enter in all the information about an event, but to set the DATE of that event as the "date" of the "post" so it would show up chronologically – kind of like an events calendar. The problem is that WordPress gives all posts with a date in the future a "post_status" of "future"… so if you're looking for posts with a status of "publish" – you won't find them. There was a plugin that I found that considered all posts with "future" status to be "publish" without making any core file modifications – but I found it also has a side effect of showing those "future" posts mixed in with my list of pages. I was concerned that this would cause too much confusion and opted instead to make a very minor change to one of the core files. (I've now gotten into the habit of keeping a log of any core file changes I make so that upgrades aren't too stressful. If the changes are kept to a minimum -upgrading shouldn't be too bad and the changes can be made again to the new updated files)

So, in order to change the status of those posts – and get them to show up normally, I edited wp-includes/post.php, at about line 667, and changed this line:
$post_status = 'future';
to this instead:
$post_status = 'publish';

Now, in order to pull out JUST the next 3 upcoming events, I again did a custom post query. (in my sidebar.php template file)
<?php
//first set up what is the current date/time
$now = gmdate('Y-m-d H:i:59');
$pageposts = $wpdb->get_results ("SELECT * FROM wp_posts, wp_term_relationships WHERE wp_term_relationships.object_id = wp_posts.ID && wp_term_relationships.term_taxonomy_id = '3' && wp_posts.post_status = 'publish' && wp_posts.post_category = '0' && wp_posts.post_type = 'post' && wp_posts.post_date_gmt > '".$now."' order by post_date asc limit 3");
foreach ($pageposts as $post):
setup_postdata($post);
?>
<h3><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h3>
<p class="date"><?php the_time('F jS, Y') ?></p>
<?php the_excerpt(); ?>
<?php
// to find out if there ARE any future events being displayed, I set this variable up so I can test for it later...
$nextevents = true; ?>
<?php endforeach; ?>

FYI – That "3" in red/bold… that's the category ID for my events category.

So that's all well and good – but what if it's a slow month and there aren't any future events yet. I don't want that bar to empty… So I figure I'll show the last (just past) event instead…
<?php
//if no future events show last (1) event
if (!isset($nextevents)) {
$now = gmdate('Y-m-d H:i:59');
$pageposts = $wpdb->get_results ("SELECT * FROM wp_posts, wp_term_relationships WHERE wp_term_relationships.object_id = wp_posts.ID && wp_term_relationships.term_taxonomy_id = '3' && wp_posts.post_status = 'publish' && wp_posts.post_category = '0' && wp_posts.post_type = 'post' && wp_posts.post_date_gmt < '".$now."' order by post_date asc limit 1");
foreach ($pageposts as $post):
setup_postdata($post);
?>
<h3><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h3>
<p class="date"><?php the_time('F jS, Y') ?></p>
<?php the_excerpt(); ?>
<?php endforeach; ?>
<?php } ?>

Those two things were probably the toughest. I do wish there was a setting in WordPress somewhere so I can turn that setting posts in the future to PUBLISH instead of future. But I don't think there's a hook for it. Maybe they'll add it in – and a plugin can be written to do that – so that no core modifications are necessary…

3) Fun with navigation
**Updated 6/3/08** I've since been having some trouble with the code I posted originally. The new code that I've been using is simpler and works consistently. I just use this where I want the subnavigation to go:

<?php
if($post->post_parent)
$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0"); else
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
if ($post->post_parent) {
$parentpage = $wpdb->get_row("SELECT ID, post_title, post_name FROM $wpdb->posts WHERE ID = '".$post->post_parent."'");
} else {
$parentpage = $wpdb->get_row("SELECT ID, post_title, post_name FROM $wpdb->posts WHERE ID = '".$post->ID."'");
}
if ($children) { ?>
<ul id="subnav" class="clearfix">
<li<?php if ($post->post_parent == "0") { echo ' class="current_page_item"'; } ?>><a href="<?php echo get_permalink($parentpage->ID); ?>"><?php echo $parentpage->post_title; ?></a></li>
<?php echo $children; ?>
</ul>
<?php } ?>

**end update.** I'm leaving the old code up in this post in case it ends up being useful for some reason – but with the new version of wordpress (2.5) it doesn't work and the code above is simpler anyway.

So the next trick was getting the subnavigation to work the way we wanted. There was some main nav items (pages) and some of them would have subnavigation. If the page did have subnavigation, we wanted to make the main page part of the list of pages under that main heading. So for example… Here is some main nav items:

About the museum – Donations – Photo Gallery

About the museum has the following sub pages: (Directions – Membership) But when you click on the "About the museum" main navigation – we want that page to be the "default" first page… so in the sub nav area you'd have:

About the muesum
Directions
Membership

Otherwise, I think it wouldn't be clear how you get to that first (top-level) page…

But I don't ALWAYS want to show that main nav item in the sub navigation… Photo Gallery is only one page – there's no need for subnavigation on that page at all… (will probably make more sense if you go see the finished version of the site and click around on the pages…)

In any case, this is how I did the subnavigation. Using a trick I'd posted about before – I get the list of subpages this way: (This goes at the very top of my header.php template file)

<?php
$page = $wp_query->post;
$parent_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE ID ='$page->post_parent;'");
if(!$parent_id) $parent_id = $post->ID;
?>

But now I also need to know if the page I'm on has subpages at all… and I need the name and the title of the parent page.. (you'll see why and how I use this shortly)

<?php
$getasubpage = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_parent = '$parent_id'");
$hassubpages = false;
if ($getasubpage) {
$hassubpages = true;
$parentpage = $wpdb->get_row("SELECT post_title, post_name FROM $wpdb->posts WHERE ID = '$parent_id'");
}
?>

Now where I want to list our subnavigation:

<ul id="subnav">
<?php if(wp_list_pages("child_of=".$parent_id."&echo=0")): ?>
<li<?php if ($parent_id == $post->ID) { echo ' class="current_page_item"'; } ?>><a href="<?php echo "/".$parentpage->post_name."/"; ?>"><?php echo $parentpage->post_title; ?></a></li>
<?php wp_list_pages("title_li=&child_of=".$parent_id."&sort_column=menu_order&depth=1");?>
<?php endif; ?>
</ul>

5 Responses to "Using WordPress (with some modifications) as a CMS"

1 | Elm

February 19th, 2008 at 10:03 am

Avatar

Looks like very creative and good work. Well done!

What was the name of the plugin you found for changing the post_status from future into publish?

Keep it up. Cheers

2 | tom petek

February 22nd, 2008 at 11:53 am

Avatar

I'd like to know if you some suggestions for my navigation problem:

I use a single-line header nav bar with a single-line sub-page nav bar beneath it. I also employ a list down the left sidebar. Everything's dynamic. As the viewer moves through the pages, parent page links, current level links, and child links all take their rightful place.

The problem is I have a page with 35 sub-pages. Obviously 35 links doesn't fit on a nav bar. Any possibility to provide a scrolling nav bar has stymied me. Any thoughts?

Thanks in advance for your consideration. Any help would be greatly appreciated. I need to find a solution before I pull out all my hair and go prematurely bald. Thanks again.

3 | Jennifer

February 23rd, 2008 at 1:20 pm

Avatar

@tom
35 sub pages sounds like A LOT. I think this is more a design and site architecture issue – kinda feels like 35 pages just shouldn't be part of a navigation – or if it does – then it needs to be organized into manageable (navigatable) chunks. (Is navigatable a word?? Heh. Well, it is now! LOL!)

Also – when you start to get even close to the double digit (and certainly beyond) of nav items – I don't think they should go across the top in the very least.

On a project I worked on a few months ago that had a large number of sub pages, I broke them down into categories, which you could then click to "show/hide" to see the list of pages. It may technically be "mystery meat" navigation – but probably that is better than so many links you'll never find the one you need.

That's my $.02 :)

4 | Jennifer

April 3rd, 2008 at 9:07 pm

Avatar

@note to self :)
Tried to do the above recently in a new site using wordpress ver 2.5 and it wasn't working. Not sure when this page was added to the codex but here is a simpler way to pull in those other posts:
http://codex.wordpress.org/Template_Tags/get_posts

When I clone myself so I have more time, I'll update the post to reflect the new method from the codex. :/

5 | indojepang

April 14th, 2008 at 8:47 pm

Avatar

Yes I agree.. much simpler with template tags.. 😀

Featured Sponsors

Genesis Framework for WordPress

Advertise Here


  • Scott: Just moved changed the site URL as WP's installed in a subfolder. Cookie clearance worked for me. Thanks!
  • Stephen Lareau: Hi great blog thanks. Just thought I would add that it helps to put target = like this:1-800-555-1212 and
  • Cord Blomquist: Jennifer, you may want to check out tp2wp.com, a new service my company just launched that converts TypePad and Movable Type export files into WordPre

About


Advertisements