Source for file Flexy.php
Documentation is available at Flexy.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
// $Id: Flexy.php 334846 2014-09-12 04:50:56Z alan_k $
// Standard 'Original Flavour' Flexy compiler
// this does the main conversion, (eg. for {vars and methods})
// it relays into Compiler/Tag & Compiler/Flexy for tags and namespace handling.
require_once 'HTML/Template/Flexy/Tokenizer.php';
require_once 'HTML/Template/Flexy/Token.php';
class HTML_Template_Flexy_Compiler_Flexy extends HTML_Template_Flexy_Compiler {
* reference to calling controller
* @var $flexy HTML_Template_Flexy
* The current template (Full path)
* when using flexy::contents - this contains the map of
* <... flexy:conntents="KEY">.....VALUE ...<...>
var $contentStrings = array ();
* @params object HTML_Template_Flexy
* @params string|false string to compile of false to use a file.
* @return string filename of template
function compile ($flexy, $string=false )
// read the entire file into one variable
// note this should be moved to new HTML_Template_Flexy_Token
// and that can then manage all the tokens in one place..
global $_HTML_TEMPLATE_FLEXY_COMPILER;
$this->currentTemplate = $flexy->currentTemplate;
$gettextStrings = &$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'];
$gettextStrings = array (); // reset it.
if (@$this->options['debug']) {
echo " compiling template $flexy->currentTemplate<BR>";
$flexy->_elements = array ();
// replace this with a singleton??
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions'] = $this->options;
$GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'] = array ();
$GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'] = $flexy->currentTemplate;
$GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] = '';
$GLOBALS['_HTML_TEMPLATE_FLEXY']['compiledTemplate']= $flexy->compiledTemplate;
// initialize Translation 2, and
$this->flexy->initializeTranslator ();
// PRE PROCESS {_(.....)} translation markers.
if (strpos($data, '{_(') !== false ) {
$data = $this->preProcessTranslation ($data);
if (!$this->options['forceCompile'] && isset ($_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)])) {
$res = $_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)];
$tokenizer = new HTML_Template_Flexy_Tokenizer ($data);
$tokenizer->fileName = $flexy->currentTemplate;
$tokenizer->options ['ignore_html'] = $this->options['nonHTML'];
require_once 'HTML/Template/Flexy/Token.php';
$res = HTML_Template_Flexy_Token ::buildTokens ($tokenizer);
if ($this->is_a ($res, 'PEAR_Error')) {
$_HTML_TEMPLATE_FLEXY_COMPILER['cache'][md5($data)] = $res;
// technically we shouldnt get here as we dont cache errors..
if ($this->is_a ($res, 'PEAR_Error')) {
// turn tokens into Template..
$data = $res->compile ($this);
if ($this->is_a ($data, 'PEAR_Error')) {
$data = $GLOBALS['_HTML_TEMPLATE_FLEXY']['prefixOutput'] . $data;
if ( $flexy->options ['debug'] > 1 ) {
if ($this->options['nonHTML']) {
// at this point we are into writing stuff...
if ($flexy->options ['compileToString']) {
if ( $flexy->options ['debug']) {
echo "<B>Returning string:<BR>\n";
$flexy->elements = $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'];
$file = $flexy->compiledTemplate;
if (isset ($flexy->options ['output.block'])) {
list ($file, $part) = explode('#', $file);
if( ($cfp = fopen($file, 'w')) ) {
if ($flexy->options ['debug']) {
echo " <B>Writing: </B>$file<BR>\n";
// make the timestamp of the two items match.
if ($file != $flexy->compiledTemplate ) {
chmod($flexy->compiledTemplate , 0775 );
// make the timestamp of the two items match.
return HTML_Template_Flexy ::staticRaiseError ('HTML_Template_Flexy::failed to write to '. $flexy->compiledTemplate ,
unlink($flexy->getTextStringsFile );
if($gettextStrings && ($cfp = fopen( $flexy->getTextStringsFile , 'w') ) ) {
chmod($flexy->getTextStringsFile , 0664 );
if( $GLOBALS['_HTML_TEMPLATE_FLEXY']['elements'] &&
($cfp = fopen( $flexy->elementsFile , 'w') ) ) {
chmod($flexy->elementsFile , 0664 );
* do the early tranlsation of {_(......)_} text
function preProcessTranslation ($data) {
global $_HTML_TEMPLATE_FLEXY_COMPILER;
$lmatches = explode ('{_(', $data);
foreach ($lmatches as $k) {
if (false === strpos($k, ')_}')) {
//echo '<PRE>';print_r($matches);
// we may need to do some house cleaning here...
$_HTML_TEMPLATE_FLEXY_COMPILER['gettextStrings'] = $matches;
// ** leaving in the tag (which should be ignored by the parser..
// we then get rid of the tags during the toString method in this class.
foreach($matches as $v) {
$data = str_replace('{_('. $v. ')_}', '{_('. $this->flexy->translateString ($v). ')_}', $data);
* Flag indicating compiler is inside {_( .... )_} block, and should not
* add to the gettextstrings array.
var $inGetTextBlock = false;
* This is the base toString Method, it relays into toString{TokenName}
* @param object HTML_Template_Flexy_Token_*
* @return string string to build a template
function toString ($element)
static $len = 26; // strlen('HTML_Template_Flexy_Token_');
if ($this->options ['debug'] > 1 ) {
//echo htmlspecialchars(print_r($x,true))."<BR>\n";
if ($element->token == 'GetTextStart') {
$this->inGetTextBlock = true;
if ($element->token == 'GetTextEnd') {
$this->inGetTextBlock = false;
return $this->{'toString'. $type}($element);
$add = $element->compileChildren ($this);
if ($this->is_a($add, 'PEAR_Error')) {
$add = $element->close ->compile ($this);
if ($this->is_a($add, 'PEAR_Error')) {
* HTML_Template_Flexy_Token_Else toString
* @param object HTML_Template_Flexy_Token_Else
* @return string string to build a template
function toStringElse ($element)
// pushpull states to make sure we are in an area.. - should really check to see
// if the state it is pulling is a if...
if ($element->pullState () === false ) {
return $this->appendHTML (
" <font color=\"red\">Unmatched {else:} on line: {$element->line }</font>"
return $this->appendPhp ("} else {");
* HTML_Template_Flexy_Token_End toString
* @param object HTML_Template_Flexy_Token_Else
* @return string string to build a template
function toStringEnd ($element)
// pushpull states to make sure we are in an area.. - should really check to see
// if the state it is pulling is a if...
if ($element->pullState () === false ) {
return $this->appendHTML (
" <font color=\"red\">Unmatched {end:} on line: {$element->line }</font>"
return $this->appendPhp ("}");
* HTML_Template_Flexy_Token_EndTag toString
* @param object HTML_Template_Flexy_Token_EndTag
* @return string string to build a template
function toStringEndTag ($element)
return $this->toStringTag ($element);
* HTML_Template_Flexy_Token_Foreach toString
* @param object HTML_Template_Flexy_Token_Foreach
* @return string string to build a template
function toStringForeach ($element)
$loopon = $element->toVar ($element->loopOn );
if ($this->is_a($loopon, 'PEAR_Error')) {
$ret = 'if ($this->options[\'strict\'] || ('.
'is_array('. $loopon. ') || ' .
'is_object(' . $loopon . '))) ' .
'foreach(' . $loopon . " ";
$ret .= " as \${$element->key }";
$ret .= " => \${$element->value }";
$element->pushVar ($element->key);
$element->pushVar ($element->value );
return $this->appendPhp ($ret);
* HTML_Template_Flexy_Token_If toString
* @param object HTML_Template_Flexy_Token_If
* @return string string to build a template
function toStringIf ($element)
$var = $element->toVar ($element->condition );
if ($this->is_a($var, 'PEAR_Error')) {
$ret = "if (". $element->isNegative . $var . ") {";
return $this->appendPhp ($ret);
* converts :h, :u, :r , .....
* @param object HTML_Template_Flexy_Token_Method|Var
* @return array prefix,suffix
function getModifierWrapper ($element)
$modifier = strlen(trim($element->modifier )) ? $element->modifier : ' ';
$prefix = 'echo urlencode(';
$prefix = 'echo \'<pre>\'; echo htmlspecialchars(print_r(';
$suffix = ',true)); echo \'</pre>\';';
$numberformat = @$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'];
$prefix = 'echo number_format(';
$suffix = $GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['numberFormat'] . ')';
case 'b': // nl2br + htmlspecialchars
$prefix = 'echo nl2br(htmlspecialchars(';
$prefix = 'echo htmlentities(';
$prefix = 'echo htmlspecialchars(';
$prefix = 'echo $this->plugin("'. trim($element->modifier ) . '",';
return array ($prefix, $suffix);
* HTML_Template_Flexy_Token_Var toString
* @param object HTML_Template_Flexy_Token_Method
* @return string string to build a template
function toStringVar ($element)
// ignore modifier at present!!
$var = $element->toVar ($element->value );
if ($this->is_a($var, 'PEAR_Error')) {
list ($prefix, $suffix) = $this->getModifierWrapper ($element);
return $this->appendPhp ( $prefix . $var . $suffix . ';');
* HTML_Template_Flexy_Token_Method toString
* @param object HTML_Template_Flexy_Token_Method
* @return string string to build a template
function toStringMethod ($element)
// set up the modifier at present!!
list ($prefix, $suffix) = $this->getModifierWrapper ($element);
if ($element->isConditional ) {
$prefix = 'if ('. $element->isNegative;
// check that method exists..
// if (method_exists($object,'method');
$bits = explode('.', $element->method );
$var = $element->toVar ($object);
if ($this->is_a($var, 'PEAR_Error')) {
if (($object == 'GLOBALS') &&
$GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['globalfunctions']) {
// we should check if they something weird like: GLOBALS.xxxx[sdf](....)
$prefix = 'if ($this->options[\'strict\'] || (isset('. $var.
') && method_exists('. $var ." , '{$method}'))) " . $prefix;
$var = $element->toVar ($element->method );
if ($this->is_a($var, 'PEAR_Error')) {
foreach($element->args as $a) {
$var = $element->toVar ($a);
if ($this->is_a($var, 'PEAR_Error')) {
if ($element->isConditional ) {
return $this->appendPhp ($ret);
* HTML_Template_Flexy_Token_Processing toString
* @param object HTML_Template_Flexy_Token_Processing
* @return string string to build a template
function toStringProcessing ($element)
// if it's XML then quote it..
return $this->appendPhp ("echo '" . str_replace("'", "\\". "'", $element->value ) . "';");
// otherwise it's PHP code - so echo it..
* HTML_Template_Flexy_Token_Text toString
* @param object HTML_Template_Flexy_Token_Text
* @return string string to build a template
function toStringText ($element)
// first get rid of stuff thats not translated etc.
// empty strings => output.
// comments -> just output
// our special tags -> output..
return $this->appendHtml ($element->value );
// dont add comments to translation lists.
if (substr($element->value , 0 , 4 ) == '<!--') {
return $this->appendHtml ($element->value );
// ignore anything wrapped with {_( .... )_}
if ($this->inGetTextBlock ) {
return $this->appendHtml ($element->value );
if (!$element->isWord ()) {
return $this->appendHtml ($element->value );
// grab the white space at start and end (and keep it!
$value = ltrim($element->value );
$value = rtrim($element->value );
$value = trim($element->value );
// convert to escaped chars.. (limited..)
//$value = strtr($value,$cleanArray);
// this only applies to html templates
if (empty ($this->flexy ->options ['nonHTML'])) {
$this->addStringToGettext ($value);
$value = $this->flexy ->translateString ($value);
return $this->appendHtml ($front . $value . $rear);
* HTML_Template_Flexy_Token_Cdata toString
* @param object HTML_Template_Flexy_Token_Cdata ?
* @return string string to build a template
function toStringCdata ($element)
return $this->appendHtml ($element->value );
* Adds a string to the gettext array.
* @param mixed preferably.. string to store
function addStringToGettext ($string)
if (!empty ($this->options ['disableTranslate'])) {
if (substr($string, 0 , 4 ) == '<!--') {
$GLOBALS['_HTML_TEMPLATE_FLEXY_COMPILER']['gettextStrings'][] = $string;
* HTML_Template_Flexy_Token_Tag toString
* @param object HTML_Template_Flexy_Token_Tag
* @return string string to build a template
function toStringTag ($element) {
$original = $element->getAttribute ('ALT');
// techncially only input type=(submit|button|input) alt=.. applies, but we may
// as well translate any occurance...
if ( (($element->tag == 'IMG') || ($element->tag == 'INPUT'))
$this->addStringToGettext ($original);
$quote = $element->ucAttributes ['ALT']{0 };
$element->ucAttributes ['ALT'] = $quote . $this->flexy ->translateString ($original). $quote;
$original = $element->getAttribute ('TITLE');
$this->addStringToGettext ($original);
$quote = $element->ucAttributes ['TITLE']{0 };
$element->ucAttributes ['TITLE'] = $quote . $this->flexy ->translateString ($original). $quote;
if (strpos($element->tag , ':') === false ) {
$bits = explode(':', $element->tag );
if ($namespace{0 } == '/') {
$namespace = substr($namespace, 1 );
if (empty ($this->tagHandlers [$namespace])) {
require_once 'HTML/Template/Flexy/Compiler/Flexy/Tag.php';
$this->tagHandlers [$namespace] = &HTML_Template_Flexy_Compiler_Flexy_Tag ::factory ($namespace, $this);
if (!$this->tagHandlers [$namespace] ) {
return HTML_Template_Flexy ::staticRaiseError ('HTML_Template_Flexy::failed to create Namespace Handler '. $namespace .
' in file ' . $GLOBALS['_HTML_TEMPLATE_FLEXY']['filename'],
return $this->tagHandlers [$namespace]->toString ($element);
* - where else does this affect
function classExists ($class)
Documentation generated on Mon, 11 Mar 2019 15:59:56 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|