<?php
/**
* Haml parser.
*
* @link http://haml.hamptoncatlin.com/ Original Haml parser (for Ruby)
* @license http://www.opensource.org/licenses/mit-license.php MIT (X11) License
* @author Amadeusz Jasak <hide@address.com>
* @package phpHaml
*/
/**
* Haml parser.
*
* @link http://haml.hamptoncatlin.com/ Original Haml parser (for Ruby)
* @license http://www.opensource.org/licenses/mit-license.php MIT (X11) License
* @author Amadeusz Jasak <hide@address.com>
* @package phpHaml
*/
class HamlParser
{
/**
* Haml source
*
* @var string
*/
public $sSource = '';
/**
* Files path
*
* @var string
*/
protected $sPath = '';
/**
* Compile templates??
*
* @var boolean
*/
protected $bCompile = true;
/**
* Filename
*
* @var string
*/
protected $sFile = '';
/**
* Parent parser
*
* @var object
*/
protected $oParent = null;
/**
* Children parsers
*
* @var array
*/
protected $aChildren = array();
/**
* Indent level
*
* @var integer
*/
public $iIndent = -1;
/**
* Translation function name.
*
* @var string
*/
public $sTranslate = 'fake_translate';
/**
* Temporary directory
*
* @var string
*/
protected $sTmp = '';
/**
* Block of PHP code
*
* @var boolean
*/
protected $bBlock = false;
/**
* The constructor
*
* @param string Path to files
* @param boolean/string Compile templates (can be path)
* @param object Parent parser
*/
public function __construct($sPath = false, $bCompile = true, $oParent = null)
{
if ($sPath)
$this->setPath($sPath);
$this->bCompile = $bCompile;
if (is_string($bCompile))
$this->setTmp($bCompile);
else
$this->setTmp($sPath);
if ($oParent)
$this->setParent($oParent);
}
/**
* Set parent parser
*
* @param object Parent parser
* @return object
*/
public function setParent($oParent)
{
$this->oParent = $oParent;
return $this;
}
/**
* Set files path
*
* @param string File path
* @return object
*/
public function setPath($sPath)
{
$this->sPath = realpath($sPath);
return $this;
}
/**
* Set filename
*
* @param string Filename
* @return object
*/
public function setFile($sPath)
{
if (file_exists($sPath))
$this->sFile = $sPath;
else
$this->sFile = "{$this->sPath}/$sPath";
$this->setSource(file_get_contents($this->sFile));
return $this;
}
/**
* Return filename to include
*
* @param string Name
* @return string
*/
public function getFilename($sName)
{
return "{$this->sPath}/$sName.haml";
}
/**
* Real source
*
* @var string
*/
public $sRealSource = '';
/**
* Set source code
*
* @param string Source
* @return object
*/
public function setSource($sHaml)
{
$this->sSource = trim($sHaml, self::TOKEN_INDENT);
$this->sRealSource = $sHaml;
return $this;
}
/**
* Set temporary directory
*
* @param string Directory
* @return object
*/
public function setTmp($sTmp)
{
$this->sTmp = realpath($sTmp);
return $this;
}
/**
* Render the source or file
*
* @return string
*/
public function render()
{
$__aSource = explode(self::TOKEN_LINE, $this->sSource = $this->parseBreak($this->sSource));
$__sCompiled = '';
if (count($__aSource) == 1)
$__sCompiled = $this->parseLine($__aSource[0]);
else
{
if (($__sC = $this->compiled()) && $this->bCompile)
$__sCompiled = $__sC;
else
{
$__iIndent = 0;
$__iIndentLevel = 0;
foreach ($__aSource as $__iKey => $__sLine)
{
$__iLevel = $this->countLevel($__sLine);
if ($__iLevel <= $__iIndentLevel)
$__iIndent = $__iIndentLevel = 0;
if (preg_match('/\\'.self::TOKEN_LEVEL.'([0-9]+)$/', $__sLine, $__aMatches))
{
$__iIndent = (int)$__aMatches[1];
$__iIndentLevel = $__iLevel;
$__sLine = preg_replace('/\\'.self::TOKEN_LEVEL."$__iIndent$/", '', $__sLine);
}
$__sLine = str_repeat(self::TOKEN_INDENT, $__iIndent * self::INDENT) . $__sLine;
$__aSource[$__iKey] = $__sLine;
if (preg_match('/^(\s*)'.self::TOKEN_INCLUDE.' (.+)/', $__sLine, $aMatches))
{
$__sIncludeSource = $this->sourceIndent(file_get_contents($this->getFilename($aMatches[2])), $__iIndent ? $__iIndent : $__iLevel);
$__sLine = str_replace($aMatches[1] . self::TOKEN_INCLUDE . " {$aMatches[2]}", $__sIncludeSource, $__sLine);
$__aSource[$__iKey] = $__sLine;
$this->sSource = implode(self::TOKEN_LINE, $__aSource);
}
}
$__aSource = explode(self::TOKEN_LINE, $this->sSource = $this->parseBreak($this->sSource));
$__sCompiled = $this->compile($this->parseFile($__aSource));
}
ob_end_flush();
ob_start();
foreach (self::$aVariables as $__sName => $__mValue)
$$__sName = $__mValue;
require $__sCompiled;
$c = trim(ob_get_contents());
foreach ($this->aFilters as $mFilter)
$c = call_user_func($mFilter, $c);
ob_clean();
return $c;
}
return $__sCompiled;
}
/**
* Check for compiled template
*
* @return string Compiled filename
*/
public function compiled()
{
if (!$this->bCompile)
return false;
$sSourceHash = '';
if (function_exists('hash'))
$sSourceHash = hash('md5', $this->sSource);
else
$sSourceHash = md5($this->sSource);
$sFilename = "{$this->sTmp}/$sSourceHash.hphp";
if (file_exists($sFilename))
return $sFilename;
else
return false;
}
/**
* Save compiled template
*
* @param string Compiled template
* @return string Filename
*/
public function compile($sCompiled)
{
$sSourceHash = '';
if (function_exists('hash'))
$sSourceHash = hash('md5', $this->sSource);
else
$sSourceHash = md5($this->sSource);
$sFilename = "{$this->sTmp}/$sSourceHash.hphp";
file_put_contents($sFilename, $sCompiled);
return $sFilename;
}
/**
* Render the source or file
*
* @return string
*/
public function __toString()
{
return $this->render();
}
/**
* Parse multiline
*
* @param string File content
* @return string
*/
public function parseBreak($sFile)
{
$sFile = preg_replace('/\\'.self::TOKEN_BREAK.'\s*/', '', $sFile);
return $sFile;
}
/**
* Return source of child
*
* @param integer Level
* @return string
*/
public function getAsSource($iLevel)
{
$x = ($this->iIndent - $iLevel - 1) * self::INDENT;
$sSource = '';
if ($x >= 0)
$sSource = preg_replace('|^'.str_repeat(self::TOKEN_INDENT, ($iLevel + 1) * self::INDENT).'|', '', $this->sRealSource);
foreach ($this->aChildren as $oChild)
$sSource .= self::TOKEN_LINE.$oChild->getAsSource($iLevel);
return trim($sSource, self::TOKEN_LINE);
}
/**
* Create and append line to parent
*
* @param string Line
* @param object Parent parser
* @return object
*/
public function createLine($sLine, $parent)
{
$oHaml = new HamlParser($this->sPath, $this->bCompile, $parent);
$oHaml->setSource($sLine);
$oHaml->iIndent = $parent->iIndent + 1;
$parent->aChildren[] = $oHaml;
return $oHaml;
}
/**
* Parse file
*
* @param array Array of source lines
* @return string
*/
protected function parseFile($aSource)
{
$aLevels = array(-1 => $this);
$sCompiled = '';
foreach ($aSource as $sSource)
{
$iLevel = $this->countLevel($sSource);
$aLevels[$iLevel] = $this->createLine($sSource, $aLevels[$iLevel - 1]);
}
foreach ($this->aChildren as $oChild)
$sCompiled .= $oChild->render();
return $sCompiled;
}
/**
* List of text processing blocks
*
* @var array
*/
protected static $aBlocks = array();
/**
* Register block
*
* @param mixed Callable
* @param string Name
* @return object
*/
public function registerBlock($mCallable, $sName = false)
{
if (!$sName)
$sName = serialize($mCallable);
self::$aBlocks[$sName] = $mCallable;
return $this;
}
/**
* Unregister block
*
* @param string Name
* @return object
*/
public function unregisterBlock($sName)
{
unset(self::$aBlocks[$sName]);
return $this;
}
/**
* Parse text block
*
* @param string Block name
* @param string Data
* @return string
*/
public function parseTextBlock($sName, $sText)
{
return call_user_func(self::$aBlocks[$sName], $sText);
}
/**
* Parse line
*
* @param string Line
* @return string
*/
public function parseLine($sSource)
{
$sParsed = '';
$sRealBegin = '';
$sRealEnd = '';
$sParsedBegin = '';
$sParsedEnd = '';
$bParse = true;
// Doctype parsing
if (preg_match('/^'.self::TOKEN_DOCTYPE.'(.*)/', $sSource, $aMatches))
{
$aMatches[1] = trim($aMatches[1]);
if ($aMatches[1] == '')
$aMatches[1] = '1.1';
$sParsed = self::$aDoctypes[$aMatches[1]]."\n";
} else
// PHP instruction
if (preg_match('/^'.self::TOKEN_INSTRUCTION_PHP.' (.*)/', $sSource, $aMatches))
{
$bBlock = false;
// Check for block
if (preg_match('/^('.implode('|', self::$aPhpBlocks).')/', $aMatches[1]))
$this->bBlock = $bBlock = true;
$sParsedBegin = "<?php {$aMatches[1]}" . ($bBlock ? ' {' : ';') . " ?>\n";
if ($bBlock)
$sParsedEnd = "<?php } ?>\n";
} else
// Text block
if (preg_match('/^'.self::TOKEN_TEXT_BLOCKS.'(.+)/', $sSource, $aMatches))
{
$sParsed = $this->indent($this->parseTextBlock($aMatches[1], $this->getAsSource($this->iIndent)));
$this->aChildren = array();
} else
// Check for PHP
if (preg_match('/^'.self::TOKEN_PARSE_PHP.' (.*)/', $sSource, $aMatches))
$sParsed = $this->indent("<?php echo {$aMatches[1]}; ?>\n");
else
{
$aAttributes = array();
$sAttributes = '';
$sTag = 'div';
$sToParse = '';
$sContent = '';
$sAutoVar = '';
// Parse options
preg_match('/\\'.self::TOKEN_OPTIONS_LEFT.'(.*?)\\'.self::TOKEN_OPTIONS_RIGHT.'/', $sSource, $aMatches);
if (count($aMatches) > 1)
{
$sSource = str_replace($aMatches[0], '', $sSource);
$aOptions = explode(self::TOKEN_OPTIONS_SEPARATOR, $aMatches[1]);
foreach ($aOptions as $sOption)
{
$aOption = explode(self::TOKEN_OPTION_VALUE, trim($sOption));
foreach ($aOption as $k => $o)
$aOption[$k] = trim($o);
$sOptionName = ltrim($aOption[0], self::TOKEN_OPTION);
$aAttributes[$sOptionName] = $aOption[1];
}
}
$sFirst = '['.self::TOKEN_TAG.'|'.self::TOKEN_ID.'|'.self::TOKEN_CLASS.'|'.self::TOKEN_PARSE_PHP.']';
if (preg_match("/($sFirst.*?) (.*)/", $sSource, $aMatches))
{
$sToParse = $aMatches[1];
$sContent = $aMatches[2];
} else
if (preg_match("/($sFirst.*)/", $sSource, $aMatches))
$sToParse = $aMatches[1];
else
{
// Check for comment
if (!preg_match('/^\\'.self::TOKEN_COMMENT.'(.*)/', $sSource, $aMatches))
{
$sParsed = $this->indent($sSource);
foreach ($this->aChildren as $oChild)
$sParsed .= $oChild;
}
else
{
$aMatches[1] = trim($aMatches[1]);
if ($aMatches[1] && !preg_match('/\[.*\]/', $aMatches[1]))
$sParsed = $this->indent(wordwrap($aMatches[1], 60, "\n"), 1)."\n";
}
$bParse = false;
}
if ($bParse)
{
$bPhp = false;
$bClosed = false;
// Match tag
if (preg_match('/^'.self::TOKEN_TAG.'([a-zA-Z0-9]*)/', $sToParse, $aMatches))
$sTag = $aMatches[1];
// Match ID
if (preg_match('/'.self::TOKEN_ID.'([a-zA-Z0-9_]*)/', $sToParse, $aMatches))
$aAttributes['id'] = "'{$aMatches[1]}'";
// Match classes
if (preg_match_all('/\\'.self::TOKEN_CLASS.'([a-zA-Z0-9_]*)/', $sToParse, $aMatches))
$aAttributes['class'] = '\''.implode(' ', $aMatches[1]).'\'';
// Check for PHP
if (preg_match('/'.self::TOKEN_PARSE_PHP.'/', $sToParse))
{
$sContentOld = $sContent;
$sContent = "<?php echo $sContent; ?>\n";
$bPhp = true;
}
// Match translating
if (preg_match('/\\'.self::TOKEN_TRANSLATE.'$/', $sToParse, $aMatches))
{
if (!$bPhp)
$sContent = "'$sContent'";
else
$sContent = $sContentOld;
$sContent = "<?php echo {$this->sTranslate}($sContent); ?>\n";
}
// Match single tag
if (preg_match('/\\'.self::TOKEN_SINGLE.'$/', $sToParse))
$bClosed = true;
// Match brackets
if (preg_match('/\\'.self::TOKEN_AUTO_LEFT.'(.*?)\\'.self::TOKEN_AUTO_RIGHT.'/', $sToParse, $aMatches))
$sAutoVar = $aMatches[1];
if (!empty($aAttributes) || !empty($sAutoVar))
$sAttributes = '<?php $this->writeAttributes('.$this->arrayExport($aAttributes).(!empty($sAutoVar) ? ", \$this->parseSquareBrackets($sAutoVar)" : '' ).'); ?>';
$this->bBlock = $this->oParent->bBlock;
$iLevelM = $this->oParent->bBlock || $this->bBlock ? -1 : 0;
// Check for block tag
if (!$this->isInline($sTag) && !$this->isClosed($sTag) && !$bClosed)
{
$sParsedBegin = $this->indent("<$sTag$sAttributes>", $iLevelM);
if (!empty($sContent))
if (strlen($sContent) > 60)
$sParsed = $this->indent(wordwrap($sContent, 60, "\n"), 1+$iLevelM);
else
$sParsed = $this->indent($sContent, 1+$iLevelM);
$sParsedEnd = $this->indent("</$sTag>", $iLevelM);
} else
// Check for inline tag
if ($this->isInline($sTag) && !$bClosed)
{
$sParsedBegin = $this->indent("<$sTag$sAttributes>", $iLevelM, false);
$sParsed = $sContent;
$sParsedEnd = "</$sTag>\n";
}
// Check for closed tag
else
$sParsedBegin = $this->indent("<$sTag$sAttributes />", $iLevelM);
}
}
foreach ($this->aChildren as $oChild)
$sParsed .= $oChild;
// Check for IE comment
if (preg_match('/^\\'.self::TOKEN_COMMENT.'\[(.*?)\](.*)/', $sSource, $aMatches))
{
$aMatches[2] = trim($aMatches[2]);
if (count($this->aChildren) == 0)
{
$sParsedBegin = $this->indent("<!--[{$aMatches[1]}]> $sParsedBegin", 0, false);
$sParsed = $aMatches[2];
$sParsedEnd = "$sParsedEnd <![endif]-->\n";
}
else
{
$sParsed = $sParsedBegin.$sParsed.$sParsedEnd;
$sParsedBegin = $this->indent("<!--[{$aMatches[1]}]>");
$sParsedEnd = $this->indent("<![endif]-->");
}
} else
// Check for comment
if (preg_match('/^\\'.self::TOKEN_COMMENT.'(.*)/', $sSource, $aMatches))
{
$aMatches[1] = trim($aMatches[1]);
if (count($this->aChildren) == 0)
{
$sParsedBegin = $this->indent("<!-- $sParsedBegin", 0, false);
$sParsed = $aMatches[1];
$sParsedEnd = "$sParsedEnd -->\n";
}
else
{
$sParsed = $sParsedBegin.$sParsed.$sParsedEnd;
$sParsedBegin = $this->indent("<!--");
$sParsedEnd = $this->indent("-->");
}
}
$sCompiled = $sRealBegin.$sParsedBegin.$sParsed.$sParsedEnd.$sRealEnd;
return $sCompiled;
}
/**
* Indent line
*
* @param string Line
* @param integer Additional indention level
* @param boolean Add new line
* @return string
*/
protected function indent($sLine, $iAdd = 0, $bNew = true)
{
$aLine = explode("\n", $sLine);
$sIndented = '';
foreach ($aLine as $sLine)
$sIndented .= str_repeat(' ', $this->iIndent + $iAdd).($bNew ? "$sLine\n" : $sLine);
return $sIndented;
}
/**
* Indent Haml source
*
* @param string Source
* @param integer Level
* @return string
*/
protected function sourceIndent($sSource, $iLevel)
{
$aSource = explode(self::TOKEN_LINE, $sSource);
foreach ($aSource as $sKey => $sValue)
$aSource[$sKey] = str_repeat(self::TOKEN_INDENT, $iLevel * self::INDENT) . $sValue;
$sSource = implode(self::TOKEN_LINE, $aSource);
return $sSource;
}
/**
* Count level of line
*
* @param string Line
* @return integer
*/
protected function countLevel($sLine)
{
return (strlen($sLine) - strlen(trim($sLine, self::TOKEN_INDENT))) / self::INDENT;
}
/**
* Check for inline tag
*
* @param string Tag
* @return boolean
*/
protected function isInline($sTag)
{
return in_array($sTag, self::$aInlineTags);
}
/**
* Check for closed tag
*
* @param string Tag
* @return boolean
*/
protected function isClosed($sTag)
{
return in_array($sTag, self::$aClosedTags);
}
const TOKEN_LINE = "\n";//+
const TOKEN_INDENT = ' ';//+
const TOKEN_TAG = '%';//+
const TOKEN_ID = '#';//+
const TOKEN_CLASS = '.';//+
const TOKEN_OPTIONS_LEFT = '{';//+
const TOKEN_OPTIONS_RIGHT = '}';//+
const TOKEN_OPTIONS_SEPARATOR = ',';//+
const TOKEN_OPTION = ':'; //+
const TOKEN_OPTION_VALUE = '=>';//+
const TOKEN_INSTRUCTION_PHP = '-'; //+
const TOKEN_PARSE_PHP = '=';//+
const TOKEN_DOCTYPE = '!!!';//+
const TOKEN_INCLUDE = '!!'; //+
const TOKEN_COMMENT = '/'; //+
const TOKEN_TRANSLATE = '$'; //+
const TOKEN_LEVEL = '?'; //+
const TOKEN_SINGLE = '/'; //+
const TOKEN_BREAK = '|'; //+
const TOKEN_AUTO_LEFT = '[';//+
const TOKEN_AUTO_RIGHT = ']';//+
const TOKEN_TEXT_BLOCKS = ':'; //+
const INDENT = 2;//+
/**
* Doctype definitions
*
* @var string
*/
protected static $aDoctypes = array
(
'1.1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
'Strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
'Transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
'Frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
'XML' => "<?php echo '<?xml version=\"1.0\" encoding=\"utf-8\" ?>'; ?>\n"
);
/**
* List of inline tags
*
* @var array
*/
protected static $aInlineTags = array
(
'a', 'strong', 'b', 'em', 'i', 'h1', 'h2', 'h3', 'h4',
'h5', 'h6', 'span', 'title', 'li', 'dt', 'dd', 'code',
'cite', 'td', 'th', 'abbr', 'acronym', 'legend'
);
/**
* List of closed tags (like br, link...)
*
* @var array
*/
protected static $aClosedTags = array('br', 'hr', 'link', 'meta', 'img', 'input');
/**
* List of PHP blocks
*
* @var array
*
*/
protected static $aPhpBlocks = array('if', 'else', 'elseif', 'while', 'switch', 'for', 'do');
// Template engine
/**
* Template variables
*
* @var array
*/
protected static $aVariables = array();
/**
* Assign variable
*
* @param string Name
* @param mixed Value
* @return object
*/
public function assign($sName, $sValue)
{
self::$aVariables[$sName] = $sValue;
return $this;
}
/**
* Assign associative array of variables
*
* @param array Data
* @return object
*/
public function append($aData)
{
self::$aVariables = array_merge(self::$aVariables, $aData);
return $this;
}
/**
* Removes variables
*
* @return object
*/
public function clearVariables()
{
self::$aVariables = array();
return $this;
}
/**
* Remove all compiled templates
*
* @return object
*/
public function clearCompiled()
{
$oDirs = new DirectoryIterator($this->sTmp);
foreach ($oDirs as $oDir)
if (!$oDir->isDot())
if (preg_match('/\.hphp/', $oDir->getPathname()))
unlink($oDir->getPathname());
return $this;
}
/**
* Return compiled template
*
* @param string Filename
* @return string
*/
public function fetch($sFilename = false)
{
if ($sFilename)
$this->setFile($sFilename);
return $this->render();
}
/**
* Display template
*
* @param string Filename
*/
public function display($sFilename = false)
{
echo $this->fetch($sFilename);
}
/**
* List of registered filters
*
* @var array
*/
protected $aFilters = array();
/**
* Register output filter
*
* @param callable Filter
* @param string Name
* @return object
*/
public function registerFilter($mCallable, $sName = false)
{
if (!$sName)
$sName = serialize($mCallable);
$this->aFilters[$sName] = $mCallable;
return $this;
}
/**
* Unregister output filter
*
* @param string Name
* @return object
*/
public function unregisterFilter($sName)
{
unset($this->aFilters[$sName]);
return $this;
}
/**
* Return array of template variables
*
* @return array
*/
public function getVariables()
{
return self::$aVariables;
}
/**
* Parse variable in square brackets
*
* @param mixed Variable
* @return array Attributes
*/
protected function parseSquareBrackets($mVariable)
{
$sType = gettype($mVariable);
$aAttr = array();
$sId = '';
if ($sType == 'object')
{
static $__objectNamesCache;
if (!is_array($__objectNamesCache))
$__objectNamesCache = array();
$sClass = get_class($mVariable);
if (!$__objectNamesCache[$sClass])
$__objectNamesCache[$sClass] = $sType = trim(preg_replace('/([A-Z][a-z]*)/', '$1_', $sClass), '_');
else
$sType = $__objectNamesCache[$sClass];
if (method_exists($mVariable, 'getID'))
$sId = $mVariable->getID(); else
if (!empty($mVariable->ID))
$sId = $mVariable->ID;
}
if ($sId == '')
$sId = substr(md5(uniqid(serialize($mVariable).rand(), true)), 0, 8);
$aAttr['class'] = strtolower($sType);
$aAttr['id'] = "{$aAttr['class']}_$sId";
return $aAttr;
}
/**
* Write attributes
*/
protected function writeAttributes()
{
$aAttr = array();
foreach (func_get_args() as $aArray)
$aAttr = array_merge($aAttr, $aArray);
foreach ($aAttr as $sName => $sValue)
if ($sValue)
echo " $sName=\"".htmlentities($sValue).'"';
}
/**
* Export array
*
* @return string
*/
protected function arrayExport()
{
$sArray = 'array (';
$aArray = $aNArray = array();
foreach (func_get_args() as $aArg)
$aArray = array_merge($aArray, $aArg);
foreach ($aArray as $sKey => $sValue)
$aNArray[] = "'$sKey' => $sValue";
$sArray .= implode(', ', $aNArray).')';
return $sArray;
}
}
if (!function_exists('fake_translate'))
{
/**
* Fake translation function used
* as default translation function
* in HamlParser
*
* @param string
* @return string
*/
function fake_translate($s)
{
return $s;
}
}
/**
* This is the simpliest way to use
* Haml templates. Global variables
* are automatically assigned to
* template.
*
* @param string Haml parser filename
* @param array Associative array of additional variables
* @param string Temporary directory (default is directory of Haml templates)
* @param boolean Register get, post, session, server and cookie variables
*/
function display_haml($sFilename, $aVariables = array(), $sTmp = true, $bGPSSC = false)
{
global $__oHaml;
$sPath = realpath($sFilename);
if (!is_object($__oHaml))
$__oHaml = new HamlParser(dirname($sPath), $sTmp);
$__oHaml->append($GLOBALS);
if ($bGPSSC)
{
$__oHaml->append($_GET);
$__oHaml->append($_POST);
$__oHaml->append($_SESSION);
$__oHaml->append($_SERVER);
$__oHaml->append($_COOKIE);
}
$__oHaml->append($aVariables);
$__oHaml->display($sFilename);
}
?>