<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://gwiki3.thatlinuxbox.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tom</id>
		<title>GeeklogWiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://gwiki3.thatlinuxbox.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tom"/>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/Special:Contributions/Tom"/>
		<updated>2026-04-06T04:57:28Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.5</generator>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6643</id>
		<title>Installing Geeklog:System Requirements</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6643"/>
				<updated>2022-09-27T17:22:56Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Installation - System Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation - System Requirements ==&lt;br /&gt;
&lt;br /&gt;
The system requirements for installing Geeklog v2.2.2 (the last time the requirements changed) and later are as follows:&lt;br /&gt;
&lt;br /&gt;
# Web server - one of the following&lt;br /&gt;
## Apache Web Server&lt;br /&gt;
## Microsoft IIS (Internet Information Server)&lt;br /&gt;
# PHP v5.6.4 or higher (including PHP v8.1) with the following extensions&lt;br /&gt;
## mbstring Extension&lt;br /&gt;
## bzip2 Extension&lt;br /&gt;
## mysql or mysqli Extension (To enable MySQL support)&lt;br /&gt;
## pgsql Extension (To enable Postgresql support)&lt;br /&gt;
## OpenSSL Extension (To enable the Geeklog OAuth Login process)&lt;br /&gt;
## JSON Extension (For Filemanager and Database tools)&lt;br /&gt;
## fileinfo (To enable thumbnail creation of images in articles) (for IIS only as fileinfo is integrated into Apache)&lt;br /&gt;
## cURL (Not required but recommended for the reCaptcha plugin)&lt;br /&gt;
# Database server - one of the following&lt;br /&gt;
## MySQL 4.1.3 or higher (MySQL 5 recommended)&lt;br /&gt;
## Postgresql 9.1.7 or later&lt;br /&gt;
# The ability to create a new database or to have access to an existing one&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6642</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6642"/>
				<updated>2022-09-27T17:22:16Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Logo.gif]]&lt;br /&gt;
