Customizing layout with PHP-NukeThemes
From ThemesWiki
| Official Page |
| Project Documentation |
| Download |
|
In this tutorial, we are going to transform the look of the Dinosaur Portal with the help of a new PHP-Nuke theme. A PHP-Nuke theme is a collection of HTML files, CSS styles, images, and PHP code that defines the layout and appearance of your pages, and hence, the look and feel of your site. Through the use of themes, without having to touch the inner workings of PHP-Nuke, you can create a new look for your site, enforced throughout the site. There is even the possibility of allowing the user to choose a personal theme.
Creating a PHP-Nuke theme gives your site its own special look, distinguishing it from other PHP-Nuke-created sites and offers an effective outlet for your creative talents. Creating a theme requires some knowledge of HTML, confidence in working with CSS and PHP, but most important is some imagination and creativity!
[edit] Theme Management
Basically, a theme is a folder that sits inside the themes folder in your PHP-Nuke installation. Different themes correspond to different folders in the themes folder, and adding or removing a theme is as straightforward as adding or removing the relevant folder from the themes folder.
By default, you will find around 14 themes in a standard PHP-Nuke installation. DeepBlue is the default theme.
Themes can be chosen in one of two ways:
- By the administrator: You can simply select the required theme from the General Site Info panel of the Site Preferences administration menu and save the changes. The theme selected by the administrator is the default theme for the site and will be seen by all users of the site, registered or unregistered.
- By the user: Users can override the default theme set by the administrator from the Themes option of the Your Account module. This sets a new, personal, theme that will be displayed to that user. Note that this isn't a theme especially customized for that user; it is just one chosen from the list of standard themes installed on your site.
Unregistered visitors do not have an option to choose a theme; they have to become registered users.
[edit] Theme File Structure
Let's start with the default theme, DeepBlue. If you open up the DeepBlue folder within the themes folder in the root of your PHP-Nuke installation, you will find three folders and two files. The three folders are:
-
forums: This folder contains the theme for the Forums module. This is not strictly a requirement of a PHP-Nuke theme, and not every PHP-Nuke theme has a forums theme. The Forums module (otherwise known as phpBB) has its own theme 'engine'. The purpose of including a theme for the forums is that you have consistency between the rest of your PHP-Nuke display and the phpBB display. -
images: This folder contains the image files used by your theme. These include the site logo, background images, and graphics for blocks among others. As mentioned earlier, within this folder can be other folders containing images to override the standard icons. -
style: This folder contains the CSS files for your theme. Usually, there is one CSS file in the style folder,style.css. Each theme will make use of itsstyle.cssfile, and this is the file into which we will add our style definitions when the time comes.
Of the two files, index.html is simply there to prevent people browsing to your themes folder and seeing what it contains; visiting this page in a browser simply produces a blank page. It is a very simple security measure.
The themes.php file is a PHP code file, and is where all the action happens. This file must always exist within a theme folder. We will concentrate on this file later when we customize the theme.
In other themes you will find more files; we will look at these later.
[edit] Installing a New Theme
Installing and uninstalling themes comes down to adding or removing folders from the themes folder, and whenever a list of available themes is presented, either in the Site Preferences menu or the Your Accounts module, PHP-Nuke refreshes this list by getting the names of the folders in the themes folder.
You will find a huge range of themes on the Web. For example, there is a gallery of themes at: http://nukecops.com/modules.php?set_albumName=packs&op=modload&name=Gallery& file=index&include=view_album.php
Many of these are themes written for older versions of PHP-Nuke, but most are still compatible with the newer releases.
There is also a live demonstration of some themes at:
http://www.portedmods.com/styles/
On this page you can select the new theme and see it applied immediately, before you download it.
[edit] Removing an Existing Theme
To remove a theme from your PHP-Nuke site you simply remove the corresponding folder from the themes folder, and it will no longer be available to PHP-Nuke.
However, you should be careful when removing themes what if somebody is actually using that theme?
- If a user has that theme selected as their personal theme, and you remove that theme, then that user's personal theme will revert to the default theme selected in Site Preferences.
- If you remove the site's default theme, then you will break your site!
Deleting the site's default theme will produce either a blank screen or messages like the following when you attempt to view your site.
Warning: head(themes/NonExistentTheme/theme.php) [[http://www.php.net/function.head function.head]]: failed to create stream: No such file or directory in c:\nuke\html\header.php on line 31
The only people who can continue to use your site in this situation are those who have selected a personal theme for themselves and only if that theme is still installed.
To correct such a faux pas, make a copy of one of the other themes in your themes
folder (unless you happen to have a copy of the theme you just deleted elsewhere), and rename it to the name of the theme you just deleted.
In conclusion, removing themes should only be a problem if you somehow manage to remove your site's default theme. For users who have selected the theme you just removed, their theme will revert to the default theme and life goes on for them.
A final caveat about the names of theme folders; do not use spaces in the names of the folders in
the themes folder this can lead to strange behavior when the list of themes is
displayed in the drop-down menus for users to select from.
[edit] From an Existing Theme to a New Theme
We'll create a new theme for the Dinosaur Portal by making changes to an existing theme. This will not only make you feel like the theme master, but it will also serve to illustrate the nature of
the theme-customization problem. We'll be making changes all over the place adding and replacing things in HTML and PHP files but it will be worth it. Another thing to bear in mind is that we're creating a completely different looking site without making any changes to the inner parts of PHP-Nuke. At this point, all we are changing is the theme definition.
The theme for the Dinosaur Portal will have a warm, tropical feel to it to evoke the atmosphere of a steaming, tropical, prehistoric jungle, and will use lots of orange color on the page.
First of all, we need a theme on which to conduct our experiments. We'll work on the 3D‑Fantasy theme.
[edit] Starting Off
The first thing we will do is to create a new theme folder, which will be a copy of the 3D‑Fantasy theme.
Open up the themes folder in your file explorer, and create a copy of the 3D-Fantasy folder. Rename this copy as TheDinosaurPortal.
Now log into your site as testuser, and from the Your Account module, select TheDinosaurPortal as the theme. Your site will immediately switch to this theme, but it will look exactly like 3D‑Fantasy, because, at the moment, it is!
You will also need some images from the code download for this tutorial; you will find them in the SiteImages folder of this tutorial's code.
[edit] Replacing Traces of the Old Theme
The theme that we are about to work on has many occurrences of 3D-Fantasy in a number of files, such as references to images. We will have to remove these first of all, or else our new theme will be looking in the wrong folder for images and other resources.
Open each of the files below in your text editor, and replace every occurrence of 3D‑Fantasy with TheDinosaurPortal in a text editor, we'll use Wordpad.
"You can use the replace functionality of your editor to do this. For example, in Wordpad, select Edit | Replace; enter the text to be replaced, and then click Replace All to replace all the occurrences in
the open file. After making all the changes, save each file:
-
blocks.html -
footer.html -
header.html -
story_home.html -
story_page.html -
theme.php -
tables.php
[edit] Templates and PHP Files
We've just encountered two types of file in the theme folder PHP code files (theme.php and tables.php) and HTML files (blocks.html, footer.html,
and so on). Before we go any further, we need to have a quick discussion of what roles these types of file play in the theme construction.
[edit] PHP Files
The PHP files do the main work of the theme. These files contain the definitions of some functions that handle the display of the page header and how an individual block or article is formatted, among other tasks. These functions are called from other parts of PHP-Nuke when required. We'll talk about them when they are required later in the tutorial. Part of our customization work will be to make some changes to these functions and have them act in a different way when called.
Historically, the code for a PHP-Nuke theme consisted of a single PHP file, theme.php. One major drawback of this was the difficulty you would have in editing this file in the 'design' view of an HTML editor. Instead of seeing the HTML that you wished to edit, you probably wouldn't
see anything in the 'design' view of most HTML editors, since the HTML was inextricably intertwined with the PHP code. This made creating a new theme, or even editing an existing theme, not something for the faint-hearted you had to be confident with your PHP coding to make sure you were changing
the right places, and in the right way.
The theme.php file consists of a number of functions that are called from other parts
of PHP-Nuke when required. These functions are how the theme does its work.
One of the neat appearances in recent versions of PHP-Nuke is the use of a 'mini‑templating' engine for themes. Not all themes make use of this method (DeepBlue is one theme that doesn't), and that is one of the reasons we are working with 3D-Fantasy as our base theme, since it does follow the 'templating' model.
[edit] Templates
The HTML files that we modified above are the theme templates. They consist of HTML, without any PHP code. Each template is responsible for a particular part of the page, and is called into action by the functions of the theme when required.
One advantage of using these templates is that they can be easily edited in visual HTML editors, such as Macromedia's Dreamweaver, without any PHP code to interfere with the page design.
Another advantage of using these templates is to separate logic from presentation. The idea of a template is that it should determine how something is displayed (its presentation). The template makes use of some data supplied to it, but acquiring and choosing this data (the logic) is not done in the template. The template is processed or evaluated by the 'template engine', and output is generated. The template engine in this case is the theme.php file.
To see how the template and PHP-Nuke 'communicate', let's look at an extract from the header.html file in the 3D-Fantasy folder:
<a href="index.php"> <img src="themes/3D-Fantasy/images/logo.gif" border="0" alt="Welcome to $sitename" align="left"> </a>
The $sitename text (shown highlighted) is an example of what we'll call a placeholder. There is a correspondence between these placeholders and PHP variables that have the same name as the placeholder text. Themes that make use of this templating process more or less replace any text beginning with $ in the template by the value of the corresponding PHP variable.
This means that you can make use of variables from PHP-Nuke itself in your themes; these could be
the name of your site ($sitename), your site slogan, or even information about the user. In fact, you can add your own PHP code to create a new variable, which you can then display from within one of the templates.
To complete the discussion, we will look at how the templates are processed in PHP‑Nuke. The code below is a snippet from one of the themeheader() function in the theme.php file. This particular snippet is taken from the 3D-Fantasy theme.
function themeheader()
{
global $user, $banners, $sitename, $slogan, $cookie, $prefix,
$anonymous, $db;
... code continues ....
$tmpl_file = "themes/3D-Fantasy/header.html";
$thefile = implode("", file($tmpl_file));
$thefile = addslashes($thefile);
$thefile = "\$r_file=\"".$thefile."\";";
eval($thefile);
print $r_file;
... code continues ....
The processing starts with the line where the $tmpl_file variable is defined. This variable is set to the file name of the template to be processed, in this case header.html. The next line grabs the content of the file as a string. Let's suppose the header.html file contained the text You're welcomed to $sitename, thanks for coming!. Then, continuing in the code above, the $thefile variable would eventually hold this:
\$r_file = \" You\'re welcomed to $sitename, thanks for coming!\";
This looks very much like a PHP statement, and that is exactly what PHP-Nuke is attempting to create. The eval() function executes the statement; it defines the variable $r_file as above. This is equivalent to putting this line straight into the code:
$r_file = " You\'re welcomed to $sitename, thanks for coming!";
If this line were in the PHP code, the value of the $sitename variable will be inserted into the string, and this is exactly how the placeholders in the templates are replaced with the values of the corresponding PHP variables.
This means that the placeholders in templates can only use variables accessible at the point in the code where the template is processed with the eval() function. This means any parameters passed to the function at the time global variables that have been announced with the global statement or any variables local to the function that have been defined before the line with the eval() function. This does mean that you will have to study the function processing the template to see what variables are available. In the examples in this tutorial we'll look at the most relevant variables.
The templates do not allow for any form of 'computation' within them; you cannot use loops or call PHP functions. You do your computations 'outside' the template in the theme.php file, and the results are 'pulled' into the template and displayed from there.
Now that we're familiar with what we're going to be working with, let's get started.
[edit] Changing the Page Header
The first port of call will be creating a new version of the page header. We will make these customizations:
- Changing the site logo graphic
- Changing the layout of the page header
- Adding a welcome message to the user, and displaying the user's avatar
- Adding a drop-down list of topics to the header
- Creating a navigation bar
[edit] Time For Action Changing the Site Logo Graphic
- Grab the
logo.giffile from theSiteImagesfolder in the code download. - Copy it to the
themes/TheDinosaurPortal/imagesfolder, overwriting the existinglogo.giffile. - Refresh the page in your browser. The logo will have changed!
What Just Happened?
The logo.gif file in the images folder is the site logo. We replaced it with a new banner, and immediately the change came into effect.
[edit] Time For Action Changing the Site Header Layout
- In the theme folder is a file called
header.html. Open up this file in a text editor, we'll use Wordpad. - Replace all the code in this file with the following:
<!-- Time For Action Changing the Site Header Layout --> <table border="0" cellspacing="0" cellpadding="6" width="100%" bgcolor="#FFCC33"> <tr valign="middle"> <td width="60%" align="right" rowspan="2"> <a href="index.php"><img src="themes/$GLOBALS[ThemeSel]/images/logo.gif" border="1" alt="Welcome to $sitename"> </a></td> <td width="40%" colspan="2"> <p align="center"><b>WELCOME TO $sitename!</b></td> </tr> <tr> <td width="20%">GAP</td> <td width="20%">GAP</td> </tr> </table> <!-- End of Time for Action --> $public_msg<br> <table cellpadding="0" cellspacing="0" width="99%" border="0" align="center" bgcolor="#ffffff"> <tr><td bgcolor="#ffffff" valign="top">
- Save the
header.htmlfile. - Refresh your browser. The site header now looks like this:
What Just Happened?
The header.html file is the template responsible for formatting the site header. Changing this file will change the format of your site header.
We simply created a table that displays the site logo in the left-hand column, a welcome message in the right-hand column, and under that, two GAPs that we will add more to in a moment. We set the background color of the table to an orange color (#FFCC33). We used the $sitename placeholder to display the name of the site from the template.
Note that everything after the line:
in our new header.html file is from the original file. (The characters here denote an HTML comment that is not displayed in the browser). This is because the end of the header.html file starts a new table that will continue in other templates. If we had removed these lines, the page output would have been broken.
There was another interesting thing we used in the template, the $GLOBALS[ThemeSel] placeholder:
<a href="index.php"><img src="themes/$GLOBALS[ThemeSel]/images/logo.gif"
ThemeSel is a global variable that holds the name of the current theme it's either the default site theme or the user's chosen theme. Although it's a global variable, using just $ThemeSel in the template would give a blank, this is because it has not been declared as global by the function in PHP-Nuke that consumes the header.html template. However, all the global variables can be accessed through the $GLOBALS array, and using $GLOBALS[ThemeSel] accesses this particular global variable. Note that this syntax is different from the way you may usually access elements of the $GLOBALS array in PHP. You might use $GLOBALS['ThemeSel'] or $GLOBALS["ThemeSel"]. Neither of these work in the template so we have to use the form without the ' or ".
[edit] Time For Action Fixing and Adding the Topics List
Next we'll add the list of topics as a drop-down box to the page header. The visitor will be able to select one of the topics from the box, and then the list of stories from that topic will be displayed to them through the News module. Also, the current topic will be selected in the drop-down box to avoid confusion.
This task involves fixing some bugs in the current version of the 3D-Fantasy theme.
- First of all, open the
theme.phpfile and find the following line in thethemeheader()function definition: $topics_list = "<select name=\"topic\" onChange='submit()'>\n"; - Replace this line with these two lines: global $new_topic; $topics_list = "<select name=\"new_topic\" onChange='submit()'>\n";
- If you move a few lines down in the
themeheader()function, you will find this line: if ($topicid==$topic) { $sel = "selected "; } - Replace
$topicwith$new_topicin this line to get: if ($topicid==$new_topic) { $sel = "selected "; } - Save the
theme.phpfile. - Open the
header.htmlfile in your text editor, and where the secondGAPis, make the modifications as shown below:<td width="20%">GAP</td> <td width="20%"><form action="modules.php?name=News&new_topic" method="post"> Select a Topic:<br>$topics_list</select></form></td> </tr> </table> <!-- End of Time for Action -->
- Save the
header.htmlfile. - Refresh your browser. You will see the new drop-down box in your page header:
What just Happened?
The themeheader() function is the function in theme.php responsible for processing the header.html template, and outputting the page header.
The $topics_list variable has already been created for us in the themeheader() function, and can be used from the header.html template. It is a string of HTML that defines an HTML select drop-down list consisting of the topic titles.
However, the first few steps require us to make a change to the $topics_list variable, correcting the name of the select element and also using the correct variable to ensure the current topic (if any) is selected in the drop-down box. The select element needs to have the name of new_topic, so that the News module is able to identify which topic we're after.
This is all done with the changes to the theme.php file. First, we add the global statement to access the $new_topic variable, before correcting the name of the select element:
global $new_topic; $topics_list = "<select name=\"new_topic\" onChange='submit()'>\n";
The next change we made is to make sure we are looking for the $new_topic variable, not the $topic variable, which isn't even defined:
if ($topicid==$new_topic) { $sel = "selected "; }
Now the $topics_list variable is corrected, all we have to do is add a placeholder for this variable to the header.html template, and some more HTML around it. We added the placeholder for $topics_list to display the drop-down list, and a message to go with it encouraging the reader to select a topic into one of the GAP table cells we created in the new‑look header.
The list of topics will be contained in a form tag, and when the user selects a topic, the form will be posted back to the server to the News module, and the stories in the selected topic will be displayed. (The extra HTML that handles submitting the form is contained with the $topics_list variable.)
<form action="modules.php?name=News" method="post"> Select a Topic:
$topics_list
All that remains now is to close the select tag the tag was opened in the $topics_list variable but not closed and then close the form tag:
</select></form>
When the page is displayed, this is the HTML that PHP-Nuke produces for the topics drop-down list:
<form action="modules.php?name=News&new_topic" method="post"> Select a Topic:<br><select name="topic" onChange='submit()'> <option value="">All Topics</option> <option value="1">The Dinosaur Portal</option> <option value="2">Dinosuar Hunting</option> </select></form>
[edit] Time For Action Adding a Welcome Message to the User
We will add some more information the page header; a friendly message to salute our visitors:
- Open the
theme.phpfile in your text editor, and inside thethemeheader()function definition, find the following line: $theuser = " Welcome $username!"; - Change that line to the following: $theuser = " Hi $username!, how you doing?";
- Save the
theme.phpfile. - Open the
header.htmlfile, and modify the remainingGAPas shown below:<td width="20%">$theuser</td> <td width="20%"><form action="modules.php?name=News" method="post"> Select a Topic:<br>$topics_list</select></form></td> </tr></table> </div> <!-- End of Time for Action -->
- Save the
header.htmlfile. - Refresh the browser. A polite welcome is displayed to the user:
What Just Happened?
The $theuser variable already contained a message of the form Welcome <username>! However, we wanted a friendlier greeting, so we edited the definition of the $theuser variable in theme.php. The $username variable, used to define $theuser, holds the name of the user, and had been set up earlier in the themeheader() function definition.
After that was done, all we had to do was add a placeholder for the $theuser variable into our template, and we were away.
The introductory Hi was added to the $theuser string because if the user is not logged in, a link to Create an Account is displayed instead. If we had put Hi in the template instead of the variable, it would say Hi Create An Account to a new visitor, which could be rather confusing.
[edit] Time For Action Adding the User Avatar
We've said hello to our user, now let's show the user their face well, their avatar at least. We will display their avatar underneath the welcome message:
- In the
theme.phpfile, add the following code immediately after the line we just modified (shown highlighted it's in thethemeheader()function definition if you have lost track):$theuser = "Hi $username!, how you doing?"; $profile = getusrinfo($user); $avatar = $profile['user_avatar']; if ($avatar) { $theuser .= "<br><center> <img src=\"modules/Forums/images/avatars/$avatar\" alt=\"Your Face!\"></center>\n"; } - Save the
theme.phpfile. - Refresh your browser to see the avatar.
What Just Happened?
Extended information about the user is obtained through a call to the getusrinfo() function, passing in the $user variable. The $user global variable holds a limited amount of information about the user, including the username and password, which is used to identify the user and retrieve their profile. This is all done in the getusrinfo() function in the mainfile.php file. This function returns an array of data to us, which we store in an array we call $profile.
The exciting bit of data for us is the avatar entry in our $profile array (accessed through $profile['avatar']). This contains the filename of the user avatar image, and all we have to do is add the path to the avatar images in the Forums module and we have a picture.
If the user isn't logged in, this bit of code won't even be executed, so there is no need to worry about not finding an avatar image for a non-existent user.
[edit] Time For Action Adding a Horizontal Navigation Bar
Now we'll take the first steps towards adding a horizontal navigation bar. These first steps will not produce a very exciting result; we will put the finishing touches to this when we use CSS in the next section.
- Open the
header.htmlfile, and add the highlighted code as shown below:Select a Topic:<br>$topics_list</select></form></td> </tr> <tr> <td colspan="3" > <div id="navBar"> <a href="index.php">Home</a> <a href="modules.php?name=Downloads">Downloads</a> <a href="modules.php?name=Encyclopedia">Encyclopedia</a> <a href="modules.php?name=Your_Account">Your Account</a> <a href="modules.php?name=Submit_News">Submit News</a> </div> </td> </tr> </table> <!-- End of Time for Action -->
- Save the file.
- Refresh your browser, and your navigation bar will be there:
What Just Happened?
All that we did here was to insert an extra row into the page header table, and then add a couple of links to that row. We had to set the colspan for the td element to 3, since there are three columns in the table, and our row was to have only one column that spans the entire width of the table.
[edit] Time For Action Changing Some Background Colors
There are a couple of global variables defined by the theme that can be used by various modules of PHP-Nuke. Two of these are $bgcolor1 and $bgcolor2. These define background colors, and are used, for example, by the comments navigation bar:
- Open the
theme.phpfile in your text editor. - Find the definition of the
$bgcolor1and$bgcolor2variables: $bgcolor1 = "#d5d5d5"; $bgcolor2 = "#7b91ac"; - Change them to the following: $bgcolor1 = "#FFCC33"; $bgcolor2 = "#FFCC99";
- Save the
theme.phpfile.
Now view one of the stories on your site, and have a look at the comments navigation bar; the dark and light shades of blue have been replaced by dark and light shades of orange:
What Just Happened?
We set new values for the $bgcolor1 and $bgcolor2 global variables. We set $bgcolor2 to a dark orange and $bgcolor1 to a lighter orange. After making the change, we had a look at the comments navigation bar, which is one place where these background colors are actually used. These variables are also used in the Downloads, News, Statistics, and Web Links modules among others, and are used to control the 'shading' or background color of a number of elements.
[edit] Working with the Stylesheet
Now it's time to start making changes to the theme's Cascading Style Sheet (CSS) file, the stylesheet. Using the stylesheet will allow us to move formatting details out of the theme's HTML templates (and PHP code).
However, to prepare the way for using the stylesheet we will sometimes find ourselves having to remove some hardcoded HTML attributes from the templates (or PHP code). We will need to do this because these HTML attributes will override our settings in the CSS file, and our changes to the stylesheet won't be seen. We will also find that, as we move the formatting from the templates and PHP code into the stylesheet, we get greater control over the formatting of our elements. As we make further customizations to our theme in this tutorial, we will move the formatting responsibility to the stylesheet and out of the templates.
[edit] Time For Action Background Image with Style
The first thing we're going to do is set the background image of the page from the CSS file.
- Grab the
background.jpgfile from theSiteImagesfolder in the code download, and copy it to thethemes/TheDinosaurPortal/imagesfolder. - Open the
theme.phpfile in your text editor. - Inside the
themeheader()function definition, find the following line:echo "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#363636\" vlink=\"#363636\" alink=\"#d5ae83\"><br>\n\n\n";
- Remove all the attributes after
<body>, and then remove the<br>, to produce the following:echo "<body>\n\n\n";
- Save the file.
- In the
stylefolder of the theme you will find thestyle.cssfile; open this file in your text editor. - Delete the following line:
BODY {FONT-FAMILY: Verdana,Helvetica; FONT-SIZE: 10px} - Move your cursor to the end of this file (you may have to move to the right‑hand end of the last line in the file and press Enter to create a new line).
- Enter the following into the file:
body { color:#000000; background-image: url(../images/background.jpg); font-family: arial, helvetica, sans-serif; font-size: 1em; } - Save the
style.cssfile. - Refresh your browser nothing should have changed!
What Just Happened?
The first three steps were preparing the way for using CSS we removed the hardcoded HTML attributes from the body tag. We could have set the background image from the line in the themeheader() function with the background attribute of the body tag, but controlling the format of the body tag from the stylesheet will offer us greater flexibility.
Every theme has its own stylesheet, style.css, located in the style subfolder of its folder. To add any CSS information, we make changes there. That's what the remainder of the steps do.
Once we are in style.css, we remove the existing style information for the body tag (step 4). This leaves us a clean slate for creating new style information for this tag.
The new style information known as properties in CSS parlance is added in step 9. First of all, we added properties for the body tag:
body {
color:#000000;
background-image: url(../images/background.jpg);
font-family: arial, helvetica, sans-serif;
font-size: 1em;
}
The color property specifies the color of the text used in the body of the document here we've gone for black (#000000). The background-image property specifies the image used for the body background. The font-family and font-size properties are simple enough. The font-size has been specified using the em units, setting the font-size in relative units.
The path to the background-image property is interesting:
url(../images/background.jpg)
This path is relative to the stylesheet, unlike the path to images used from the templates in the theme, which are relative to the root of our PHP-Nuke installation (like /themes/TheDinosaurPortal/images/logo.gif for example).
To get from the stylesheet (in TheDinosaurPortal/style/style.css) you have to go up a folder (../) bringing you to the TheDinosuarPortal folder, and then into the images folder. Specifying background images using CSS in this way means that you bypass the need for including the name of the theme.
When you view the new page, you will see that much of our background image is obscured by large blocks of white on the page. We need to look into the header.html to find what is responsible for this. In the last few lines of the header.html file you will find:
<table cellpadding="0" cellspacing="0" width="99%" border="0" align="center" bgcolor="#ffffff"> <tr><td bgcolor="#ffffff" valign="top">
We need to remove the two bgcolor="#fffff" instances to get:
<table cellpadding="0" cellspacing="0" width="99%" border="0" align="center" > <tr><td valign="top">
Then we can resave the header.html file. When you refresh your browser, the background image should be more clearly visible. The bgcolor="#ffffff" attributes we just removed were setting the background color of the main part of the page to white. The table starting at the end of header.html contains the block and module output, and the background image was being hidden by the white background color of this table, which will fill up most of the page when the page is finished.
[edit] Time For Action Changing the Links
In the last task we also removed the definitions for displaying links from the body tag. Now we will add these to the stylesheet:
- Open the
style.cssfile in your text editor. - Delete the following four lines (only the first line is shown in full, the other lines contain the same text between the braces):
A:link {BACKGROUND: none; COLOR: #000000; FONT-SIZE: 11px; FONT-FAMILY: Verdana, Helvetica; TEXT-DECORATION: underline} A:active {...} A:visited {...} A:hover {...} - Move your cursor to the end of this file, and add these lines:
a {text-decoration:none; color:red; font-weight:bold;} - Save the
style.cssfile, and refresh your browser.
What Just Happened?
We specified a new definition for links in the CSS stylesheet. We removed the line under the link with the text-decoration:none setting, and set the color of a link to red, and made it bold.
Note that we removed four link definitions and replaced them with one. The color of a standard link is defined by a:link, and a:visited takes care of links that have been visited. The behavior of a link as you click on it is determined by a:active. These settings correspond to the values of the link, alink, and vlink HTML attributes we removed from the body tag in theme.php.
The a:hover definition comes into play when you move your mouse cursor over a link and takes care of that link's format. We will make use of that in a moment. For our settings here, we have simply set all links to look the same using a in the stylesheet rather than a:link, a:active, and so on, means the definition will apply to all links, regardless of whether the visitor is hovering their mouse cursor over the link, or if they have already clicked on that link.
[edit] Time For Action Changing the OpenTable() Function
The OpenTable() and CloseTable() functions defined in tables.php are used to enclose elements on the page, and they are used throughout PHP-Nuke.
- In the
TheDinosaurPortalfolder is a file calledtables.php. Open it in your text editor. - Select all the text in this file and delete it.
- Add the following text to this file:
<?php function OpenTable() { echo "\n<table class=\"openTable\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\"> <tr> <td>"; } function CloseTable() { echo "\n</td> </tr></table> <br>"; } function OpenTable2() { echo "\n<table class=\"openTable\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\"> <tr> <td>"; } function CloseTable2() { echo "\n</td> </tr></table> <br>"; } ?> - Save the
tables.phpfile. - Open the
style.cssfile and add the following to the end of the file:table.openTable { border:1px black solid; background-color:white; padding-top:8px;padding-bottom:8px; padding-left:4px;padding-right:4px; } - Save the
style.cssfile, view the homepage of your site, and have a look at the message at the top of the middle column:
What Just Happened?
The OpenTable() and CloseTable() functions are used throughout PHP-Nuke to define how elements in the main body of the page are enclosed. The OpenTable() function starts the element, usually a table, and the CloseTable() function finishes it. For our example here, we simply removed all the existing code and started from scratch with the definitions; all we had to do was to define these functions, as well as OpenTable2() and CloseTable2(), which are used less frequently but still need a definition. Note that we have just used the same code for the definition of this pair of functions as we did for the first pair.
OpenTable() starts a new table. This table only needs one column because of its simple design; the table will just hold content; it won't do anything fancy since we already have enough striking elements on our page.
function OpenTable()
{
echo "\n<table class=\"openTable\"
cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">
<tr>
<td>";
}
We mark the table with the openTable class, which we will define in the stylesheet, so we can basically forget about these functions now. We begin the output with a newline \n character, to aid readability of the HTML source.
The CloseTable() function is simple all it has to do is close the single td element, and then close off the table:
function CloseTable()
{
echo "\n</td>
</tr></table>
<br>";
}
The final step is to create the openTable class in the stylesheet:
table.openTable {
border:1px black solid;
background-color:white;
padding-top:8px;padding-bottom:8px;
padding-left:4px;padding-right:4px;
}
We specified a thin border for the table, (a one-pixel solid-black border), some padding to move the text away from the edge of the table, and a background color of white for the element. Note that specifying the border like this in the stylesheet, rather than using the border attribute of the table tag, gives us a border only around the outside of the table, rather than borders around the cells of the table.
[edit] Time For Action Styling the Navigation Bar
Now we can make our navigation bar actually look good. So far, it just looks like a group of links. A few additions to the stylesheet and it will be transformed.
- Open the
style.cssfile in your text editor. - Add the following to the end of the file:
div#navBar { text-align:center; margin:4px; font-family:Arial; font-weight:bold; } div#navBar a { color:#000000; padding: 5px 4px 5px 5px; border: 2px solid #808080; background: #cccccc; text-decoration: none; } div#navBar a:hover { border-color: #000000; color: #ffffff; background: #336699; } - Save the file, and refresh your browser. The image below shows the mouse being hovered over the Encyclopedia link:
- Open the
header.htmlfile in your text editor, and make the highlighted change shown below:<td colspan="3" class="navBarRow"> <div id="navBar">
- Save the
header.htmlfile, open thestyle.cssfile again, and add this to the end:td.navBarRow { padding: 6px; background-color: #2F5376; color: #FFFFFF; font-size:14pt; font-weight:bold; font-family:arial, helvetica, sans-serif; margin-left:8px; margin-right:8px; line-height: 1.5em; } - Save the file and refresh your browser.
What Just Happened?
You may recall that when we created the navigation bar, it was wrapped in a div element with an id attribute:
<div id="navBar">
We can use the id of the element so that styles can be applied only to things within it:
div#navBar {
text-align:center; margin:4px;
font-family:Arial; font-weight:bold;
}
The div#navbar syntax means the definition that follows will only be applied to the div element with the id navbar. We do this to center its contents (with text‑align:center), set a margin, and define the font.
However, we can continue this syntax to define the style for links contained in the div element:
div#navBar a {
color:#000000;
padding: 5px 4px 5px 5px;
border: 2px solid #808080;
background: #cccccc;
text-decoration: none;
}
This sets the style for a link in our navbar div element. We define the color of the text (black), some padding around the text, a background color (#cccccc, a pale grey), and remove the underlining of links with text-decoration:none;. The other thing we do is set the border for each link. The border is 2 pixel wide, a solid line, and colored #808080, which is a darker grey. This is what gives each link its own little box.
The next definition, div#navBar a:hover, allows the links to behave differently when the mouse cursor hovers over them. This removes the need for any kind of OnMouseOver JavaScript to produce 'roll-over' effects; the stylesheet now takes care of this.
div#navBar a:hover {
border-color: #000000;
color: #ffffff;
background: #336699;
}
Here the definition changes the background colors, text color, and the border color. All the other settings defined by div#navbar a will be 'inherited', so there is no need to specify these settings again.
The final steps added a class attribute to the table column holding the navigation bar, and in the style.css file we set the definition for this class. We added some padding and margins to give the bar some spacing, and set the background color to a dark-blue color (#2F5376).
[edit] Changing Blocks
Our next area of customization will be blocks. We will create new blocks in a moment, but first of all we will do some quick customizations to put greater control of the display of blocks into the hands of the theme.
[edit] Time For Action Show Right-Hand Blocks on All Pages
You will notice that the right-hand blocks are not displayed for all modules; they are displayed on the homepage, and also for some modules such as Downloads. Our next change will be to make the right-hand blocks appear on every page, for every module.
- Open the
theme.phpfile in your text editor. - Find the
themefooter()function definition, and locate the following lines within that piece of code:if (defined('INDEX_FILE')) { - Change the first line as shown below:
//if (defined('INDEX_FILE')) { - Save the file.
- Now open up any module, and your right-hand blocks will be there.
What Just Happened?
The variable INDEX_FILE is set by certain modules when the 'front page' of that module is displayed. The front page is the page displayed when there is no file value in the query string of the URL. On all other pages, INDEX_FILE is not set.
The change we made in the code comments out a check for this value being set. Only if the check is true will the next section of code execute. That section of code is shown below you will see it contains a call to blocks("right"). This is the function call for displaying the right-hand blocks.
if (defined('INDEX_FILE'))
{
$tmpl_file = "themes/TheDinosaurPortal/center_right.html";
$thefile = implode("", file($tmpl_file));
$thefile = addslashes($thefile);
$thefile = "\$r_file=\"".$thefile."\";";
eval($thefile);
print $r_file;
blocks("right");
}
Since we comment out the check to see if the INDEX_FILE constant is defined, the code enclosed by the braces ({ and }) will always execute, and the blocks will always be displayed.
[edit] Time For Action Hide Right-Hand Blocks For Certain Modules
Now we've got the right-hand blocks on every page. This can be a bit much the presence of the right‑hand blocks can make the page feel rather 'heavy'.
Next we are going to see how to turn off the right-hand blocks for certain modules. For our example, we'll turn off the blocks for the Downloads, Feedback, and Search modules.
- Open the
theme.phpfile in your text editor. - Add the highlighted lines of code to the top of the file after the color definitions:
$textcolor2 = "#000000"; global $packt_hideRightBlocks; $packt_hideRightBlocks = array('Downloads'=>1,'Feedback'=>1, 'Search'=>1); if(file_exists("themes/TheDinosaurPortal/tables.php")){ - Find the line we commented out in the previous task in the
themefooter()function definition. - Add the following two lines of code between the commented line and the brace:
// if (defined('INDEX_FILE')) global $packt_hideRightBlocks, $module_name; if (!$packt_hideRightBlocks[$module_name]) { - Save the
theme.phpfile. - In your browser, check that the right-hand blocks are displayed on the homepage and on the Topics module page, but not on the Downloads, Search, and Feedback pages.
What Just Happened?
We created a global variable, $packt_hideRightBlocks at the top of the theme.php file. This variable is an array, and contains entries for the names of the modules that we will hide the right‑hand blocks for. If we want the right-hand blocks shown for a particular module, we do not include it in the array.
We added the prefix packt_ to the variable name in order to avoid potential clashes with other global variables. The definition of the array shows we want to hide the right-hand blocks for the Downloads, Feedback, and Search modules.
Note that we had to put a global prefix before the definition of the $packt_hideRightBlocks statement to declare it as a global variable. We had to explicitly declare this variable as global because otherwise the variable will be scoped to the function that included the theme.php file, and this is the head() function in the header.php file. (This file is in the root of the PHP-Nuke installation, and is not part of a theme.) We'll talk more about this file later.
The idea now is simple we need to get the name of the current module, and then see if there is an entry for that in our array. If there is, we won't display the right-hand blocks.
We are able to add code to the themefooter() function at just the point we were working with in the previous task. First we add the global statement, to access the $packt_hideRightBlocks and $module_name global variables from our function. The $module_name global variable is defined by the 'core' of PHP-Nuke, and contains the name of the current module.
Next we check if there is an entry in the $packt_hideRightBlocks array with the name of $module_name.
if (!$packt_hideRightBlocks[$module_name])
In fact, the code actually checks that there isn't such an entry the ! character in front of the check means 'not'. If there is no such entry, then the code to display the right-hand blocks will be executed. Thus only a module whose name is not in the $packt_hideRightBlocks array will have right-hand blocks displayed.
- If you want to turn off this feature, and have all the right-hand blocks displayed for all modules, simply comment out the
ifstatement line. - If you want to use this feature to only show blocks for certain specified modules, change the check to the following:
if ($packt_hideRightBlocks[$module_name])
Now the right-hand blocks will only be shown for modules whose name is in the $packt_hideRightBlocks array.
It is also very easy to apply this method to handle the left-hand blocks. All you'd need is to set up an array called $packt_hideLeftBlocks, similar to our $packt_hideRightBlocks array, and then apply the same code to themeheader() function before the blocks("left") function call. Make sure you have some alternative form of navigation if you turn off the left-hand blocks you could well have removed the Modules menu block!
[edit] Time For Action Making the Block Titles Uppercase
Let's continue tweaking the block display:
- Open the
theme.phpfile in your text editor, and find thethemesidebox()function definition. - Add the highlighted line immediately after the first line of the function definition:
function themesidebox($title, $content) { $title = strtoupper($title); - Save the
theme.phpfile. - Refresh your browser, and you will note your block titles are now in uppercase.
What Just Happened?
The themesidebox() function controls the display of blocks. It simply grabs the blocks.html template, processes it, and spits out the result, producing a block. This function is called whenever any part of the application wants a block drawn.
The block title is held in the $title variable, and all we did was use the PHP strtoupper() function to convert the current title into uppercase. After that, the block display carries on as usual.
[edit] Time For Action Creating a New Block
Now we've got blocks all over our page but they're not 'our' blocks. Well, not yet. Our next job is to create a new block design. Now we will really feel that we are stamping our identity on our site.
- You will need to grab the
blockTop.gif,blockBottom.gif, andblockBackground.giffiles from theSiteImagesfolder in the code download and copy them to theimagesfolder in theTheDinosaurPortalfolder. - In the theme folder, you will find the
blocks.htmlfile. Open it in your text editor. - Delete the existing code, and enter this new code:
<table width="176px" cellspacing=0> <tr height="28"> <td background="themes/TheDinosaurPortal/images/blockTop.gif"> </td> </tr> <tr> <td background="themes/TheDinosaurPortal/images/blockBackground.gif"> <div class="blockTitle">$title</div> </td> </tr> <tr> <td background="themes/TheDinosaurPortal/images/blockBackground.gif"> <div class="blockContent">$content</div> </td> </tr> <tr height="28"> <td background="themes/TheDinosaurPortal/images/blockBottom.gif"> </td> </tr> </table> <br>
- Save the
blocks.htmlfile, and refresh your browser. The blocks should have changed: - Now open the
style.cssfile in your text editor. - Add the following style definitions to the end of the file:
div.blockContent { margin-left:8px; margin-right:8px; padding-bottom:8px; padding-top:8px; padding-left:0px; padding-right:0px; } div.blockTitle { background: #ffffff; margin-left:8px; margin-right:8px; color:black; padding-top:2px; padding-bottom:2px; font-size:1.2em; font-weight:bold; font-family:arial, verdana; text-align:center; } - Save the
style.cssfile, and refresh your browser. You'll see this:
What Just Happened?
The blocks.html file is the template used for displaying blocks. It uses two placeholders, $title and $content, which contain the title and content of the block respectively.
Our block consists of a single HTML table, set to a width of 176 pixels:
| Placeholder | Description |
|---|---|
$title
| The title of the story. |
$thetext
| The short description of the story. |
$aid
| The name of the administrator who posted the story to the site. |
$informant
| The username of the story creator. |
$datetime
| The date the story was posted. |
$posted
| Uses $aid, $time, and $timezone to produce text of the form Posted on <time> <timezone> by <name of administrator>, and also mentions the number of times the story has been read (provided by $counter).
|
$content
| The summary text ($thetext) of the story, prefixed by <name of the story creator> writes, and with any notes for the story attached on the end.
|
$t_image
| The path to the topic image. |
$topictext
| The full title of the topic. |
$counter
| The number of times the story has been read. |
$notes
| Any notes added by the administrator when the story was posted. This is not a variable passed to the function, but can be accessed with a |
$time
| The time the story was posted. The variable $timezone contains the author's timezone.
|
[edit] Changing the Layout of the Story Extended View
To change the layout of a story's extended view, you change the story_page.html template. Our new story_page.html template is below, and it is similar to the story_home.html template. The main differences are shown highlighted:
<table class="storyBack" width="100%" cellspacing=0 cellpadding=0> <tr> <td class="cornertl"></td><td></td><td class="cornertr" width="10"></td> </tr> <tr> <td></td><td class="storyTitle">$title</td> <td></td> </tr> <tr height=6><td colspan=3></td></tr> <tr> <td></td> <td > <table class="openTable" width="100%"> <tr><td> <span style="float:right;"> <img src="$t_image" align="middle" border="1" alt="$topictext"></span> $content</td> </tr> </table> </td> <td></td> </tr> <tr> <td class="cornerbl"></td><td></td> <td class="cornerbr" width="10"></td> </tr> </table>
This time, we use <span style="float:right;"> to have the topic image positioned on the right of the table, with the text flowing to the side of it.
The story_page.html template is processed by the themearticle() function in theme.php. This function has similar variables to those shown in the table for the themeindex() function, although in themearticle(), the $thetext variable actually contains the story introduction and the story extended text.
You will note that the same placeholder, $content, is used in both the story_home.html and story_page.html templates. In story_home.html, it holds the short description of the story, and in story_page.html, it holds the short description plus the extended text.
There are some lines in themearticle() that are worth noting, since they determine the whether the creator's name is added to the start of the story:
if ("$aid" == "$informant")
{
$content = "$thetext$notes\n";
}
else
{
if($informant != "")
{
$content = ".....";
}
else
{
$content = "$anonymous ";
}
$content .= ""._WRITES." <i>\"$thetext\"</i>$notes\n";
}
If the author who posted the story ($aid) is the same as the user who wrote the story ($informant), then the content of story is just the story description, story extended text, and any notes for the story. There is no mention of the story creator or who posted the story in the $content variable if the story creator is the same as the administrator who posted the story to the site.
If the story was written by someone other than the administrator, the content of the story becomes <username> writes, and then the story description, story extended text, and any notes for the story
are enclosed in quotes and are put into italics. If the story was not submitted anonymously, a link to the Your Account details of the story creator is created for the user name. (We have replaced that part of the code with ..... for brevity here.)
If you want to change the way the extended text view of the story is displayed, going beyond what the template can do, these lines in themearticle() are a good place to start.
[edit] Changing the Footer
The footer is the last part of the theme. The footer template is the footer.html file, and we will create a new template for it, based on the table that we created for OpenTable(). Here is the new footer template:
</td></tr></table> <br> <center> <table class="openTable" cellspacing="0" cellpadding="0" width=\"50%\"> <tr> <td align="center">$footer_message</td> </tr> </table> <center>
The first line closes off the table that was started at the end of header.html; without it, our page would not look right. After that, we create a new table with the openTable class that we defined for the table in the OpenTable() function earlier. This table will be centered in the page, and have a width of 50% of the page:
There is only one placeholder in this template, $footer_message. This contains the copyright message, which must be displayed in order to comply with PHP-Nuke's license.
Our theme is complete!
[edit] Adding a Favicon
A Favicon is a small image displayed in the navigation bar of the browser, and also in the list of bookmarks:
The Favicon is not something we can actually control with the theme, but it is the finishing touch for the site, and it does lead us into another interesting area of PHP-Nuke customization. Favicons behave rather strangely in Internet Explorer, and you will find that you need to add a site to your Favorites before the Favicon is displayed.
First of all, the Favicon is an image in a special format, ICO format. The file consists of a couple of copies of the same image at different sizes (16x16 and 32x32 usually). We will need to convert any standard graphical image we plan to use to this format before we continue.
You can download a free command-line tool to convert from PNG files to ICO files here:
http://www.winterdrache.de/freeware/png2ico/
There is an executable version of the application for Windows there, and instructions on how to use it. For other platforms you will have to compile the code yourself.
In the code download, there is a file called favicon.ico in the SiteImages folder that has already been converted. This should be copied to the images folder in the root of your PHP‑Nuke installation.
All that remains now is to add a link to this file. This link is not something that is handled by the theme, since it goes between the <head> and </head> tags of the document, which are beyond the control of the theme.
What we need to do is open our text editor, and enter the following code into a blank document:
<?php echo "<link rel=\"SHORTCUT ICON\" href=\"images/favicon.ico?\">\n"; ?>
The output of this file is the HTML required for the browser to download and display the Favicon. The location of the Favicon is indicated by the href attribute.
Save this file as custom_head.php in the folder includes\custom_files in the root of the PHP‑Nuke installation.
Now when you refresh your browser, the Favicon will be displayed in the browser bar:
[edit] Including Custom Files
The \includes\custom_files folder can hold files with specific names that PHP-Nuke can process at various points. The advantage of this approach is that you can throw your code into the PHP-Nuke core 'mix' without having to hack its inner workings. This folder was new in PHP-Nuke 7.6. In earlier versions, you could use the my_header.php file in the includes folder to achieve similar results, but the custom_files folder in PHP-Nuke 7.6 introduced greater flexibility.
- Anything output from the
custom_head.phpfile will be added between the<head>and</head>tag of the document. - Anything output from a file called
custom_header.phpwill be added to the output from theheader.phpfile. This means it will be output after the</head>tag and before the theme kicks in. Similarly, anything output from thecustom_footer.phpfile will be added to the output from thefooter.phpfile. - Any code in a file called
custom_mainfile.phpwill be executed before any of the code in themainfile.phpfile.
[edit] Page Output from Start to Finish
We've made many changes to customize a theme in this tutorial, and now we are ready for a detailed overview of exactly how the theme controls the appearance of