File: //opt/cloudlinux/alt-php54/root/usr/share/pear/HTML/Template/Flexy/Compiler/Flexy/Tag.php
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 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 */
if ( (substr(phpversion(),0,1) < 5) && !function_exists('clone')) {
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_Flexy_Tag
{
/**
* Parent Compiler for
*
* @var object HTML_Template_Flexy_Compiler
*
* @access public
*/
var $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
* @access public
*/
static function &factory($type,&$compiler) {
if (!$type) {
$type = 'Tag';
}
$class = 'HTML_Template_Flexy_Compiler_Flexy_' . $type;
if ($compiler->classExists($class)) {
$ret = new $class;
$ret->compiler = &$compiler;
return $ret;
}
$filename = 'HTML/Template/Flexy/Compiler/Flexy/' . ucfirst(strtolower($type)) . '.php';
if (!HTML_Template_Flexy_Compiler_Flexy_Tag::fileExistsInPath($filename)) {
$ret = HTML_Template_Flexy_Compiler_Flexy_Tag::factory('Tag',$compiler);
return $ret;
}
// if we dont have a handler - just use the basic handler.
if (!file_exists(dirname(__FILE__) . '/'. ucfirst(strtolower($type)) . '.php')) {
$type = 'Tag';
}
include_once 'HTML/Template/Flexy/Compiler/Flexy/' . ucfirst(strtolower($type)) . '.php';
$class = 'HTML_Template_Flexy_Compiler_Flexy_' . $type;
if (!$compiler->classExists($class)) {
$ret = false;
return $ret;
}
$ret = HTML_Template_Flexy_Compiler_Flexy_Tag::factory($type,$compiler);
return $ret;
}
/**
*
* Check that a file exists in the "include_path"
*
* @param string Filename
*
* @return boolean true if it is in there.
* @access public
*/
static function fileExistsInPath($filename) {
if (isset($GLOBALS['_'.__CLASS__]['cache'][$filename])) {
return $GLOBALS['_'.__CLASS__]['cache'][$filename];
}
$bits = explode(PATH_SEPARATOR,ini_get('include_path'));
foreach($bits as $b) {
if (file_exists("$b/$filename")) {
return $GLOBALS['_'.__CLASS__]['cache'][$filename] = true;
}
}
return $GLOBALS['_'.__CLASS__]['cache'][$filename] = false;
}
/**
* The current element to parse..
*
* @var object
* @access public
*/
var $element;
/**
* Flag to indicate has attribute flexy:foreach (so you cant mix it with flexy:if!)
*
* @var boolean
* @access public
*/
var $hasForeach = false;
/**
* 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);
}
// look for flexy:ignore..
$flexyignore = $this->parseAttributeIgnore();
// rewriting should be done with a tag.../flag.
$this->reWriteURL("HREF");
$this->reWriteURL("SRC");
$this->reWriteURL("BACKGROUND");
// handle elements
if (($ret =$this->_parseTags()) !== false) {
return $ret;
}
// these add to the close tag..
$ret = $this->parseAttributeForeach();
$ret .= $this->parseAttributeIf();
// support Custom Attributes...
require_once 'HTML/Template/Flexy/Compiler/Flexy/CustomFlexyAttributes.php';
$customFlexyAttributes = new HTML_Template_Flexy_Compiler_Flexy_CustomFlexyAttributes($this->compiler);
$customFlexyAttributes->doCustomAttributes($element);
$add = $this->toStringOpenTag($element,$ret);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
// post stuff this is probably in the wrong place...
if ($element->postfix) {
foreach ($element->postfix as $e) {
$add = $e->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
} else if ($this->element->postfix) { // if postfixed by self..
foreach ($this->element->postfix as $e) {
$add = $e->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
}
$tmp = $this->toStringChildren($element,$ret);
if (is_object($tmp) && is_a($tmp,'PEAR_Error')) {
return $tmp;
}
$tmp = $this->toStringCloseTag($element,$ret);
if (is_object($tmp) && is_a($tmp,'PEAR_Error')) {
return $tmp;
}
// reset flexyignore
$_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');
fwrite($fh,$ret);
fclose($fh);
}
return $ret;
}
/**
* convert a tag into compiled version
* @arg object Element
* @arg inout output string to template
* @return none? or pear error.
*
*/
function toStringOpenTag(&$element,&$ret)
{
// START ADDITION...
if ((empty($element->tag)) || (empty($element->oTag))) {
return;
}
// ...END ADDITION
// spit ou the tag and attributes.
if ($element->oTag{0} == '?') {
$ret .= '<?php echo "<"; ?>';
} else {
$ret .= "<";
}
$ret .= $element->oTag;
//echo '<PRE>'.print_r($element->attributes,true);
foreach ($element->attributes as $k=>$v) {
// if it's a flexy tag ignore it.
if (strtoupper($k) == 'FLEXY:RAW') {
if (!is_array($v) || !isset($v[1]) || !is_object($v[1])) {
return $this->_raiseErrorWithPositionAndTag(
'flexy:raw only accepts a variable or method call as an argument, eg.'.
' flexy:raw="{somevalue}" you provided something else.' .
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$add = $v[1]->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= ' ' . $add;
continue;
}
if (strtoupper(substr($k,0,6)) == 'FLEXY:') {
continue;
}
// true == an attribute without a ="xxx"
if ($v === true) {
$ret .= " $k";
continue;
}
// if it's an input with value or placeholder...
// the output the translated value..
if (is_string($v) && (in_array($element->tag , array('INPUT','TEXTAREA'))) &&
(strtoupper($k) == 'VALUE' || strtoupper($k) == 'PLACEHOLDER' )
) {
// look up the translation..
$v = '"'. htmlspecialchars(
$this->compiler->flexy->translateString(substr($v,1,-1))
) .'"';
}
// if it's a string just dump it.
if (is_string($v)) {
$v = str_replace(array('{_(',')_}'),array('',''),$v);
$ret .= " {$k}={$v}";
continue;
}
// 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..
if (is_object($v)) {
$add = $v->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
continue;
}
// otherwise its a key="sometext{andsomevars}"
$ret .= " {$k}=";
foreach($v as $item) {
if (is_string($item)) {
// skip translation strings in tags.
$item = str_replace(array('{_(',')_}'),array('',''),$item);
$ret .= $item;
continue;
}
$add = $item->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
}
$ret .= ">";
}
/**
* compile children to string.
* @arg object Element
* @arg inout output string to template
* @return none? or pear error.
*/
function toStringChildren(&$element,&$ret)
{
// dump contents of script raw - to prevent gettext additions..
// print_r($element);
// make sure tag isn't empty because it wouldn't make sense to output script without script tags
if (((! empty($element->tag)) && ($element->tag == 'SCRIPT'))
|| ((! empty($element->oTag)) && ($element->oTag == 'SCRIPT'))) {
foreach($element->children as $c) {
//print_R($c);
if (!$c) {
continue;
}
if ($c->token == 'Text') {
$ret .= $c->value;
continue;
}
// techically we shouldnt have anything else inside of script tags.
// as the tokeinzer is supposted to ignore it..
}
return;
}
$add = $element->compileChildren($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
/**
* compile closing tag to string.
* @arg object Element
* @arg inout output string to template
* @return none? or pear error.
*/
function toStringCloseTag(&$element,&$ret)
{
// output the closing tag.
// If the tag is empty don't output closing tags, just output postfixes if any exist...
if ( !$element->close) {
return;
}
if ((! empty($element->tag)) && (! empty($element->oTag)))
{
$add = $element->close->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
return;
}
// RICK - added by me
// element has a seperate closing tag (eg. </something>) and opening and closing tags should be removed
// because FLEXY:OMITTAG element attribute is set, but still need postfix stuff like for ending ifs and foreach
// so this is NOT OPTIONAL if foreach and if are not optional.
if ($element->close->postfix) {
foreach ($element->close->postfix as $e) {
$add = $e->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
return;
}
if ($this->element->close->postfix) { // if postfixed by self..
foreach ($this->element->close->postfix as $e) {
$add = $e->compile($this->compiler);
if (is_object($add) && is_a($add,'PEAR_Error')) {
return $add;
}
$ret .= $add;
}
return;
}
}
/**
* Reads an flexy:foreach attribute -
*
*
* @return string to add to output.
* @access public
*/
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');
}
return $flexyignore;
}
/**
* Reads an flexy:foreach attribute -
*
*
* @return string to add to output.
* @access public
*/
function parseAttributeForeach()
{
global $_HTML_TEMPLATE_FLEXY;
$foreach = $this->element->getAttribute('FLEXY:FOREACH');
if ($foreach === false) {
return '';
}
//var_dump($foreach);
$this->element->hasForeach = true;
// create a foreach element to wrap this with.
$foreachTokens = explode( ",", $foreach ); //usual
$first = array_shift($foreachTokens);
// we will accept first argument as a method call.. with arguments.
// this however does not deal with '#' with commas and braces insed very weill..
if (strpos($first, '(') !== false) {
while (strpos($first, ')') === false) {
if (!count($foreachTokens)) {
return $this->_raiseErrorWithPositionAndTag(
"Missing Closer on functin call: An flexy:foreach attribute was found. flexy:foreach="$foreach"<BR>
the syntax is <sometag flexy:foreach="onarray,withvariable[,withanothervar] ><BR>",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$first .= ',' . array_shift($foreachTokens);
}
}
array_unshift($foreachTokens, $first);
$foreachObj = $this->element->factory('Foreach',
$foreachTokens,
$this->element->line);
// failed = probably not enough variables..
if ($foreachObj === false) {
return $this->_raiseErrorWithPositionAndTag(
"Missing Arguments: An flexy:foreach attribute was found. flexy:foreach="$foreach"<BR>
the syntax is <sometag flexy:foreach="onarray,withvariable[,withanothervar] ><BR>",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// does it have a closetag?
if (!$this->element->close) {
if ($this->element->getAttribute('/') === false) {
return $this->_raiseErrorWithPositionAndTag(
"A flexy:foreach attribute was found without a corresponding </{$this->element->tag} tag",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// it's an xhtml tag!
$this->element->postfix = array($this->element->factory("End", '', $this->element->line));
} else {
$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.
* @access public
*/
function parseAttributeIf()
{
// dont use the together, if is depreciated..
$if = $this->element->getAttribute('FLEXY:IF');
if ($if === false) {
return '';
}
if (isset($this->element->hasForeach)) {
return $this->_raiseErrorWithPositionAndTag("You may not use FOREACH and IF tags in the same tag",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// allow if="!somevar"
$ifnegative = '';
if ($if{0} == '!') {
$ifnegative = '!';
$if = substr($if,1);
}
// if="xxxxx"
// 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 $this->_raiseErrorWithPositionAndTag(
"IF tags only accept simple object.variable or object.method() values. {$if}",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
if (substr($if,-1) == ')') {
// grab args..
$args = substr($if,strpos($if,'(')+1,-1);
// simple explode ...
$args = strlen(trim($args)) ? explode(',',$args) : array();
//print_R($args);
// this is nasty... - we need to check for quotes = eg. # at beg. & end..
$args_clean = array();
for ($i=0; $i<count($args); $i++) {
if ($args[$i]{0} != '#') {
$args_clean[] = $args[$i];
continue;
}
// single # - so , must be inside..
if ((strlen($args[$i]) > 1) && ($args[$i]{strlen($args[$i])-1}=='#')) {
$args_clean[] = $args[$i];
continue;
}
$args[$i] .=',' . $args[$i+1];
// remove args+1..
array_splice($args,$i+1,1);
$i--;
// reparse..
}
$ifObj = $this->element->factory('Method',
array('if:'.$ifnegative.substr($if,0,strpos($if,'(')), $args_clean),
$this->element->line);
} else {
$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));
} else {
return $this->_raiseErrorWithPositionAndTag(
"An flexy:if attribute was found in <{$this->element->name} tag without a corresponding </{$this->element->name} tag",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
} else {
$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)
* @access private
*/
function _parseTags()
{
global $_HTML_TEMPLATE_FLEXY_TOKEN;
// doesnt really need strtolower etc. as php functions are not case sensitive!
/* always render script correctly */
if (0 == strcasecmp($this->element->tag,"script")) {
return $this->parseTagScript();
}
if ($this->element->getAttribute('FLEXY:DYNAMIC')) {
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('ID') )
);
}
if ($this->element->getAttribute('FLEXY:IGNOREONLY') !== false) {
return false;
}
if ($_HTML_TEMPLATE_FLEXY_TOKEN['flexyIgnore']) {
return false;
}
$tag = $this->element->tag;
if (strpos($tag,':') !== false) {
$bits = explode(':',$tag);
$tag = $bits[1];
}
if (in_array(strtolower($tag), array('menulist','textbox','checkbox'))) {
$method = 'parseXulTag';
} else {
$method = 'parseTag'.$tag;
if (!method_exists($this,$method)) {
return false;
}
}
if (($this->element->getAttribute('NAME') === false) &&
($this->element->getAttribute('ID') === false) ) {
return false;
}
// do any of the attributes use flexy data...
//foreach ($this->element->attributes as $k=>$v) {
// if (is_array($v)) {
// return false;
// }
//}
//echo "call $method" . serialize($this->element->attributes). "\n";
return $this->$method();
// allow the parse methods to return output.
}
/**
* produces the code for dynamic elements
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function getElementPhp($id,$mergeWithName=false,$varsOnly = false) {
global $_HTML_TEMPLATE_FLEXY;
static $tmpId=0;
if (!$id) {
return $this->_raiseErrorWithPositionAndTag("Dynamic tags require an ID value",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
// dont mix and match..
if (($this->element->getAttribute('FLEXY:IF') !== false) ||
($this->element->getAttribute('FLEXY:FOREACH') !== false) )
{
return $this->_raiseErrorWithPositionAndTag(
" 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, HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
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;
} else {
$id = $this->element->getAttribute('ID');
}
$mergeWithName = true;
}
if (isset($_HTML_TEMPLATE_FLEXY['elements'][$id])) {
// echo "<PRE>";print_r($this);print_r($_HTML_TEMPLATE_FLEXY['elements']);echo "</PRE>";
return $this->_raiseErrorWithPositionAndTag(
"The Dynamic tag Name '$id' has already been used previously by tag <{$_HTML_TEMPLATE_FLEXY['elements'][$id]->tag}>",
null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$ret = '';
$unset = '';
//echo '<PRE>';print_r($this->element);echo '</PRE>';
if (isset($this->element->ucAttributes['FLEXY:USE'])) {
$ar = $this->element->ucAttributes['FLEXY:USE'];
$str = '';
for($i =1; $i < count($ar) -1; $i++) {
switch(true) {
case (is_object($ar[$i]) && is_a($ar[$i], 'HTML_Template_Flexy_Token_Var')):
$str .= '. ' . $ar[$i]->toVar($ar[$i]->value). ' ';
break;
case is_string($ar[$i]):
$str .= '. ' . $ar[0] . $ar[$i] . $ar[0];
break;
default:
return $this->_raiseErrorWithPositionAndTag(
"unsupported type found in attribute, use flexy:ignore to prevent parsing or remove it. " .
print_r($this->element,true),
null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
}
$str = trim(ltrim($str,'.'));
$_HTML_TEMPLATE_FLEXY['elements'][$id] = $this->toElement($this->element);
return $ret .
'
if (!isset($this->elements['.$str.'])) {
echo "ELEMENT MISSING $str";
}
echo $this->elements['.$str.']->toHtml();' .$unset;
}
if ($this->elementUsesDynamic($this->element)) {
$used = array();
foreach ($this->element->attributes as $attribute => $attributeValue) {
if (!is_array($attributeValue)) {
continue;
}
if (strtoupper(substr($attribute,0,6)) == 'FLEXY:') {
continue;
}
unset($this->element->attributes[$attribute]);
// generate code to put data into value..
$output_avar = '$this->elements[\''.$id.'\']->attributes[\''.$attribute.'\']';
$used[] = "'{$attribute}'";
$ret .= "\nif (!isset({$output_avar})) {\n";
// get the " or ' that encapsulates the element.
$wrapper = array_shift($attributeValue);
array_pop($attributeValue);
$ret .= " {$output_avar} = '';\n";
//echo '<PRE>';print_r($attributeValue);echo '</PRE>';
foreach($attributeValue as $item) {
if (is_string($item)) {
$ret .= " {$output_avar} .= {$wrapper}{$item}{$wrapper};\n";
continue;
}
if (!is_object($item) || !is_a($item, 'HTML_Template_Flexy_Token_Var')) {
return $this->_raiseErrorWithPositionAndTag(
"unsupported type found in attribute, use flexy:ignore to prevent parsing or remove it. " .
print_r($this->element,true),
null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$var = $item->toVar($item->value);
if (is_object($var) && is_a($var, 'PEAR_Error')) {
return $var;
}
list($prefix,$suffix) = $this->compiler->getModifierWrapper($item);
$prefix = substr($prefix,4);
$ret .= " {$output_avar} .= {$prefix}{$var}{$suffix};\n";
}
$ret .= "}\n";
}
$ret .= "\$_attributes_used = array(".implode(',',$used).");\n";
$unset = "\n".'if (isset($_attributes_used)) { foreach($_attributes_used as $_a) {'."\n".
' unset($this->elements[\''. $id .'\']->attributes[$_a]);'."\n" .
"}}\n";
}
// 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 ($varsOnly) { // used by form tag.
return array($ret,$unset);
}
if ($var = $this->element->getAttribute('FLEXY:NAMEUSES')) {
// force var to use name (as radio buttons pick up id.)
$ename = $this->element->getAttribute('NAME');
$printfnamevar = $printfvar = 'sprintf(\''.$ename .'\','.$this->element->toVar($var) .')';
// support id replacement as well ...
$idreplace = '';
if (strtolower($this->element->getAttribute('TYPE')) == 'radio') {
$ename = $this->element->getAttribute('ID');
$printfvar = 'sprintf(\''.$ename .'\','.$this->element->toVar($var) .')';
}
if ($this->element->getAttribute('ID')) {
$idvar = 'sprintf(\''.$this->element->getAttribute('ID') .'\','.$this->element->toVar($var) .')';
$idreplace = '$_element->attributes[\'id\'] = '.$idvar.';';
}
return $ret . '
$_element = $this->mergeElement(
$this->elements[\''.$id.'\'],
isset('.$this->element->toVar($var).') && isset($this->elements['.$printfnamevar .']) ? $this->elements['.$printfnamevar .'] : false
);
$_element->attributes[\'name\'] = '.$printfnamevar. ';
' . $idreplace . '
echo $_element->toHtml();' .$unset;
}
if ($mergeWithName) {
$name = $this->element->getAttribute('NAME');
//if ((strtolower($this->element->getAttribute('TYPE')) == 'checkbox') && (substr($name,-2) == '[]')) {
// $name = substr($name,0,-2);
//}
if (!$name) {
return $ret .'
$_element = $this->elements[\''.$id.'\'];
echo $_element->toHtml();' . $unset;
} else {
return $ret .
'
$_element = $this->elements[\''.$id.'\'];
if (isset($this->elements[\''.$name.'\'])) {
$_element = $this->mergeElement($_element,$this->elements[\''.$name.'\']);
}
echo $_element->toHtml();' . $unset;
}
}
return $ret . 'echo $this->elements[\''.$id.'\']->toHtml();'. $unset;
}
/**
* Reads an Script tag - check if PHP is allowed.
*
* @return false|PEAR_Error
* @access public
*/
function parseTagScript()
{
$lang = $this->element->getAttribute('LANGUAGE');
if (!$lang) {
return false;
}
$lang = strtoupper($lang);
$allow = $GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['allowPHP'];
if ($allow === true) {
return false;
}
if ($lang == "PHP") {
if ($allow == 'delete') {
return '';
}
return $this->_raiseErrorWithPositionAndTag('PHP code found in script (script)',
HTML_TEMPLATE_FLEXY_ERROR_SYNTAX,HTML_TEMPLATE_FLEXY_ERROR_RETURN
);
}
return false;
}
/**
* Reads an Input tag - build a element object for it
*
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseTagInput()
{
global $_HTML_TEMPLATE_FLEXY;
$utype = strtoupper($this->element->getAttribute('TYPE'));
if (in_array($utype, array('SUBMIT','BUTTON','INPUT',''))) {
$this->compiler->addStringToGettext(
$this->element->getAttribute('VALUE')
);
}
if (in_array($utype, array('TEXT','PASSWORD'))) {
$this->compiler->addStringToGettext(
$this->element->getAttribute('PLACEHOLDER')
);
}
// form elements : format:
//value - fill out as PHP CODE
// as a general rule, this uses name, rather than ID except on
// radio
$mergeWithName = false;
$id = $this->element->getAttribute('NAME');
if (isset($this->element->ucAttributes['FLEXY:RAW'])) {
return $this->_raiseErrorWithPositionAndTag(
"Flexy:raw can only be used with flexy:ignore, to prevent conversion of html ".
"elements to flexy elements",
null, HTML_TEMPLATE_FLEXY_ERROR_DIE
);
}
// checkboxes need more work.. - at the momemnt assume one with the same value...
if (!in_array(strtoupper($this->element->getAttribute('TYPE')), array('RADIO'))) {
if (!$id) {
return false;
}
return $this->compiler->appendPhp($this->getElementPhp( $id,$mergeWithName));
}
// now we are only dealing with radio buttons.. which are a bit odd...
// we need to create a generic holder for this based on the name..
// this is only really available for use with setting stuff...
if (!isset($_HTML_TEMPLATE_FLEXY['elements'][$id])) {
$_HTML_TEMPLATE_FLEXY['elements'][$id] = new HTML_Template_Flexy_Element("input",
array('type'=>'radio'));
}
// we dont really care if it is getting reused loads of times.. (expected as each radio button will use it.
$name = $id;
$id = $this->element->getAttribute('ID');
if (!$id) {
$id = $name . '_' . $this->element->getAttribute('VALUE');
}
// this get's tricky as we could end up with elements with the same name... (if value was not set..,
// or two elements have the same name..
$mergeWithName = true;
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)
* @access public
*/
function parseTagTextArea()
{
// create a translatable string for placeholder addString should handle if it does not exist..
$this->compiler->addStringToGettext(
$this->element->getAttribute('PLACEHOLDER')
);
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)
* @access public
*/
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)
* @access public
*/
function parseTagForm()
{
global $_HTML_TEMPLATE_FLEXY;
$copy = clone($this->element);
$copy->children = array();
$id = $this->element->getAttribute('NAME');
// dont make forms dynamic if they dont have a name..
if (!$id) {
return false;
}
// this adds the element to the elements array.
$old = clone($this->element);
$this->element = $copy;
list($prefix,$suffix) = $this->getElementPhp($id,false,true);
$this->element= $old;
return
$this->compiler->appendPhp($prefix .'echo $this->elements[\''.$id.'\']->toHtmlnoClose();'.$suffix) .
$this->element->compileChildren($this->compiler) .
$this->compiler->appendHtml( "</{$copy->oTag}>");
}
/**
* Deal with Label - build a element object for it (unless flexyignore is set)
*
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseTagLabel()
{
if (empty($GLOBALS['_HTML_TEMPLATE_FLEXY']['currentOptions']['useElementLabels'])) {
return false;
}
// this may need some protection for general usage.....
$for = $this->element->getAttribute('FOR');
$ret = '';
$tmp = $this->toStringChildren($this->element, $ret);
if (is_object($tmp) && is_a($tmp,'PEAR_Error')) {
return $tmp;
}
return $this->compiler->appendPhp(
'echo "<label for=\"' . $for . '\">";' .
'if (!empty($this->elements[\'' . $for . '\']->label)) ' .
' { echo htmlspecialchars($this->elements[\'' . $for . '\']->label); } else { ?>' .
htmlspecialchars($ret) . '<? } ' .
'echo "</label>";'
);
}
/**
* reWriteURL - can using the config option 'url_rewrite'
* format "from:to,from:to"
* only handle left rewrite.
* so
* "/images:/myroot/images"
* would change
* /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
* @return none
* @access public
*/
function reWriteURL($which)
{
global $_HTML_TEMPLATE_FLEXY;
if (!is_string($original = $this->element->getAttribute($which))) {
return;
}
if ($original == '') {
return;
}
if (empty($_HTML_TEMPLATE_FLEXY['currentOptions']['url_rewrite'])) {
return;
}
$bits = explode(",",$_HTML_TEMPLATE_FLEXY['currentOptions']['url_rewrite']);
$new = $original;
foreach ($bits as $bit) {
if (!strlen(trim($bit))) {
continue;
}
$parts = explode (':', $bit);
if (!isset($parts[1])) {
return $this->_raiseErrorWithPositionAndTag('HTML_Template_Flexy: url_rewrite syntax incorrect'.
print_r(array($bits,$bits),true),null,HTML_TEMPLATE_FLEXY_ERROR_DIE);
}
$new = preg_replace('#^'.$parts[0].'#',$parts[1], $new);
}
if ($original == $new) {
return;
}
$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
* @access public
*/
function toElement($element,$stripspaces = false)
{
require_once 'HTML/Template/Flexy/Element.php';
$ret = new HTML_Template_Flexy_Element;
if (strtolower(get_class($element)) != 'html_template_flexy_token_tag') {
$this->compiler->addStringToGettext($element->value);
return $element->value;
}
$ret->tag = strtolower($element->tag);
if ($ret->tag == 'menulist') { // for XUL menulist, remove the white space between tags..
$stripspaces = true;
}
$ats = $element->getAttributes();
if (isset($element->attributes['flexy:xhtml'])) {
$ats['flexy:xhtml'] = true;
}
foreach(array_keys($ats) as $a) {
$ret->attributes[$a] = $this->unHtmlEntities($ats[$a]);
}
//print_r($ats);
if (!$element->children) {
return $ret;
}
// children - normally to deal with <element>
//print_r($this->children);
foreach(array_keys($element->children) as $i) {
// not quite sure why this happens - but it does.
if (!is_object($element->children[$i])) {
continue;
}
if ($stripspaces && (strtolower(get_class($element->children[$i])) != 'html_template_flexy_token_tag')) {
continue;
}
$ret->children[] = $this->toElement($element->children[$i],$stripspaces);
}
return $ret;
}
/**
* do the reverse of htmlspecialchars on an attribute..
*
* copied from get-html-translation-table man page
*
* @param mixed from attribute values
*
* @return string return
* @access public
* @see see also methods.....
*/
function unHtmlEntities ($in)
{
if (!is_string($in)) {
return $in;
}
$trans_tbl = get_html_translation_table (HTML_ENTITIES);
$trans_tbl = array_flip ($trans_tbl);
$ret = strtr ($in, $trans_tbl);
return preg_replace_callback('/&#(\d+);/m', array($this,'unHtmlEntitiesChar'),$ret);
}
function unHtmlEntitiesChar($ar) {
return chr($ar[1]);
}
/**
* Deal with XUL tags
*
* @return string | false = html output or ignore (just output the tag)
* @access public
*/
function parseXulTag()
{
// does it contain any flexy tags??
if ($this->elementUsesDynamic($this->element)) {
return false;
}
return $this->compiler->appendPhp(
$this->getElementPhp( $this->element->getAttribute('ID')));
}
/**
* Recursively search for any flexy:if flexy:foreach or {xxxx} tags inside tags..
*
* @param HTML_Template_Flexy_Token element to check.
* @return boolean true if it finds a dynamic tag.
* @access public
*/
function elementUsesDynamic($e)
{
if (!is_object($e)) {
return false;
}
if (is_a($e,'HTML_Template_Flexy_Token_Var')) {
return true;
}
if (is_a($e,'HTML_Template_Flexy_Token_Foreach')) {
return true;
}
if (is_a($e,'HTML_Template_Flexy_Token_If')) {
return true;
}
if (is_a($e,'HTML_Template_Flexy_Token_Method')) {
return true;
}
if (!is_a($e,'HTML_Template_Flexy_Token_Tag')) {
return false;
}
if ($e->getAttribute('FLEXY:IF') !== false) {
return true;
}
if ($e->getAttribute('FLEXY:FOREACH') !== false) {
return true;
}
foreach($e->attributes as $k=>$v) {
if (is_array($v) || is_object($v)) {
return true;
}
}
foreach($e->children as $c) {
if ($this->elementUsesDynamic($c)) {
return true;
}
}
return false;
}
/**
* calls HTML_Template_Flexy::raiseError() with the current file, line and tag
* @param string Message to display
* @param type (see HTML_Template_Flexy::raiseError())
* @param boolean isFatal.
*
* @access private
*/
function _raiseErrorWithPositionAndTag($message, $type = null, $fatal = HTML_TEMPLATE_FLEXY_ERROR_RETURN ) {
global $_HTML_TEMPLATE_FLEXY;
$message = "Error:{$_HTML_TEMPLATE_FLEXY['filename']} on Line {$this->element->line}" .
" in Tag <{$this->element->tag}>:<BR>\n" . $message;
return HTML_Template_Flexy::staticRaiseError($message, $type, $fatal);
}
}