Skip to content

Instantly share code, notes, and snippets.

@FDiskas
Last active December 13, 2022 06:37
Show Gist options
  • Save FDiskas/90894d62f566d68a8bb3 to your computer and use it in GitHub Desktop.
Save FDiskas/90894d62f566d68a8bb3 to your computer and use it in GitHub Desktop.
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* CodeIgniter
* An open source application development framework
*
* @package CodeIgniter * @author Rick Ellis
* @copyright Copyright (c) 2006, EllisLab, Inc.
* @license http://www.codeignitor.com/user_guide/license.html
* @link http://www.codeigniter.com * @since Version 1.0
*/
// ----------------------------------------------------------------------
/**
* Library: Extended Parser Class (2008-2010)
* Features: Parse templates, loaded as a view, and/or parse strings;
* Nested simple conditionals {if *}x{else}y{/if}.
* Nested conditionals (introduced in version 0.5.0);
* Array-element access; Successive same array usage;
* {Ignore} tag-pair protects a section from strip_vars but tags inside
* it are parsed. {Ignore_pre} is saved early on, and not parsed at all.
* You can use multiple ignore and ignore_pre tag-pairs.
* Tips: - Use Parse() to load a standard view with the php being processed.
* Parse_string() allows you, for instance, to build an email-message
* with simple template logic, or a partial view.
* - The cleanup unused tags option (strip_vars) is optional and should
* IMO be avoided. Better is to set all variables, be it empty. The parse
* will then automatically replace them with empties. Currently strip_vars
* generates a php error on various curly-brackets like inside javascript.
* For the time being, either protect javascript with ignore, or don't
* strip tags. Another reason to not strip_vars is, it also removes tags
* that might be in your data, like an article discussing parser {tags}.
* Version: 0.5.1
* Changes: 0.5.1 small typo's and bugs
* 0.5.0 gdmac. nested conditionals. option (default) to convert
* delimiters inside data to hmtl-entities.
* 0.4.1 gdmac. fixme1 fixed, process all tag-pairs before singles.
* changed: remove ignore tags, even when strip_tags==false
* 0.4 gdmac. Mashup of parser versions, ignore tag, extra code and debug
* 0.3 rafsoaken. cleanup, test-suite, parse, array, booleans etc.
* 0.2 isaiahdw. conditionals
* 0.1 adamp1. cleanup unused tags and tag-pairs
* Todo: - To get this going, we need some nice documentation with it
* - set_options and better error-reporting and handling (malformed tags).
* - fix for stripping tags on curly brackets like in javascript
* - option to check for empty (next to isset)
* - conditional combinations {if {is_admin}==1 AND {username}==Tim}
* - general optimization and debugging
*
* Install: Put in /application/libraries/ as parser.php instead as MY_parser.php
* Since most methods of the class changed, it made sense to not extend
* the default parser anymore.
*
* Discuss: http://codeigniter.com/forums/viewthread/68878/P45/
*
* usage: See the parser_test controller for some examples
*
* */
class MY_Parser extends CI_Parser {
var $CI;
var $_ignore = array();
var $_template;
var $_conditionals;
var $_data;
var $l_delim = '{';
var $r_delim = '}';
var $options = array
(
// convert delimiters in data to entities. { = &#123; } = &#125;
'convert_delimiters' => array( true, '&#123;', '&#125;')
);
// --------------------------------------------------------------------
// Loads a view (and parses the php). Then parses pseudo-variables contained
// in the specified template and replace them with the data in the second param.
// Param return: output or return as string. Param strip_vars, removes
// unused pseudo-variables.
//
function parse($template, $data, $return = FALSE, $strip_vars = FALSE)
{
$this->CI =& get_instance();
$template = $this->CI->load->view($template, $data, TRUE);
return $this->parse_string($template, $data, $return, $strip_vars);
}
// --------------------------------------------------------------------
// Parse a string as a template
//
function parse_string($template, $data, $return = TRUE, $strip_vars = FALSE)
{
if ($template == '') {
return FALSE;
}
// have a local references to $template and $data in the class
$this->CI =& get_instance();
$this->_template =& $template;
$this->_data =& $data;
$this->_ignore = array(); // start empty on
// store ignore_pre tag data early
$this->_store_ignored('ignore_pre');
// first round process tag data, pairs first
foreach ($data as $key => $val)
{
if (is_array($val)) $template = $this->_parse_pair($key, $val, $template);
}
foreach ($data as $key => $val)
{
if (is_array($val)==false) $template = $this->_parse_single($key, $val, $template);
}
// parse array elements
foreach ($data as $key => $val)
{
if (is_array($val)) $template = $this->_parse_array_elems($key, $val, $template);
}
// Check for conditional statements
$this->_conditionals = $this->_find_nested_conditionals($template);
if($this->_conditionals)
{
$template = $this->_parse_conditionals($template);
}
// Store ignore tags
$this->_store_ignored('ignore');
// Strip empty pseudo-variables
if ($strip_vars)
{
// Todo: Javascript with curly brackets most times generates an error
$reg = "(".$this->l_delim."(.*)".$this->r_delim.")";
if (preg_match_all($reg, $template, $m))
{
foreach($m[1] as $value)
{
$value = preg_quote($value, '/');
$template = preg_replace('#'.$this->l_delim.$value.$this->r_delim.'(.+)'.$this->l_delim.'/'.$value.$this->r_delim.'#sU', "", $template);
$template = str_replace ("{".$value."}", "", $template);
}
}
}
// retrieve al ignored data
if(!empty($this->_ignore))
{
$this->_restore_ignored();
}
if ($return == FALSE)
{
$this->CI->output->append_output($template);
}
return $template;
}
// --------------------------------------------------------------------
//
function _restore_ignored()
{
foreach($this->_ignore as $key => $item)
{
$this->_template = str_replace($item['id'], $item['txt'], $this->_template);
}
// data stored in $this->_template
return true;
}
// --------------------------------------------------------------------
//
function _store_ignored($name)
{
if (FALSE === ($matches = $this->_match_pair($this->_template, $name)))
{
// var_dump($name,$matches);
return false;
}
foreach( $matches as $key => $tagpair)
{
// store $tagpair[1] and replace $tagpair[0] in template with unique identifier
$this->_ignore[$name.$key] = array(
'txt' => $tagpair[1],
'id' => '__'.$name.$key.'__'
);
// strip it and place a temporary string
$this->_template = str_replace($tagpair[0], $this->_ignore[$name.$key]['id'], $this->_template);
}
return true;
}
// --------------------------------------------------------------------
//
function _parse_array_elems($name, $arr, $template)
{
foreach($arr as $arrKey=>$arrVal) {
if(!is_array($arrVal)) {
$template = $this->_parse_single("$name $arrKey", $arrVal, $template);
}
}
return $template;
}
// --------------------------------------------------------------------
// TODO: restore usage of custom left and right delimiter
//
function _find_nested_conditionals($template)
{
// any conditionals found?
$f = strpos($template, '{if');
if ($f === false)
{
return false;
}
$found_ifs = array();
$found_open = strpos($template, '{if');
while ( $found_open !== false)
{
$found_ifs[] = $found_open;
$found_open = strpos($template, '{if', $found_open+3);
}
// print_r($found_ifs);
// -----------------------------------------------------------------------------
// find all nested ifs. Yeah!
for($key = 0; $key < sizeof($found_ifs); ++$key)
{
$open_tag = $found_ifs[$key];
$found_close = strpos($template, '{/if}', $open_tag);
/*msg*/ if($found_close === false){ echo("\n Error. No matching /if found for opening tag at: $open_tag"); exit(); }
$new_open = $open_tag;
$new_close = $found_close;
// -------------------------------------------------------------------------
// find new {if inside a chunk, if found find next close tag
$i=0; // fail safe, for now test 100 nested ifs maximum :-)
$found_blocks=array();
do
{
// does it have an open_tag inside?
$chunk = substr($template, $new_open+3, $new_close - $new_open - 3);
$found_open = strpos($chunk, '{if');
if($found_open !== false)
{
$new_close = $new_close+5;
$new_close = strpos($template, '{/if}', $new_close);
/* msg */ if($new_close===false) { echo("\n Error. No matching /if found for opening tag at: $found_open"); exit(); }
$new_open = $new_open + $found_open + 3;
$found_blocks[] = $new_open;
}
$i++;
}
while( $found_open !== FALSE && ($i < 100) );
// store it
$length = $new_close - $open_tag + 5; // + 5 to catch closing tag
$chunk = substr($template, $open_tag, $length);
$conditionals[$open_tag]=array
(
'start' => $open_tag,
'stop' => $open_tag + $length,
'raw_code' => $chunk,
'found_blocks' => $found_blocks
);
}// end for all found ifs
// walk thru conditionals[] and extract condition_string and replace nested
$regexp = '#{if (.*)}(.*){/if}#sU';
foreach($conditionals as $key => $conditional)
{
$found_blocks = $conditional['found_blocks'];
$conditional['parse'] = $conditional['raw_code'];
if(!empty($found_blocks))
{
foreach($found_blocks as $num)
{
// it contains another conditional, replace with unique identifier for later
$unique = "__pparse{$num}__";
$conditional['parse'] = str_replace($conditionals[$num]['raw_code'], $unique, $conditional['parse']);
}
}
$conditionals[$key]['parse'] = $conditional['parse'];
if(preg_match($regexp, $conditional['parse'], $preg_parts, PREG_OFFSET_CAPTURE))
{
// echo "\n"; print_r($preg_parts);
$raw_code = $preg_parts[0][0];
$cond_str = $preg_parts[1][0] !=='' ? $preg_parts[1][0] : '';
$insert = $preg_parts[2][0] !=='' ? $preg_parts[2][0] : '';
/* msg */ if($raw_code !== $conditional['parse']){ echo "\n Error. raw_code differs from first run!\n$raw_code\n{$conditional['raw_code']}";exit; }
if(preg_match('/({|})/', $cond_str, $problematic_conditional))
{
// Problematic conditional, delimiters found or something
// if strip_vars, remove whole raw_code, for now bye-bye
/* msg */ echo "\n Error. Found delimiters in condition to test\n: $cond_str";
exit;
}
// store condition string and insert
$conditionals[$key]['cond_str'] = $cond_str;
$conditionals[$key]['insert'] = $insert;
}
else
{
/* msg */ echo "\n Error in conditionals (preg parse) No conditional found or some was not closed properly";
exit();
// todo
$conditionals[$key]['cond_str'] = '';
$conditionals[$key]['insert'] = '';
}
}
return $conditionals;
}
// -------------------------------------------------------------------------
//
function _parse_conditionals($template)
{
if(empty ($this->_conditionals))
{
return $template;
}
$conditionals =& $this->_conditionals;
foreach($conditionals as $key => $conditional)
{
$raw_code = $conditional['raw_code'];
$cond_str = $conditional['cond_str'];
$insert = $conditional['insert'];
if($cond_str!=='' AND !empty($insert))
{
// Get the two values
$cond = preg_split("/(\!=|==|<=|>=|<>|<|>|AND|XOR|OR|&&)/", $cond_str);
// Do we have a valid if statement?
if(count($cond) == 2)
{
// Get condition and compare
preg_match("/(\!=|==|<=|>=|<>|<|>|AND|XOR|OR|&&)/", $cond_str, $cond_m);
array_push($cond, $cond_m[0]);
// Remove quotes - they cause to many problems!
// trim first, removes whitespace if there are no quotes
$cond[0] = preg_replace("/[^a-zA-Z0-9_\s\.,-]/", '', trim($cond[0]));
$cond[1] = preg_replace("/[^a-zA-Z0-9_\s\.,-]/", '', trim($cond[1]));
if(is_int($cond[0]) && is_int($cond[1]))
{
$delim = "";
}
else
{
$delim ="'";
}
// Test condition
$to_eval = "\$result = ($delim$cond[0]$delim $cond[2] $delim$cond[1]$delim);";
eval($to_eval);
}
else // single value
{
// name isset() or number. Boolean data is 0 or 1
$result = (isset($this->_data[trim($cond_str)]) OR (intval($cond_str) AND (bool)$cond_str));
}
}
else
{
$result = false;
}
// split insert text if needed. Can be '' or 'foo', or 'foo{else}bar'
$insert = explode('{else}', $insert, 2);
if($result == TRUE)
{
$conditionals[$key]['insert'] = $insert[0];
}
else // result = false
{
$conditionals[$key]['insert'] = (isset($insert['1'])?$insert['1']:'');
}
// restore raw_code from nested conditionals in this one
foreach($conditional['found_blocks'] as $num)
{
$unique = "__pparse{$num}__";
if(strpos($conditional['insert'], $unique))
{
$conditionals[$key]['insert'] = str_replace($unique, $conditionals[$num]['raw_code'], $conditionals[$key]['insert']);
}
}
}
// end foreach conditionals.
// replace all rawcodes with inserts in the template
foreach($conditionals as $conditional) $template = str_replace($conditional['raw_code'], $conditional['insert'], $template);
return $template; // thank you, have a nice day!
}
// --------------------------------------------------------------------
// Parse a single key/value
function _parse_single($key, $val, $string)
{
if ( empty( $val ) ) return $string;
if(is_bool($val)) $val = intval($val); // boolean numbers
$convert =& $this->options['convert_delimiters'];
// convert delimiters in data
if($convert[0]) $val = str_replace(array($this->l_delim,$this->r_delim), array($convert[1],$convert[2]), $val);
return str_replace($this->l_delim.$key.$this->r_delim, $val, $string);
}
// --------------------------------------------------------------------
// Edited Parse a tag pair, now also 1-dim arrays
// Parses tag pairs: {some_tag} string... {/some_tag}
function _parse_pair($variable, $data, $string)
{
if (FALSE === ($matches = $this->_match_pair($string, $variable)))
{
return $string;
}
$singles=array();
foreach ($matches as $m)
{
$str = '';
//if(FALSE === ($matches = $this->_match_pair($string, $variable)))
foreach ($data as $rowkey => $row)
{
$temp = $m['1'];
if(is_array($row))
{
foreach ($row as $key => $val)
{
if ( ! is_array($val))
{
$temp = $this->_parse_single($key, $val, $temp);
}
else
{
$temp = $this->_parse_pair($key, $val, $temp);
}
}
$str .= $temp;
}
else
{
$singles[$rowkey]=$row;
}
}
if($singles) {
foreach($singles as $key => $value) {
$str = $this->_parse_single($key, $value, $str);
}
}
$string = str_replace($m['0'], $str, $string);
}
return $string;
}
// --------------------------------------------------------------------
// Edited Matches a variable pair (now match_all)
//
function _match_pair($string, $variable)
{
$reg = "|".preg_quote($this->l_delim . $variable . $this->r_delim)."(.+)".preg_quote($this->l_delim . '/' . $variable . $this->r_delim)."|sU";
if ( ! preg_match_all($reg, $string, $match, PREG_SET_ORDER))
{
return FALSE;
}
return $match;
}
// --------------------------------------------------------------------
// Original set_delimiters
//
function set_delimiters($l = '{', $r = '}')
{
$this->l_delim = $l;
$this->r_delim = $r;
}
}
// end class
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Test extends MY_Controller {
var $data;
// -------------------------------------------------- Constructor
function __construct()
{
parent::__construct();
}
// --------------------------------------------------
function index()
{
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
echo ' <head><meta http-equiv="Content-type" content="text/html; charset=utf-8" /></head>';
echo "<body style='font-family:courier;'><pre>";
$this->load->library('parser');
$this->load->library('unit_test');
$this->data = array
(
'boolfalse'=> false,
'booltrue'=> true,
'number' => 10,
'foo' => 'bar',
'test'=>'something',
'array'=>array(
'unique'=>'im unique',
array('id'=>'23', 'sale_price'=>12, 'price'=>15),
array('id'=>'21', 'sale_price'=>28, 'price'=>20)
),
'myarray'=>array('submitter'=>'clemens', 'id'=>1),
'title2'=> 'Single Title not in posts',
'posts'=>array(
array('title'=>'first post', 'paras'=>array('main'=>'foo', 'short'=>'bar')),
array('title'=>'second post', 'paras'=>array('main'=>'ice', 'short'=>'cold'))
),
'emptyarray' => array( ),
'emptyvar' => '',
'withdelimiters' => 'delimiters in data {if number}{test}{/if} are converted to html-entities',
'withwrongdelimiters' => 'this var has {if something wrong} with it'
);
// $this->testNestedConditionals();
// $this->testIgnore();
$this->FixMe2(); // gives php errors
// $this->testWhole();
// $this->testConditionalSyntax();
// $this->testNested();
// $this->testArray();
// $this->testErrors();
// $this->testBool();
// $this->testArrayRepeatedAndNested();
}
// --------------------------------------------------------------------
function testnestedConditionals()
{
$templates[] = '
Working with nested conditionals
{if {array unique}==im unique}
..array key unique
....{if {boolfalse}}
......im not shown
....{else}
......{if "{foo}"=="bar"}foo=bar{/if}
....ok im shown too
..{/if}
{/if}
';
$expected[] ='
Working with nested conditionals
..array key unique
....
......foo=bar
....ok im shown too
..
';
$templates[] ='
{if {myarray submitter}==clemens} doing this
.{if b} doing b
.{if c} doing c
.{if d} doing d {/if}
.after d is done
.{/if} after c is done
.{else}
.b was not set
.{/if}
.after b test, but nested inside first
{/if}
and after a nested group, outside any conditionals
';
$expected[] ='
doing this
.
.b was not set
.
.after b test, but nested inside first
and after a nested group, outside any conditionals
';
$templates[] = '{withdelimiters}
';
$expected[] = 'delimiters in data &#123;if number&#125&#123;test&#125&#123;/if&#125 are converted to html-entities
';
foreach($templates as $key => $template)
{
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testConditionalSyntax');
}
}
// --------------------------------------------------------------------
function testIgnore(){
$template = '
Testing ignore
{ignore_pre}and ignoring {test} :-)
ignore_pre is stored early. Tags not parsed nor stripped.{/ignore_pre}
nonexisting tag:{nonexistingtag}
nonexisting array:{nonexistingarray}foo {test} bar{/nonexistingarray}
empty vars or empty array() will be stripped by parse, no need for ignore
emptyarray:{emptyarray}foo {test} bar{/emptyarray}
emptyvar:{emptyvar}
{ignore}i\m ignored when stripping tags, but my vars are parsed.
test:{test} and arrays too: multi-dim-array:{posts}title:{title},{paras}main:{main} short:{short}{/paras}|{/posts}
nonexistingtag:{nonexistingtag} tag is preserved
nonexistingarray:{nonexistingarray}blah{/nonexistingarray} tag-pair is preserved
emptyarray:{emptyarray}foo {test} bar{/emptyarray} stripped by parse, not if in ignore_pre
emptyvar:{emptyvar} stripped by parse
access a one-dimensional array directly by key, dont use tag-pair:submitter:{myarray submitter} id:{myarray id}
booltrue:{if {booltrue}}True{else}False{/if}
booltrue:{if booltrue}set{else}not set{/if}
{/ignore}
{ignore}// preserve some javascript with curly-brackets
$().ready(function(){
$("#selector").addClass("something");
});
{/ignore}
Multiple ignore and ignore_pre tag-pairs are allowed
';
$expected= '
Testing ignore
and ignoring {test} :-)
ignore_pre is stored early. Tags not parsed nor stripped.
nonexisting tag:
nonexisting array:
empty vars or empty array() will be stripped by parse, no need for ignore
emptyarray:
emptyvar:
i\m ignored when stripping tags, but my vars are parsed.
test:something and arrays too: multi-dim-array:title:first post,main:foo short:bar|title:second post,main:ice short:cold|
nonexistingtag:{nonexistingtag} tag is preserved
nonexistingarray:{nonexistingarray}blah{/nonexistingarray} tag-pair is preserved
emptyarray: stripped by parse, not if in ignore_pre
emptyvar: stripped by parse
access a one-dimensional array directly by key, dont use tag-pair:submitter:clemens id:1
booltrue:True
booltrue:set
// preserve some javascript with curly-brackets
$().ready(function(){
$("#selector").addClass("something");
});
Multiple ignore and ignore_pre tag-pairs are allowed
';
$expected_not_stripped= '
Testing ignore
and ignoring {test} :-)
ignore_pre is stored early. Tags not parsed nor stripped.
nonexisting tag:{nonexistingtag}
nonexisting array:{nonexistingarray}foo something bar{/nonexistingarray}
empty vars or empty array() will be stripped by parse, no need for ignore
emptyarray:
emptyvar:
i\m ignored when stripping tags, but my vars are parsed.
test:something and arrays too: multi-dim-array:title:first post,main:foo short:bar|title:second post,main:ice short:cold|
nonexistingtag:{nonexistingtag} tag is preserved
nonexistingarray:{nonexistingarray}blah{/nonexistingarray} tag-pair is preserved
emptyarray: stripped by parse, not if in ignore_pre
emptyvar: stripped by parse
access a one-dimensional array directly by key, dont use tag-pair:submitter:clemens id:1
booltrue:True
booltrue:set
// preserve some javascript with curly-brackets
$().ready(function(){
$("#selector").addClass("something");
});
Multiple ignore and ignore_pre tag-pairs are allowed
';
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n$expected<hr />";
echo $this->unit->run($returned,$expected,'TestIgnore with strip_tags true');
$returned = $this->parser->parse_string($template, $this->data, true, false);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n$expected_not_stripped<hr />";
echo $this->unit->run($returned,$expected_not_stripped,'TestIgnore with strip_tags false');
}
// --------------------------------------------------------------------
function FixMe2(){
$template = '
{nonexistingvar} is shown at error
// some javascript with curly-brackets
$().ready(function(){
$("#selector").addClass("something");
});
{/ignore}
and test:{test}
';
$expected= '
{nonexistingvar} is shown at error
// some javascript with curly-brackets to ignore
$().ready(function(){
$("#selector").addClass("something");
});
{/ignore}
and more text at the end. test:Something
';
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n$expected<hr />";
echo $this->unit->run($returned,$expected,'FixMe2 borks on javascript brackets');
}
// --------------------------------------------------------------------
function testWhole(){
$template = '
{if 10 > 8}10 is greater then 8{/if}
{if "bar"=={foo}}Foo is equal to bar{/if}
{if {test}!="asdfsd"}Test is not equal to asdfsd{/if}
{if "something"=={test}}Test is equal to "{test}"{/if}
{if test}Test is set{/if}
{if randomjunk}This should never show{else}This should always show{/if}
{array}ID: {id}, {if {sale_price} > 20}Sale Price: {sale_price}{else}Price: {price}{/if}
{/array}
{if "something something"=="something something"}Testing{else}test{/if}';
$expected= '
10 is greater then 8
Foo is equal to bar
Test is not equal to asdfsd
Test is equal to "something"
Test is set
This should always show
ID: 23, Price: 15
ID: 21, Sale Price: 28
Testing';
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n$expected<hr />";
echo $this->unit->run($returned,$expected,'testWhole');
}
// --------------------------------------------------------------------
function testConditionalSyntax(){
//number comparisons
$templates[] = '{if 10 > 8}10 is greater then 8{/if}';
$expected[] = '10 is greater then 8';
$templates[] = '{if "10" > "8"}10 is greater then 8{/if}';
$expected[] = '10 is greater then 8';
//!this should be wrong as we are comparing strings!
$templates[] = '{if " 20" > "18 "}10 is greater then 8{/if}';
$expected[] = '';
$templates[] = '{if 10 < 8}10 is greater then 8{/if}';
$expected[] = '';
$templates[] = '{if 10}number 10{/if}';
$expected[] = 'number 10';
$templates[] = '{if "10 "}it\s a string{/if}';
$expected[] = '';
$templates[] = '{if {number} >= 8}10 is greater then 8{/if}';
$expected[] = '10 is greater then 8';
$templates[] = '{if 8 != {number} }10 is greater then 8{/if}';
$expected[] = '10 is greater then 8';
//string comparisons
$templates[] = '{if {foo}!=bar}Foo is not bar{/if}';
$expected[] = '';
$templates[] = '{if {foo}==bar}Foo is bar{/if}';
$expected[] = 'Foo is bar';
//also wrong!
$templates[] = '{if {foo}=="bar "}Foo is bar{/if}';
$expected[] = '';
$templates[] = '{if "bar"=={foo}}Foo is bar{/if}';
$expected[] = 'Foo is bar';
$templates[] = '{if foo}Foo exists{/if}'; //attention we can't
$expected[] = 'Foo exists';
$templates[] = '{if schmafu}schmafu exists{/if}';
$expected[] = '';
//now with else constructs
$templates[] = '{if schmafu}schmafu exists{else}schmafu doesn\'t exist{/if}';
$expected[] = 'schmafu doesn\'t exist';
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testConditionalSyntax');
}
}
//-------------------------------------------------
function testNested(){
$templates[] = '{array}{id}{foo}{/array}';
$expected[] = '23bar21bar';
$templates[] = '{array}{if {id}> 22}{foo}{/if}{/array}';
$expected[] = 'bar';
$templates[] = '{array}{if {id}=={foo}}can\'t be true{else} {test} strange is happening.. <br />{/if}
{/array}';
$expected[] = ' something strange is happening.. <br />
something strange is happening.. <br />
';
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testNested');
}
}
function testArray(){
$templates[]="{array unique}";
$expected[]="im unique";
$templates[]="{array}{unique}{/array}";
$expected[]="im uniqueim unique";
$templates[]="{array}{unique} {id} {/array}";
$expected[]="im unique 23 im unique 21 ";
$templates[]="name:{myarray submitter} id:{myarray id}";
$expected[]="name:clemens id:1";
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testArray');
}
}
function testErrors(){
$templates[]="{notexisting}";
$expected[]="";
$err_expected[]="{notexisting}";
$templates[]="{array}test {notexisting}{/array}";
$expected[]="test test ";
$err_expected[]="test {notexisting}test {notexisting}";
$templates[]="{array}{if notexisting}hello{else}test {/if}{/array}";
$expected[]="test test ";
$err_expected[]="test test ";
$templates[]="{array}{if {id}==23}hello23{else}hello{id}{/if} {/array}";
$expected[]="hello23 hello21 ";
$err_expected[]="hello23 hello21 ";
$templates[]="{array}{if {id}==23}hello23{else}{idontexist}{array me_neither}hello{id}{/if} {/array}";
$expected[]="hello23 hello21 ";
$err_expected[]="hello23 {idontexist}{array me_neither}hello21 ";
$templates[]="{if ihaveafriend}logged_in{else}goaway{/if} number:{myarray id}!";
$expected[]="goaway number:1!";
$err_expected[]="goaway number:1!";
// strip_tags off should keep unset variables
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, false);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$err_expected[$key]}<hr />";
echo $this->unit->run($returned,$err_expected[$key],'testErrors strip_tags = true');
}
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testErrors strip_tags = false');
}
}
function testBool(){
$templates[]="{if {booltrue}}its true!{else}its false :({/if}";
$expected[]="its true!";
$templates[]="{if {boolfalse}}its true!{else}its false :({/if}";
$expected[]="its false :(";
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testBool');
}
}
function testArrayRepeatedAndNested(){
$templates[]="{array}test{/array} and another time: {array}me{/array}";
$expected[]="testtest and another time: meme";
$templates[]="{posts}Post:{title}
{paras}{main}
{short}
{/paras}{/posts}";
$expected[]="Post:first post
foo
bar
Post:second post
ice
cold
";
foreach($templates as $key => $template){
$returned = $this->parser->parse_string($template, $this->data, true, true);
echo "<pre>INPUT:\n$template<hr />RETURNED:\n$returned<hr />EXPECTED:\n{$expected[$key]}<hr />";
echo $this->unit->run($returned,$expected[$key],'testArrayRepeatedAndNested');
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment