Cross Platform Themes: WordPress & Habari
In my last post I wrote about the concept of desiging dual use themes, that is themes that will work across multiple platforms. I don’t mean themes that are ported to another platform, but one single theme that will work on both. That is what I am doing for my re-theme of this site, and in this post I will explain how I have gone about it.
There are enough similarities between the WordPress theme system and the Habari, rawPHP theme engine that it is fairly easy to switch between the two. Despite this there are also some very significant differences.
WordPress uses PHP functions as template tags. These functions use the GLOBAL keyword to access the data in the main classes. Habari outputs the information straight from the classes.
//WordPress <?php the_title(); ?> //Habari <?php echo $post->title_out; ?>
The different approaches also mean the loops work differently. The WordPress loop uses a function to change the post class to the next post. Habari uses a foreach loop because the classes can be accessed directly:
//WordPress <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> //post content <?php endwhile; else: ?> <p><?php _e('Sorry, no posts matched your criteria.'); ?></p> <?php endif; ?> //Habari <?php foreach( $posts as $post ) { ?> //post content <?php } ?>
The important point about these differences is that it creates several possible methods of making the theme work.
Option 1 - IF
It is easy to determine whether the theme is running on WordPress or Habari. There are a lot of constants and classes that are unique. I chose to test the $theme object to make sure it extends the Theme class.
if ( isset( $theme ) && is_subclass_of( $theme , 'theme' ) ) { define('WORDPRESS',0); define('HABARI',1); } else { define('WORDPRESS',1); define('HABARI',0); }
I’ve also set constants for both WordPress and Habari so the code can be a bit clearer as to what platform is being tested against.
The problem with using IF statements to test these constants is it means adding a great deal of complexity to the code, and duplicating large chuncks of HTML. Not Ideal.
Option 2 - Emulate
Emulating either of the platforms seems like a good idea, but doing it within the theme itself is likely to bring difficulties. The theme engines load the content in different ways, so scope things in different ways, and this is likely to add a lot of extra work.
Option 3 - The third way
Option 3 is to let go of the way themes work on both platforms and create a new set of controls to act as a translator between the two. This is the method I decided to use.
The method
First things first, I needed a way to run code independently for each platform. Thankfully WordPress themes look for and include functions.php automatically, and Habari themes look for theme.php. Each platform ignores the file of the other so adding platform independent code is no problem.
Habari looks for an instantiates the class in this file as the variable $theme, so it seemed logical to group all the functions inside this class, and do the same for WordPress. Using this method, I could then convert every theme function call to a public method of $theme. I just need to make sure the methods are named the same in both classes.
To make things a little easier I also used a hook in the WordPress version to get the $post and $posts variables.
For example, The WordPress title tag method now looks like this:
public function post_title(){ return apply_filters( 'the_title', $this->post->post_title ); }
The class defined in theme.php that Habari will load looks like this:
public function post_title(){ return $this->post->title_out; }
In both cases I am simply returning a value, so the theme uses:
echo $theme->post_title();
Note that in the WordPress version I added a hook to collect the global $post and $posts object and bring them into the class so that there is no need to use global in each function.
The loop
Obviously this is all fine until we come to multiple posts. The WordPress loop and Habari loop operate in very different ways to each other. Habari uses a simple foreach loop on the $posts object to return each $post object, and WordPress uses a function in a while loop to test if there is a next post. To make them both work together I needed to use the same loop for each. It seemed most logical to use something closer to the WordPress model:
while ( $theme->next_post() ) { //post data here }
The code in both classes is exactly the same:
public function next_post(){ $current = current($this->posts); if ( $current == false ){ reset($this->posts); return false; } else { $this->post = $current; next($this->posts); return true; } }
Template Hierarchy
To deal with the differences in template hierarchy I simple decided to go with the Habari version. Rather than mess about with the template system and rewrite it I have simply added an include statement into the WordPress files. index.php includes home.php; although WordPress will use home anyway but won’t work without an index.php file. archive.php includes multiple.php and so on.
Complexity
Of course the whole theme is more complicated than what you see here, and I still have some way to go. I have written a menu builder, a lot more replacement theme tags, and a stylesheet that outputs different colours and graphics links depending on platform, but hopefully this peek should give you the gist of it.
If you have any questions let me know and I will add to this post as needed. For the technically minded I have attached the header.php, multiple.php, theme.php and functions.php files to download: Sample code for cross compatible themes
Add New Comment
Viewing 2 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment