OUTDATED: Creating a separate admin theme
NOTE: This article was originally posted here.
Note2: Drupal5 has an administration theme selector built in. No need for these shenanigans.
Want to create a front page that's styled differently from the rest of your site? Perhaps you need a separate admin theme? Or how about a login page which only shows the login block and nothing else? With a little PHP knowledge these problems are easy to solve.
Note: You must be using the PHPTemplate theme engine for your theme. An easy way to determine this is by looking for files ending in .tpl.php within your site's theme folder. PHPTemplate is compatible with Drupal 4.6 and up. As a matter of fact, it's the default theme engine for Drupal 4.7 since it combines the best of both worlds for designers and programmers. Designers get an easy way to manipulate HTML lightly sprinkled with PHP variables for dynamic content, and developers get a fast rendering template system that's a snap to extend. Here's what a template looks like using PHPTemplate.
<div class="node">
<h2 class="title"><a href="/<?php print $node_url?>"><?php print $title?></a></h2>
<span class="submitted"><?php print $submitted?></span>
<span class="taxonomy"><?php print $terms?></span>
<div class="content"><?php print $content?></div>
<div class="links">» <?php print $links?></div>
</div>Developers can override any of the above PHP variables or even add new ones to pass to the template for the designer to use. What most folks don't know is that for every template section, PHPTemplate looks for a special variable named template_file which stores the name of the file to execute. This is your key to conditionally loading different theme files.
Working with template_file
Intercepting PHPTemplates' default variables is accomplished through creating a new function named _phptemplate_variables() within your theme. Navigate to your site's current theme folder and look for a file called template.php. If that file doesn't exist, create it. Now add the following function:
<?php
/**
* Intercept template variables
*
* @param $hook
* The name of the theme function being executed
* @param $vars
* A sequential array of variables passed to the theme function.
*/
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
// more code here...
}
return $vars;
}
?>This function is called by Drupal just after a template engine call is made. Examples of this include: loading the node template, the block template or what we want, the page template. The $hook parameter above is the name of the template section the system is calling (node, block, page, etc).
First the system assigns a bunch of default variables. In the case of page hook: $sidebar_left, $sidebar_right, $footer_message, $search_box, $title, $content, etc. If _phptemplate_variables() exists, any values set there will override the defaults, including your opportunity to change the name of the template file the system should be looking for. Let's take a look at our first example.
Separate Administration Theme
The admin area is known for its wide tables which can be difficult to style when they're found nowhere else on your main site. Many folks find themselves wishing for a separate theme. Here's how to do it.
<?php
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'page':
if ((arg(0) == 'admin')) {
$vars['template_file'] = 'page-admin';
}
break;
}
return $vars;
}
?>Here we're changing value of $vars['template_file'] from page.tpl.php to page-admin.tpl.php.
Let's build our new admin theme. You probably want to use the Blue Marine layout as the admin theme. If your already using Blue Marine for the rest of your site that's okay as you'll get that basic idea. Grab a copy of page.tpl.php from the Blue Marine theme and paste it into your theme folder and rename the file to page-admin.tpl.php. Next, we want this file to use a separate stylesheet, so copy the Blue Marine style.css file and rename it to admin-style.css. Finally edit page-admin.tpl.php so it knows about the new CSS file.
<?php //print $styles ?>
<style type="text/css" media="all">@import "<?php print base_path(). $directory; ?>/admin-style.css";</style>Now navigate to your admin section and behold the marvels of PHPTemplate.
Custom Front Page
Here's how we do the special front page on Lullabot.com.
<?php
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'page':
global $user;
if ($vars['is_front']) {
$vars['template_file'] = 'page-index';
}
break;
}
return $vars;
}
?>Create a file called page-index.tpl.php and start styling away.
Stand-alone Login Page
Sometimes you want the login/register page to stand alone, with no other action for a user to take.
<?php
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'page':
global $user;
if (arg(0) == 'user'){
if ($user->uid == 0) {
$vars['template_file'] = 'page-login';
}
elseif (arg(1) == 'login' || arg(1) == 'register' || arg(1) == 'password' ) {
$vars['template_file'] = 'page-login';
}
}
break;
}
return $vars;
}
?>Create a page-login.tpl.php such as the following
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $language ?>" xml:lang="<?php print $language ?>">
<head>
<title><?php print $head_title ?></title>
<?php print $head ?>
<?php print $styles ?>
</head>
<body<?php print $onload_attributes ?>>
<table border="0" cellpadding="0" cellspacing="0" id="header">
<tr>
<td id="logo">
<?php if ($logo) { ?><a href="/<?php print $base_path ?>" title="<?php print t('Home') ?>"><img src="/<?php print $logo ?>" alt="<?php print t('Home') ?>" /></a><?php } ?>
<?php if ($site_name) { ?><h1 class='site-name'><a href="/<?php print $base_path ?>" title="<?php print t('Home') ?>"><?php print $site_name ?></a></h1><?php } ?>
<?php if ($site_slogan) { ?><div class='site-slogan'><?php print $site_slogan ?></div><?php } ?>
</td>
<td id="menu"></td>
</tr>
<tr>
<td colspan="2"><div><?php print $header ?></div></td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0" id="content">
<tr>
<td valign="top">
<div id="main">
<?php //print $breadcrumb ?>
<h1 class="title"><?php print $title ?></h1>
<div class="tabs"><?php print $tabs ?></div>
<div id="help"><?php print $help ?></div>
<?php print $messages ?>
<?php print $content; ?>
</div>
</td>
</tr>
</table>
<?php print $closure ?>
</body>
</html>
One more thing
In order to round out my Admin theme, I had to add another bit of code to my template.php file to make node/add and node/#/edit use the Admin theme as well. Here is the full code of my template.php file.
<?phpfunction _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'page':
if ((arg(0) == 'admin')) {
$vars['template_file'] = 'page-admin';
}
else if ((arg(0) == 'node')){
if((arg(1) == 'add') || (arg(2) == 'edit')){
$vars['template_file'] = 'page-admin';
}
}
break;
}
return $vars;
}
?>
Using an alternate page.tpl based on the URI
If you're using URL aliases to separate your site, you can use Apache's REQUEST_URI to drive an alternative page.tpl. PHP stashes this in the _SERVER['REQUEST_URI'] global so all you need is a function like this in your template.php:
function _phptemplate_variables($hook, $vars = array())
{
if ($hook == 'page' &&
substr($_SERVER['REQUEST_URI'], 0, 6) == '/house') {
$vars['template_file'] = 'page-house';
}
return $vars;
}
In other words, if your URI is www.foo.com/house/bedroom, it will use the page-house.tpl template.