2001-07-24 11:39:00 +00:00
< ? php
2005-04-09 12:26:45 +00:00
/**
*
* @ package phpBB3
* @ version $Id $
2005-10-02 17:49:16 +00:00
* @ copyright ( c ) 2005 phpBB Group , sections ( c ) 2001 ispi of Lincoln Inc
2005-04-09 12:26:45 +00:00
* @ license http :// opensource . org / licenses / gpl - license . php GNU Public License
*
2002-07-14 14:33:30 +00:00
*/
2001-07-24 11:39:00 +00:00
2006-03-19 14:23:21 +00:00
/**
*/
if ( ! defined ( 'IN_PHPBB' ))
{
exit ;
}
2005-04-09 12:26:45 +00:00
/**
* @ package phpBB3
*
* Template class .
*
* psoTFX - Completion of file caching , decompilation routines and implementation of
* conditionals / keywords and associated changes
*
* The interface was inspired by PHPLib templates , and the template file ( formats are
* quite similar )
*
* The keyword / conditional implementation is currently based on sections of code from
* the Smarty templating engine ( c ) 2001 ispi of Lincoln , Inc . which is released
* ( on its own and in whole ) under the LGPL . Section 3 of the LGPL states that any code
* derived from an LGPL application may be relicenced under the GPL , this applies
* to this source
*
* DEFINE directive inspired by a request by Cyberalien
*/
2003-07-13 15:13:59 +00:00
class template
2003-04-23 14:55:13 +00:00
{
2001-07-24 11:39:00 +00:00
// variable that holds all the data we'll be substituting into
2002-07-14 14:33:30 +00:00
// the compiled templates. Takes form:
// --> $this->_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value
2001-07-24 11:39:00 +00:00
// if it's a root-level variable, it'll be like this:
2002-07-14 14:33:30 +00:00
// --> $this->_tpldata[.][0][varname] == value
2001-07-24 11:39:00 +00:00
var $_tpldata = array ();
2001-08-30 22:20:23 +00:00
2002-07-14 14:33:30 +00:00
// Root dir and hash of filenames for each template handle.
2002-06-22 11:48:10 +00:00
var $root = '' ;
2003-07-17 15:16:25 +00:00
var $cachepath = '' ;
2002-07-14 14:33:30 +00:00
var $files = array ();
2001-08-30 22:20:23 +00:00
2002-07-14 14:33:30 +00:00
// this will hash handle names to the compiled/uncompiled code for that handle.
2001-07-24 11:39:00 +00:00
var $compiled_code = array ();
2001-08-30 22:20:23 +00:00
2002-07-14 14:33:30 +00:00
// Various counters and storage arrays
var $block_names = array ();
var $block_else_level = array ();
var $block_nesting_level = 0 ;
2003-04-23 14:55:13 +00:00
var $static_lang ;
2005-12-04 20:25:51 +00:00
/**
* Set template location
* @ public
*/
2003-09-29 00:20:17 +00:00
function set_template ( $static_lang = false )
2001-07-24 11:39:00 +00:00
{
2003-07-13 15:13:59 +00:00
global $phpbb_root_path , $config , $user ;
2003-03-18 14:58:07 +00:00
2005-12-22 16:28:27 +00:00
if ( file_exists ( $phpbb_root_path . 'styles/' . $user -> theme [ 'template_path' ] . '/template' ))
2003-07-13 15:13:59 +00:00
{
2005-12-22 16:28:27 +00:00
$this -> root = $phpbb_root_path . 'styles/' . $user -> theme [ 'template_path' ] . '/template' ;
$this -> cachepath = $phpbb_root_path . 'cache/tpl_' . $user -> theme [ 'template_path' ] . '_' ;
2003-07-13 15:13:59 +00:00
}
2001-07-24 11:39:00 +00:00
2003-04-23 14:55:13 +00:00
$this -> static_lang = $static_lang ;
2001-07-24 11:39:00 +00:00
return true ;
}
2005-12-04 20:25:51 +00:00
/**
* Set custom template location ( able to use directory outside of phpBB )
* @ public
*/
2005-10-09 17:59:27 +00:00
function set_custom_template ( $template_path , $template_name , $static_lang = false )
{
global $phpbb_root_path ;
$this -> root = $template_path ;
$this -> cachepath = $phpbb_root_path . 'cache/ctpl_' . $template_name . '_' ;
$this -> static_lang = $static_lang ;
return true ;
}
2005-12-04 20:25:51 +00:00
/**
* Sets the template filenames for handles . $filename_array
* should be a hash of handle => filename pairs .
* @ public
*/
2001-08-30 22:20:23 +00:00
function set_filenames ( $filename_array )
2001-07-24 11:39:00 +00:00
{
2002-11-07 23:21:14 +00:00
if ( ! is_array ( $filename_array ))
2001-07-24 11:39:00 +00:00
{
2001-08-30 22:20:23 +00:00
return false ;
2001-07-24 11:39:00 +00:00
}
2001-08-30 22:20:23 +00:00
2002-11-07 23:21:14 +00:00
foreach ( $filename_array as $handle => $filename )
2001-07-24 11:39:00 +00:00
{
2002-11-07 23:21:14 +00:00
if ( empty ( $filename ))
2002-07-14 14:33:30 +00:00
{
2003-04-23 14:55:13 +00:00
trigger_error ( " template error - Empty filename specified for $handle " , E_USER_ERROR );
2002-07-14 14:33:30 +00:00
}
2002-06-22 11:48:10 +00:00
$this -> filename [ $handle ] = $filename ;
2003-07-13 15:13:59 +00:00
$this -> files [ $handle ] = $this -> root . '/' . $filename ;
2001-07-24 11:39:00 +00:00
}
2001-08-30 22:20:23 +00:00
2001-07-24 11:39:00 +00:00
return true ;
}
2005-12-04 20:25:51 +00:00
/**
* Destroy template data set
* @ public
*/
2002-07-14 14:33:30 +00:00
function destroy ()
{
$this -> _tpldata = array ();
}
2005-12-04 20:25:51 +00:00
/**
* Display handle
* @ public
*/
2004-01-10 12:23:24 +00:00
function display ( $handle , $include_once = true )
2002-07-14 14:33:30 +00:00
{
2003-04-23 14:55:13 +00:00
global $user ;
2002-06-22 11:48:10 +00:00
2003-04-23 14:55:13 +00:00
if ( $filename = $this -> _tpl_load ( $handle ))
{
2004-01-10 12:23:24 +00:00
( $include_once ) ? include_once ( $filename ) : include ( $filename );
2003-04-23 14:55:13 +00:00
}
else
{
eval ( ' ?>' . $this -> compiled_code [ $handle ] . '<?php ' );
2002-06-22 11:48:10 +00:00
}
2002-07-14 14:33:30 +00:00
2001-07-24 11:39:00 +00:00
return true ;
}
2001-08-30 22:20:23 +00:00
2005-12-04 20:25:51 +00:00
/**
* Display the handle and assign the output to a template variable
* @ public
*/
function assign_display ( $handle , $template_var , $return_content = false , $include_once = true )
{
ob_start ();
$this -> display ( $handle , $include_once );
2005-12-05 18:52:23 +00:00
$contents = ob_get_clean ();
2005-12-04 20:25:51 +00:00
if ( $return_content )
{
return $contents ;
}
$this -> assign_var ( $template_var , $contents );
return true ;
}
/**
* Load a compiled template if possible , if not , recompile it
* @ private
*/
2003-04-23 14:55:13 +00:00
function _tpl_load ( & $handle )
2001-07-24 11:39:00 +00:00
{
2005-12-04 20:25:51 +00:00
global $user , $phpEx , $config ;
2002-07-14 14:33:30 +00:00
2003-07-17 15:16:25 +00:00
$filename = $this -> cachepath . $this -> filename [ $handle ] . '.' . (( $this -> static_lang ) ? $user -> data [ 'user_lang' ] . '.' : '' ) . $phpEx ;
2002-07-14 14:33:30 +00:00
2003-11-29 23:42:10 +00:00
$recompile = (( $config [ 'load_tplcompile' ] && @ filemtime ( $filename ) < filemtime ( $this -> files [ $handle ])) || ! file_exists ( $filename )) ? true : false ;
2003-09-29 00:20:17 +00:00
2003-04-18 14:32:32 +00:00
// Recompile page if the original template is newer, otherwise load the compiled version
2003-09-29 00:20:17 +00:00
if ( ! $recompile )
2002-07-14 14:33:30 +00:00
{
2003-04-23 14:55:13 +00:00
return $filename ;
}
2002-07-14 14:33:30 +00:00
2005-12-04 20:25:51 +00:00
global $db , $phpbb_root_path ;
include_once ( $phpbb_root_path . 'includes/functions_template.' . $phpEx );
$compile = new template_compile ( $this );
2003-07-13 15:13:59 +00:00
2003-04-23 14:55:13 +00:00
// If the file for this handle is already loaded and compiled, do nothing.
if ( ! empty ( $this -> uncompiled_code [ $handle ]))
{
2003-04-18 14:32:32 +00:00
return true ;
2002-07-14 14:33:30 +00:00
}
2003-04-23 14:55:13 +00:00
// If we don't have a file assigned to this handle, die.
if ( ! isset ( $this -> files [ $handle ]))
{
trigger_error ( " template->_tpl_load(): No file specified for handle $handle " , E_USER_ERROR );
}
2006-03-25 16:19:20 +00:00
// Just compile if no user object is present (happens within the installer)
if ( ! $user )
{
$compile -> _tpl_load_file ( $handle );
return false ;
}
2005-12-22 16:28:27 +00:00
if ( $user -> theme [ 'template_storedb' ])
2003-08-06 15:45:13 +00:00
{
$sql = 'SELECT * FROM ' . STYLES_TPLDATA_TABLE . '
2005-12-22 16:28:27 +00:00
WHERE template_id = ' . $user->theme[' template_id ' ] . "
2004-08-01 12:31:21 +00:00
AND ( template_filename = '" . $db->sql_escape($this->filename[$handle]) . "'
2003-08-06 15:45:13 +00:00
OR template_included LIKE '%" . $db->sql_escape($this->filename[$handle]) . ":%' ) " ;
$result = $db -> sql_query ( $sql );
if ( $row = $db -> sql_fetchrow ( $result ))
{
do
{
2005-12-22 16:28:27 +00:00
if ( $row [ 'template_mtime' ] < filemtime ( $phpbb_root_path . 'styles/' . $user -> theme [ 'template_path' ] . '/template/' . $row [ 'template_filename' ]))
2003-08-06 15:45:13 +00:00
{
if ( $row [ 'template_filename' ] == $this -> filename [ $handle ])
{
2005-12-13 20:58:28 +00:00
$compile -> _tpl_load_file ( $handle );
2003-08-06 15:45:13 +00:00
}
else
{
$this -> files [ $row [ 'template_filename' ]] = $this -> root . '/' . $row [ 'template_filename' ];
2005-12-13 20:58:28 +00:00
$compile -> _tpl_load_file ( $row [ 'template_filename' ]);
2003-08-06 15:45:13 +00:00
unset ( $this -> compiled_code [ $row [ 'template_filename' ]]);
unset ( $this -> files [ $row [ 'template_filename' ]]);
}
}
if ( $row [ 'template_filename' ] == $this -> filename [ $handle ])
{
2005-12-13 20:58:28 +00:00
$this -> compiled_code [ $handle ] = $compile -> compile ( trim ( $row [ 'template_data' ]));
$compile -> compile_write ( $handle , $this -> compiled_code [ $handle ]);
2003-08-06 15:45:13 +00:00
}
else
{
// Only bother compiling if it doesn't already exist
if ( ! file_exists ( $this -> cachepath . $row [ 'template_filename' ] . '.' . (( $this -> static_lang ) ? $user -> data [ 'user_lang' ] . '.' : '' ) . $phpEx ))
{
$this -> filename [ $row [ 'template_filename' ]] = $row [ 'template_filename' ];
2005-12-13 20:58:28 +00:00
$compile -> compile_write ( $row [ 'template_filename' ], $compile -> compile ( trim ( $row [ 'template_data' ])));
2003-08-06 15:45:13 +00:00
unset ( $this -> filename [ $row [ 'template_filename' ]]);
}
}
}
while ( $row = $db -> sql_fetchrow ( $result ));
}
$db -> sql_freeresult ( $result );
return false ;
}
2005-12-04 20:25:51 +00:00
$compile -> _tpl_load_file ( $handle );
2003-08-06 15:45:13 +00:00
return false ;
}
2005-12-04 20:25:51 +00:00
/**
* Assign key variable pairs from an array
* @ public
*/
2002-07-14 14:33:30 +00:00
function assign_vars ( $vararray )
{
2002-11-07 23:21:14 +00:00
foreach ( $vararray as $key => $val )
2002-07-14 14:33:30 +00:00
{
$this -> _tpldata [ '.' ][ 0 ][ $key ] = $val ;
}
return true ;
}
2005-12-04 20:25:51 +00:00
/**
* Assign a single variable to a single key
* @ public
*/
2002-07-14 14:33:30 +00:00
function assign_var ( $varname , $varval )
{
$this -> _tpldata [ '.' ][ 0 ][ $varname ] = $varval ;
return true ;
}
2002-08-22 21:40:51 +00:00
2005-12-04 20:25:51 +00:00
/**
* Assign key variable pairs from an array to a specified block
* @ public
*/
2001-07-24 11:39:00 +00:00
function assign_block_vars ( $blockname , $vararray )
{
2004-07-08 22:41:04 +00:00
if ( strpos ( $blockname , '.' ) !== false )
2001-07-24 11:39:00 +00:00
{
2001-08-30 22:20:23 +00:00
// Nested block.
2001-07-24 11:39:00 +00:00
$blocks = explode ( '.' , $blockname );
$blockcount = sizeof ( $blocks ) - 1 ;
2002-07-14 14:33:30 +00:00
2004-08-01 12:31:21 +00:00
$str = & $this -> _tpldata ;
for ( $i = 0 ; $i < $blockcount ; $i ++ )
2001-07-24 11:39:00 +00:00
{
2004-08-01 12:31:21 +00:00
$str = & $str [ $blocks [ $i ]];
$str = & $str [ sizeof ( $str ) - 1 ];
}
2002-07-14 14:33:30 +00:00
2006-02-21 10:32:19 +00:00
$s_row_count = isset ( $str [ $blocks [ $blockcount ]]) ? sizeof ( $str [ $blocks [ $blockcount ]]) : 0 ;
$vararray [ 'S_ROW_COUNT' ] = $s_row_count ;
2005-04-11 21:32:22 +00:00
// Assign S_FIRST_ROW
2006-02-21 10:32:19 +00:00
if ( ! $s_row_count )
2005-04-11 21:32:22 +00:00
{
$vararray [ 'S_FIRST_ROW' ] = true ;
}
// Now the tricky part, we always assign S_LAST_ROW and remove the entry before
// This is much more clever than going through the complete template data on display (phew)
$vararray [ 'S_LAST_ROW' ] = true ;
2006-02-21 10:32:19 +00:00
if ( $s_row_count > 0 )
2005-04-11 21:32:22 +00:00
{
2006-02-21 10:32:19 +00:00
unset ( $str [ $blocks [ $blockcount ]][( $s_row_count - 1 )][ 'S_LAST_ROW' ]);
2005-04-11 21:32:22 +00:00
}
2001-07-24 11:39:00 +00:00
// Now we add the block that we're actually assigning to.
// We're adding a new iteration to this block with the given
// variable assignments.
2006-03-12 23:19:55 +00:00
$str [ $blocks [ $blockcount ]][] = $vararray ;
2001-07-24 11:39:00 +00:00
}
else
{
// Top-level block.
2006-02-21 10:32:19 +00:00
$s_row_count = ( isset ( $this -> _tpldata [ $blockname ])) ? sizeof ( $this -> _tpldata [ $blockname ]) : 0 ;
$vararray [ 'S_ROW_COUNT' ] = $s_row_count ;
2005-04-11 21:32:22 +00:00
// Assign S_FIRST_ROW
2006-02-21 10:32:19 +00:00
if ( ! $s_row_count )
2005-04-11 21:32:22 +00:00
{
$vararray [ 'S_FIRST_ROW' ] = true ;
}
// We always assign S_LAST_ROW and remove the entry before
$vararray [ 'S_LAST_ROW' ] = true ;
2006-02-21 10:32:19 +00:00
if ( $s_row_count > 0 )
2005-04-11 21:32:22 +00:00
{
2006-02-21 10:32:19 +00:00
unset ( $this -> _tpldata [ $blockname ][( $s_row_count - 1 )][ 'S_LAST_ROW' ]);
2005-04-11 21:32:22 +00:00
}
2001-07-24 11:39:00 +00:00
// Add a new iteration to this block with the variable assignments
// we were given.
2006-03-12 23:19:55 +00:00
$this -> _tpldata [ $blockname ][] = $vararray ;
2001-07-24 11:39:00 +00:00
}
2001-08-30 22:20:23 +00:00
2001-07-24 11:39:00 +00:00
return true ;
}
2003-04-18 14:32:32 +00:00
2005-04-09 12:26:45 +00:00
/**
* Change already assigned key variable pair ( one - dimensional - single loop entry )
*
* Some Examples :
* < code >
*
2006-03-12 23:19:55 +00:00
* alter_block_array ( 'loop' , $vararray ); // Insert vararray at the beginning
2005-04-09 12:26:45 +00:00
* alter_block_array ( 'loop' , $vararray , 2 ); // Insert vararray at position 2
* alter_block_array ( 'loop' , $vararray , array ( 'KEY' => 'value' )); // Insert vararray at the position where the key 'KEY' has the value of 'value'
* alter_block_array ( 'loop' , $vararray , false ); // Insert vararray at first position
2005-12-27 08:50:42 +00:00
* alter_block_array ( 'loop' , $vararray , true ); // Insert vararray at last position (assign_block_vars equivalence)
2005-04-09 12:26:45 +00:00
*
* alter_block_array ( 'loop' , $vararray , 2 , 'change' ); // Change/Merge vararray with existing array at position 2
* alter_block_array ( 'loop' , $vararray , array ( 'KEY' => 'value' ), 'change' ); // Change/Merge vararray with existing array at the position where the key 'KEY' has the value of 'value'
* alter_block_array ( 'loop' , $vararray , false , 'change' ); // Change/Merge vararray with existing array at first position
* alter_block_array ( 'loop' , $vararray , true , 'change' ); // Change/Merge vararray with existing array at last position
*
* </ code >
*
* @ param string $blockname the blockname , for example 'loop'
* @ param array $vararray the var array to insert / add or merge
* @ param mixed $key Key to search for
*
* array : KEY => VALUE [ the key / value pair to search for within the loop to determine the correct position ]
*
* int : Position [ the position to change or insert at directly given ]
*
* If key is false the position is set to 0
*
* If key is true the position is set to the last entry
*
* @ param insert | change $mode Mode to execute
*
* If insert , the vararray is inserted at the given position ( position counting from zero ) .
*
* If change , the current block gets merged with the vararray ( resulting in new key / value pairs be added and existing keys be replaced by the new value ) .
*
* Since counting begins by zero , inserting at the last position will result in this array : array ( vararray , last positioned array )
* and inserting at position 1 will result in this array : array ( first positioned array , vararray , following vars )
*
2005-12-04 20:25:51 +00:00
* @ public
2005-04-09 12:26:45 +00:00
*/
2004-10-30 17:11:58 +00:00
function alter_block_array ( $blockname , $vararray , $key = false , $mode = 'insert' )
{
if ( strpos ( $blockname , '.' ) !== false )
{
// Nested blocks are not supported
return false ;
}
// Change key to zero (change first position) if false and to last position if true
if ( $key === false || $key === true )
{
2005-12-27 08:50:42 +00:00
$key = ( $key === false ) ? 0 : sizeof ( $this -> _tpldata [ $blockname ]);
2004-10-30 17:11:58 +00:00
}
// Get correct position if array given
if ( is_array ( $key ))
{
// Search array to get correct position
list ( $search_key , $search_value ) = @ each ( $key );
$key = NULL ;
foreach ( $this -> _tpldata [ $blockname ] as $i => $val_ary )
{
if ( $val_ary [ $search_key ] === $search_value )
{
$key = $i ;
break ;
}
}
// key/value pair not found
if ( $key === NULL )
{
return false ;
}
}
// Insert Block
if ( $mode == 'insert' )
{
// Make sure we are not exceeding the last iteration
2005-12-27 08:50:42 +00:00
if ( $key >= sizeof ( $this -> _tpldata [ $blockname ]))
2004-10-30 17:11:58 +00:00
{
$key = sizeof ( $this -> _tpldata [ $blockname ]);
2005-12-27 08:50:42 +00:00
unset ( $this -> _tpldata [ $blockname ][( $key - 1 )][ 'S_LAST_ROW' ]);
$vararray [ 'S_LAST_ROW' ] = true ;
2004-10-30 17:11:58 +00:00
}
2005-12-27 08:50:42 +00:00
else if ( $key === 0 )
{
unset ( $this -> _tpldata [ $blockname ][ 0 ][ 'S_FIRST_ROW' ]);
$vararray [ 'S_FIRST_ROW' ] = true ;
}
2004-10-30 17:11:58 +00:00
// Re-position template blocks
for ( $i = sizeof ( $this -> _tpldata [ $blockname ]); $i > $key ; $i -- )
{
$this -> _tpldata [ $blockname ][ $i ] = $this -> _tpldata [ $blockname ][ $i - 1 ];
$this -> _tpldata [ $blockname ][ $i ][ 'S_ROW_COUNT' ] = $i ;
}
// Insert vararray at given position
$vararray [ 'S_ROW_COUNT' ] = $key ;
2006-03-12 23:19:55 +00:00
$this -> _tpldata [ $blockname ][ $key ] = $vararray ;
2004-10-30 17:11:58 +00:00
return true ;
}
// Which block to change?
if ( $mode == 'change' )
{
2005-12-27 08:50:42 +00:00
if ( $key == sizeof ( $this -> _tpldata [ $blockname ]))
{
$key -- ;
}
2006-03-12 23:19:55 +00:00
$this -> _tpldata [ $blockname ][ $key ] = array_merge ( $this -> _tpldata [ $blockname ][ $key ], $vararray );
2004-10-30 17:11:58 +00:00
return true ;
}
}
2005-12-04 20:25:51 +00:00
/**
* Include a seperate template
* @ private
*/
2003-04-18 14:32:32 +00:00
function _tpl_include ( $filename , $include = true )
{
2003-04-23 14:55:13 +00:00
$handle = $filename ;
2003-04-18 14:32:32 +00:00
$this -> filename [ $handle ] = $filename ;
2003-07-13 15:13:59 +00:00
$this -> files [ $handle ] = $this -> root . '/' . $filename ;
2003-04-18 14:32:32 +00:00
2003-04-23 14:55:13 +00:00
$filename = $this -> _tpl_load ( $handle );
2003-08-10 18:33:25 +00:00
2003-04-23 14:55:13 +00:00
if ( $include )
{
2003-09-29 00:20:17 +00:00
global $user ;
if ( $filename )
2003-07-11 23:28:56 +00:00
{
2003-10-11 23:58:57 +00:00
include_once ( $filename );
2003-09-29 00:20:17 +00:00
return ;
2003-07-11 23:28:56 +00:00
}
2003-09-29 00:20:17 +00:00
eval ( ' ?>' . $this -> compiled_code [ $handle ] . '<?php ' );
2003-04-18 14:32:32 +00:00
}
}
2001-07-24 11:39:00 +00:00
}
2001-08-26 14:04:27 +00:00
2002-06-22 11:48:10 +00:00
?>