Creating your own Phorum template
=================================

This documents describes how to create your own template for
Phorum. The document is not conclusive, but there should be
enough information in here to get you started.

In this document, {phorum dir} is the location where you installed
the Phorum software.


Table of contents:

1. General information on Phorum templates
   1.1 Template directory structure
   1.2 How Phorum handles templates
   1.3 Starting your own template
2. The Phorum template language
   2.1 Introduction
   2.2 General syntax
   2.3 Need the power of PHP?
   2.4 Data types
       2.4.1 Integers
       2.4.2 Strings
       2.4.3 PHP constants
       2.4.4 Template variables
   2.5 Statements
       2.5.1 Display a value
       2.5.2 Add comments
       2.5.3 DEFINE
       2.5.4 VAR
       2.5.5 IF .. ELSEIF .. ELSE
       2.5.6 LOOP
       2.5.7 INCLUDE
       2.5.8 HOOK


1. General information on Phorum templates
-------------------------------------------------------------------------------


 1.1 Template directory structure
 --------------------------------

 TODO: About templates/<template name> and the important files within
 TODO: the template directory.


 1.2 How Phorum handles templates
 --------------------------------

 TODO: About automatic compilation, cache dir, automatic recompilation,
 TODO: .tpl files vs. .php files.


 1.3 Starting your own template
 ------------------------------

   Here are the steps that you have to take to create your own template:

   1) Take the default template directory from {phorum dir}/templates/default
      and copy it over to another directory, for example
      {phorum dir}/templates/mytemplate.

   2) Edit {phorum dir}/templates/mytemplate/info.php. In this file you
      have to edit at least the $name variable, e.g. to
      $name = "My very own template";

      You can hide the template from the user's template selection box
      by setting $template_hide = 1. If you do this, you can only
      select this template through the admin interface (this makes
      most sense if you set the display-settings to fixed through
      the admin interface).

   3) Open Phorum's admin page {phorum url}/admin.php and go to
      "General Settings". There you'll find the option "Default Template".
      Set that option to your own template. You also have to configure the
      template in the settings of each single forum.


   That's it. You are now using your own template. From here on you can start
   tweaking the template files in your {phorum dir}/templates/mytemplate
   directory. Phorum uses its own template language to allow for dynamic
   templates without using PHP. More information on this can be found in
   chapter 2.

   For most installations, the following template files will be most
   interesting:

   - header.tpl     The header which will be added before each page;
   - footer.tpl     The footer which will be added after each page;
   - settings.tpl   Here you can change colors and fonts;
   - css.tpl        This file holds all CSS definitions for Phorum.


