Version: 2.0
Type: Class
Category: Other
License: GNU General Public License
Description: Guise is a template class written in PHP that allows you to keep HTML seperate from your PHP code. This is especially helpful for larger projects or when you're working with a team in keeping things organized and readable.
<?php
/**
* Guise Template Class 2.0
* (c)2008 TD Fellows
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**#@+
* Constants
*/
/**
* New Line
*/
define( 'GUISE_NL', "\n" );
/**
* @author TD Fellows <tdfellows@users.sourceforge.net>
* @copyright 2008 TD Fellows
* @version 2.0
* @package Guise
*/
class Guise
{
/**
* The last occuring error.
*
* @access public
* @var string
*/
public $errstr = '';
/**#@+
* Private variables
* @access private
*/
/**
* With Debugging enabled, errors will be verbose.
*
* @var boolean
*/
private $debugging = false;
/**
* Array containing structured template data.
*
* @var array
*/
private $template_items = array();
/**
* Array containing structured template data.
*
* @var array
*/
private $block_templates = array();
/**
* Root template directory.
*
* @var string
*/
private $template_root = '';
/**#@-*/
/**#@+
* Public functions
* @access public
*/
/**
* Constructor.
*
* @param string $path Path to template directory
* @param boolean $debug Enables debugging
*/
public function Guise( $path = '/', $debug = false )
{
if ( !$this->set_root( $path ) ) {
return false;
} else {
$this->debugging = $debug;
return true;
}
}
/**
* Clear item and block template arrays.
*/
public function clear()
{
$this->template_items = array();
$this->block_templates = array();
}
/**
* Set template root directory. {@link $template_root}
*
* @param string $path Path to template directory
* @return boolean
*/
public function set_root( $path )
{
if ( substr( $path, -1 ) != '/' ) {
$path .= '/';
}
if ( is_dir( $path ) ) {
$this->template_root = $path;
return true;
} else {
$this->set_error( 'Guise->set_root', "(<b>$root</b>) is not a valid directory." );
return false;
}
}
/**
* Add an item or array to the item array.
*
* @param string $item_name Name of variable or array
* @param string $item_value Value of variable
* @return boolean
*/
public function add_item( $item_name, $item_value = null )
{
if ( is_array( $item_name ) ) {
foreach( $item_name as $key => $value ) {
$this->template_items[$key] = $value;
}
return true;
} else {
if ( empty( $item_name ) ) {
$this->set_error( 'Guise->add_item', 'item name must not be empty.' );
return false;
} else {
$this->template_items[$item_name] = $item_value;
return true;
}
}
}
/**
* Compile files with structured array.
*
* @param string $files List of files to be parsed seperated by commas.
* @return string|boolean
*/
public function compile( $files )
{
$handle = 0;
$page = '';
$line = '';
$file_list = explode( ',', $files );
foreach( $file_list as $file ) {
if ( substr( $file, 1, 2 ) != ":/" && substr( $file, 0, 1 ) != "/" ) {
$file = $this->template_root.$file;
}
if ( !file_exists( $file ) ) {
$this->set_error( 'Guise->compile', "(<b>$file</b>) no such file." );
return false;
} else {
$handle = @fopen( $file, 'r' );
}
if ( $handle ) {
while ( !feof( $handle ) ) {
$line = fgets( $handle );
if ( preg_match( '/^(.*?)(\<block(.*?)name\=(\"|\')(.*?)(\"|\')(.*?)\>)(.*?)$/i', $line, $block_matches ) ) {
$line = $this->load_blocks( $handle, $block_matches );
}
if ( preg_match_all( '/\<item(.*?)name\=(\"|\')(.*?)(\"|\')(.*?)\>/i', $line, $vars ) ) {
foreach( $vars[0] as $key => $value ) {
$line = str_replace( $value, $this->template_items[$vars[3][$key]], $line );
}
}
if ( preg_match_all( '/(\"|\')(item\.([a-z0-9_]*))(\"|\')/i', $line, $vars ) ) {
foreach( $vars[2] as $key => $value ) {
$line = str_replace( $value, $this->template_items[$vars[3][$key]], $line );
}
}
$page .= $line;
}
} else {
$this->set_error( 'Guise->compile', "(<b>$file</b>) unable to open stream." );
return false;
}
}
$page = $this->compile_blocks( $this->template_items, $page );
$page = $this->cleanup( $page );
return $page;
}
/**#@-*/
/**#@+
* Private functions
* @access private
*/
/**
* Remove left over template information.
*
* @param string $string The string to be cleaned
* @return string
*/
private function cleanup( $string )
{
$matches = array(
"/\<item(.*?)\>/i",
"/\<block(.*?)\>/i"
);
$string = preg_replace( $matches, "", $string );
if ( preg_match( '/<\/block\>/', $string ) ) {
$this->set_error( 'Guise->compile', 'invalid block usage. One or more blocks may not be parsed.' );
}
return $string;
}
/**
* Set last occuring error, echo on debug.
*
* @param string $subject Where the error was encountered
* @param string $error Error string
*/
private function set_error( $subject, $error )
{
$this->last_error = "<br /><b>Warning</b>: $subject, $error<br />";
if ( $this->debugging ) {
echo $this->last_error;
}
}
/**
* Move block templates from the main template to an array.
*
* @param integer $handle File handle
* @param string $block_matches Array from preg_match matching start of block
* @return string
*/
private function load_blocks( $handle, $block_matches )
{
if ( trim( $block_matches[1] ) != '' ) {
$source_tpl = $block_matches[1];
}
if ( trim( $block_matches[8] ) != '' ) {
$block_tpl = $block_matches[8].GUISE_NL;
}
$block_name = $block_matches[5];
if ( empty( $block_name ) ) {
$this->set_error( 'Guise->compile', 'invalid BLOCK format. NAME attribute must contain a value.' );
$source_tpl = $block_matches[0];
return $source_tpl;
} else {
$source_tpl .= "<block name='$block_name'>";
}
while ( !feof( $handle ) ) {
$line = fgets( $handle );
if ( preg_match( '/^(.*?)\<\/block\>(.*?)$/i', $line, $end_matches ) ) {
if ( trim( $end_matches[1] ) != '' ) {
$block_tpl .= $end_matches[1];
}
$source_tpl .= $end_matches[2];
break;
} elseif ( preg_match( '/^(.*?)(\<block(.*?)name\=(\"|\')(.*?)(\"|\')(.*?)\>)(.*?)$/i', $line, $child_matches ) ) {
$block_tpl .= $this->load_blocks( $handle, $child_matches );
} else {
$block_tpl .= $line;
}
}
$this->block_templates[$block_name] = $block_tpl;
return $source_tpl;
}
/**
* Compile blocks.
*
* @param array $start_array Point in the item array to begin parsing
* @param string $source_tpl The source template, either a page or block
* @return string
*/
private function compile_blocks( $start_array, $source_tpl )
{
$result = $source_tpl;
$cycle_result = '';
$block_name = '';
$block_tpl = '';
foreach( $start_array as $start_key => $start_value ) {
if ( is_array( $start_array[$start_key] ) ) {
$block_name = $start_key;
$block_tpl = $this->block_templates[$start_key];
for ( $i=0; ;$i++ ) {
if ( array_key_exists( $i, $start_array[$block_name] ) ) {
$cycle_result = $block_tpl;
foreach( $start_array[$block_name][$i] as $contents_key => $contents_value ) {
if ( is_array( $contents_value ) ) {
$cycle_result = $this->compile_blocks(
$start_array[$block_name][$i],
$cycle_result );
} else {
$cycle_result = preg_replace(
"/\<item(.*?)name\=(\"|\')$contents_key(\"|\')(.*?)\>/i",
$contents_value,
$cycle_result );
$cycle_result = preg_replace(
"/(\"|\')(item\.($contents_key))(\"|\')/i",
'"'.$contents_value.'"',
$cycle_result );
}
}
$result = str_replace(
"<block name='$block_name'>",
$cycle_result."<block name='$block_name'>",
$result );
} else {
break;
}
}
}
}
return $result;
}
/**#@-*/
}
?>