&lt;br /&gt;
== Geeklog Documentation ==&lt;br /&gt;
&lt;br /&gt;
This is the main entry for Documentation for the [https://www.geeklog.net/ Geeklog] Content Management System (CMS).  The current version is v2.2.2. For more information about this version please read [https://www.geeklog.net/article.php/geeklog-v2-2-2 this announcement article].&lt;br /&gt;
&lt;br /&gt;
If you are upgrading from Geeklog v2.1.3 or older please make sure your 3rd party Geeklog plugins are updated to the latest version and support at least Geeklog v2.2.0. Plugins are now required to use the function COM_createHTMLDocument. This replaces the depreciated functions COM_siteHeader and COM_siteFooter. If you are unsure if a plugin supports Geeklog v2.2.0 then either disable it before you upgrade Geeklog, or uninstall it.&lt;br /&gt;
&lt;br /&gt;
Also, there have been some changes with blocks and topics between Geeklog 2.0.0 and 1.8.2sr1 so not all plugins may work with 2.1.0 or higher unless they have been updated. If you are upgrading your site that is 2.0.0 or older make sure all the plugins you use are compatible with Geeklog 2.1.0 or higher.&lt;br /&gt;
&lt;br /&gt;
This documentation is a result of community action.  Everyone is invited to [http://wiki.geeklog.net/wiki/index.php?title=Special:Userlogin sign up] and participate.  If you see an omission you can fill it in.  If you see a mistake, correct it.  If you see where things could be better organized, change it.  If you have a note about a particular configuration, add it.  In other words: We need your help to make it better!&lt;br /&gt;
&lt;br /&gt;
* [[Geeklog Documentation]]:&lt;br /&gt;
*# [[Introduction]]&lt;br /&gt;
*# [[Installation]]&lt;br /&gt;
*# [[Administration]]&lt;br /&gt;
*# [[Users Documentation|User's Documentation]]&lt;br /&gt;
*# [[Programmers/Developers Documentation]]&lt;br /&gt;
* Quick Links:&lt;br /&gt;
*# [[Complete Table of Contents]]&lt;br /&gt;
*# [[Special:AllPages|List of all Articles]]&lt;br /&gt;
*# [[Getting Started]] with Geeklog Development&lt;br /&gt;
*# [[Google Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6641</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6641"/>
				<updated>2022-01-13T15:22:47Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* PHP Code in a Template Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments. If you want these comments to appear in the cache and the HTML source of the page you can in the Geeklog Configuration enable &amp;quot;Template Comments in Output&amp;quot;. See example 3 to see how to use a comment.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
    {!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
    myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
   {!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 5 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. Remember you need to be very careful when using PHP and selecting variable names for variables you create in your code. Make sure they are unique as variables can unintentionally be overwritten if they are for example global in scope and/or are local in scope but are being used in the Geeklog function already that will be evaluating your PHP code.&lt;br /&gt;
&lt;br /&gt;
To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6640</id>
		<title>Installing Geeklog:System Requirements</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6640"/>
				<updated>2020-04-19T21:50:36Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Installation - System Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation - System Requirements ==&lt;br /&gt;
&lt;br /&gt;
The system requirements for installing Geeklog v2.2.1 (the last time the requirements changed) and later are as follows:&lt;br /&gt;
&lt;br /&gt;
# Web server - one of the following&lt;br /&gt;
## Apache Web Server&lt;br /&gt;
## Microsoft IIS (Internet Information Server)&lt;br /&gt;
# PHP v5.6.4 or higher (including PHP v7) with the following extensions&lt;br /&gt;
## mbstring Extension&lt;br /&gt;
## bzip2 Extension&lt;br /&gt;
## mysql or mysqli Extension (To enable MySQL support)&lt;br /&gt;
## pgsql Extension (To enable Postgresql support)&lt;br /&gt;
## OpenSSL Extension (To enable the Geeklog OAuth Login process)&lt;br /&gt;
## JSON Extension (For Filemanager and Database tools)&lt;br /&gt;
## fileinfo (To enable thumbnail creation of images in articles) (for IIS only as fileinfo is integrated into Apache)&lt;br /&gt;
## cURL (Not required but recommended for the reCaptcha plugin)&lt;br /&gt;
# Database server - one of the following&lt;br /&gt;
## MySQL 4.1.3 or higher (MySQL 5 recommended)&lt;br /&gt;
## Postgresql 9.1.7 or later&lt;br /&gt;
# The ability to create a new database or to have access to an existing one&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6639</id>
		<title>Installing Geeklog:System Requirements</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6639"/>
				<updated>2020-04-19T21:50:25Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Installation - System Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation - System Requirements ==&lt;br /&gt;
&lt;br /&gt;
The system requirements for installing Geeklog v2.2.1 (the last time the requirements changed) and later are as follows:&lt;br /&gt;
&lt;br /&gt;
# Web server - one of the following&lt;br /&gt;
## Apache Web Server&lt;br /&gt;
## Microsoft IIS (Internet Information Server)&lt;br /&gt;
# PHP v5.6.4 or higher (including PHP 7) with the following extensions&lt;br /&gt;
## mbstring Extension&lt;br /&gt;
## bzip2 Extension&lt;br /&gt;
## mysql or mysqli Extension (To enable MySQL support)&lt;br /&gt;
## pgsql Extension (To enable Postgresql support)&lt;br /&gt;
## OpenSSL Extension (To enable the Geeklog OAuth Login process)&lt;br /&gt;
## JSON Extension (For Filemanager and Database tools)&lt;br /&gt;
## fileinfo (To enable thumbnail creation of images in articles) (for IIS only as fileinfo is integrated into Apache)&lt;br /&gt;
## cURL (Not required but recommended for the reCaptcha plugin)&lt;br /&gt;
# Database server - one of the following&lt;br /&gt;
## MySQL 4.1.3 or higher (MySQL 5 recommended)&lt;br /&gt;
## Postgresql 9.1.7 or later&lt;br /&gt;
# The ability to create a new database or to have access to an existing one&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6638</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6638"/>
				<updated>2020-04-19T21:49:18Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Logo.gif]]&lt;br /&gt;
&lt;br /&gt;
== Geeklog Documentation ==&lt;br /&gt;
&lt;br /&gt;
This is the main entry for Documentation for the [https://www.geeklog.net/ Geeklog] Content Management System (CMS).  The current version is v2.2.1sr1. For more information about this version please read [https://www.geeklog.net/article.php/geeklog-v2-2-1sr1 this announcement article].&lt;br /&gt;
&lt;br /&gt;
If you are upgrading from Geeklog v2.1.3 or older please make sure your 3rd party Geeklog plugins are updated to the latest version and support at least Geeklog v2.2.0. Plugins are now required to use the function COM_createHTMLDocument. This replaces the depreciated functions COM_siteHeader and COM_siteFooter. If you are unsure if a plugin supports Geeklog v2.2.0 then either disable it before you upgrade Geeklog, or uninstall it.&lt;br /&gt;
&lt;br /&gt;
Also, there have been some changes with blocks and topics between Geeklog 2.0.0 and 1.8.2sr1 so not all plugins may work with 2.1.0 or higher unless they have been updated. If you are upgrading your site that is 2.0.0 or older make sure all the plugins you use are compatible with Geeklog 2.1.0 or higher.&lt;br /&gt;
&lt;br /&gt;
This documentation is a result of community action.  Everyone is invited to [http://wiki.geeklog.net/wiki/index.php?title=Special:Userlogin sign up] and participate.  If you see an omission you can fill it in.  If you see a mistake, correct it.  If you see where things could be better organized, change it.  If you have a note about a particular configuration, add it.  In other words: We need your help to make it better!&lt;br /&gt;
&lt;br /&gt;
* [[Geeklog Documentation]]:&lt;br /&gt;
*# [[Introduction]]&lt;br /&gt;
*# [[Installation]]&lt;br /&gt;
*# [[Administration]]&lt;br /&gt;
*# [[Users Documentation|User's Documentation]]&lt;br /&gt;
*# [[Programmers/Developers Documentation]]&lt;br /&gt;
* Quick Links:&lt;br /&gt;
*# [[Complete Table of Contents]]&lt;br /&gt;
*# [[Special:AllPages|List of all Articles]]&lt;br /&gt;
*# [[Getting Started]] with Geeklog Development&lt;br /&gt;
*# [[Google Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6637</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6637"/>
				<updated>2020-04-16T15:07:36Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Sites */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history, install.html, changes.html, themevars.html files in docs (both English and Japanese) with the latest info about the version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository. Note: no old compressed install packages will note be rolled into the new package.&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** '''IMPORTANT:''' Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the Downloads plugin&lt;br /&gt;
** In Downloads plugin, move any releases not current to Geeklog-&amp;gt;Old Versions (like previous version of Geeklog or older betas and RCs). Need to clear cache after so block updates.&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net as users cannot change themes.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* The demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6636</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6636"/>
				<updated>2020-04-16T13:31:44Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history, install.html, changes.html, themevars.html files in docs (both English and Japanese) with the latest info about the version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository. Note: no old compressed install packages will note be rolled into the new package.&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** '''IMPORTANT:''' Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the Downloads plugin&lt;br /&gt;
** In Downloads plugin, move any releases not current to Geeklog-&amp;gt;Old Versions (like previous version of Geeklog or older betas and RCs). Need to clear cache after so block updates.&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net as users cannot change themes.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6635</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6635"/>
				<updated>2020-02-27T12:00:29Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Updating geeklog.net */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository. Note: no old compressed install packages will note be rolled into the new package.&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** '''IMPORTANT:''' Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the Downloads plugin&lt;br /&gt;
** In Downloads plugin, move any releases not current to Geeklog-&amp;gt;Old Versions (like previous version of Geeklog or older betas and RCs). Need to clear cache after so block updates.&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net as users cannot change themes.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6634</id>
		<title>Installing Geeklog:System Requirements</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6634"/>
				<updated>2020-02-27T11:59:13Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Installation - System Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation - System Requirements ==&lt;br /&gt;
&lt;br /&gt;
The system requirements for installing Geeklog v2.2.1 (the last time the requirements changed) and later are as follows:&lt;br /&gt;
&lt;br /&gt;
# Web server - one of the following&lt;br /&gt;
## Apache Web Server&lt;br /&gt;
## Microsoft IIS (Internet Information Server)&lt;br /&gt;
# PHP 5.6.4 or higher with the following extensions&lt;br /&gt;
## mbstring Extension&lt;br /&gt;
## bzip2 Extension&lt;br /&gt;
## mysql or mysqli Extension (To enable MySQL support)&lt;br /&gt;
## pgsql Extension (To enable Postgresql support)&lt;br /&gt;
## OpenSSL Extension (To enable the Geeklog OAuth Login process)&lt;br /&gt;
## JSON Extension (For Filemanager and Database tools)&lt;br /&gt;
## fileinfo (To enable thumbnail creation of images in articles) (for IIS only as fileinfo is integrated into Apache)&lt;br /&gt;
## cURL (Not required but recommended for the reCaptcha plugin)&lt;br /&gt;
# Database server - one of the following&lt;br /&gt;
## MySQL 4.1.3 or higher (MySQL 5 recommended)&lt;br /&gt;
## Postgresql 9.1.7 or later&lt;br /&gt;
# The ability to create a new database or to have access to an existing one&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6633</id>
		<title>Installing Geeklog:System Requirements</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6633"/>
				<updated>2020-02-27T11:57:37Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Installation - System Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation - System Requirements ==&lt;br /&gt;
&lt;br /&gt;
The system requirements for installing Geeklog 2.2.1 and later are as follows:&lt;br /&gt;
&lt;br /&gt;
# Web server - one of the following&lt;br /&gt;
## Apache Web Server&lt;br /&gt;
## Microsoft IIS (Internet Information Server)&lt;br /&gt;
# PHP 5.6.4 or higher with the following extensions&lt;br /&gt;
## mbstring Extension&lt;br /&gt;
## bzip2 Extension&lt;br /&gt;
## mysql or mysqli Extension (To enable MySQL support)&lt;br /&gt;
## pgsql Extension (To enable Postgresql support)&lt;br /&gt;
## OpenSSL Extension (To enable the Geeklog OAuth Login process)&lt;br /&gt;
## JSON Extension (For Filemanager and Database tools)&lt;br /&gt;
## fileinfo (To enable thumbnail creation of images in articles) (for IIS only as fileinfo is integrated into Apache)&lt;br /&gt;
## cURL (Not required but recommended for the reCaptcha plugin)&lt;br /&gt;
# Database server - one of the following&lt;br /&gt;
## MySQL 4.1.3 or higher (MySQL 5 recommended)&lt;br /&gt;
## Postgresql 9.1.7 or later&lt;br /&gt;
# The ability to create a new database or to have access to an existing one&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6632</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6632"/>
				<updated>2020-02-27T11:56:05Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Logo.gif]]&lt;br /&gt;
&lt;br /&gt;
== Geeklog Documentation ==&lt;br /&gt;
&lt;br /&gt;
This is the main entry for Documentation for the [https://www.geeklog.net/ Geeklog] Content Management System (CMS).  The current version is v2.2.1. For more information about this version please read [https://www.geeklog.net/article.php/geeklog-v2-2-1 this announcement article].&lt;br /&gt;
&lt;br /&gt;
If you are upgrading from Geeklog v2.1.3 or older please make sure your 3rd party Geeklog plugins are updated to the latest version and support at least Geeklog v2.2.0. Plugins are now required to use the function COM_createHTMLDocument. This replaces the depreciated functions COM_siteHeader and COM_siteFooter. If you are unsure if a plugin supports Geeklog v2.2.0 then either disable it before you upgrade Geeklog, or uninstall it.&lt;br /&gt;
&lt;br /&gt;
Also, there have been some changes with blocks and topics between Geeklog 2.0.0 and 1.8.2sr1 so not all plugins may work with 2.1.0 or higher unless they have been updated. If you are upgrading your site that is 2.0.0 or older make sure all the plugins you use are compatible with Geeklog 2.1.0 or higher.&lt;br /&gt;
&lt;br /&gt;
This documentation is a result of community action.  Everyone is invited to [http://wiki.geeklog.net/wiki/index.php?title=Special:Userlogin sign up] and participate.  If you see an omission you can fill it in.  If you see a mistake, correct it.  If you see where things could be better organized, change it.  If you have a note about a particular configuration, add it.  In other words: We need your help to make it better!&lt;br /&gt;
&lt;br /&gt;
* [[Geeklog Documentation]]:&lt;br /&gt;
*# [[Introduction]]&lt;br /&gt;
*# [[Installation]]&lt;br /&gt;
*# [[Administration]]&lt;br /&gt;
*# [[Users Documentation|User's Documentation]]&lt;br /&gt;
*# [[Programmers/Developers Documentation]]&lt;br /&gt;
* Quick Links:&lt;br /&gt;
*# [[Complete Table of Contents]]&lt;br /&gt;
*# [[Special:AllPages|List of all Articles]]&lt;br /&gt;
*# [[Getting Started]] with Geeklog Development&lt;br /&gt;
*# [[Google Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6631</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6631"/>
				<updated>2019-12-18T15:23:50Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository. Note: no old compressed install packages will note be rolled into the new package.&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** '''IMPORTANT:''' Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the Downloads plugin&lt;br /&gt;
** In Downloads plugin, move any releases not current to Geeklog-&amp;gt;Old Versions (like previous version of Geeklog or older betas and RCs). Need to clear cache after so block updates.&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6630</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6630"/>
				<updated>2019-11-15T17:33:17Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** '''IMPORTANT:''' Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the Downloads plugin&lt;br /&gt;
** In Downloads plugin, move any releases not current to Geeklog-&amp;gt;Old Versions (like previous version of Geeklog or older betas and RCs). Need to clear cache after so block updates.&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6629</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6629"/>
				<updated>2019-11-15T16:47:29Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** '''IMPORTANT:''' Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6628</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6628"/>
				<updated>2019-11-15T16:47:14Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Updating geeklog.net */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6627</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6627"/>
				<updated>2019-11-15T16:44:14Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6626</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6626"/>
				<updated>2019-11-15T16:43:35Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
*** Make sure to tag the release after you have committed the change-files file into the repository as we want these changes included as part of the version (for actual releases not betas)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=New_Installation&amp;diff=6625</id>
		<title>New Installation</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=New_Installation&amp;diff=6625"/>
				<updated>2019-11-12T11:55:40Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Folder/File Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Folder/File Setup ==&lt;br /&gt;
* First [https://www.geeklog.net/downloads/index.php?cid=8 download] the latest Geeklog version&lt;br /&gt;
* Download the tarball into any directory.&lt;br /&gt;
* move the file to your webroot&lt;br /&gt;
&amp;lt;pre&amp;gt;tar -zxvf geeklog*.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Change into the Geeklog directory &lt;br /&gt;
&amp;lt;pre&amp;gt;cd geeklog-1.*&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Copy all files to your primary directory with &lt;br /&gt;
&amp;lt;pre&amp;gt;cp -Rf * /home/username/public_html&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Change the access rights in the directories:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown -R webuser:webuser *&lt;br /&gt;
chmod -R 755 logs&lt;br /&gt;
chmod -R 755 backups&lt;br /&gt;
chmod -R 755 data&lt;br /&gt;
chmod -R 755 public_html/backend&lt;br /&gt;
chmod -R 755 public_html/images/articles&lt;br /&gt;
chmod -R 755 pulic_html/images/topics&lt;br /&gt;
chmod -R 755 public_html/images/userphotos/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Database ==&lt;br /&gt;
&lt;br /&gt;
* Create your MySQL database, MySQL account, grant privileges to MySQL account.&lt;br /&gt;
* As root create the MySQL database and access rights:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mysql -u root&lt;br /&gt;
mysql&amp;gt; create database geeklog_db;&lt;br /&gt;
mysql&amp;gt;grant all on geeklog.* to geeklog@localhost identified by 'yourgeeklogpassword';&lt;br /&gt;
mysql&amp;gt;quit&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install ==&lt;br /&gt;
&lt;br /&gt;
* run www.yourdomain.foo/admin/install/index.php&lt;br /&gt;
* follow the instructions&lt;br /&gt;
* login to your page using default Admin/password&lt;br /&gt;
* change password&lt;br /&gt;
* remove directory public_html/admin/install&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=New_Installation&amp;diff=6624</id>
		<title>New Installation</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=New_Installation&amp;diff=6624"/>
				<updated>2019-11-12T11:55:27Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Folder/File Setup ==&lt;br /&gt;
* First [https://www.geeklog.net/downloads/index.php?cid=88 download] the latest Geeklog version&lt;br /&gt;
* Download the tarball into any directory.&lt;br /&gt;
* move the file to your webroot&lt;br /&gt;
&amp;lt;pre&amp;gt;tar -zxvf geeklog*.tar.gz&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Change into the Geeklog directory &lt;br /&gt;
&amp;lt;pre&amp;gt;cd geeklog-1.*&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Copy all files to your primary directory with &lt;br /&gt;
&amp;lt;pre&amp;gt;cp -Rf * /home/username/public_html&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Change the access rights in the directories:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chown -R webuser:webuser *&lt;br /&gt;
chmod -R 755 logs&lt;br /&gt;
chmod -R 755 backups&lt;br /&gt;
chmod -R 755 data&lt;br /&gt;
chmod -R 755 public_html/backend&lt;br /&gt;
chmod -R 755 public_html/images/articles&lt;br /&gt;
chmod -R 755 pulic_html/images/topics&lt;br /&gt;
chmod -R 755 public_html/images/userphotos/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Database ==&lt;br /&gt;
&lt;br /&gt;
* Create your MySQL database, MySQL account, grant privileges to MySQL account.&lt;br /&gt;
* As root create the MySQL database and access rights:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mysql -u root&lt;br /&gt;
mysql&amp;gt; create database geeklog_db;&lt;br /&gt;
mysql&amp;gt;grant all on geeklog.* to geeklog@localhost identified by 'yourgeeklogpassword';&lt;br /&gt;
mysql&amp;gt;quit&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Install ==&lt;br /&gt;
&lt;br /&gt;
* run www.yourdomain.foo/admin/install/index.php&lt;br /&gt;
* follow the instructions&lt;br /&gt;
* login to your page using default Admin/password&lt;br /&gt;
* change password&lt;br /&gt;
* remove directory public_html/admin/install&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6623</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6623"/>
				<updated>2019-11-08T17:44:13Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.''' Best way to do this is delete the .gitignore file and then check for any new files.&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6622</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6622"/>
				<updated>2019-11-08T17:38:03Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Confirm git is installed on server that install package is being built on so the &amp;quot;changed-files&amp;quot; file gets updated properly&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** '''Make sure no extra files exist as they will get included in the package. This includes db-config.php, siteconfig.php and any images and cached files.'''&lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6621</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6621"/>
				<updated>2019-10-25T00:49:45Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* The Tarball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.properties&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” and “build.properties” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6620</id>
		<title>Installing Geeklog:System Requirements</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Installing_Geeklog:System_Requirements&amp;diff=6620"/>
				<updated>2019-05-28T13:24:18Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Installation - System Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Installation - System Requirements ==&lt;br /&gt;
&lt;br /&gt;
The system requirements for installing Geeklog 2.1.2 and later are as follows:&lt;br /&gt;
&lt;br /&gt;
# Web server - one of the following&lt;br /&gt;
## Apache Web Server&lt;br /&gt;
## Microsoft IIS (Internet Information Server)&lt;br /&gt;
# PHP 5.3.3 or higher with the following extensions&lt;br /&gt;
## mbstring Extension&lt;br /&gt;
## bzip2 Extension&lt;br /&gt;
## mysql or mysqli Extension (To enable MySQL support)&lt;br /&gt;
## pgsql Extension (To enable Postgresql support)&lt;br /&gt;
## OpenSSL Extension (To enable the Geeklog OAuth Login process)&lt;br /&gt;
## JSON Extension (For Filemanager and Database tools)&lt;br /&gt;
## fileinfo (To enable thumbnail creation of images in articles) (for IIS only as fileinfo is integrated into Apache)&lt;br /&gt;
## cURL (Not required but recommended for the reCaptcha plugin)&lt;br /&gt;
# Database server - one of the following&lt;br /&gt;
## MySQL 4.1.3 or higher (MySQL 5 recommended)&lt;br /&gt;
## Postgresql 9.1.7 or later&lt;br /&gt;
# The ability to create a new database or to have access to an existing one&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6618</id>
		<title>OAuth</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6618"/>
				<updated>2019-04-07T15:59:08Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Google */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is OAuth? ==&lt;br /&gt;
&lt;br /&gt;
The idea behind OAuth is to get rid of the need to register separately with all the websites out there that require registration before you can use them. Instead of having to keep track of all the different accounts, you can use one login on every website that supports OAuth.&lt;br /&gt;
&lt;br /&gt;
To quote the [http://OAuth.net/ OAuth homepage]:&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OAuth is a free and open protocol. It is not owned by any corporation.&lt;br /&gt;
&lt;br /&gt;
== OAuth in Geeklog ==&lt;br /&gt;
&lt;br /&gt;
OAuth support in Geeklog differs slightly from the [[Remote Authentication]] support, but only in that it requires a separate login prompt.&lt;br /&gt;
&lt;br /&gt;
To activate OAuth support there are several steps.&lt;br /&gt;
&lt;br /&gt;
First you must go to the Configuration Admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Users and Submissions &amp;gt; Users &amp;gt; User Login Method[OAuth]&lt;br /&gt;
&lt;br /&gt;
Set this option to &amp;quot;true&amp;quot;. Just below this configuration option you will find the other OAuth settings. Currently Geeklog supports logging in via Facebook, LinkedIn, Twitter, Yahoo, and Google via OAuth. For each of these login methods you will find an option to enable it and two text boxes for you to enter an Application Id and Application Secret Key (see below to find out how to get an Id and Secret Key). Each of these items needs to be filled out before the login button for it will be enabled. Once you have filled out the required information remember to then save the configuration changes.&lt;br /&gt;
&lt;br /&gt;
Other requirements needed to enable Geeklogs OAuth Login process is you must have the PHP extension OpenSSL loaded on your web server. &lt;br /&gt;
&lt;br /&gt;
The Geeklog User Submission Queue must also be set to false in the Geeklog Configuration. Currently a new remote user cannot be added to the submission queue for approval later on.&lt;br /&gt;
&lt;br /&gt;
When you log out, you will see one or more new login buttons in your site's User Functions block, below the normal login options:&lt;br /&gt;
&lt;br /&gt;
[[Image:OAuth-login.png|border]]&lt;br /&gt;
&lt;br /&gt;
The first time any user clicks on one of the OAuth login buttons they will be redirected to the website offering the OAuth login (Facebook, LinkedIn or Twitter). Here (if they are not currently logged into the website) they will be asked to login. Once logined they will then be asked if they wish to give permission to your Geeklog website to access some of your personal information. If the user approves the request they will then be redirected back to the Geeklog website which will then use the information to create a Geeklog user account and log them into the Geeklog website. If the user does not approve the request for information they will still be redirected back to the website but no Geeklog user account will be created.&lt;br /&gt;
&lt;br /&gt;
The next time the user logs into your Geeklog website using the same OAuth login method Geeklog will check with the website providing the OAuth login to see if you are logged in the site. If not the user will be redirected to the site to login. Once they have the site will the redirect back to your Geeklog website. &lt;br /&gt;
&lt;br /&gt;
When Geeklog uses OAuth to login it's users, it will never see your OAuth password - it will only get an &amp;quot;okay&amp;quot; back from the OAuth provider if you authenticated successfully.&lt;br /&gt;
&lt;br /&gt;
Once a user has logged in via OAuth, they are just like any other Geeklog user. They can be added to groups, change their profile, do whatever else you allow your users to do on your site. And yes, OAuth users can also be banned.&lt;br /&gt;
&lt;br /&gt;
Users that log in through OAuth are automatically added to the &amp;quot;Remote Users&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
* Currently, OAuth 1.0, 1.0a and 2.0 is supported (depends on what the OAuth provider supports).&lt;br /&gt;
&lt;br /&gt;
== OAuth Login Methods ==&lt;br /&gt;
&lt;br /&gt;
General review...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Facebook ===&lt;br /&gt;
&lt;br /&gt;
Please note:&lt;br /&gt;
* To use Facebook Login your website must use SSL.&lt;br /&gt;
* Use Strict Mode for Redirect URIs on the Facebook Web App defaults to Strict and cannot be changed for new login apps created in the Facebook developer portal. This means you must specify the exact Valid OAuth Redirect URIs used by Geeklog. For example: https://www.yoursitehere.com/users.php?oauth_login=facebook&lt;br /&gt;
* You may need to also submit the Login for Facebook review before location / user photo can be retrieved. You have to include a screencast showing how you login and use the Facebook data.&lt;br /&gt;
&lt;br /&gt;
Access Facebook 'Create an Application' page, and input form.&lt;br /&gt;
&lt;br /&gt;
Please go to Facebook Apps page https://developers.facebook.com/apps&lt;br /&gt;
&lt;br /&gt;
=== LinkedIn ===&lt;br /&gt;
&lt;br /&gt;
Access LinkedIn 'List of Applications' page, and click 'Add New Application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.linkedin.com/secure/developer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Twitter ===&lt;br /&gt;
&lt;br /&gt;
Access 'Applications Using Twitter' page and click 'Register a new application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://dev.twitter.com/apps/new&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Application Type: Select 'Browser'&amp;lt;br&amp;gt;&lt;br /&gt;
Callback URL: Input URL same as Website&amp;lt;br&amp;gt;&lt;br /&gt;
Default Access type: Select 'Read &amp;amp; Write'&amp;lt;br&amp;gt;&lt;br /&gt;
Use Twitter for login: Check&amp;lt;br&amp;gt;&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=twitter&lt;br /&gt;
&lt;br /&gt;
=== Microsoft Live ===&lt;br /&gt;
&lt;br /&gt;
Allows users to login with their Hotmail, Live or Outlook email accounts&lt;br /&gt;
Please go to Microsoft Live Connect Developer Center page https://manage.dev.live.com/AddApplication.aspx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Google ===&lt;br /&gt;
&lt;br /&gt;
Note: Google will shutdown Google+ on April 2, 2019. As of Geeklog v2.2.1 we will move from the Google+ OAuth scope to the Google OAuth scope. Because of this change you may need to update your Google API key&lt;br /&gt;
&lt;br /&gt;
Google APIs console page http://code.google.com/apis/console in the API access tab&lt;br /&gt;
&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=google&lt;br /&gt;
&lt;br /&gt;
=== Yahoo ===&lt;br /&gt;
&lt;br /&gt;
Yahoo Apps page https://developer.apps.yahoo.com/wsregapp/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GitHub ===&lt;br /&gt;
&lt;br /&gt;
GitHub Developer page https://developer.github.com/v3/oauth/&lt;br /&gt;
&lt;br /&gt;
Create a new GitHub Application: https://github.com/settings/applications/new&lt;br /&gt;
&lt;br /&gt;
Redirection URL (Authorization callback URL): http://www.yoursitehere.com/users.php?oauth_login=github&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://OAuth.net/ OAuth homepage]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6617</id>
		<title>OAuth</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6617"/>
				<updated>2019-04-07T15:45:51Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Facebook */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is OAuth? ==&lt;br /&gt;
&lt;br /&gt;
The idea behind OAuth is to get rid of the need to register separately with all the websites out there that require registration before you can use them. Instead of having to keep track of all the different accounts, you can use one login on every website that supports OAuth.&lt;br /&gt;
&lt;br /&gt;
To quote the [http://OAuth.net/ OAuth homepage]:&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OAuth is a free and open protocol. It is not owned by any corporation.&lt;br /&gt;
&lt;br /&gt;
== OAuth in Geeklog ==&lt;br /&gt;
&lt;br /&gt;
OAuth support in Geeklog differs slightly from the [[Remote Authentication]] support, but only in that it requires a separate login prompt.&lt;br /&gt;
&lt;br /&gt;
To activate OAuth support there are several steps.&lt;br /&gt;
&lt;br /&gt;
First you must go to the Configuration Admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Users and Submissions &amp;gt; Users &amp;gt; User Login Method[OAuth]&lt;br /&gt;
&lt;br /&gt;
Set this option to &amp;quot;true&amp;quot;. Just below this configuration option you will find the other OAuth settings. Currently Geeklog supports logging in via Facebook, LinkedIn, Twitter, Yahoo, and Google via OAuth. For each of these login methods you will find an option to enable it and two text boxes for you to enter an Application Id and Application Secret Key (see below to find out how to get an Id and Secret Key). Each of these items needs to be filled out before the login button for it will be enabled. Once you have filled out the required information remember to then save the configuration changes.&lt;br /&gt;
&lt;br /&gt;
Other requirements needed to enable Geeklogs OAuth Login process is you must have the PHP extension OpenSSL loaded on your web server. &lt;br /&gt;
&lt;br /&gt;
The Geeklog User Submission Queue must also be set to false in the Geeklog Configuration. Currently a new remote user cannot be added to the submission queue for approval later on.&lt;br /&gt;
&lt;br /&gt;
When you log out, you will see one or more new login buttons in your site's User Functions block, below the normal login options:&lt;br /&gt;
&lt;br /&gt;
[[Image:OAuth-login.png|border]]&lt;br /&gt;
&lt;br /&gt;
The first time any user clicks on one of the OAuth login buttons they will be redirected to the website offering the OAuth login (Facebook, LinkedIn or Twitter). Here (if they are not currently logged into the website) they will be asked to login. Once logined they will then be asked if they wish to give permission to your Geeklog website to access some of your personal information. If the user approves the request they will then be redirected back to the Geeklog website which will then use the information to create a Geeklog user account and log them into the Geeklog website. If the user does not approve the request for information they will still be redirected back to the website but no Geeklog user account will be created.&lt;br /&gt;
&lt;br /&gt;
The next time the user logs into your Geeklog website using the same OAuth login method Geeklog will check with the website providing the OAuth login to see if you are logged in the site. If not the user will be redirected to the site to login. Once they have the site will the redirect back to your Geeklog website. &lt;br /&gt;
&lt;br /&gt;
When Geeklog uses OAuth to login it's users, it will never see your OAuth password - it will only get an &amp;quot;okay&amp;quot; back from the OAuth provider if you authenticated successfully.&lt;br /&gt;
&lt;br /&gt;
Once a user has logged in via OAuth, they are just like any other Geeklog user. They can be added to groups, change their profile, do whatever else you allow your users to do on your site. And yes, OAuth users can also be banned.&lt;br /&gt;
&lt;br /&gt;
Users that log in through OAuth are automatically added to the &amp;quot;Remote Users&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
* Currently, OAuth 1.0, 1.0a and 2.0 is supported (depends on what the OAuth provider supports).&lt;br /&gt;
&lt;br /&gt;
== OAuth Login Methods ==&lt;br /&gt;
&lt;br /&gt;
General review...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Facebook ===&lt;br /&gt;
&lt;br /&gt;
Please note:&lt;br /&gt;
* To use Facebook Login your website must use SSL.&lt;br /&gt;
* Use Strict Mode for Redirect URIs on the Facebook Web App defaults to Strict and cannot be changed for new login apps created in the Facebook developer portal. This means you must specify the exact Valid OAuth Redirect URIs used by Geeklog. For example: https://www.yoursitehere.com/users.php?oauth_login=facebook&lt;br /&gt;
* You may need to also submit the Login for Facebook review before location / user photo can be retrieved. You have to include a screencast showing how you login and use the Facebook data.&lt;br /&gt;
&lt;br /&gt;
Access Facebook 'Create an Application' page, and input form.&lt;br /&gt;
&lt;br /&gt;
Please go to Facebook Apps page https://developers.facebook.com/apps&lt;br /&gt;
&lt;br /&gt;
=== LinkedIn ===&lt;br /&gt;
&lt;br /&gt;
Access LinkedIn 'List of Applications' page, and click 'Add New Application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.linkedin.com/secure/developer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Twitter ===&lt;br /&gt;
&lt;br /&gt;
Access 'Applications Using Twitter' page and click 'Register a new application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://dev.twitter.com/apps/new&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Application Type: Select 'Browser'&amp;lt;br&amp;gt;&lt;br /&gt;
Callback URL: Input URL same as Website&amp;lt;br&amp;gt;&lt;br /&gt;
Default Access type: Select 'Read &amp;amp; Write'&amp;lt;br&amp;gt;&lt;br /&gt;
Use Twitter for login: Check&amp;lt;br&amp;gt;&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=twitter&lt;br /&gt;
&lt;br /&gt;
=== Microsoft Live ===&lt;br /&gt;
&lt;br /&gt;
Allows users to login with their Hotmail, Live or Outlook email accounts&lt;br /&gt;
Please go to Microsoft Live Connect Developer Center page https://manage.dev.live.com/AddApplication.aspx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Google ===&lt;br /&gt;
&lt;br /&gt;
Note: Google will shutdown Google+ on April 2, 2019. As of Geeklog v2.2.1 this OAuth login method will be removed on upgrade and all current user accounts that are setup to use Google+ will be converted to a regular Geeklog user account.&lt;br /&gt;
&lt;br /&gt;
Google APIs console page http://code.google.com/apis/console in the API access tab&lt;br /&gt;
&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=google&lt;br /&gt;
&lt;br /&gt;
=== Yahoo ===&lt;br /&gt;
&lt;br /&gt;
Yahoo Apps page https://developer.apps.yahoo.com/wsregapp/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GitHub ===&lt;br /&gt;
&lt;br /&gt;
GitHub Developer page https://developer.github.com/v3/oauth/&lt;br /&gt;
&lt;br /&gt;
Create a new GitHub Application: https://github.com/settings/applications/new&lt;br /&gt;
&lt;br /&gt;
Redirection URL (Authorization callback URL): http://www.yoursitehere.com/users.php?oauth_login=github&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://OAuth.net/ OAuth homepage]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6616</id>
		<title>OAuth</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6616"/>
				<updated>2019-04-07T15:44:57Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Facebook */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is OAuth? ==&lt;br /&gt;
&lt;br /&gt;
The idea behind OAuth is to get rid of the need to register separately with all the websites out there that require registration before you can use them. Instead of having to keep track of all the different accounts, you can use one login on every website that supports OAuth.&lt;br /&gt;
&lt;br /&gt;
To quote the [http://OAuth.net/ OAuth homepage]:&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OAuth is a free and open protocol. It is not owned by any corporation.&lt;br /&gt;
&lt;br /&gt;
== OAuth in Geeklog ==&lt;br /&gt;
&lt;br /&gt;
OAuth support in Geeklog differs slightly from the [[Remote Authentication]] support, but only in that it requires a separate login prompt.&lt;br /&gt;
&lt;br /&gt;
To activate OAuth support there are several steps.&lt;br /&gt;
&lt;br /&gt;
First you must go to the Configuration Admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Users and Submissions &amp;gt; Users &amp;gt; User Login Method[OAuth]&lt;br /&gt;
&lt;br /&gt;
Set this option to &amp;quot;true&amp;quot;. Just below this configuration option you will find the other OAuth settings. Currently Geeklog supports logging in via Facebook, LinkedIn, Twitter, Yahoo, and Google via OAuth. For each of these login methods you will find an option to enable it and two text boxes for you to enter an Application Id and Application Secret Key (see below to find out how to get an Id and Secret Key). Each of these items needs to be filled out before the login button for it will be enabled. Once you have filled out the required information remember to then save the configuration changes.&lt;br /&gt;
&lt;br /&gt;
Other requirements needed to enable Geeklogs OAuth Login process is you must have the PHP extension OpenSSL loaded on your web server. &lt;br /&gt;
&lt;br /&gt;
The Geeklog User Submission Queue must also be set to false in the Geeklog Configuration. Currently a new remote user cannot be added to the submission queue for approval later on.&lt;br /&gt;
&lt;br /&gt;
When you log out, you will see one or more new login buttons in your site's User Functions block, below the normal login options:&lt;br /&gt;
&lt;br /&gt;
[[Image:OAuth-login.png|border]]&lt;br /&gt;
&lt;br /&gt;
The first time any user clicks on one of the OAuth login buttons they will be redirected to the website offering the OAuth login (Facebook, LinkedIn or Twitter). Here (if they are not currently logged into the website) they will be asked to login. Once logined they will then be asked if they wish to give permission to your Geeklog website to access some of your personal information. If the user approves the request they will then be redirected back to the Geeklog website which will then use the information to create a Geeklog user account and log them into the Geeklog website. If the user does not approve the request for information they will still be redirected back to the website but no Geeklog user account will be created.&lt;br /&gt;
&lt;br /&gt;
The next time the user logs into your Geeklog website using the same OAuth login method Geeklog will check with the website providing the OAuth login to see if you are logged in the site. If not the user will be redirected to the site to login. Once they have the site will the redirect back to your Geeklog website. &lt;br /&gt;
&lt;br /&gt;
When Geeklog uses OAuth to login it's users, it will never see your OAuth password - it will only get an &amp;quot;okay&amp;quot; back from the OAuth provider if you authenticated successfully.&lt;br /&gt;
&lt;br /&gt;
Once a user has logged in via OAuth, they are just like any other Geeklog user. They can be added to groups, change their profile, do whatever else you allow your users to do on your site. And yes, OAuth users can also be banned.&lt;br /&gt;
&lt;br /&gt;
Users that log in through OAuth are automatically added to the &amp;quot;Remote Users&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
* Currently, OAuth 1.0, 1.0a and 2.0 is supported (depends on what the OAuth provider supports).&lt;br /&gt;
&lt;br /&gt;
== OAuth Login Methods ==&lt;br /&gt;
&lt;br /&gt;
General review...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Facebook ===&lt;br /&gt;
&lt;br /&gt;
Please note:&lt;br /&gt;
- To use Facebook Login your website must use SSL.&lt;br /&gt;
- Use Strict Mode for Redirect URIs on the Facebook Web App defaults to Strict and cannot be changed for new login apps created in the Facebook developer portal. This means you must specify the exact Valid OAuth Redirect URIs used by Geeklog. For example: https://www.yoursitehere.com/users.php?oauth_login=facebook&lt;br /&gt;
- You may need to also submit the Login for Facebook review before location / user photo can be retrieved. You have to include a screencast showing how you login and use the Facebook data.&lt;br /&gt;
&lt;br /&gt;
Access Facebook 'Create an Application' page, and input form.&lt;br /&gt;
&lt;br /&gt;
Please go to Facebook Apps page https://developers.facebook.com/apps&lt;br /&gt;
&lt;br /&gt;
=== LinkedIn ===&lt;br /&gt;
&lt;br /&gt;
Access LinkedIn 'List of Applications' page, and click 'Add New Application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.linkedin.com/secure/developer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Twitter ===&lt;br /&gt;
&lt;br /&gt;
Access 'Applications Using Twitter' page and click 'Register a new application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://dev.twitter.com/apps/new&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Application Type: Select 'Browser'&amp;lt;br&amp;gt;&lt;br /&gt;
Callback URL: Input URL same as Website&amp;lt;br&amp;gt;&lt;br /&gt;
Default Access type: Select 'Read &amp;amp; Write'&amp;lt;br&amp;gt;&lt;br /&gt;
Use Twitter for login: Check&amp;lt;br&amp;gt;&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=twitter&lt;br /&gt;
&lt;br /&gt;
=== Microsoft Live ===&lt;br /&gt;
&lt;br /&gt;
Allows users to login with their Hotmail, Live or Outlook email accounts&lt;br /&gt;
Please go to Microsoft Live Connect Developer Center page https://manage.dev.live.com/AddApplication.aspx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Google ===&lt;br /&gt;
&lt;br /&gt;
Note: Google will shutdown Google+ on April 2, 2019. As of Geeklog v2.2.1 this OAuth login method will be removed on upgrade and all current user accounts that are setup to use Google+ will be converted to a regular Geeklog user account.&lt;br /&gt;
&lt;br /&gt;
Google APIs console page http://code.google.com/apis/console in the API access tab&lt;br /&gt;
&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=google&lt;br /&gt;
&lt;br /&gt;
=== Yahoo ===&lt;br /&gt;
&lt;br /&gt;
Yahoo Apps page https://developer.apps.yahoo.com/wsregapp/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GitHub ===&lt;br /&gt;
&lt;br /&gt;
GitHub Developer page https://developer.github.com/v3/oauth/&lt;br /&gt;
&lt;br /&gt;
Create a new GitHub Application: https://github.com/settings/applications/new&lt;br /&gt;
&lt;br /&gt;
Redirection URL (Authorization callback URL): http://www.yoursitehere.com/users.php?oauth_login=github&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://OAuth.net/ OAuth homepage]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6615</id>
		<title>OAuth</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6615"/>
				<updated>2019-04-06T16:58:26Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Facebook */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is OAuth? ==&lt;br /&gt;
&lt;br /&gt;
The idea behind OAuth is to get rid of the need to register separately with all the websites out there that require registration before you can use them. Instead of having to keep track of all the different accounts, you can use one login on every website that supports OAuth.&lt;br /&gt;
&lt;br /&gt;
To quote the [http://OAuth.net/ OAuth homepage]:&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OAuth is a free and open protocol. It is not owned by any corporation.&lt;br /&gt;
&lt;br /&gt;
== OAuth in Geeklog ==&lt;br /&gt;
&lt;br /&gt;
OAuth support in Geeklog differs slightly from the [[Remote Authentication]] support, but only in that it requires a separate login prompt.&lt;br /&gt;
&lt;br /&gt;
To activate OAuth support there are several steps.&lt;br /&gt;
&lt;br /&gt;
First you must go to the Configuration Admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Users and Submissions &amp;gt; Users &amp;gt; User Login Method[OAuth]&lt;br /&gt;
&lt;br /&gt;
Set this option to &amp;quot;true&amp;quot;. Just below this configuration option you will find the other OAuth settings. Currently Geeklog supports logging in via Facebook, LinkedIn, Twitter, Yahoo, and Google via OAuth. For each of these login methods you will find an option to enable it and two text boxes for you to enter an Application Id and Application Secret Key (see below to find out how to get an Id and Secret Key). Each of these items needs to be filled out before the login button for it will be enabled. Once you have filled out the required information remember to then save the configuration changes.&lt;br /&gt;
&lt;br /&gt;
Other requirements needed to enable Geeklogs OAuth Login process is you must have the PHP extension OpenSSL loaded on your web server. &lt;br /&gt;
&lt;br /&gt;
The Geeklog User Submission Queue must also be set to false in the Geeklog Configuration. Currently a new remote user cannot be added to the submission queue for approval later on.&lt;br /&gt;
&lt;br /&gt;
When you log out, you will see one or more new login buttons in your site's User Functions block, below the normal login options:&lt;br /&gt;
&lt;br /&gt;
[[Image:OAuth-login.png|border]]&lt;br /&gt;
&lt;br /&gt;
The first time any user clicks on one of the OAuth login buttons they will be redirected to the website offering the OAuth login (Facebook, LinkedIn or Twitter). Here (if they are not currently logged into the website) they will be asked to login. Once logined they will then be asked if they wish to give permission to your Geeklog website to access some of your personal information. If the user approves the request they will then be redirected back to the Geeklog website which will then use the information to create a Geeklog user account and log them into the Geeklog website. If the user does not approve the request for information they will still be redirected back to the website but no Geeklog user account will be created.&lt;br /&gt;
&lt;br /&gt;
The next time the user logs into your Geeklog website using the same OAuth login method Geeklog will check with the website providing the OAuth login to see if you are logged in the site. If not the user will be redirected to the site to login. Once they have the site will the redirect back to your Geeklog website. &lt;br /&gt;
&lt;br /&gt;
When Geeklog uses OAuth to login it's users, it will never see your OAuth password - it will only get an &amp;quot;okay&amp;quot; back from the OAuth provider if you authenticated successfully.&lt;br /&gt;
&lt;br /&gt;
Once a user has logged in via OAuth, they are just like any other Geeklog user. They can be added to groups, change their profile, do whatever else you allow your users to do on your site. And yes, OAuth users can also be banned.&lt;br /&gt;
&lt;br /&gt;
Users that log in through OAuth are automatically added to the &amp;quot;Remote Users&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
* Currently, OAuth 1.0, 1.0a and 2.0 is supported (depends on what the OAuth provider supports).&lt;br /&gt;
&lt;br /&gt;
== OAuth Login Methods ==&lt;br /&gt;
&lt;br /&gt;
General review...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Facebook ===&lt;br /&gt;
&lt;br /&gt;
1. To use Facebook Login your website must use SSL.&lt;br /&gt;
&lt;br /&gt;
2. Use Strict Mode for Redirect URIs on the Facebook Web App defaults to Strict and cannot be changed for new login apps created in the Facebook developer portal. This means you must specify the exact Valid OAuth Redirect URIs used by Geeklog. For example: https://www.yoursitehere.com/users.php?oauth_login=facebook&lt;br /&gt;
&lt;br /&gt;
3. You will need to submit the Login for Facebook review before location / user photo can be retrieved. You have to include a screencast showing how you login and use the Facebook data.&lt;br /&gt;
&lt;br /&gt;
Access Facebook 'Create an Application' page, and input form.&lt;br /&gt;
&lt;br /&gt;
Please go to Facebook Apps page https://developers.facebook.com/apps&lt;br /&gt;
&lt;br /&gt;
=== LinkedIn ===&lt;br /&gt;
&lt;br /&gt;
Access LinkedIn 'List of Applications' page, and click 'Add New Application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.linkedin.com/secure/developer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Twitter ===&lt;br /&gt;
&lt;br /&gt;
Access 'Applications Using Twitter' page and click 'Register a new application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://dev.twitter.com/apps/new&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Application Type: Select 'Browser'&amp;lt;br&amp;gt;&lt;br /&gt;
Callback URL: Input URL same as Website&amp;lt;br&amp;gt;&lt;br /&gt;
Default Access type: Select 'Read &amp;amp; Write'&amp;lt;br&amp;gt;&lt;br /&gt;
Use Twitter for login: Check&amp;lt;br&amp;gt;&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=twitter&lt;br /&gt;
&lt;br /&gt;
=== Microsoft Live ===&lt;br /&gt;
&lt;br /&gt;
Allows users to login with their Hotmail, Live or Outlook email accounts&lt;br /&gt;
Please go to Microsoft Live Connect Developer Center page https://manage.dev.live.com/AddApplication.aspx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Google ===&lt;br /&gt;
&lt;br /&gt;
Note: Google will shutdown Google+ on April 2, 2019. As of Geeklog v2.2.1 this OAuth login method will be removed on upgrade and all current user accounts that are setup to use Google+ will be converted to a regular Geeklog user account.&lt;br /&gt;
&lt;br /&gt;
Google APIs console page http://code.google.com/apis/console in the API access tab&lt;br /&gt;
&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=google&lt;br /&gt;
&lt;br /&gt;
=== Yahoo ===&lt;br /&gt;
&lt;br /&gt;
Yahoo Apps page https://developer.apps.yahoo.com/wsregapp/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GitHub ===&lt;br /&gt;
&lt;br /&gt;
GitHub Developer page https://developer.github.com/v3/oauth/&lt;br /&gt;
&lt;br /&gt;
Create a new GitHub Application: https://github.com/settings/applications/new&lt;br /&gt;
&lt;br /&gt;
Redirection URL (Authorization callback URL): http://www.yoursitehere.com/users.php?oauth_login=github&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://OAuth.net/ OAuth homepage]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6614</id>
		<title>OAuth</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=OAuth&amp;diff=6614"/>
				<updated>2019-03-11T19:15:37Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Google */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is OAuth? ==&lt;br /&gt;
&lt;br /&gt;
The idea behind OAuth is to get rid of the need to register separately with all the websites out there that require registration before you can use them. Instead of having to keep track of all the different accounts, you can use one login on every website that supports OAuth.&lt;br /&gt;
&lt;br /&gt;
To quote the [http://OAuth.net/ OAuth homepage]:&lt;br /&gt;
&lt;br /&gt;
:&amp;quot;An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OAuth is a free and open protocol. It is not owned by any corporation.&lt;br /&gt;
&lt;br /&gt;
== OAuth in Geeklog ==&lt;br /&gt;
&lt;br /&gt;
OAuth support in Geeklog differs slightly from the [[Remote Authentication]] support, but only in that it requires a separate login prompt.&lt;br /&gt;
&lt;br /&gt;
To activate OAuth support there are several steps.&lt;br /&gt;
&lt;br /&gt;
First you must go to the Configuration Admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Users and Submissions &amp;gt; Users &amp;gt; User Login Method[OAuth]&lt;br /&gt;
&lt;br /&gt;
Set this option to &amp;quot;true&amp;quot;. Just below this configuration option you will find the other OAuth settings. Currently Geeklog supports logging in via Facebook, LinkedIn, Twitter, Yahoo, and Google via OAuth. For each of these login methods you will find an option to enable it and two text boxes for you to enter an Application Id and Application Secret Key (see below to find out how to get an Id and Secret Key). Each of these items needs to be filled out before the login button for it will be enabled. Once you have filled out the required information remember to then save the configuration changes.&lt;br /&gt;
&lt;br /&gt;
Other requirements needed to enable Geeklogs OAuth Login process is you must have the PHP extension OpenSSL loaded on your web server. &lt;br /&gt;
&lt;br /&gt;
The Geeklog User Submission Queue must also be set to false in the Geeklog Configuration. Currently a new remote user cannot be added to the submission queue for approval later on.&lt;br /&gt;
&lt;br /&gt;
When you log out, you will see one or more new login buttons in your site's User Functions block, below the normal login options:&lt;br /&gt;
&lt;br /&gt;
[[Image:OAuth-login.png|border]]&lt;br /&gt;
&lt;br /&gt;
The first time any user clicks on one of the OAuth login buttons they will be redirected to the website offering the OAuth login (Facebook, LinkedIn or Twitter). Here (if they are not currently logged into the website) they will be asked to login. Once logined they will then be asked if they wish to give permission to your Geeklog website to access some of your personal information. If the user approves the request they will then be redirected back to the Geeklog website which will then use the information to create a Geeklog user account and log them into the Geeklog website. If the user does not approve the request for information they will still be redirected back to the website but no Geeklog user account will be created.&lt;br /&gt;
&lt;br /&gt;
The next time the user logs into your Geeklog website using the same OAuth login method Geeklog will check with the website providing the OAuth login to see if you are logged in the site. If not the user will be redirected to the site to login. Once they have the site will the redirect back to your Geeklog website. &lt;br /&gt;
&lt;br /&gt;
When Geeklog uses OAuth to login it's users, it will never see your OAuth password - it will only get an &amp;quot;okay&amp;quot; back from the OAuth provider if you authenticated successfully.&lt;br /&gt;
&lt;br /&gt;
Once a user has logged in via OAuth, they are just like any other Geeklog user. They can be added to groups, change their profile, do whatever else you allow your users to do on your site. And yes, OAuth users can also be banned.&lt;br /&gt;
&lt;br /&gt;
Users that log in through OAuth are automatically added to the &amp;quot;Remote Users&amp;quot; group.&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===&lt;br /&gt;
&lt;br /&gt;
* Currently, OAuth 1.0, 1.0a and 2.0 is supported (depends on what the OAuth provider supports).&lt;br /&gt;
&lt;br /&gt;
== OAuth Login Methods ==&lt;br /&gt;
&lt;br /&gt;
General review...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Facebook ===&lt;br /&gt;
&lt;br /&gt;
Access Facebook 'Create an Application' page, and input form.&amp;lt;br&amp;gt;&lt;br /&gt;
Please go to Facebook Apps page https://developers.facebook.com/apps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== LinkedIn ===&lt;br /&gt;
&lt;br /&gt;
Access LinkedIn 'List of Applications' page, and click 'Add New Application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://www.linkedin.com/secure/developer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Twitter ===&lt;br /&gt;
&lt;br /&gt;
Access 'Applications Using Twitter' page and click 'Register a new application'.&amp;lt;br&amp;gt;&lt;br /&gt;
https://dev.twitter.com/apps/new&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Application Type: Select 'Browser'&amp;lt;br&amp;gt;&lt;br /&gt;
Callback URL: Input URL same as Website&amp;lt;br&amp;gt;&lt;br /&gt;
Default Access type: Select 'Read &amp;amp; Write'&amp;lt;br&amp;gt;&lt;br /&gt;
Use Twitter for login: Check&amp;lt;br&amp;gt;&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=twitter&lt;br /&gt;
&lt;br /&gt;
=== Microsoft Live ===&lt;br /&gt;
&lt;br /&gt;
Allows users to login with their Hotmail, Live or Outlook email accounts&lt;br /&gt;
Please go to Microsoft Live Connect Developer Center page https://manage.dev.live.com/AddApplication.aspx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Google ===&lt;br /&gt;
&lt;br /&gt;
Note: Google will shutdown Google+ on April 2, 2019. As of Geeklog v2.2.1 this OAuth login method will be removed on upgrade and all current user accounts that are setup to use Google+ will be converted to a regular Geeklog user account.&lt;br /&gt;
&lt;br /&gt;
Google APIs console page http://code.google.com/apis/console in the API access tab&lt;br /&gt;
&lt;br /&gt;
Redirection URL: http://www.yoursitehere.com/users.php?oauth_login=google&lt;br /&gt;
&lt;br /&gt;
=== Yahoo ===&lt;br /&gt;
&lt;br /&gt;
Yahoo Apps page https://developer.apps.yahoo.com/wsregapp/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GitHub ===&lt;br /&gt;
&lt;br /&gt;
GitHub Developer page https://developer.github.com/v3/oauth/&lt;br /&gt;
&lt;br /&gt;
Create a new GitHub Application: https://github.com/settings/applications/new&lt;br /&gt;
&lt;br /&gt;
Redirection URL (Authorization callback URL): http://www.yoursitehere.com/users.php?oauth_login=github&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://OAuth.net/ OAuth homepage]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6613</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6613"/>
				<updated>2018-11-30T14:07:21Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Example 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments. If you want these comments to appear in the cache and the HTML source of the page you can in the Geeklog Configuration enable &amp;quot;Template Comments in Output&amp;quot;. See example 3 to see how to use a comment.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
    {!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
    myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
   {!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 5 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6612</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6612"/>
				<updated>2018-11-30T14:06:52Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Example 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments. If you want these comments to appear in the cache and the HTML source of the page you can in the Geeklog Configuration enable &amp;quot;Template Comments in Output&amp;quot;. See example 3 to see how to use a comment.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
    {!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
    myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   {!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 5 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6611</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6611"/>
				<updated>2018-11-30T14:06:30Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Comments */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments. If you want these comments to appear in the cache and the HTML source of the page you can in the Geeklog Configuration enable &amp;quot;Template Comments in Output&amp;quot;. See example 3 to see how to use a comment.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
    {!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
    myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
   {!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 5 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6610</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6610"/>
				<updated>2018-11-30T14:03:17Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Example 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
    {!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
    myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
   {!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 5 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6609</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6609"/>
				<updated>2018-11-30T14:02:23Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Example 4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
{!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
{!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 5 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6608</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6608"/>
				<updated>2018-11-30T14:02:11Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Example 3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
In this example, we set the array myVar and then print it out using a while loop:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!set myVar array('a', 'b') !!}&lt;br /&gt;
{!!set myCount 0 !!}&lt;br /&gt;
{!!while !empty(array_slice({myVar}, {myCount}, 1)) !!}&lt;br /&gt;
{!!set myVar1 array_slice({myVar}, {myCount}, 1)[0] !!}&lt;br /&gt;
myVar: {myVar1}&amp;lt;br&amp;gt;&lt;br /&gt;
{!inc myCount}&lt;br /&gt;
{!endwhile!}&lt;br /&gt;
The output then looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
myVar: a&lt;br /&gt;
myVar: b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Static_Pages_Plugin&amp;diff=6607</id>
		<title>Static Pages Plugin</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Static_Pages_Plugin&amp;diff=6607"/>
				<updated>2018-11-26T21:51:16Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Accessing Geeklog Variables and Logic Processing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is it? ==&lt;br /&gt;
&lt;br /&gt;
The Static Pages plugin was originally aimed at creating pages with static content (as opposed to the dynamic pages created by Geeklog) - hence the name. Pages like an &amp;quot;about us&amp;quot; page, a mission statement, etc. would come to mind.&lt;br /&gt;
&lt;br /&gt;
Since then, people have used the static pages for all kinds of things and with the inclusion of PHP into static pages, even the original name isn't quite right any more ...&lt;br /&gt;
History&lt;br /&gt;
&lt;br /&gt;
The plugin was originally written by Tony Bibbs and is included with Geeklog as a pre-installed plugin since Geeklog 1.3.5. An extended version of the plugin was started by Phill Gillespie and later supported by Tom Willet. The extended version was the first to allow the use of PHP in static pages and also supported proper Geeklog permissions.&lt;br /&gt;
&lt;br /&gt;
With Geeklog 1.3.8 and Static Pages 1.3, these two versions were merged again. Static Pages 1.3 also introduced some new features that were not included in either of its predecessors.&lt;br /&gt;
Features&lt;br /&gt;
&lt;br /&gt;
* supports use of PHP&lt;br /&gt;
* editable page ID to make more readable URLs&lt;br /&gt;
* Static pages can be displayed on Geeklog's index and topic pages and can even replace it entirely (&amp;quot;splash screen&amp;quot;)&lt;br /&gt;
* &amp;quot;cloning&amp;quot; of existing pages&lt;br /&gt;
* Makes use of Geeklog's URL rewrite feature&lt;br /&gt;
* Supports autolinks and provides a [staticpage:] autotag&lt;br /&gt;
* proper support for Geeklog permissions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Use of PHP ==&lt;br /&gt;
&lt;br /&gt;
=== Activating PHP ===&lt;br /&gt;
&lt;br /&gt;
'''Important:''' For security reasons, the use of PHP in static pages is disabled by default.&lt;br /&gt;
&lt;br /&gt;
To enable it, you will have to grant the 'staticpages.PHP' permission to the &amp;quot;Static Page Admin&amp;quot; group. To do this, log in as the Admin and from the Admin's Only block, select &amp;quot;Groups&amp;quot;. Find the &amp;quot;Static Page Admin&amp;quot; group and edit it by clicking on the name of the group. At the bottom of the page, you will find a list of &amp;quot;Rights&amp;quot; (permissions) that can be granted to all members of this group. Note that 'staticpages.delete' and 'staticpages.edit' are checked, while 'staticpages.PHP' is not checked. To allow members of the Static Page Admin group to use PHP in static pages, you will have to check the 'staticpages.PHP' checkbox and save your changes.&lt;br /&gt;
&lt;br /&gt;
In addition to the 'staticpages.PHP' permission discussed above, there is also a global flag, $_SP_CONF['allow_php'], that can be used to disable the use of PHP in static pages entirely. When set to 0, it will override the 'staticpages.PHP' permission and disable all use of PHP in static pages. The flag is located in the static pages' config.php file in the plugins/staticpages directory.&lt;br /&gt;
Usage&lt;br /&gt;
&lt;br /&gt;
''The use of PHP in static pages may result in security issues if not used properly. Use this feature with care!''&lt;br /&gt;
&lt;br /&gt;
The use of PHP has to be enabled for each individual static page. Below the content edit field, you will find a drop-down menu with the following options:&lt;br /&gt;
&lt;br /&gt;
* do not execute PHP&lt;br /&gt;
Obivously, when you select this option, any PHP code in the static page will not be executed but will instead be printed out as-is.&lt;br /&gt;
* execute PHP (return)&lt;br /&gt;
If you select this option, PHP code in static pages will be executed. The 'return' indicates that the code should return any output it generates, using a PHP return statement, instead of printing it out directly. This is the PHP option as introduced with the Static Pages plugin 1.3.&lt;br /&gt;
* execute PHP&lt;br /&gt;
Again, this option will enable execution of PHP. Only this time, the PHP code can actually use echo and print statements without having the output interfere with the page layout.&lt;br /&gt;
&lt;br /&gt;
Please note that when embedding PHP code in a static page, your code should not be enclosed in the PHP &amp;lt;?php and ?&amp;gt; tags. Instead, it is assumed that the static page contains the PHP code that would normally go between those two tags.&lt;br /&gt;
&lt;br /&gt;
When selecting the second of the above PHP execution options (&amp;quot;execute PHP&amp;quot;) you can, however, switch back and forth between PHP and plain HTML like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;echo &amp;quot;Hello&amp;quot;; ?&amp;gt;, &amp;lt;b&amp;gt;world&amp;lt;/b&amp;gt;, &amp;lt;?php echo &amp;quot;how are you?&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example would print out &amp;quot;Hello, world, how are you?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Page ID ==&lt;br /&gt;
&lt;br /&gt;
When creating a new static page, it will be assigned a page ID automatically. This ID consists of the date and time and up to three random digits. When you anticipate that the URL of this page may be used a lot, e.g. quoted in emails, it may make sense to use a more readable ID for the page.&lt;br /&gt;
&lt;br /&gt;
The static pages editor will let you change the page ID. For example, you may want to rename the ID for your &amp;quot;about&amp;quot; page from &amp;quot;20030313100131123&amp;quot; to &amp;quot;about&amp;quot;, thus creating a URL like&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php?page=about&lt;br /&gt;
&lt;br /&gt;
which looks much nicer when quoted (and is easier to remember). You could further improve this by making use of Geeklog's URL rewrite feature.&lt;br /&gt;
&lt;br /&gt;
Please note that you should only use letters and digits for the page ID. Avoid national special characters, most punctuation characters ('-' and '.' should be okay, though) and spaces. The static page editor will catch some illegal characters but not all of them ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Static Pages on the index page ==&lt;br /&gt;
&lt;br /&gt;
Geeklog 1.3.8 introduced a new concept for use by plugins, called Center Blocks. Basically, this means that any plugin can place blocks in the center area of a Geeklog site, i.e. among the stories.&lt;br /&gt;
&lt;br /&gt;
When you check the &amp;quot;Centerblock&amp;quot; option for a static page, you can use the &amp;quot;Position&amp;quot; and &amp;quot;Topic&amp;quot; drop-downs to chose where this static page will be displayed. For &amp;quot;Position&amp;quot;, the options are &amp;quot;Top Of Page&amp;quot;, &amp;quot;After Featured Story&amp;quot;, &amp;quot;Bottom Of Page&amp;quot; (which should be self-explanatory) and &amp;quot;Entire Page&amp;quot;. That last option, &amp;quot;Entire Page&amp;quot;, will tell Geeklog that this static page will replace the entire index page - it will not display any stories, but only the contents of this static page. This is useful e.g. for &amp;quot;splash&amp;quot; screens or Welcome pages.&lt;br /&gt;
&lt;br /&gt;
'''Tip:''' When using a static page as a &amp;quot;splash&amp;quot; screen, you may need a link that takes your visitors to the normal index page, i.e. the list of current stories. To do this, create a link to index.php?display=all&lt;br /&gt;
&lt;br /&gt;
The second drop-down, &amp;quot;Topic&amp;quot;, lets you restrict the display of a static page to only a certain topic, the homepage only, or all pages (i.e. all topic pages and the homepage). This is the same as the options you have for blocks.&lt;br /&gt;
&lt;br /&gt;
'''Tip:''' You can combine these options with the permission settings. This will let you, for example, create a &amp;quot;welcome&amp;quot; page that is only displayed to anonymous users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sorting ==&lt;br /&gt;
&lt;br /&gt;
'''Centerblocks:''' When you have more than one static page that would appear in the same section of the center area (e.g. two static pages that would be displayed at the top of the index page), you can chose the order in which they appear by setting the $_SP_CONF['sort_by'] variable in the plugin's config.php file to one of id (sort by page id), date (sort by last changed date), or title (sort by page title). The default is to sort by page id.&lt;br /&gt;
&lt;br /&gt;
'''Menu entries:''' It's also possible to sort the static pages that are displayed in the site's menu (if you're using a theme that uses the {plg_menu_elements} variables in its header.thtml). Set the $_SP_CONF['sort_menu_by'] variable (again, in the plugin's config.php file) to one of id (sort by page id), date (sort by last changed date), label (sort by the menu label), or title (sort by page title).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Wrapping Static Pages in a block ==&lt;br /&gt;
&lt;br /&gt;
You can chose to have a static page wrapped in a Geeklog block by checking the &amp;quot;wrap static page in a block&amp;quot; option in the static pages editor. If selected, the page's title will be used as the block title.&lt;br /&gt;
&lt;br /&gt;
The plugin's config.php file also has a flag, $_SP_CONF['in_block'], which is used as the default for this option.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cloning Static Pages ==&lt;br /&gt;
&lt;br /&gt;
When you have a lot of similar static pages you may want to make a copy of an existing page and then edit that copy. This can easily be done by clicking on the [C] from the list of static pages. Doing so will create a copy of that page with a new page ID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== URL rewriting ==&lt;br /&gt;
&lt;br /&gt;
Please note that this feature is considered experimental and is known not to work with IIS.&lt;br /&gt;
&lt;br /&gt;
Geeklog supports a form of URL rewriting, i.e. change the look of URLs such that they are more search engine friendly. For example, instead of&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php?page=20030313100131123&lt;br /&gt;
&lt;br /&gt;
the URL could look like this&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php/20030313100131123&lt;br /&gt;
&lt;br /&gt;
Some search engines are known not to index pages when the URL includes characters like '?' and '='. You could further improve the chances of this page being indexed by replacing the numeric page ID with a word or expression (preferrably something that corresponds to the page's content), e.g.&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php/about&lt;br /&gt;
&lt;br /&gt;
To make use of URL rewriting, you will need to enable it in Geeklog's config.php file by setting&lt;br /&gt;
&lt;br /&gt;
$_CONF['url_rewrite'] = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Template Static Pages ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog 1.7.1, you now have the ability for a Static Page to use another Static Page as a template. What this allows you to do is create one template page and then have it be used by one or more other Static Pages as a base. This feature is ideal for people who have a number of similar formatted Static Pages. For example if you have a bunch of product pages that need to look the same but they have different titles, product image, and product description. A Static Page Template would be ideal here. You can just supply the text in one page and have it use the other for the formatting. If you ever need to change the formatting of these pages at a later date all you need to do is just update the template Static Page. To set this functionality up, you need to do a couple of things.&lt;br /&gt;
&lt;br /&gt;
The first thing you must do is create a template Static Page. To do this you first need to create a Static Page. Once in the editor you need to give the page a Title and an ID. You then need to check the &amp;quot;Template&amp;quot; check box option. Once this is done, you can enter your HTML code in the content section. Where ever you have a spot where you want data from another Static Page to go, you can put a template variable there. This template variable can be any unique text you want. An example of this would be something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var1}&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;Bye World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var2}&amp;lt;/p&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have assigned a static page as a template, most features in the editor are not available to you to use. This includes the Menu options, Page Format, Comments, Meta Information, Centerblock and the PHP option. Also by themselves template Static Pages will not appear in search results, Site Statistics or in the What's New Block.&lt;br /&gt;
&lt;br /&gt;
The second thing you need to do now is, create a page that will use your new template Static Page. To do this, create a new Static Page. Once you are in the Static Page editor you then need to select your new template from the &amp;quot;Use Template&amp;quot; option. Once selected, you can then enter your template variable information into the content section of the editor. This information is XML and needs to be formatted properly and include the correct attributes and tags like the sample below:&lt;br /&gt;
&lt;br /&gt;
NOTE: These examples have been updated for use with Geeklog 2.1.3. As of Geeklog 2.1.3 curly brackets are automatically used to surround variable names in the templates. With Geeklog 2.1.2 and lower the variable name required the use of {curly brackets}. So Geeklog v2.1.2 and lower the staticpage which uses a template must have variable names like (with {curley_brackets}):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;page&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;{tpl_var1}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 1&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;{tpl_var2}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 2&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;{tpl_var3}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;True&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/page&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Geeklog v2.1.3 and later the curly brackets are not needed around the variable names. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;page&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 1&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 2&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;True&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/page&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should have the same number of variables here, as in your template Static Page. Each of the name attributes of the variable tag should be one of the template variables from the template Static Page.  Any information you want to appear would go between the data tags.  If this information contains other tags (like HTML) then you need to wrap it in CDATA so it will not be parsed. Here is an example of how to use CDATA:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;&amp;lt;![CDATA[&lt;br /&gt;
	&amp;lt;p&amp;gt;Test Variable Data 1&amp;lt;/p&amp;gt;&lt;br /&gt;
    ]]&amp;gt;&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most functions of the Static Page editor are available to this page with the exception of allowing PHP to be used and Post Mode.  Your &amp;quot;Post Mode&amp;quot; option should be set as &amp;quot;HTML Formatted&amp;quot;. If there is an error in your XML this could throw a PHP error when you attempt to view the page. You also need to make sure that this page and the template Static Page have the same permissions. If the user can view this page and not the template Static Page assigned to it then the page will not display properly.&lt;br /&gt;
&lt;br /&gt;
=== Accessing Geeklog Variables and Logic Processing ===&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 and Static Page Plugin v1.6.9 the staticpage template feature has improved. Instead of the Staticpage plugin itself replacing template variables and autotags it has now handed over this funcitionaly for the most part to the [[Caching_Template_Library |Geeklog Caching Template Class]]. This means that template Static page can now use many features of the template class including access to [[Caching_Template_Library#TEMPLATE_OPTIONS |default variables]] like {anonymous_user} and {device_mobile}. Plus [[Caching_Template_Library#Automatic_Language_File_Variables |Lanaguage File Variables]]. It also means that [[Caching_Template_Library#Logic_Processing_2 |Logic Processing]] can now be used! This means you can include If and Else statements, Loops, and also include PHP code in Staticpage Template Pages. So for example in a template Staticpage you can now display content depending on a variable like {device_mobile) or another variable that has been defined in your Staticpage (like {tpl_var3} from the sample above). &lt;br /&gt;
&lt;br /&gt;
As of Geeklog 2.2.1 the Static Pages plugin also adds its own addition default template variables. There are 3: the static page title (sp_title}, created date (sp_created), and last modified date {sp_modified}. All dates returned by these template variables are ISO 8601 dates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var1}&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;Bye World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var2}&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{!if device_mobile}&lt;br /&gt;
&amp;lt;p&amp;gt;The paragraph will only display on mobile devices.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;The paragraph will only display on desktop and laptops.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&lt;br /&gt;
{!if tpl_var3}&lt;br /&gt;
&amp;lt;p&amp;gt;test_variable contains a string.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;test_variable contains a 0, is empty, or does not exist.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This is a test to access a language variable: {$LANG_DB_BACKUP[database_admin]}&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This is a test to access the Staticpage title: {sp_title}&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Deleting pages with their owner ==&lt;br /&gt;
&lt;br /&gt;
As all objects in Geeklog, static pages have an owner (the user that created the static page). When that user's account is deleted for some reason, any static pages owned by that user can either be deleted as well or they can be assigned to another user in Geeklog's Root group. The config.php file for the Static Pages plugin has the following option:&lt;br /&gt;
&lt;br /&gt;
$_SP_CONF['delete_pages'] = 0;&lt;br /&gt;
&lt;br /&gt;
If set to 0 (which is the default), static pages will not be deleted with their owner, but assigned to a member of the Root group instead (the user with the lowest user ID, most likely the Admin). If you change this to 1, static pages will be deleted when their owner's account is deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Static_Pages_Plugin&amp;diff=6606</id>
		<title>Static Pages Plugin</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Static_Pages_Plugin&amp;diff=6606"/>
				<updated>2018-11-26T21:49:57Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Accessing Geeklog Variables and Logic Processing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is it? ==&lt;br /&gt;
&lt;br /&gt;
The Static Pages plugin was originally aimed at creating pages with static content (as opposed to the dynamic pages created by Geeklog) - hence the name. Pages like an &amp;quot;about us&amp;quot; page, a mission statement, etc. would come to mind.&lt;br /&gt;
&lt;br /&gt;
Since then, people have used the static pages for all kinds of things and with the inclusion of PHP into static pages, even the original name isn't quite right any more ...&lt;br /&gt;
History&lt;br /&gt;
&lt;br /&gt;
The plugin was originally written by Tony Bibbs and is included with Geeklog as a pre-installed plugin since Geeklog 1.3.5. An extended version of the plugin was started by Phill Gillespie and later supported by Tom Willet. The extended version was the first to allow the use of PHP in static pages and also supported proper Geeklog permissions.&lt;br /&gt;
&lt;br /&gt;
With Geeklog 1.3.8 and Static Pages 1.3, these two versions were merged again. Static Pages 1.3 also introduced some new features that were not included in either of its predecessors.&lt;br /&gt;
Features&lt;br /&gt;
&lt;br /&gt;
* supports use of PHP&lt;br /&gt;
* editable page ID to make more readable URLs&lt;br /&gt;
* Static pages can be displayed on Geeklog's index and topic pages and can even replace it entirely (&amp;quot;splash screen&amp;quot;)&lt;br /&gt;
* &amp;quot;cloning&amp;quot; of existing pages&lt;br /&gt;
* Makes use of Geeklog's URL rewrite feature&lt;br /&gt;
* Supports autolinks and provides a [staticpage:] autotag&lt;br /&gt;
* proper support for Geeklog permissions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Use of PHP ==&lt;br /&gt;
&lt;br /&gt;
=== Activating PHP ===&lt;br /&gt;
&lt;br /&gt;
'''Important:''' For security reasons, the use of PHP in static pages is disabled by default.&lt;br /&gt;
&lt;br /&gt;
To enable it, you will have to grant the 'staticpages.PHP' permission to the &amp;quot;Static Page Admin&amp;quot; group. To do this, log in as the Admin and from the Admin's Only block, select &amp;quot;Groups&amp;quot;. Find the &amp;quot;Static Page Admin&amp;quot; group and edit it by clicking on the name of the group. At the bottom of the page, you will find a list of &amp;quot;Rights&amp;quot; (permissions) that can be granted to all members of this group. Note that 'staticpages.delete' and 'staticpages.edit' are checked, while 'staticpages.PHP' is not checked. To allow members of the Static Page Admin group to use PHP in static pages, you will have to check the 'staticpages.PHP' checkbox and save your changes.&lt;br /&gt;
&lt;br /&gt;
In addition to the 'staticpages.PHP' permission discussed above, there is also a global flag, $_SP_CONF['allow_php'], that can be used to disable the use of PHP in static pages entirely. When set to 0, it will override the 'staticpages.PHP' permission and disable all use of PHP in static pages. The flag is located in the static pages' config.php file in the plugins/staticpages directory.&lt;br /&gt;
Usage&lt;br /&gt;
&lt;br /&gt;
''The use of PHP in static pages may result in security issues if not used properly. Use this feature with care!''&lt;br /&gt;
&lt;br /&gt;
The use of PHP has to be enabled for each individual static page. Below the content edit field, you will find a drop-down menu with the following options:&lt;br /&gt;
&lt;br /&gt;
* do not execute PHP&lt;br /&gt;
Obivously, when you select this option, any PHP code in the static page will not be executed but will instead be printed out as-is.&lt;br /&gt;
* execute PHP (return)&lt;br /&gt;
If you select this option, PHP code in static pages will be executed. The 'return' indicates that the code should return any output it generates, using a PHP return statement, instead of printing it out directly. This is the PHP option as introduced with the Static Pages plugin 1.3.&lt;br /&gt;
* execute PHP&lt;br /&gt;
Again, this option will enable execution of PHP. Only this time, the PHP code can actually use echo and print statements without having the output interfere with the page layout.&lt;br /&gt;
&lt;br /&gt;
Please note that when embedding PHP code in a static page, your code should not be enclosed in the PHP &amp;lt;?php and ?&amp;gt; tags. Instead, it is assumed that the static page contains the PHP code that would normally go between those two tags.&lt;br /&gt;
&lt;br /&gt;
When selecting the second of the above PHP execution options (&amp;quot;execute PHP&amp;quot;) you can, however, switch back and forth between PHP and plain HTML like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;echo &amp;quot;Hello&amp;quot;; ?&amp;gt;, &amp;lt;b&amp;gt;world&amp;lt;/b&amp;gt;, &amp;lt;?php echo &amp;quot;how are you?&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above example would print out &amp;quot;Hello, world, how are you?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Page ID ==&lt;br /&gt;
&lt;br /&gt;
When creating a new static page, it will be assigned a page ID automatically. This ID consists of the date and time and up to three random digits. When you anticipate that the URL of this page may be used a lot, e.g. quoted in emails, it may make sense to use a more readable ID for the page.&lt;br /&gt;
&lt;br /&gt;
The static pages editor will let you change the page ID. For example, you may want to rename the ID for your &amp;quot;about&amp;quot; page from &amp;quot;20030313100131123&amp;quot; to &amp;quot;about&amp;quot;, thus creating a URL like&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php?page=about&lt;br /&gt;
&lt;br /&gt;
which looks much nicer when quoted (and is easier to remember). You could further improve this by making use of Geeklog's URL rewrite feature.&lt;br /&gt;
&lt;br /&gt;
Please note that you should only use letters and digits for the page ID. Avoid national special characters, most punctuation characters ('-' and '.' should be okay, though) and spaces. The static page editor will catch some illegal characters but not all of them ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Static Pages on the index page ==&lt;br /&gt;
&lt;br /&gt;
Geeklog 1.3.8 introduced a new concept for use by plugins, called Center Blocks. Basically, this means that any plugin can place blocks in the center area of a Geeklog site, i.e. among the stories.&lt;br /&gt;
&lt;br /&gt;
When you check the &amp;quot;Centerblock&amp;quot; option for a static page, you can use the &amp;quot;Position&amp;quot; and &amp;quot;Topic&amp;quot; drop-downs to chose where this static page will be displayed. For &amp;quot;Position&amp;quot;, the options are &amp;quot;Top Of Page&amp;quot;, &amp;quot;After Featured Story&amp;quot;, &amp;quot;Bottom Of Page&amp;quot; (which should be self-explanatory) and &amp;quot;Entire Page&amp;quot;. That last option, &amp;quot;Entire Page&amp;quot;, will tell Geeklog that this static page will replace the entire index page - it will not display any stories, but only the contents of this static page. This is useful e.g. for &amp;quot;splash&amp;quot; screens or Welcome pages.&lt;br /&gt;
&lt;br /&gt;
'''Tip:''' When using a static page as a &amp;quot;splash&amp;quot; screen, you may need a link that takes your visitors to the normal index page, i.e. the list of current stories. To do this, create a link to index.php?display=all&lt;br /&gt;
&lt;br /&gt;
The second drop-down, &amp;quot;Topic&amp;quot;, lets you restrict the display of a static page to only a certain topic, the homepage only, or all pages (i.e. all topic pages and the homepage). This is the same as the options you have for blocks.&lt;br /&gt;
&lt;br /&gt;
'''Tip:''' You can combine these options with the permission settings. This will let you, for example, create a &amp;quot;welcome&amp;quot; page that is only displayed to anonymous users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sorting ==&lt;br /&gt;
&lt;br /&gt;
'''Centerblocks:''' When you have more than one static page that would appear in the same section of the center area (e.g. two static pages that would be displayed at the top of the index page), you can chose the order in which they appear by setting the $_SP_CONF['sort_by'] variable in the plugin's config.php file to one of id (sort by page id), date (sort by last changed date), or title (sort by page title). The default is to sort by page id.&lt;br /&gt;
&lt;br /&gt;
'''Menu entries:''' It's also possible to sort the static pages that are displayed in the site's menu (if you're using a theme that uses the {plg_menu_elements} variables in its header.thtml). Set the $_SP_CONF['sort_menu_by'] variable (again, in the plugin's config.php file) to one of id (sort by page id), date (sort by last changed date), label (sort by the menu label), or title (sort by page title).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Wrapping Static Pages in a block ==&lt;br /&gt;
&lt;br /&gt;
You can chose to have a static page wrapped in a Geeklog block by checking the &amp;quot;wrap static page in a block&amp;quot; option in the static pages editor. If selected, the page's title will be used as the block title.&lt;br /&gt;
&lt;br /&gt;
The plugin's config.php file also has a flag, $_SP_CONF['in_block'], which is used as the default for this option.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cloning Static Pages ==&lt;br /&gt;
&lt;br /&gt;
When you have a lot of similar static pages you may want to make a copy of an existing page and then edit that copy. This can easily be done by clicking on the [C] from the list of static pages. Doing so will create a copy of that page with a new page ID.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== URL rewriting ==&lt;br /&gt;
&lt;br /&gt;
Please note that this feature is considered experimental and is known not to work with IIS.&lt;br /&gt;
&lt;br /&gt;
Geeklog supports a form of URL rewriting, i.e. change the look of URLs such that they are more search engine friendly. For example, instead of&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php?page=20030313100131123&lt;br /&gt;
&lt;br /&gt;
the URL could look like this&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php/20030313100131123&lt;br /&gt;
&lt;br /&gt;
Some search engines are known not to index pages when the URL includes characters like '?' and '='. You could further improve the chances of this page being indexed by replacing the numeric page ID with a word or expression (preferrably something that corresponds to the page's content), e.g.&lt;br /&gt;
&lt;br /&gt;
 http://www.example.com/staticpages/index.php/about&lt;br /&gt;
&lt;br /&gt;
To make use of URL rewriting, you will need to enable it in Geeklog's config.php file by setting&lt;br /&gt;
&lt;br /&gt;
$_CONF['url_rewrite'] = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Template Static Pages ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog 1.7.1, you now have the ability for a Static Page to use another Static Page as a template. What this allows you to do is create one template page and then have it be used by one or more other Static Pages as a base. This feature is ideal for people who have a number of similar formatted Static Pages. For example if you have a bunch of product pages that need to look the same but they have different titles, product image, and product description. A Static Page Template would be ideal here. You can just supply the text in one page and have it use the other for the formatting. If you ever need to change the formatting of these pages at a later date all you need to do is just update the template Static Page. To set this functionality up, you need to do a couple of things.&lt;br /&gt;
&lt;br /&gt;
The first thing you must do is create a template Static Page. To do this you first need to create a Static Page. Once in the editor you need to give the page a Title and an ID. You then need to check the &amp;quot;Template&amp;quot; check box option. Once this is done, you can enter your HTML code in the content section. Where ever you have a spot where you want data from another Static Page to go, you can put a template variable there. This template variable can be any unique text you want. An example of this would be something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var1}&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;Bye World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var2}&amp;lt;/p&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have assigned a static page as a template, most features in the editor are not available to you to use. This includes the Menu options, Page Format, Comments, Meta Information, Centerblock and the PHP option. Also by themselves template Static Pages will not appear in search results, Site Statistics or in the What's New Block.&lt;br /&gt;
&lt;br /&gt;
The second thing you need to do now is, create a page that will use your new template Static Page. To do this, create a new Static Page. Once you are in the Static Page editor you then need to select your new template from the &amp;quot;Use Template&amp;quot; option. Once selected, you can then enter your template variable information into the content section of the editor. This information is XML and needs to be formatted properly and include the correct attributes and tags like the sample below:&lt;br /&gt;
&lt;br /&gt;
NOTE: These examples have been updated for use with Geeklog 2.1.3. As of Geeklog 2.1.3 curly brackets are automatically used to surround variable names in the templates. With Geeklog 2.1.2 and lower the variable name required the use of {curly brackets}. So Geeklog v2.1.2 and lower the staticpage which uses a template must have variable names like (with {curley_brackets}):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;page&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;{tpl_var1}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 1&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;{tpl_var2}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 2&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;{tpl_var3}&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;True&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/page&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Geeklog v2.1.3 and later the curly brackets are not needed around the variable names. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;page&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 1&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var2&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;Test Variable Data 2&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var3&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;True&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/page&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should have the same number of variables here, as in your template Static Page. Each of the name attributes of the variable tag should be one of the template variables from the template Static Page.  Any information you want to appear would go between the data tags.  If this information contains other tags (like HTML) then you need to wrap it in CDATA so it will not be parsed. Here is an example of how to use CDATA:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;tpl_var1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;data&amp;gt;&amp;lt;![CDATA[&lt;br /&gt;
	&amp;lt;p&amp;gt;Test Variable Data 1&amp;lt;/p&amp;gt;&lt;br /&gt;
    ]]&amp;gt;&amp;lt;/data&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most functions of the Static Page editor are available to this page with the exception of allowing PHP to be used and Post Mode.  Your &amp;quot;Post Mode&amp;quot; option should be set as &amp;quot;HTML Formatted&amp;quot;. If there is an error in your XML this could throw a PHP error when you attempt to view the page. You also need to make sure that this page and the template Static Page have the same permissions. If the user can view this page and not the template Static Page assigned to it then the page will not display properly.&lt;br /&gt;
&lt;br /&gt;
=== Accessing Geeklog Variables and Logic Processing ===&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 and Static Page Plugin v1.6.9 the staticpage template feature has improved. Instead of the Staticpage plugin itself replacing template variables and autotags it has now handed over this funcitionaly for the most part to the [[Caching_Template_Library |Geeklog Caching Template Class]]. This means that template Static page can now use many features of the template class including access to [[Caching_Template_Library#TEMPLATE_OPTIONS |default variables]] like {anonymous_user} and {device_mobile}. Plus [[Caching_Template_Library#Automatic_Language_File_Variables |Lanaguage File Variables]]. It also means that [[Caching_Template_Library#Logic_Processing_2 |Logic Processing]] can now be used! This means you can include If and Else statements, Loops, and also include PHP code in Staticpage Template Pages. So for example in a template Staticpage you can now display content depending on a variable like {device_mobile) or another variable that has been defined in your Staticpage (like {tpl_var3} from the sample above). As of Geeklog 2.2.1 the Static Pages plugin also adds its own addition template variables for the static page title (sp_title}, created date (sp_created), and last modified date {sp_modified}. All dates returned by these template variables are ISO 8601 dates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var1}&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;Bye World!&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;{tpl_var2}&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{!if device_mobile}&lt;br /&gt;
&amp;lt;p&amp;gt;The paragraph will only display on mobile devices.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;The paragraph will only display on desktop and laptops.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&lt;br /&gt;
{!if tpl_var3}&lt;br /&gt;
&amp;lt;p&amp;gt;test_variable contains a string.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;test_variable contains a 0, is empty, or does not exist.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This is a test to access a language variable: {$LANG_DB_BACKUP[database_admin]}&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This is a test to access the Staticpage title: {sp_title}&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Deleting pages with their owner ==&lt;br /&gt;
&lt;br /&gt;
As all objects in Geeklog, static pages have an owner (the user that created the static page). When that user's account is deleted for some reason, any static pages owned by that user can either be deleted as well or they can be assigned to another user in Geeklog's Root group. The config.php file for the Static Pages plugin has the following option:&lt;br /&gt;
&lt;br /&gt;
$_SP_CONF['delete_pages'] = 0;&lt;br /&gt;
&lt;br /&gt;
If set to 0 (which is the default), static pages will not be deleted with their owner, but assigned to a member of the Root group instead (the user with the lowest user ID, most likely the Admin). If you change this to 1, static pages will be deleted when their owner's account is deleted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6605</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6605"/>
				<updated>2018-11-26T21:46:09Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Replacement Variable Manipulation Modifiers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output. (as of Geeklog v2.2.1)&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6604</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6604"/>
				<updated>2018-11-26T21:13:21Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Replacement Variable Manipulation Modifiers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :h Call strip_tags on the variable before output.&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6603</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6603"/>
				<updated>2018-08-15T17:16:46Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* TEMPLATE_OPTIONS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL() (Note: This returns the current URL as PHP sees it on the server. If the server is setup to rewrite the URL then it may be different from the actual URL)&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6602</id>
		<title>Caching Template Library</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Caching_Template_Library&amp;diff=6602"/>
				<updated>2018-08-15T17:15:10Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* TEMPLATE_OPTIONS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction == &lt;br /&gt;
&lt;br /&gt;
The Caching Template Library (CTL) is the template engine in Geeklog. A template engine facilitates a manageable way to separate application logic and content from its presentation. This allows the programmer to focus specifically on the application and the template designer to focus on the presentation. It also allows site administrators to easily manipulate the look and feel of their site without having to know the application or become a programmer.&lt;br /&gt;
&lt;br /&gt;
The benefits of the Caching Template Library are that it adds the following features to Geeklog. These features benefit both the site administrator and the plugin developer.&lt;br /&gt;
&lt;br /&gt;
* Compiles templates to PHP code for enhanced page load speeds.&lt;br /&gt;
* Adds logic processing to the templates.&lt;br /&gt;
* Ability to specify multiple locations to search for templates.&lt;br /&gt;
&lt;br /&gt;
== Compiles Templates to PHP code == &lt;br /&gt;
&lt;br /&gt;
One of the unique aspects about the Caching Template Library is template compiling. This means the Caching Template Library reads the template files and creates PHP scripts from them. Once they are created, they are executed from then on. Therefore there is no costly template file parsing for each request. Each template can take full advantage of the PHP compiler and cache solutions such as eAccelerator, ionCube mmCache or Zend Accelerator to name a few. Some anecdotal experience with performance testing can be found in the forum.&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One design goal of the Caching Template Library is the separation of application logic and presentation logic. This means templates can certainly contain logic under the condition that it is for presentation only. Things such as checking if a specific variable is set and adjusting the display appropriately is a good example of presentation logic. Also, if you desire no logic in your templates you certainly can do so by boiling the content down to text and variables only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Not just for Templates ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog v2.1.3 you can set a View instead of a template file when using the Caching Template Library. A View is basically a large string of text that can be compiled by the Caching Template Library. The text string can there for contain the same type of logic processing, template variables and autotags as a normal template file. With the view, developers can even assign their own template variables or access the default ones automatically like site_url, anonymous_user, and device_mobile. The first plugin to support this is the Static Pages Plugin v1.6.9. For more information on how this works see [[Static_Pages_Plugin#Accessing_Geeklog_Variables_and_Logic_Processing |Static Pages plugin wiki page]].&lt;br /&gt;
&lt;br /&gt;
Template Blocks are supported via a View as well. The only thing that is not supported for Views is the ability to have a Template Block within another Template Block.&lt;br /&gt;
&lt;br /&gt;
== Multiple Template Source Paths ==&lt;br /&gt;
&lt;br /&gt;
There are many templates files within the Geeklog system, plus all the template files that plugins use as well. If you want to change the look and feel of a site, generally only a small number of template files are actually modified. Having the ability to specify multiple templates paths allows you to have a base location for templates, and then simply copy the ones you wish to modify to an alternative location (usually the /custom folder in the same directory.) This reduces the overall disk storage needed on the server, and also provides a method to quickly see which templates have been modified. It also means that your modified template files will not be overwritten during a software upgrade.&lt;br /&gt;
&lt;br /&gt;
Plugins can also support multiple template paths which allows for template files to be included with a plugin install for more than one theme. Currently the core plugins, media gallery and the forum support this. For more information on this and how to implement it please read [[Theme_Developers_Guide#Theme_Specific_Plugin_Templates |Theme Specific Plugin Templates]].&lt;br /&gt;
&lt;br /&gt;
== Benefits ==&lt;br /&gt;
&lt;br /&gt;
Benefits of the Caching Template Library include:&lt;br /&gt;
&lt;br /&gt;
* It is extremely fast.&lt;br /&gt;
* It is efficient since the PHP parser does the dirty work.&lt;br /&gt;
* No template parsing overhead, only compiles once.&lt;br /&gt;
* It is smart about recompiling only the template files that have changed.&lt;br /&gt;
* The {!if}..{!else}..{!endif} constructs are passed to the PHP parser, so the {!if…} expression syntax can be as simple or as complex an evaluation as you like.&lt;br /&gt;
* It is possible to embed PHP code right in your template files, although this may not be needed (nor recommended) since the engine is so customizable.&lt;br /&gt;
* Built-in caching support.&lt;br /&gt;
* Multiple template sources.&lt;br /&gt;
&lt;br /&gt;
Overall, the Caching Template Library brings a significant amount of value and features to a Geeklog site.&lt;br /&gt;
&lt;br /&gt;
= Developer Information = &lt;br /&gt;
&lt;br /&gt;
== Template Variable Naming Convention ==&lt;br /&gt;
&lt;br /&gt;
Template variables follow a strict naming convention. A template variable consist of letters, digits, one or more underscore, period, dash or square brackets, and are delimited by curly brackets. Examples can be found in Geeklog theme files (files with the extension thtml). &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{template_variable}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If any other character is found within curly brackets then the text is not considered a template variable at all, and therefor doesn’t follow the template class rules for unknown setting of remove, comment or keep. The text will just be left as is.&lt;br /&gt;
&lt;br /&gt;
There are a few special cases where a '$' and ':' may be used in a template variable. This includes the use of the [[Caching_Template_Library#Automatic_Language_File_Variables|Automatic Language File Variables]] and the [[Caching_Template_Library#Replacement_Variable_Manipulation_Modifiers |Variable Manipulation Modifiers]].&lt;br /&gt;
&lt;br /&gt;
== Version Checks ==&lt;br /&gt;
&lt;br /&gt;
You can tell that the caching template library is installed and what version of the library is running by checking if TEMPLATE_VERSION is defined using the PHP function defined().&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE_OPTIONS ==&lt;br /&gt;
&lt;br /&gt;
At the top of the file is an array of TEMPLATE_OPTIONS. These options are global options for all templates created by Geeklog. They are:&lt;br /&gt;
&lt;br /&gt;
''' 'path_cache' (required) '''&lt;br /&gt;
&lt;br /&gt;
This option points to the cache directory. If you don't like the name “layout_cache”, this is where you change it. By default it is equal to “$_CONF['path_data']”.”layout_cache/”.&lt;br /&gt;
&lt;br /&gt;
''' 'path_prefixes' (required) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of ALL paths under which templates may be found. The cached name of the template file is based on the path of the template file. These array entries are used to strip off the redundant portions of the path. The order they appear here is important because once a match is found other prefixes will not be checked. Basically they should be included in this entry with the longest paths going first.&lt;br /&gt;
&lt;br /&gt;
By default, the options are:&lt;br /&gt;
&lt;br /&gt;
* the root of your themes directories ($_CONF['path_html']/layout).&lt;br /&gt;
* the root of your plugins directory ($_CONF['path']/plugins).&lt;br /&gt;
* the root of your server ('/') Do not remove this one!!&lt;br /&gt;
&lt;br /&gt;
In a hosted environment, you might want to add your account's home directory before the last entry.&lt;br /&gt;
&lt;br /&gt;
''' 'unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the default unknown handler. If it isn't set, default unknowns become 'remove', as usual. The other options are 'comment' and 'keep'.&lt;br /&gt;
&lt;br /&gt;
''' 'force_unknowns' (optional) '''&lt;br /&gt;
&lt;br /&gt;
Sets the unknown handler regardless of the calling code's settings. This is useful for debugging a set of templates as you only have to modify the template class in one place.&lt;br /&gt;
&lt;br /&gt;
''' 'default_vars' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This is a list of template variables that is set for every instance of the template object. The most obvious use for this is stuff like $_CONF['site_url']. This way the theme author doesn't have to rely on the dev team remembering to include such variables in every template.&lt;br /&gt;
&lt;br /&gt;
The default values are:&lt;br /&gt;
&lt;br /&gt;
* 'site_url' ⇒ $_CONF['site_url']&lt;br /&gt;
* 'site_admin_url' ⇒ $_CONF['site_admin_url']&lt;br /&gt;
* 'layout_url' ⇒ $_CONF['layout_url']&lt;br /&gt;
* 'XHTML' ⇒ XHTML&lt;br /&gt;
* 'anonymous_user' ⇒ COM_isAnonUser(),&lt;br /&gt;
* 'device_mobile' ⇒ $_DEVICE-&amp;gt;is_mobile(),&lt;br /&gt;
* 'front_page' ⇒ COM_onFrontpage(),&lt;br /&gt;
* 'current_url' ⇒ COM_getCurrentURL()&lt;br /&gt;
&lt;br /&gt;
''' 'incl_phpself_header' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean option is used to control the inclusion of anti-spoofing text in the resulting cache files. It defaults to true. If your cache directories can be accessed by remote browser (because you cannot create files outside your webroot) you must set this value to true or risk a security issue with your cache files.&lt;br /&gt;
&lt;br /&gt;
When true, the following is added to the top of every cached template file with filename replaced with the current filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php if (strpos($_SERVER['PHP_SELF'], basename($filename)) !== false) {&lt;br /&gt;
    die ('This file can not be used on its own.');&lt;br /&gt;
} ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' 'cache_by_language' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This boolean variable determines whether or not to create unique cache files per language instance. When cache_by_language is on, a directory is created under the data/layout_cache directory for each language enabled and accessed on your website. Templates that take advantage of the Automatic Language file variables features are described below. These variables are replaced when the cache file is created instead of dynamically each time the cache is hit.&lt;br /&gt;
&lt;br /&gt;
Unless you have tight filesystem restrictions, you should set this variable to true to maximize your potential system speed up.&lt;br /&gt;
&lt;br /&gt;
''' 'hook' (optional) '''&lt;br /&gt;
&lt;br /&gt;
This advanced feature is designed for use by developers and theme makers. It is described more fully elsewhere in this documentation. It provides ways for a developer to hook calls to various methods on the Template class in order to modify the generated output without modifying the code creating the output.&lt;br /&gt;
&lt;br /&gt;
== TEMPLATE-&amp;gt;set_root() ==&lt;br /&gt;
&lt;br /&gt;
The set_root method now accepts an array of root directories. When files are added to the class using set_file, the files are checked against the array of root directories in order. The first path listed overrides subsequent paths. So the most common use for multiple roots is in plugins that might be themed. The theme directory should come first followed by the plugin's template directory. That way the theme's file take precedence over the plugin's default templates.&lt;br /&gt;
&lt;br /&gt;
Plugins typically create templates using a function to guess at the correct path:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath ($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            if (empty ($path)) {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            } else {&lt;br /&gt;
                $layout_path = $_CONF['path_layout'] . 'calendar/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            if (is_dir ($layout_path)) {&lt;br /&gt;
                $retval = $layout_path;&lt;br /&gt;
            } else {&lt;br /&gt;
                $retval = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
                if (!empty ($path)) {&lt;br /&gt;
                    $retval .= '/' . $path;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return $retval;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is potentially a problem if the theme doesn't copy over all the files needed by set_file. Now this is possible:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $template = new Template(&lt;br /&gt;
                        array($_CONF['path_layout'].'calendar/additional/path',&lt;br /&gt;
                              $_CONF['path'].'plugins/calendar/templates/additional/path'&lt;br /&gt;
                             )&lt;br /&gt;
                  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        function calendar_templatePath($path = '')&lt;br /&gt;
        {&lt;br /&gt;
            global $_CONF;&lt;br /&gt;
 &lt;br /&gt;
            $layout_path = $_CONF['path_layout'] . 'calendar';&lt;br /&gt;
            $plugin_path = $_CONF['path'] . 'plugins/calendar/templates';&lt;br /&gt;
            if (!empty($path)) {&lt;br /&gt;
                $layout_path .= '/' . $path;&lt;br /&gt;
                $plugin_path .= '/' . $path;&lt;br /&gt;
            }&lt;br /&gt;
 &lt;br /&gt;
            return Array($layout_path, $plugin_path);&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        $template = new Template(calendar_templatePath('additional/path'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Another benefit of this is that if you only want to modify a subset of a plugin's templates for your theme, you only need to put the subset of files in the theme directory. Having multiple root directories means any files not in the themes directory are taken from the default directory.&lt;br /&gt;
&lt;br /&gt;
== Replacement Variable Manipulation Modifiers ==&lt;br /&gt;
&lt;br /&gt;
Modifiers can be applied to replacement variables using the format {variable:m} where variable is a normal replacement variable and m is the modifier. Multiple modifiers can be applied in series {variable:u:s}. The following modifiers currently exist:&lt;br /&gt;
&lt;br /&gt;
* :u Call urlencode on the variable before output.&lt;br /&gt;
* :s Call htmlspecialchars on the variable before output.&lt;br /&gt;
* :t### Truncates the variable to ### characters.&lt;br /&gt;
&lt;br /&gt;
Using these options should be done with care, making sure the calling code hasn't already applied an output filter to the data. Likewise, these calls should not be used on any variable containing HTML.&lt;br /&gt;
&lt;br /&gt;
== Automatic Language File Variables ==&lt;br /&gt;
&lt;br /&gt;
Add any text you want to the template while still following the Geeklog text internationaliztion guidelines. Any variable in the form {$LANG_abc[xx]} will lookup the index in the stated language array. So {$LANG_ADMIN['save']} will be replaced by the same text as that placed on all the Save buttons in the system. Template files are no longer limited to the text labels delivered by the coder. Text from the language variable is automatically passed through htmlspecialchars before output. Language variables cannot be used in simple action variables. Advanced action variables can use them.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// code like this&lt;br /&gt;
  $T-&amp;gt;set_var('lang_username',$LANG_USER['name']);&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
  $T-&amp;gt;set_var('username', $username);&lt;br /&gt;
&lt;br /&gt;
// and the template&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{lang_username}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// becomes&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{$LANG_USER[name]}:&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{username}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
There are plans to do research at some future date into which is faster, setting a variable from a LANG array, or putting the LANG array reference directly into the template.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
One way to save on having a large number of template files is use template blocks. 1 or more blocks can exist inside a template file and these blocks can also be nested (blocks within blocks). In the example below the template file contains a select control called &amp;quot;select1&amp;quot; with a template variable called &amp;quot;options&amp;quot;. There is also a template block called &amp;quot;select-option&amp;quot; with some other variable names.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;select name=&amp;quot;select1&amp;quot;&amp;gt;&lt;br /&gt;
{options}&lt;br /&gt;
&amp;lt;/select&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- BEGIN select-option --&amp;gt;&lt;br /&gt;
&amp;lt;option value=&amp;quot;{value}&amp;quot; {selected}&amp;gt;{option_name}&amp;lt;/option&amp;gt;&lt;br /&gt;
&amp;lt;!-- END select-option --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The sample PHP code below makes use of this template and it's block and loads in some options from the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$t = COM_newTemplate($_CONF['path_layout']);&lt;br /&gt;
$t -&amp;gt;set_file('control', 'control.thtml');&lt;br /&gt;
$t -&amp;gt;set_block('control', 'select-options'); &lt;br /&gt;
&lt;br /&gt;
$selectedvalue = 2;&lt;br /&gt;
$sql = &amp;quot;SELECT * FROM some_table&amp;quot;;&lt;br /&gt;
$result = DB_query($sql);&lt;br /&gt;
$numRows = DB_numRows($result);&lt;br /&gt;
for ($i = 0; $i &amp;lt; $numRows; $i++) {&lt;br /&gt;
    $A = DB_fetchArray($result, true);&lt;br /&gt;
    $t -&amp;gt;set_var('value', $A['somevalue']);&lt;br /&gt;
    $t -&amp;gt;set_var('option_name', $A['somename']);&lt;br /&gt;
    if ($A['somevalue'] == $selectedvalue) {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', 'selected=&amp;quot;selected&amp;quot;');&lt;br /&gt;
    } else {&lt;br /&gt;
        $t -&amp;gt;set_var('selected', '');&lt;br /&gt;
    }&lt;br /&gt;
    $t-&amp;gt;parse('options', 'select-option', true);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$t-&amp;gt;finish($t-&amp;gt;parse('output', 'control'));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Logic Processing ==&lt;br /&gt;
&lt;br /&gt;
One of the biggest benefits of the Template Caching Library is the ability to place logic into the templates. This section assumes you know how to use the old template library.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The template library uses variable substitution in template files to create output. All template constructs are contained within braces: {variable}. The simplest construct is the variable as just shown.&lt;br /&gt;
The new library adds action variables to the mix. Actions are also contained within braces and the first character of an action is an exclaimation point: '''{!'''action parameters'''}'''. Actions usually do not output anything to the final output. Instead they control what is output around them. In these cases, the action will act as a block within the template contained between two actions. The second action is usually the same as the first with the word 'end' prepended: '''{!'''endaction'''}'''.&lt;br /&gt;
&lt;br /&gt;
CTL v2.2 introduced advanced actions. These have the format '''{!!'''action parameter '''!!}'''. The space and exclamation point are required. Advanced actions allow you to place more complicated values as the parameter field. Instead of assuming parameters are template variables, advanced action parameters that reference template variables must include the braces just like they do in other parts of the template. So while a simple if might look like this '''{!'''if var'''}''', the advanced if can look like this '''{!!'''if {var} == 'a' || {var} == 'b' '''!!}''' (note the number of exclamation points) Advanced actions are closed by standard '''{!'''endaction'''}''' constructs. (note: one exclamation point).  Complex conditions can also contain calls to any global function and if you want you can also include template variables within the function call (ie as a function variable).&lt;br /&gt;
&lt;br /&gt;
In this example we use a template variable {uid} (defined by some other process) in an Advanced Action. We use it to call the function COM_isAnonUser to see if the id is the anonymous Geeklog user:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if COM_isAnonUser({uid}) !!}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;User {uid} is NOT an anonymous user.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
==== Simple Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!if variable}&lt;br /&gt;
{!endif}&lt;br /&gt;
|| The !if action shows the contained block if the variable evaluates to true. Note that the value 0 evaluates to true.&lt;br /&gt;
|-&lt;br /&gt;
|| {!else}&lt;br /&gt;
|| This action must appear between !if and !endif. It breaks the !if block into true and false halves. The block from !if to !else contains the text displayed if the condition is true. The block between !else and !endif contains the text displayed if the condition is false. &lt;br /&gt;
|-&lt;br /&gt;
|| {!elseif variable}&lt;br /&gt;
|| This combines else and if together to allow multiple possible conditions to be evaluated.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Looping Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!while variable}&lt;br /&gt;
{!endwhile}&lt;br /&gt;
|| Similar to if, the contained block is displayed repeatedly as long as variable is true. If the variable starts out false the block is never displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!loop variable}&lt;br /&gt;
{!endloop}&lt;br /&gt;
|| Creates a variable called variable__loopvar. The contained block is executed 'variable' times with varialbe__loopvar counting from 1 to 'variable' for each iteration. If variable is less than zero, counting goes downward starting at -1. variable__loopvar is deleted (unset) when the loop exits.&lt;br /&gt;
|-&lt;br /&gt;
|| {!break}&lt;br /&gt;
|| Exits a loop prematurely. The rest of the block is not processed and processing continues after the !endwhile or !endloop.&lt;br /&gt;
|-&lt;br /&gt;
|| {!continue}&lt;br /&gt;
|| Ends a loop block prematurely. The rest of the block is not processed and processing continues for the next iteration of the loop.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc variable}&lt;br /&gt;
|| The variable is incremented by 1. If it is a non-numeric string, the value '1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec variable}&lt;br /&gt;
|| The variable is decremented by 1. If it is a non-numeric string, the value '-1' is placed in it.&lt;br /&gt;
|-&lt;br /&gt;
|| {!inc+echo variable}&lt;br /&gt;
|| As !inc and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!dec+echo variable}&lt;br /&gt;
|| As !dec and the number is displayed.&lt;br /&gt;
|-&lt;br /&gt;
|| {!unset variable}&lt;br /&gt;
|| Removes the variable from the template's internal variable list.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Advanced Actions ====&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
! Action || Description&lt;br /&gt;
|-&lt;br /&gt;
|| {!!if condition !!}&lt;br /&gt;
|| The condition may contain any template construct that does not end with !}.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!while condition !!}&lt;br /&gt;
|| Works like the simple {!while var} but can take any complex condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!global var,… !!}&lt;br /&gt;
|| 	Pulls the global vars into the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!echo condition !!}&lt;br /&gt;
|| Echo's the complex condition to the cached PHP output.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!set var value/expression !!}&lt;br /&gt;
|| Assign the variable the listed value or set any complex expression or condition.&lt;br /&gt;
|-&lt;br /&gt;
|| {!!autotag ... !!}&lt;br /&gt;
|| Works like so '''{!!autotag story:welcome !!}''' (this is for autotag '''[story:welcome]''') and allows you to set an autotag in a template file. &lt;br /&gt;
&lt;br /&gt;
Works with autotags that have a close tag as well but you must encompass the entire autotag (including the close tag) in one action and include one half of the square brackets for example '''[tag:foo]some text here[/tag]''' would become '''{!!autotag tag:foo]some text here[/tag !!}''' in the template. &lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot embed template variables within autotags or any other Actions.&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
&lt;br /&gt;
You can include comments in the template files that do not appear in the cached PHP file by enclosing the comment within {# and #} symbols. This is useful for explaining why you have some weird construct in your code without cluttering the cached template with lots of HTML comments.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Example 1 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if, elseif, and else condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {display_type} == '12' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals 12.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!!elseif {display_type} == 'yawn' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable equals yawn.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when display_type template variable is anything else.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 2 ====&lt;br /&gt;
In this example we use a template variable in an Advanced Action if condition:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{!!if {template_var} == 'info' OR {template_var} == 'info2' !!}&lt;br /&gt;
&amp;lt;p&amp;gt;Display this text when template_var equals info or info2.&amp;lt;/p&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 3 ====&lt;br /&gt;
In this (contrived) example, the only template variable is 'count' and it is set to 3:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{# This is an example of a comment #}&lt;br /&gt;
&lt;br /&gt;
{!!set count 3 !!}&lt;br /&gt;
&lt;br /&gt;
{!loop count}&lt;br /&gt;
{count__loopvar} of {count}: {!inc+echo total}&lt;br /&gt;
{!!if count__loopvar == &amp;quot;2&amp;quot; !!}{!inc count}{!endif}&amp;lt;br&amp;gt;&lt;br /&gt;
{!endloop}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the template is parsed twice without resetting count between parses, the output looks like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 of 3: 1&lt;br /&gt;
2 of 3: 2&lt;br /&gt;
3 of 4: 3&lt;br /&gt;
4 of 4: 4&lt;br /&gt;
1 of 4: 5&lt;br /&gt;
2 of 4: 6&lt;br /&gt;
3 of 5: 7&lt;br /&gt;
4 of 5: 8&lt;br /&gt;
5 of 5: 9&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example 4 ====&lt;br /&gt;
This example is Geeklog specific to help illustrate how you might use even the simplest !if construct:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( $_USER['uid'] &amp;gt;= 2 ) {  // user is logged in...&lt;br /&gt;
    $T-&amp;gt;set_var('onlyloggedinusers', 'Some feature only for logged in users');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the template, you can now check whether the user is logged in by checking for the existence of the {onlyloggedinusers} variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;pageheader&amp;quot;&amp;gt;&lt;br /&gt;
  Show the page header&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
{!if onlyloggedinusers}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;Logged in users can do more here, thanks for logging in!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!else}&lt;br /&gt;
  &amp;lt;div class=&amp;quot;boldtext&amp;quot;&amp;gt;If you login, you can do more!&amp;lt;/div&amp;gt;&lt;br /&gt;
{!endif}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple example, but it does illustrate the capability and the power. No longer in the PHP code do you need to handle the non-logged in case.&lt;br /&gt;
&lt;br /&gt;
== PHP Code in a Template Files ==&lt;br /&gt;
&lt;br /&gt;
This feature allows you to embed PHP code directly in templates. To embed PHP code directly in a template, use the following example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;welcomeanddate-text&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;span class=&amp;quot;gl_user-menu-right&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php global $_USER, $_CONF; if (isset($_USER['uid']) &amp;amp;&amp;amp; $_USER['uid'] &amp;gt; 1) { ?&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/usersettings.php?mode=edit&amp;quot;&amp;gt;{$LANG01[48]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=logout&amp;quot;&amp;gt;{$LANG01[35]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } else {&lt;br /&gt;
if ($_CONF['disable_new_user_registration']==0) {?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=new&amp;quot;&amp;gt;{$LANG04[27]}&amp;lt;/a&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;{site_url}/users.php?mode=login&amp;quot;&amp;gt;{$LANG01[58]}&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;?php } ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice how all PHP is surrounded by &amp;lt;?php ''' php_code_here ''' ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is another example that will return the template variable 'title' from the template class (if it is set).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
    echo $this-&amp;gt;get_var('title');&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The most common problem you will run into with the template cache is forgetting they are there. If you go into a .thtml file and make a change and it isn't showing up, you may need to delete the cached file as the algorithm to overwrite them only works when the file dates are correct. Some FTP systems and web consoles screw up the file times of uploaded files preventing the class from updating the cached PHP file. To ease this process, there is an entry in the Admin Command &amp;amp; Control screen labeled Clear Template Cache.&lt;br /&gt;
&lt;br /&gt;
== Tip 'n Tricks ==&lt;br /&gt;
&lt;br /&gt;
The Caching Template Class works with variables and array's may be used in its interface (API). You may encounter a GOTCHA when you mix simple arrays and hashes in some places.&lt;br /&gt;
&lt;br /&gt;
The set_var call has two forms: set_var($var_name, $var_value) and set_var($var_names_array). This array is definitely a hash (a key-value pair).  &lt;br /&gt;
The get_var call has two forms: get_var($var_name) and get_var($var_names_array). This array is definitely a simple array (numeric keys).  &lt;br /&gt;
So, setting variables using set_var($myArray) would work, while get_var($myArray) would NOT work. Instead use get_var(array_keys($myArray)).  &lt;br /&gt;
The API call get_vars however is suited to accept a hash, but only a hash.&lt;br /&gt;
&lt;br /&gt;
Same goes for clear_var($myArray). One easily mistakes here when processing data from mySql as rows: set_var($row) and clear_var(array_keys($row)).&lt;br /&gt;
And now, there is no API call clear_vars available.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, the following could be useful:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('newvar', 'newvalue'); ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Using php code in a template, a global variable could be used to hand over data to the next template in a chain of templates. In case the template does specific calculations, generates a graph, or else. This comes in handy with auto tags.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php $GLOBALS['myVar'] = $this-&amp;gt;get_var('some_variable'); ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php $this-&amp;gt;set_var('some_variable', $GLOBALS['myVar']) ?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page is based on original content from the glFusion Wiki - https://www.glfusion.org/wiki/glfusion:development:usingtemplates - modified for Geeklog - Licensed under [https://creativecommons.org/licenses/by-sa/4.0/ CC Attribution-Share Alike v4.0].&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6601</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6601"/>
				<updated>2018-06-26T15:17:49Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Sites */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
* Backup the server files and database.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6600</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Main_Page&amp;diff=6600"/>
				<updated>2018-06-26T14:41:51Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Logo.gif]]&lt;br /&gt;
&lt;br /&gt;
== Geeklog Documentation ==&lt;br /&gt;
&lt;br /&gt;
This is the main entry for Documentation for the [https://www.geeklog.net/ Geeklog] CMS and weblog engine.  The current version is 2.2.0. For more information about this version please read [https://www.geeklog.net/article.php/geeklog-v2-2-0 this announcement article].&lt;br /&gt;
&lt;br /&gt;
If you are upgrading from Geeklog v2.1.3 or older please make sure your 3rd party Geeklog plugins are updated to the latest version and support Geeklog v2.2.0. Plugins are now required to use the function COM_createHTMLDocument. This replaces the depreciated functions COM_siteHeader and COM_siteFooter. If you are unsure if a plugin supports Geeklog v2.2.0 then either disable it before you upgrade Geeklog, or uninstall it.&lt;br /&gt;
&lt;br /&gt;
Also, there have been some changes with blocks and topics between Geeklog 2.0.0 and 1.8.2sr1 so not all plugins may work with 2.1.0 or higher unless they have been updated. If you are upgrading your site that is 2.0.0 or older make sure all the plugins you use are compatible with Geeklog 2.1.0 or higher.&lt;br /&gt;
&lt;br /&gt;
This documentation is a result of community action.  Everyone is invited to [http://wiki.geeklog.net/wiki/index.php?title=Special:Userlogin sign up] and participate.  If you see an omission you can fill it in.  If you see a mistake, correct it.  If you see where things could be better organized, change it.  If you have a note about a particular configuration, add it.  In other words: We need your help to make it better!&lt;br /&gt;
&lt;br /&gt;
* [[Geeklog Documentation]]:&lt;br /&gt;
*# [[Introduction]]&lt;br /&gt;
*# [[Installation]]&lt;br /&gt;
*# [[Administration]]&lt;br /&gt;
*# [[Users Documentation|User's Documentation]]&lt;br /&gt;
*# [[Programmers/Developers Documentation]]&lt;br /&gt;
* Quick Links:&lt;br /&gt;
*# [[Complete Table of Contents]]&lt;br /&gt;
*# [[Special:AllPages|List of all Articles]]&lt;br /&gt;
*# [[Getting Started]] with Geeklog Development&lt;br /&gt;
*# [[Google Summer of Code]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6599</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6599"/>
				<updated>2018-06-26T14:28:26Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Geeklog Sites */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download. (may have to delete template cache)&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6598</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6598"/>
				<updated>2018-05-24T16:16:37Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Other Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* If you change the database name on the Geeklog upgrade (which we have been for each new version) remember to change the cron-jobs to reflect the new database name, username, and password&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download.&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6597</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6597"/>
				<updated>2018-05-24T14:29:47Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* Other Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
** If updating lib-custom make sure to add the functions phpblock_current_versions_downloads and phpblock_whos_new &lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download.&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6596</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6596"/>
				<updated>2018-05-23T14:28:43Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* glnet_curve Theme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. No other themes should be present on Geeklog.net.&lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* &amp;lt;tt&amp;gt;lib-common.php&amp;lt;/tt&amp;gt;: add the &amp;lt;code&amp;gt;require_once&amp;lt;/code&amp;gt; line for the Bad Behavior plugin. '''Do this after the upgrade of Geeklog.'''&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download.&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6595</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6595"/>
				<updated>2018-05-23T14:27:49Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* glnet_curve Theme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. &lt;br /&gt;
** On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. &lt;br /&gt;
** As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* &amp;lt;tt&amp;gt;lib-common.php&amp;lt;/tt&amp;gt;: add the &amp;lt;code&amp;gt;require_once&amp;lt;/code&amp;gt; line for the Bad Behavior plugin. '''Do this after the upgrade of Geeklog.'''&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download.&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6594</id>
		<title>Geeklog Release Procedures</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Geeklog_Release_Procedures&amp;diff=6594"/>
				<updated>2018-05-23T14:26:30Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: /* glnet_curve Theme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page outlines the necessary steps to perform before, during, and after the release of a new Geeklog version.&lt;br /&gt;
&lt;br /&gt;
= Pre-Announcements =&lt;br /&gt;
&lt;br /&gt;
* Obviously, plans for a new release should have been discussed on [http://eight.pairlist.net/mailman/listinfo/geeklog-devel geeklog-devel]. For security releases, the discussion may happen on [http://www.geeklog.net/staticpages/index.php?page=GeeklogSecurity geeklog-security] only.&lt;br /&gt;
* Notify the [http://eight.pairlist.net/mailman/listinfo/geeklog-translations geeklog-translations] mailing list to give translators a chance and a timeframe to update their translations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= The Tarball =&lt;br /&gt;
&lt;br /&gt;
* Make sure you update history file in docs with version and release date (and readme in root directory if needed) &lt;br /&gt;
* Confirm correct Geeklog version number in /public_html/sitconfig.php, /public_html/admin/install/classes/installer.class.php, and /build.xml&lt;br /&gt;
* Make sure all language files are synched &lt;br /&gt;
** This process will use the English language files and synch with all other languages for Geeklog, The Installer, and all core plugins&lt;br /&gt;
** Open your command prompt and to the top directory of your local Geeklog repository&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat lang&lt;br /&gt;
** Once complete commit any updated language files &lt;br /&gt;
* For building an install package we use phing (which uses a config file called “build.xml” in the top directory). &lt;br /&gt;
** Go to your Geeklog repository top directory in command prompt&lt;br /&gt;
** Confirm latest repository and make sure no old compressed install packages exist (or they will be rolled into the new package).&lt;br /&gt;
** Type: .\system\build\vendor\phing\phing\bin\phing.bat dist&lt;br /&gt;
** Once the process complete you will get a file “geeklog-2.1.2.tar.gz” in the top directory&lt;br /&gt;
** If this is a beta or release candidate then the file will need to be renamed to: geeklog-2.1.2-b1.tar.gz or: geeklog-2.1.2-rc1.tar.gz&lt;br /&gt;
* Create a new release on GitHub&lt;br /&gt;
** Visit https://github.com/Geeklog-Core/geeklog/releases&lt;br /&gt;
** Create a release and make sure to tag it the correct version number (it will be tagged in the repository), for example: v2.1.2 or v2.1.2-rc1 (for release candidate) or v2.1.2-b1 (for beta)&lt;br /&gt;
* Visit Geeklog.net&lt;br /&gt;
** Add the new release to the downloads plugin&lt;br /&gt;
** Add a new article about the release pointing to the correct download&lt;br /&gt;
* unpack tarball on the server&lt;br /&gt;
* update site&lt;br /&gt;
&lt;br /&gt;
= Updating geeklog.net =&lt;br /&gt;
&lt;br /&gt;
* '''IMPORTANT:''' Disable Bad behavior plugin before upgrading Geeklog.net and then re-enable after. If you don't it may cause issues.&lt;br /&gt;
&lt;br /&gt;
The following files need special handling when updating geeklog.net:&lt;br /&gt;
&lt;br /&gt;
== glnet_curve Theme ==&lt;br /&gt;
* As of Geeklog 2.1.2 the glnet_curve is now the default theme used by Geeklog.net. It is a copy of on the Denim Curve theme with only a few changes to the header and footer template files (along with the name changes, etc.. required in functions.php). This theme is based on the Denim theme which is also required in the themes directory. On upgrades for the glnet_curve remember to update the jquery_ui directory and the images directory with any changes from the Denim Curve theme. The fonts, css, css_ltr, and css_rtl directories are also required. As far as template files are concerned only the files we modified directly for Geeklog.net should be in the glnet_curve directory and the Denim theme should be the stock theme from the release. Most changes in these files are marked with the&amp;quot;GLNET CUSTOM&amp;quot; comment.&lt;br /&gt;
* For glnet_curve theme take a copy of the &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; from denim and add it to glnet_curve. Make sure the version number is visible and add the &amp;quot;hosted by pair.com&amp;quot; link (as per our agreement with pair Networks).&lt;br /&gt;
* The Download block on the top right uses a block header template without a title, so add this to the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt;: &amp;lt;pre&amp;gt;$_BLOCK_TEMPLATE['download'] = 'blockheader-notitle-right.thtml,blockfooter.thtml';&amp;lt;/pre&amp;gt; and make sure the &amp;lt;tt&amp;gt;blockheader-notitle-right.thtml&amp;lt;/tt&amp;gt; template file exists.&lt;br /&gt;
&lt;br /&gt;
== Other Files ==&lt;br /&gt;
* remove the bundled &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;robots.txt&amp;lt;/tt&amp;gt; and use the copies already present on the webserver instead&lt;br /&gt;
* check &amp;lt;tt&amp;gt;db-config.php&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; for any required changes&lt;br /&gt;
* &amp;lt;tt&amp;gt;lib-common.php&amp;lt;/tt&amp;gt;: add the &amp;lt;code&amp;gt;require_once&amp;lt;/code&amp;gt; line for the Bad Behavior plugin. '''Do this after the upgrade of Geeklog.'''&lt;br /&gt;
&lt;br /&gt;
= Information to Update =&lt;br /&gt;
&lt;br /&gt;
== Geeklog Sites ==&lt;br /&gt;
&lt;br /&gt;
* Create a new download for the install in the Downloads plugin. Easiest way is to copy and older version of a Geeklog download. &lt;br /&gt;
** A full install tarball download belongs in the '''Geeklog''' category and the '''Geeklog''' project. An Update tarball belongs in the sub category '''Updates'''.&lt;br /&gt;
** Make sure any release previous betas or release candidates are moved to '''Old Versions''' Downloads category.&lt;br /&gt;
** Confirm Downloads button on homepage block points to the latest Geeklog download.&lt;br /&gt;
* Publish an '''article''' on geeklog.net:&lt;br /&gt;
** summarize the changes in this release&lt;br /&gt;
** include a link to the entry in the download area&lt;br /&gt;
** Convention for the story ID: &amp;lt;tt&amp;gt;geeklog-x.y.z&amp;lt;/tt&amp;gt;, e.g. geeklog-1.5.2, geeklog-1.4.0sr6&lt;br /&gt;
** Add story to the Geeklog topic and the Announcements topic (default). Make sure both are set to inherit &lt;br /&gt;
** Announcements of new versions go into the [http://www.geeklog.net/index.php?topic=announcements Announcements] topic. For security releases, either post the announcement in the [http://www.geeklog.net/index.php?topic=Security Security] topic, or post two articles (one in Announcements and the details of the security issues in Security).&lt;br /&gt;
** don't forget to send '''pingbacks''' and '''ping''' weblog directories&lt;br /&gt;
* Update the '''versionchecker.php script''' (not for betas/release candidates).&lt;br /&gt;
** Once updated, the new version of the script should be added to the [http://project.geeklog.net/cgi-bin/hgwebdir.cgi/tools/ tools repository].&lt;br /&gt;
* Send out an '''email''' to the [http://eight.pairlist.net/mailman/listinfo/geeklog-announce geeklog-announce] mailing list.&lt;br /&gt;
** Provide a brief description of the release and link to the geeklog.net article for details.&lt;br /&gt;
* Update the '''wiki frontpage''' (not for betas/release candidates)&lt;br /&gt;
* Update the '''GitHub Issue Tracker''' (not for betas/release candidates). Make sure you have a later milestone create and then move all incomplete issues and feature requests from current milestone to a later milestone. Close current milestone&lt;br /&gt;
* Notify Ironmax at Spacequad.com that the demo site needs to be updated to use the latest version of Geeklog (not for betas/release candidates). Once updated you will also need to update the Resources block with the correct version number of the demo site.&lt;br /&gt;
&lt;br /&gt;
== External Sites ==&lt;br /&gt;
&lt;br /&gt;
These sites should only be notified about final and security releases (i.e. not for betas and release candidates):&lt;br /&gt;
&lt;br /&gt;
* [http://freshmeat.net/projects/geeklog/ freshmeat.net]&lt;br /&gt;
* [http://cmsmatrix.org/matrix/cms-matrix/geeklog cmsmatrix.org]&lt;br /&gt;
* [http://php.opensourcecms.com/scripts/details.php?scriptid=32&amp;amp;name=Geeklog opensourcecms.com]&lt;br /&gt;
* [https://sourceforge.net/projects/geeklog sourceforge.net]&lt;br /&gt;
* [https://www.ohloh.net/p/geeklog ohloh.net]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Internals]]&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Upgrade_Instructions&amp;diff=6593</id>
		<title>Upgrade Instructions</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Upgrade_Instructions&amp;diff=6593"/>
				<updated>2018-03-30T19:33:24Z</updated>
		
		<summary type="html">&lt;p&gt;Tom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Upgrading is no different than a New Installation except your database already exists and needs to be updated.&lt;br /&gt;
&lt;br /&gt;
Take extreme care to back up any files from your current Geeklog installation that have any custom code in them, especially lib-custom.php (where all custom code should reside). Be sure to back up any modified themes, images, and static pages from your current installation.&lt;br /&gt;
&lt;br /&gt;
Also, please be sure to back up your database. We can't stress the importance of backing up your files and database enough.&lt;br /&gt;
&lt;br /&gt;
'''YOU HAVE BEEN WARNED'''.&lt;br /&gt;
&lt;br /&gt;
:1. Download the current version of Geeklog from Geeklog.net.&lt;br /&gt;
:2. Unpack the downloaded tarball file by running: &lt;br /&gt;
::tar -zxvf geeklog-2.0.0.tar.gz&lt;br /&gt;
::'''Note:''' Some users have reported that WinZip corrupts certain Geeklog files during decompression. This will cause errors during the installation process. You are strongly urged not to use WinZip. Try 7-Zip or WinRAR if you must decompress the file locally.&lt;br /&gt;
:3. Place the contents of geeklog-2.0.0/ into the same directory your old installation was located. For instance, if your old Geeklog was in /usr/home/www/geeklog/, then your new installation should also be in /usr/home/www/geeklog/.&lt;br /&gt;
:4. Depending on the version you're upgrading from:&lt;br /&gt;
::* '''When upgrading from Geeklog 1.4.1 or earlier:''' Put the config.php files from your old install back into their place now (the main config.php and those for the plugins). The install script will read these files during the upgrade to pre-populate the new Configuration admin panel with your settings. If you skip this step, you will end up with default settings for Geeklog and the pre-installed plugins.&lt;br /&gt;
::* '''When upgrading from Geeklog 1.5.0 or later:''' Put the db-config.php and siteconfig.php from your old install back into their place now, overwriting the files of the same name that came in the tarball. Otherwise, you would have to enter your database credentials and other information during the upgrade process again.&lt;br /&gt;
:5. Open your browser and navigate to the Geeklog installation wizard file admin/install/index.php on your web server. The path to this file will depend on where you chose to put the Geeklog files on your web server. The default location is:&lt;br /&gt;
:: http://[your_geeklog_site]/admin/install/index.php&lt;br /&gt;
&lt;br /&gt;
:6. The Geeklog installation wizard was designed to automate the upgrade process. Simply follow the installation steps.&lt;br /&gt;
&lt;br /&gt;
Once you have completed the upgrade be sure to delete the admin/install directory.&lt;/div&gt;</summary>
		<author><name>Tom</name></author>	</entry>

	</feed>