Source for file Tag.php
Documentation is available at Tag.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> |
// +----------------------------------------------------------------------+
// $Id: Tag.php 334846 2014-09-12 04:50:56Z alan_k $
/* FC/BC compatibility with php5 */
eval ('function clone($t) { return $t; }');
* Compiler That deals with standard HTML Tag output.
* Since it's pretty complex it has it's own class.
* I guess this class should deal with the main namespace
* and the parent (standard compiler can redirect other namespaces to other classes.
* one instance of these exists for each namespace.
* @version $Id: Tag.php 334846 2014-09-12 04:50:56Z alan_k $
class HTML_Template_Flexy_Compiler_Standard_Tag {
* @var object HTML_Template_Flexy_Compiler
* Factory method to create Tag Handlers
* $type = namespace eg. <flexy:toJavascript loads Flexy.php
* the default is this... (eg. Tag)
* @param string Namespace handler for element.
* @param object HTML_Template_Flexy_Compiler
* @return object tag compiler
function &factory ($type,&$compiler) {
// if we dont have a handler - just use the basic handler.
include_once 'HTML/Template/Flexy/Compiler/Standard/' . ucfirst(strtolower($type)) . '.php';
$class = 'HTML_Template_Flexy_Compiler_Standard_' . $type;
$ret->compiler = &$compiler;
* The current element to parse..
* Flag to indicate has attribute flexy:foreach (so you cant mix it with flexy:if!)
* toString - display tag, attributes, postfix and any code in attributes.
* Note first thing it does is call any parseTag Method that exists..
* @see parent::toString()
function toString ($element)
global $_HTML_TEMPLATE_FLEXY_TOKEN;
global $_HTML_TEMPLATE_FLEXY;
// store the element in a variable
$this->element = $element;
// echo "toString: Line {$this->element->line} <{$this->element->tag}>\n";
// if the FLEXYSTARTCHILDREN flag was set, only do children
// normally set in BODY tag.
// this will probably be superseeded by the Class compiler.
if (isset ($element->ucAttributes ['FLEXY:STARTCHILDREN'])) {
return $element->compileChildren ($this->compiler);
$flexyignore = $this->parseAttributeIgnore ();
// rewriting should be done with a tag.../flag.
$this->reWriteURL ("HREF");
$this->reWriteURL ("SRC");
if (($ret = $this->_parseTags ()) !== false ) {
// these add to the close tag..
$ret = $this->parseAttributeForeach ();
$ret .= $this->parseAttributeIf ();
// spit ou the tag and attributes.
if ($element->oTag {0 } == '?') {
$ret .= '<?php echo "<"; ?>';
foreach ($element->attributes as $k=> $v) {
// if it's a flexy tag ignore it.
return HTML_Template_Flexy ::staticRaiseError (
'flexy:raw only accepts a variable or method call as an argument, eg.'.
' flexy:raw="{somevalue}" you provided something else.' .
" Error on Line {$this->element->line } <{$this->element->tag }>" ,
$add = $v[1 ]->compile ($this->compiler);
// true == an attribute without a ="xxx"
// if it's a string just dump it.
// normally the value is an array of string, however
// if it is an object - then it's a conditional key.
// eg. if (something) echo ' SELECTED';
// the object is responsible for adding it's space..
$add = $v->compile ($this->compiler);
// otherwise its a key="sometext{andsomevars}"
$add = $item->compile ($this->compiler);
// post stuff this is probably in the wrong place...
foreach ($element->postfix as $e) {
$add = $e->compile ($this->compiler);
} else if ($this->element->postfix ) { // if postfixed by self..
foreach ($this->element->postfix as $e) {
$add = $e->compile ($this->compiler);
// dump contents of script raw - to prevent gettext additions..
if ($element->tag == 'SCRIPT') {
foreach($element->children as $c) {
if ($c->token == 'Text') {
// techically we shouldnt have anything else inside of script tags.
// as the tokeinzer is supposted to ignore it..
$add = $element->compileChildren ($this->compiler);
// output the closing tag.
$add = $element->close ->compile ($this->compiler);
$_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'] = $flexyignore;
if (isset ($_HTML_TEMPLATE_FLEXY['currentOptions']['output.block']) &&
($_HTML_TEMPLATE_FLEXY['currentOptions']['output.block'] == $element->getAttribute ('ID'))) {
// echo $_HTML_TEMPLATE_FLEXY['compiledTemplate'];
$fh = fopen($_HTML_TEMPLATE_FLEXY['compiledTemplate'],'w');
* Reads an flexy:foreach attribute -
* @return string to add to output.
function parseAttributeIgnore ()
global $_HTML_TEMPLATE_FLEXY_TOKEN;
$flexyignore = $_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'];
if ($this->element->getAttribute ('FLEXY:IGNORE') !== false ) {
$_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore'] = true;
$this->element->clearAttribute ('FLEXY:IGNORE');
* Reads an flexy:foreach attribute -
* @return string to add to output.
function parseAttributeForeach ()
$foreach = $this->element->getAttribute ('FLEXY:FOREACH');
if ($foreach === false ) {
$this->element->hasForeach = true;
// create a foreach element to wrap this with.
$foreachObj = $this->element->factory ('Foreach',
// failed = probably not enough variables..
if ($foreachObj === false ) {
return HTML_Template_Flexy ::staticRaiseError (
" Missing Arguments: An flexy:foreach attribute was foundon Line {$this->element->line }
in tag <{$this->element->tag } flexy:foreach="$foreach" .....><BR>
the syntax is <sometag flexy:foreach="onarray,withvariable[,withanothervar] ><BR>" ,
// does it have a closetag?
if (!$this->element->close ) {
if ($this->element->getAttribute ('/') === false ) {
return HTML_Template_Flexy ::staticRaiseError (
" A flexy:foreach attribute was found in <{$this->element->name } tag without a corresponding </{$this->element->tag }
tag on Line {$this->element->line } <{$this->element->tag }>" ,
$this->element->postfix = array ($this->element->factory ("End", '', $this->element->line ));
$this->element->close ->postfix = array ($this->element->factory ("End", '', $this->element->line ));
$this->element->clearAttribute ('FLEXY:FOREACH');
return $foreachObj->compile ($this->compiler);
* Reads an flexy:if attribute -
* @return string to add to output.
function parseAttributeIf ()
// dont use the together, if is depreciated..
$if = $this->element->getAttribute ('FLEXY:IF');
if (isset ($this->element->hasForeach )) {
return HTML_Template_Flexy ::staticRaiseError (
" You may not use FOREACH and IF tags in the same tag on Line {$this->element->line } <{$this->element->tag }>" ,
// if="xxxx.xxxx()" - should create a method prefixed with 'if:'
// these checks should really be in the if/method class..!!!
if (!preg_match('/^[_A-Z][A-Z0-9_]*(\[[0-9]+\])?((\[|%5B)[A-Z0-9_]+(\]|%5D))*'.
'(\.[_A-Z][A-Z0-9_]*((\[|%5B)[A-Z0-9_]+(\]|%5D))*)*(\\([^)]*\))?$/i',$if)) {
return HTML_Template_Flexy ::staticRaiseError (
" IF tags only accept simple object.variable or object.method() values on
Line {$this->element->line } <{$this->element->tag }>
// this is nasty... - we need to check for quotes = eg. # at beg. & end..
for ($i=0; $i< count($args); $i++ ) {
if ($args[$i]{0 } != '#') {
$args_clean[] = $args[$i];
// single # - so , must be inside..
if ((strlen($args[$i]) > 1 ) && ($args[$i]{strlen($args[$i])-1 }== '#')) {
$args_clean[] = $args[$i];
$args[$i] .= ',' . $args[$i+1 ];
$ifObj = $this->element->factory ('Method',
array ('if:'. $ifnegative. substr($if,0 ,strpos($if,'(')), $args_clean),
$ifObj = $this->element->factory ('If', $ifnegative. $if, $this->element->line );
// does it have a closetag? - you must have one - so you will have to hack in <span flexy:if=..><img></span> on tags
// that do not have close tags - it's done this way to try and avoid mistakes.
if (!$this->element->close ) {
//echo "<PRE>";print_R($this->element);
if ($this->element->getAttribute ('/') !== false ) {
$this->element->postfix = array ($this->element->factory ("End",'', $this->element->line ));
return HTML_Template_Flexy ::staticRaiseError (
" An flexy:if attribute was found in <{$this->element->name } tag without a corresponding </{$this->element->name }
tag on Line {$this->element->line } <{$this->element->tag }>" ,
$this->element->close ->postfix = array ($this->element->factory ("End",'', $this->element->line ));
$this->element->clearAttribute ('FLEXY:IF');
return $ifObj->compile ($this->compiler);
* Reads Tags - and relays to parseTagXXXXXXX
* @return string | false = html output or ignore (just output the tag)
global $_HTML_TEMPLATE_FLEXY_TOKEN;
// doesnt really need strtolower etc. as php functions are not case sensitive!
if ($this->element->getAttribute ('FLEXY:DYNAMIC')) {
return $this->compiler->appendPhp (
$this->getElementPhp ( $this->element->getAttribute ('ID') )
if ($this->element->getAttribute ('FLEXY:IGNOREONLY') !== false ) {
if ($_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore']) {
$tag = $this->element->tag;
if (strpos($tag,':') !== false ) {
$method = 'parseTag'. $tag;
// do any of the attributes use flexy data...
foreach ($this->element->attributes as $k=> $v) {
//echo "call $method" . serialize($this->element->attributes). "\n";
// allow the parse methods to return output.
* produces the code for dynamic elements
* @return string | false = html output or ignore (just output the tag)
function getElementPhp ($id,$mergeWithName=false ) {
global $_HTML_TEMPLATE_FLEXY;
return HTML_Template_Flexy ::staticRaiseError (
"Error:{ $_HTML_TEMPLATE_FLEXY['filename']} on Line { $this->element ->line } <{ $this->element ->tag }>: " .
" Dynamic tags require an ID value",
null , HTML_TEMPLATE_FLEXY_ERROR_DIE );
if (($this->element ->getAttribute ('FLEXY:IF') !== false ) ||
($this->element ->getAttribute ('FLEXY:FOREACH') !== false ) )
return HTML_Template_Flexy ::staticRaiseError (
"Error:{ $_HTML_TEMPLATE_FLEXY['filename']} on Line { $this->element ->line } <{ $this->element ->tag }>: " .
" You can not mix flexy:if= or flexy:foreach= with dynamic form elements " .
" (turn off tag to element code with flexyIgnore=0, use flexy:ignore="yes" in the tag" .
" or put the conditional outside in a span tag",
null, <a href="../HTML_Template_Flexy/_HTML_Template_Flexy-1.3.13---HTML---Template---Flexy.php.html#defineHTML_TEMPLATE_FLEXY_ERROR_DIE">HTML_TEMPLATE_FLEXY_ERROR_DIE</a>);
if ((strtolower($this->element->getAttribute('type')) == 'checkbox' ) &&
(substr($this->element->getAttribute('name'),-2) == '[]')) {
if ($this->element->getAttribute('id') === false) {
$id = 'tmpId'. (++$tmpId);
$this->element->attributes['id'] = $id;
$this->element->ucAttributes['ID'] = $id;
if (isset($_HTML_TEMPLATE_FLEXY['elements'][$id])) {
// echo "<PRE>";print_r($this);print_r($_HTML_TEMPLATE_FLEXY['elements']);echo "</PRE>";
return HTML_Template_Flexy::staticRaiseError(
"Error:{ $_HTML_TEMPLATE_FLEXY['filename']} on Line { $this->element ->line } in Tag <{ $this->element ->tag }>:<BR> " .
"The Dynamic tag Name ' $id' has already been used previously by tag <{ $_HTML_TEMPLATE_FLEXY['elements'][$id]->tag }>" ,
null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
// this is for a case where you can use a sprintf as the name, and overlay it with a variable element..
$_HTML_TEMPLATE_FLEXY['elements'][$id] = $this->toElement($this->element);
if ($var = $this->element->getAttribute('FLEXY:NAMEUSES')) {
$var = 'sprintf(\''.$id .'\','.$this->element->toVar($var) .')';
'if (!isset($this->elements['.$var.'])) $this->elements['.$var.']= $this->elements[\''.$id.'\'];
$this->elements['.$var.'] = $this->mergeElement($this->elements[\''.$id.'\'],$this->elements['.$var.']);
$this->elements['.$var.']->attributes[\'name\'] = '.$var. ';
echo $this->elements['.$var.']->toHtml();';
} elseif ($mergeWithName) {
$name = $this->element->getAttribute('NAME');
'$element = $this->elements[\''.$id.'\'];
$element = $this->mergeElement($element,$this->elements[\''.$name.'\']);
echo $element->toHtml();';
return 'echo $this->elements[\''.$id.'\']->toHtml();';
* Reads an Script tag - check if PHP is allowed.
* @return false|PEAR_Error
function parseTagScript() {
$lang = $this->element->getAttribute('LANGUAGE');
if ($GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['allowPHP']) {
return HTML_Template_Flexy::staticRaiseError('PHP code found in script',
<a href="../HTML_Template_Flexy/_HTML_Template_Flexy-1.3.13---HTML---Template---Flexy.php.html#defineHTML_TEMPLATE_FLEXY_ERROR_SYNTAX">HTML_TEMPLATE_FLEXY_ERROR_SYNTAX</a>,<a href="../HTML_Template_Flexy/_HTML_Template_Flexy-1.3.13---HTML---Template---Flexy.php.html#defineHTML_TEMPLATE_FLEXY_ERROR_RETURN">HTML_TEMPLATE_FLEXY_ERROR_RETURN</a>
* Reads an Input tag - build a element object for it
* @return string | false = html output or ignore (just output the tag)
global $_HTML_TEMPLATE_FLEXY;
if (in_array(strtoupper($this->element->getAttribute('TYPE')), array('SUBMIT','BUTTON','INPUT',''))) {
$this->compiler->addStringToGettext($this->element->getAttribute('VALUE'));
// form elements : format:
//value - fill out as PHP CODE
// as a general rule, this uses name, rather than ID except on
$id = $this->element->getAttribute('NAME');
// checkboxes need more work.. - at the momemnt assume one with the same value...
if (!isset($_HTML_TEMPLATE_FLEXY['elements'][$id])) {
// register it.. - so we dont overwrite it...
$_HTML_TEMPLATE_FLEXY['elements'][$id] = false;
} else if ($_HTML_TEMPLATE_FLEXY['elements'][$id] != false) {
return HTML_Template_Flexy::staticRaiseError(
"Error:{ $_HTML_TEMPLATE_FLEXY['filename']} on Line { $this->element ->line } " .
"in Tag <{ $this->element ->tag }>:<BR>" .
"The Dynamic tag Name ' $id' has already been used previously by " .
"tag <{ $_HTML_TEMPLATE_FLEXY['elements'][$id]->tag }>" ,
null, HTML_TEMPLATE_FLEXY_ERROR_DIE
$id = $this->element->getAttribute('ID');
return HTML_Template_Flexy::staticRaiseError("Error in { $_HTML_TEMPLATE_FLEXY['filename']} on Line { $this->element ->line } <{ $this->element ->tag }>:
Radio Input's require an ID tag.." ,
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
return $this->compiler->appendPhp($this->getElementPhp( $id,$mergeWithName));
* Deal with a TextArea tag - build a element object for it
* @return string | false = html output or ignore (just output the tag)
function parseTagTextArea()
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('NAME')));
* Deal with Selects - build a element object for it (unless flexyignore is set)
* @return string | false = html output or ignore (just output the tag)
function parseTagSelect()
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('NAME')));
* Reads an Form tag - and set up the element object header etc.
* @return string | false = html output or ignore (just output the tag)
global $_HTML_TEMPLATE_FLEXY;
$copy = clone($this->element);
$copy->children = array();
$id = $this->element->getAttribute('NAME');
// this adds the element to the elements array.
$old = clone($this->element);
$this->getElementPhp($id);
$this->compiler->appendPhp('echo $this->elements[\''.$id.'\']->toHtmlnoClose();') .
$this->element->compileChildren($this->compiler) .
$this->compiler->appendHtml( "</{ $copy->oTag }>" );
* reWriteURL - can using the config option 'url_rewrite'
* format "from:to,from:to"
* only handle left rewrite.
* "/images:/myroot/images"
* /images/xyz.gif to /myroot/images/xyz.gif
* /images/stylesheet/imagestyles.css to /myroot/images/stylesheet/imagestyles.css
* note /imagestyles did not get altered.
* will only work on strings (forget about doing /images/{someimage}
* @param string attribute to rewrite
function reWriteURL($which)
global $_HTML_TEMPLATE_FLEXY;
if (!is_string($original = $this->element->getAttribute($which))) {
if (empty($_HTML_TEMPLATE_FLEXY['currentOptions']['url_rewrite'])) {
$bits = explode(",",$_HTML_TEMPLATE_FLEXY['currentOptions']['url_rewrite']);
foreach ($bits as $bit) {
return HTML_Template_Flexy::staticRaiseError('HTML_Template_Flexy: url_rewrite syntax incorrect'.
print_r(array($bits,$bits),true),null,<a href="../HTML_Template_Flexy/_HTML_Template_Flexy-1.3.13---HTML---Template---Flexy.php.html#defineHTML_TEMPLATE_FLEXY_ERROR_DIE">HTML_TEMPLATE_FLEXY_ERROR_DIE</a>);
$this->element->ucAttributes[$which] = '"'. $new . '"';
* Convert flexy tokens to HTML_Template_Flexy_Elements.
* @param object token to convert into a element.
* @return object HTML_Template_Flexy_Element
function toElement($element) {
require_once 'HTML/Template/Flexy/Element.php';
$ret = new HTML_Template_Flexy_Element;
$this->compiler->addStringToGettext($element->value);
$ats = $element->getAttributes();
if (isset($element->attributes['flexy:xhtml'])) {
$ats['flexy:xhtml'] = true;
$ret->attributes[$a] = $this->unHtmlEntities($ats[$a]);
if (!$element->children) {
// children - normally to deal with <element>
//print_r($this->children);
// not quite sure why this happens - but it does.
$ret->children[] = $this->toElement($element->children[$i]);
* do the reverse of htmlspecialchars on an attribute..
* copied from get-html-translation-table man page
* @param mixed from attribute values
* @see see also methods.....
function unHtmlEntities ($in)
$ret = strtr ($in, $trans_tbl);
Documentation generated on Mon, 11 Mar 2019 15:59:59 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|