Difference between revisions of "Customising/Themes/1.10"

From Mahara Wiki

< Customising‎ | Themes
(Local theme overrides)
Line 200: Line 200:

Latest revision as of 17:07, 19 June 2019

This page is about Themes in Mahara version '1.10' and later.

For information about Themes in earlier Mahara versions see Customising/Themes

Creating a new theme for Mahara 1.10

  1. Create a new directory in the theme/ subdirectory (e.g. theme/ponies or similar)
  2. Copy the themeconfig.php from the default theme directory to your new directory
  3. Edit your themeconfig.php, and add a name for your theme in the $theme->displayname line.

From then on, you will have created a new theme that inherits from the raw theme. What this means is, when Mahara needs a theme file (image, CSS file or template), it will look for it in your theme's directory, and if it can't find it there it will use the one in raw/.

To override images, create a static/images directory under your theme directory. For example, to change the site logo, put a site-logo.png in theme/ponies/static/images, and this will change the site logo for the ponies theme.

You can do the same with static/style/*.css - those stylesheets will be included on the page after the parent theme's ones, so you just need to override rules you want to change.

You will probably also want to override some of the standard plugin stylesheets too. For example, if you want to change the look of the forums, the stylesheet used by the raw theme is in interaction/forum/theme/raw/static/style/style.css. To override these rules, you need to create new directories under interaction/forum/theme for your theme. So if the directory you created in step 1 was theme/ponies/, you would create the set of directories interaction/forum/theme/ponies/static/style/ and add a style.css in there, with the styles needed to override those contained in interaction/forum/theme/raw/static/style/style.css.

We hope that in most cases, theme authors won't need to create new templates, or make copies of templates from the raw theme into their new themes; a lot of the work can be done just by overriding default styles in the new theme's stylesheets.


Mahara reads theme configuration files from htdocs/theme/{$themename}/themeconfig.php. The standard Mahara distribution comes with several themes pre-installed. If new theme directories are placed under htdocs/theme, with a themeconfig.php, they will appear for selection on the Site Options page in the Admin section.

Assets: Templates & Static

The main thing that a theme provides, is a set of Dwoo templates, and a set of static assets, which are mostly images and stylesheets. The Dwoo templates are used by Mahara's Dwoo templating system to display each page. So in theory, a theme author, by rewriting the templates, can rewrite nearly the entirety of Mahara's behavior. Although in practice, most themes do no more than rearranging the order of items in the templates.


Mahara uses Dwoo, a fork of Smarty, as its backend templating engine. Developers familiar with Smarty should also read Differences between Smarty and Dwoo

Core assets

Templates for Mahara core (i.e. everything that's not a plugin) are stored in htdocs/theme/{$themename}/templates, stylesheets are stored in htdocs/theme/{$themename}/static/style, and images in htdocs/theme/{$themename}/static/images.

The directory structure under htdocs/theme/{$themename}/templates mostly mirrors the structure of the php pages on the site, so for example, the page template used on the page htdocs/admin/site/options.php is found in htdocs/theme/default/templates/admin/site/options.tpl. However this is not a strict rule; some pages in different folders may share a template, and some templates don't belong to a particular page, but are included by other templates.

If you're a theme designer you don't really need to know how to use these, but just in case, here's how:

Templates are referred to by their relative path within the theme's "templates" directory. For instance, the template located at htdocs/theme/raw/templates/artefact/artefact.tpl would be to referred to as 'artefact/artefact.tpl'. Mahara then uses theme inheritance to decide which copy of the template it should use (see the section on inheritance below).

In PHP, this is usually as part of a call to $smarty->fetch:


In Dwoo, templates can be embedded into the current template using the {include} tag.

{include file="artefact/artefact.tpl"}

Static assets are located by a call to the $THEME->get_url() method of the global $THEME object. As with templates, they're referred to by their relative path within the theme's "static" directory. For instance the image file htdocs/mahara/theme/raw/static/images/attachment.png would be referred to as "images/attachment.png".

global $THEME;
$url = $THEME->get_url('images/attachment.png');

In Dwoo, static assets can be referenced using the {theme_url} tag, which acts as a pass-through to $THEME->get_url()

<img src="{theme_url filename="images/attachment.png"}" />

Plugin assets

Plugins can also have their own templates, stylesheets, and images, which are only used by that plugin. For instance, the "My Files" page, htdocs/artefact/file/index.php, has its own template, "index.tpl". They can also contain their own static assets, for instance the Creative Commons block contains an image of the Creative Commons logo.

The location of plugin assets is a little bit more complex. They can actually live under the htdocs/theme directory or under the plugin's own directory (e.g. artefact/file). Mahara will look for the file first under the theme directory, and if it doesn't find it there it will look for it under the plugin's directory.

For the plugins in Mahara's standard distribution (such as artefact/file and artefact/internal), the preferred location for the plugin assets is in a subdirectory under the theme itself. This should have the form htdocs/theme/{themename}/{plugintype}/{pluginname}. So for instance the file artefact's "index.tpl" file should go under htdocs/theme/{themename}/artefact/file/templates/index.tpl. And the Creative Commons block's "seal.png" image should go under htdocs/theme/{themename}/blocktype/creativecommons/static/images/seal.png

Plugins assets can also live under the plugin's own directory. This is useful if you're distributing a plugin that is not part of the standard Mahara distribution, and you want it to include its own assets. In this case, the file artefact's "index.tpl" would go at htdocs/file/artefact/theme/{themename}/templates/index.tpl, and the Creative Commons block's "seal.png" image would go at htdocs/blocktype/creativecommons/theme/{themename}/static/images/seal.png. Note that the theme name is still part of the path! This is to allow a plugin to support a different appearance in different themes right out of the box. If you don't care about that, just use "raw" as the themename (see the inheritance section below)

Plugin template files are referenced as "{plugintype}:{pluginname}:path/to/template.tpl". For instance the file artefact's index.tpl file is "artefact:file:index.tpl". With this prefix in place, they're referred to exactly the same as normal templates.

{include file='artefact:file:index.tpl'}

Plugin static assets are located using the $THEME->get_url() method's optional third parameter, which takes a plugin's relative path, in the form "{plugintype}/{pluginname}". (The 2nd parameter, which defaults to false, indicates whether to return the 1st match or all matches. In most cases it makes sense to leave it false.) In Dwoo you add a "plugin" parameter to theme_url

$THEME->get_url('seal.png', false, 'blocktype/creativecommons');
{theme_url filename="seal.png" plugin="blocktype/creativecommons"}

Note: In Mahara 1.9 and earlier, plugin assets were required to be located under the plugin's own directory, and were not looked for under the htdocs/theme directory. Also, there was no "templates" subdirectory in the path to the plugin's templates. Instead, the templates sat directly under the "{themename}" directory. For example: htdocs/artefact/file/theme/{themename}/index.tpl instead of htdocs/artefact/file/theme/templates/index.tpl. For backwards-compatibily reasons, Mahara 1.10 will still check for templates in this location as well, but it is further down the search path than the "templates" directory.

Should you put plugin assets under the plugin, or the theme?

As you have no doubt noted in the above discussion, with plugin assets you have a choice. You can place them under the plugin (htdocs/{plugintype}/{pluginname}/theme/{themename}/) or under the theme (htdocs/theme/{themename}/{plugintype}/{pluginname}/). So which should you use? It depends on what you're writing:

1. Custom theme: put assets in the theme directory.

2. 3rd party plugin: put assets in the plugin's directory

3. Code to upstream into the Mahara standard distribution: put assets in the theme directory.

Custom themes and plugins are likely to be distributed on their own, which is why it makes sense to store plugin assets under the theme's and plugin's directory respectively. A custom theme may include assets for 3rd-party plugins. If a user installs the theme and doesn't have these plugins, the assets will be quietly ignored. Likewise, a 3rd-party plugin (which should at least support the "raw" theme) may include theme directories for custom themes its users are likely to have. If the user doesn't have the theme, the directory will be politely ignored.

Code meant for upstream should place plugin assets into the theme directory because it makes it easier for theme designers if all the theme assets are in one location.

Blocks that live inside artefacts

One thing to note in all this is that blocktypes can live under artefact types. For instance, the "Tagged Journal Entries" block lives inside the "Journal" artefact, at htdocs/artefact/blog/blocktype/taggedposts.

When you store such a block's assets under the htdocs/theme directory, you should include the parent artefact in the path, like so: htdocs/theme/{themename}/artefact/blog/blocktype/taggedposts/static/images/thumb.png

Templates for these blocktypes just need to mention the blocktype name, like $smarty->fetch('blocktype:comment:comment.tpl');

Static assets for these blocktypes use a pluginpath that has the artefact name in it, like $THEME->get_url('thumb.png', false, 'artefact/blog/blocktype/taggedposts');

Export code that lives under artefacts

Artefact plugins can include an "export" subdirectory, in which they have subplugins that provides compatibility with specific export plugins. For instance htdocs/artefact/file/export/html/ contains code that supports the "html" export plugin, for the "file" artefact.

These export compatibility subplugins can have their own theme assets. If they live under the htdocs/theme directory they should go in htdocs/theme/{themename}/artefact/{artefacttype}/export/{exporttype}. If they live under the artefact's own directory they should go in htdocs/artefact/{artefacttype}/export/{exporttype}/theme/{themename}.

Artefact export subplugins are referred to in dwoo as "export:{exporttype}/{artefacttype}:path/to/template.tpl". For instance "export:html/file:summary.tpl".

Artefact export subplugins don't have any static assets, except for optional stylesheets called "style.css" and "print.css" used by the html export plugin which should be located at htdocs/artefact/{artefacttype}/export/html/theme/{themename}/static/style/. These are looked for directly by the "html" export plugin, and cannot be accessed by $THEME->get_url() or $THEME->get_path(). Unlike all other plugin assets, these stylesheets must be located under the plugin's own directory.


A theme may specify a parent theme in its themeconfig.php file. If it leaves this out, the special "Raw" theme will be its parent.

You may have noted above that Mahara always refers to assets by their relative path, i.e. "view/view.tpl" and "images/site-logo.png". This is in order to support inheritance. When Mahara requests one of these assets it checks for it first in the user's current theme. If that theme doesn't have it, it checks for it under the parent theme, and then that parent's theme, and so on, all the way down to the "Raw" theme.

This allows theme authors to customize as much or as little of a theme as they want. For example, if you want a theme that looks exactly the same as the "primaryschool" theme, but with a different dashboard image, you can create a new theme that contains only a copy of "images/home-info-bkgd.png" and no other assets.

In the case of stylesheets, both the parent and child stylesheets will be served up (in that order, so the child will override the parent). Also, specific pages can require their own additional stylesheets, and in these cases the additional stylesheets from both the parent and child are served.

For example, the artefact/file plugin has its own extra stylesheets. If a user's theme is "Default", which has a parent theme of "Raw", then the user will retrieve the following stylesheets on the My Files page:


This gives us lots of flexibility but unfortunately browsers can end up doing a lot of stylesheet requests this way.

Of the pre-installed themes, the "Raw" theme is special and is used as the parent theme by all the others. Because of this, we have been able to keep the majority of the layout in the Raw theme css, and the other themes' stylesheets are much smaller because they mostly just override colours.

The child themes are a good place to look when getting started with a new theme.

We recommend using "Default" or "Raw" as a parent for all new themes.

Local theme overrides

You can also place theme assets in your /local directory, and they will be placed at the front of the asset search path. They should go under htdocs/local/theme/templates/ and htdocs/local/theme/static. You can place templates, static assets, and plugin assets in these directories. For example:


(You can also place assets here that are completely new and not referred to in any of your themes, in order to support ad-hoc hacks to your system.)

Note that the theme name is not part of the path. That's because the /local directory currently only supports one override for all themes. If you want to customize particular themes in particular ways, you're probably better off making a custom theme that uses the other theme as its parent.

Theme lang strings

Themes can include their own lang strings, to allow text used in a theme to be translatable. One prime use for this is the "homeinfo.tpl" file.


If I wanted to put some translatable text in "homeinfo.tpl" as part of a theme called mytheme.

1. Create a theme file at htdocs/theme/mytheme/lang/en.utf8/theme.mytheme.php


defined ('INTERNAL') || die();

$string['dashboardtext'] = 'Mahara rocks!';

2. You can then use the lang string in homeinfo.tpl with this Dwoo tag:

{str tag='dashboardtext' section='theme.mytheme'}

3. If your theme is translated into other languages, include them in other language directories alongside en.utf8.