2. The Phorum template language
-------------------------------------------------------------------------------


 2.1 Introduction
 ----------------

   The largest part of the code in the Phorum templates is plain HTML. To
   be able to use and display the dynamic data that has been generated by
   Phorum (like message information, lists of private messages and search
   results), Phorum uses a custom template language which can be used to
   mix the HTML code with dynamic data. The template language is a very
   simple programming language with only a few statements to use. You can
   find a description of the language in chapter 2.2.


 2.2 General syntax
 ------------------

   Templates are built using HTML (and possibly PHP) code. Embedded in
   this HTML code, there can be template language statements. All template
   statements in the templates are surrounded by "{" and "}" characters.
   Here's a simple example of what a template could look like:

      <html>
       <head>
        <title>{HTML_TITLE}</title>
       </head>
       <body>
        Your username is: {USER->username}

        {IF USER->username "george"}
          <b>Hello, George!</b>
        {/IF}
       </body>
      </html>


 2.3 Need the power of PHP?
 --------------------------

   Template writers for whom the template language is too limited can break
   into PHP at any point in the templates, using the regular <?php ... ?>
   syntax. Using the Phorum template language is not mandatory at all.

   The biggest drawback here, is that more knowledge of the Phorum
   internals is required. Most template writers will normally only be using
   HTML and the Phorum template language.

   Important:
   ----------
   To prevent confusion between PHP code blocks and template statements
   (which are both surrounded by "{" and "}" characters), always use a
   whitespace after an opening "{" character in your PHP code. So instead
   of writing:

      <?php if ($this = true) {print "It's true";} ?>

   you now have to write:

      <?php if ($this = true) { print "It's true"; } ?>

   This way you can mix PHP code with template code without running
   into problems.


 2.4 Data types
 --------------

   The template language supports four data types to use in statements:

   - Integers (see 2.4.1)
   - Strings (see 2.4.2)
   - PHP constants (see 2.4.3)
   - Template variables  (see 2.4.4)


  2.4.1 Integers
  --------------

   Integers are formatted as a sequence of numbers. Examples:

      403
      90
      4321

   Example of template code in which integers are used:

      {VAR INTEGERVAR 1000}
      The variable INTEGERVAR is {INTEGERVAR}.

      {IF INTEGERVAR 333}
         The INTEGERVAR has the value 333.
      {/IF}


  2.4.2 Strings
  -------------

   Strings are sequences of characters within quotes (both double and
   single quotes can be used). Examples:

      "this is a string value"
      "My 1st string!"
      'Single quoted string is possible too'

   Now if you need the quote which you used to surround the string with
   inside the string itself, you must escape it using \" or \'. This is
   consistent with the way that PHP strings are escaped. Examples:

      "this is a \"string\" value"
      'Single quoted \'string\' value'
      "You can use both \" and ' for strings!"

   Example of template code in which strings are used:

      {VAR QUESTION "Do you know what \"fubar\" means?"}
      {VAR CORRECT "That was the right answer!"}
      {VAR INCORRECT "No.. you were wrong!"}

      {IF ANSWER 'Fucked Up Beyond All Recognition'}
        {CORRECT}
      {ELSE}
        {INCORRECT}
      {/IF}


  2.4.3 PHP constants
  -------------------

   It's possible to define constants within PHP. This is done using
   the following type of code:

      <?php define("MY_CONSTANT", "The constant value") ?>

   You can reference a PHP constant from the template language by using
   its name, without any quotes. So the constant that was defined in the
   code above, can be used like this:

      The value of MY_CONSTANT is {MY_CONSTANT}

   Apart from defining your own PHP constants, you can also use constants
   that are already defined by PHP. Two useful constants to use are
   "true" (constant value 1) and "false" (constant value 0). Using these,
   you can write template code like this:

      {VAR SOME_OPTION true}
      {IF SOME_OPTION true}
         The options SOME_OPTION is true.
      {/IF}


  2.4.4 Template variables
  ------------------------

   About the most important data type for the template language is the
   template variable. Template variables are used by Phorum to store
   dynamic data, which can be used by your templates. These variables
   can contain both simple values and complex arrays of data.

   You can reference a template variable by using the variable's name,
   without any quotes. Note that this is the same notation that is used
   for referencing PHP constants (see 2.4.3). If there are both a constant
   and a variable with the same name, the value of the contstant will
   take precedence over the template variable.

   Examples of variables:

      NAME
      HTML_TITLE

   In case the variable is an array, you can reference array elements by
   using the following pointer notation:

      ARRAYVARIABLE->SIMPLE_ELEMENT
      ARRAYVARIABLE->ARRAY_ELEMENT->SIMPLE_ELEMENT

   Within a template, the variables are used like this:

      You username is: {USER->username}<br />
      The current forum's name is: {NAME}<br />

      {LOOP MESSAGES}
        Subject: {MESSAGES->subject}<br />
      {/LOOP}

   What variables are available for what pages is fully determined by Phorum.


 2.5 Statements
 --------------


  2.5.1 Display a value
  ---------------------

   Function:
      This is both the most simple and the most important template
      statement there is. Using this statement, you can display the
      contents of a value.

   Syntax:
      {<VALUE>}

      The <VALUE> can be any of the data types that are supported by the
      template language (see 2.4). Of course, only the use of constants or
      template variables is useful (because in a template {"SOME STRING"} is
      equivalent to simply putting SOME STRING directly in the code).

   Example:
      The name of the current forum is: {NAME}


  2.5.2 Add comments
  ------------------

   Function:
      Sometimes, it's useful to explain what you are doing when writing
      complicated templating code. In that case you can use comments to
      document what you are doing. You can also use comments to add
      general info to the template (like in the example below).

   Syntax:
      {! <COMMENT TEXT>}

      The <COMMENT TEXT> can contain any characters you like, except for "}".

   Example:
      {! This template was created by John Doe and his lovely wife Jane }


  2.5.3 DEFINE
  ------------

   Function:
      Using this statement, you can set variable definitions that can be used
      by the Phorum software. These are mainly used for doing settings from
      the template file "settings.tpl" to tweak Phorum's internal behaviour.

      Variables that have been defined using this statement are not available
      from other template statements.

   Syntax:
      {DEFINE <PHORUM VARIABLE> <VALUE>}

      What you can use for <PHORUM VARIABLE> is fully determined by the
      Phorum software (and possibly modules). The <VALUE> can be any of
      the data types that are supported by the template language (see 2.4).

   Example:
      {DEFINE list_pages_shown 5}


  2.5.4 VAR
  ---------

   Function:
      Using this statement, you can set variable definitions that can
      be used by the Phorum template language.

   Syntax:
      {VAR <TEMPLATE VARIABLE> <VALUE>}

      <TEMPLATE VARIABLE> can be an existing or a new variable name
      (see 2.4.4). The <VALUE> can be any of the data types that
      are supported by the template language (see 2.4).

   Examples:
      {VAR MY_VAR "This is my first variable!"}
      {VAR MY_VAR OTHER_VAR}
      {VAR MY_VAR 1234}

      {VAR IS_COOL true}
      {IF IS_COOL}Yes, this is cool{/IF}


  2.5.5 IF .. ELSEIF .. ELSE
  --------------------------

   Function:
      Using these statements, you can control if certain blocks of code in
      your template are processed or not, based on a given condition. This can for
      example be useful if you want certain parts of the page to be only
      visible for registered users.

   Syntax:
      {IF <CONDITION>}
         .. conditional code ..
      [{ELSEIF <CONDITION>}
         .. conditional code ..]
      [{ELSE}
         .. conditional code ..]
      {/IF}

      <CONDITION> Syntax: [NOT] <TEMPLATE VARIABLE> [<VALUE>]

      The <TEMPLATE VARIABLE> in a <CONDITION> has to be an existing
      variable name. The <VALUE> that is used in the CONDITION can be any
      of the data types that are supported by the template language
      (see 2.4).

      If a <VALUE> is used, the <TEMPLATE VARIABLE> will be compared to the
      <VALUE>. If no <VALUE> is used, then the condition will check whether
      the <TEMPLATE VARIABLE> is set and contains data.

      A condition can be negated by prepending the keyword "NOT" to it.

      Multiple conditions can be chained using the keywords AND or OR.

   Examples:
      {IF NOT LOGGEDIN}
         You are currently not logged in.
      {ELSEIF USER->username "John"}
         Hey, it's good to see you again, mr. John!
      {ELSE}
         Welcome, {USER->username}!
      {/IF}

      {IF ADMINISTRATOR true OR USER->username "John"}
         You are either an administrator or John.
      {/IF}

      {IF VARIABLE1 VARIABLE2}
         Variable 1 and 2 have the same value.
      {/IF}


  2.5.6 LOOP
  ----------

   Function:
      The LOOP statement is used for looping through the elements of array
      based template variables (for example arrays of forums, messages and
      users).

   Syntax:
      {LOOP <ARRAY VARIABLE>}
         {<ARRAY VARIABLE>}
      {/LOOP <ARRAY VARIABLE>}

   Example:
      <ul>
      {LOOP USERS}
        <li> {USERS->username} </li>
      {/LOOP}
      </ul>


   Within a LOOP, the active element is assigned to a variable that
   has the same name as the <ARRAY VARIABLE> that you are looping over. In
   our example, we are looping over USERS, which is an array of user data
   records. Within the loop, USERS is no long the array of users itself, but
   the user data record for a single user instead.


  2.5.7 INCLUDE
  -------------

   Function:
      Include another template in the template.

   Syntax:
      {INCLUDE [ONCE] <INCLUDE PAGE>}

      The <INCLUDE PAGE> that is used in the INCLUDE statement can be
      any of the data types that are supported by the template language
      (see 2.4).

      By specifiying the keyword ONCE before the template to include,
      you can make sure that that template is only included once per page.

   Examples:
      {INCLUDE "paging"}
      {INCLUDE include_page} (using a variable)
      {INCLUDE ONCE "css"}

   Limitation:
      It is not possible to use a dynamic INCLUDE statement (one where the
      <INCLUDE PAGE> is set through a template variable) within a LOOP
      statement, if the included template needs to access the active
      LOOP element. There is no problem if you use a static INCLUDE
      statement (one where the <INCLUDE PAGE> is set through a string value).

      If you really need this kind of functionality, you can work easily
      around it by assigning the active LOOP element to a new template
      variable, prior to including the dynamic <INCLUDE PAGE>. Example:

      {! include_page holds the dynamic page to include }
      {VAR include_page "some_page"}

      {LOOP loop_variable}
        {! Makes loop_variable available as temp_variable in the include }
        {VAR temp_variable loop_variable}
        {INCLUDE include_page}
      {/LOOP}

      This way you can access the active LOOP element from the included
      template through temp_variable. If you would access loop_variable
      from there, you'd see that it does not contain the active LOOP element,
      but the full array that you are looping over instead.


  2.5.8 HOOK
  ----------

   Function:
      The HOOK statement can be used to run a module hook from a template.
      By using hooks in the templates, you have an easy way for modules to
      add data to a page, without having to change the templates too much.
      Because these hooks need an activated module that acts upon them,
      creating HOOK statements is certainly for advanced users only.

   Syntax:
      {HOOK <HOOK NAME> [<ARG1> <ARG2> .. <ARGn>]}

      Both the <HOOK NAME> and the arguments that are used in the HOOK
      statement can be any of the data types that are supported by the
      template language (see 2.4).

   Examples:
      {HOOK "template_hook"}

      {LOOP MESSAGES}
        {HOOK "show_message" MESSAGES}
      {/LOOP}

      {VAR HOOKNAME "my_magic_hook"}
      {HOOK HOOKNAME "my argument"}


   Depending on the number or arguments that are used in the HOOK statement,
   different type of calls are made to the hook function for the given
   <HOOK NAME>:

   * no arguments: the hook function is called without arguments at all:
     hook_function()

   * one argument: the argument is used directly for the hook function:
     hook_function($ARG)

   * multiple arguments: the arguments are passed in an array:
     hook_function(array($ARG1, $ARG2, .. $ARGn));

   Phorum does have a couple of template hooks defined in the default
   template. Please read {phorum dir}/docs/creating_mods.txt for more
   information on these default template hooks and on modules in general.



TODO:
This should go into a separate chapter that describes template
variables and define statements that can be used in the templates.

Additional variables in settings.tpl:
{define bodies_in_list 1}
set this to 1 to have the message-bodies loaded in the list if your
template needs them.

{define all_bodies_in_threaded_read 0}
set this to 1 to have all the message-bodies also loaded in
threaded-read-view if your template needs them
