class BSTemplate
{
/**
- * The path, from the path of the application, where templates are stored
- * @var string
- */
- protected $templateDir = '';
-
- /**
- * The extension all the template files have
+ * The name of a function that is called before template parsing of phrases and conditionals occurs
* @var string
*/
- protected $extension = 'tpl';
-
+ public static $preParseHook = ':undefined:';
+
/**
* The database table name for the template cache
* @var string
*/
- protected $dbCacheTable = null;
+ public static $dbCacheTable = null;
/**
* The name of the function phrases are fetched with
* @var string
*/
- public $langcall = 'gettext';
+ public static $langcall = 'gettext';
/**
- * The name of the function phrases are sprintf() parsed with
- * @var string
+ * The template path pattern; for instance, this could be: ./templates/%s.tpl
+ * @var string
*/
- public $langconst = 'sprintf';
+ public static $templatePath = '%s';
/**
- * Array of pre-compiled templates that are stored to decrease server load
+ * Array of pre-compiled templates that are stored for optimization
* @var array
*/
- protected $cache = array();
+ protected static $cache = array();
/**
- * A list of templates that weren't cached, but are still used
- * @var array
+ * The name of the function phrases are sprintf() parsed with
+ * @var string
*/
- protected $uncached = array();
+ public static $langconst = 'sprintf';
/**
- * Whether or not the page has been flush()'d already
- * @var bool
+ * Template variables to populate
+ * @var array
*/
- protected $doneflush = false;
+ public $vars = array();
/**
- * The name of a function that is called before template parsing of phrases and conditionals occurs
- * @var string
+ * The file name of the template
+ * @var string
*/
- protected $preParseHook = ':undefined:';
+ protected $filename;
/**
- * Sets the template directory name
- *
- * @param string Template directory name
+ * Template contents
+ * @var string
*/
- public function setTemplateDirectory($dir)
- {
- $this->templateDir = BSFunctions::fetch_source_path($dir);
- }
+ protected $template;
/**
- * Sets the file extension for the templates
+ * Takes an array of template names, loads them, and then stores a
+ * parsed version for optimum speed.
*
- * @param string File extension
+ * @param array List of template names to be cached
*/
- public function setExtension($ext)
+ public static function cache($namearray)
{
- $this->extension = $ext;
+ if (!self::$dbCacheTable)
+ {
+ return; // there's no point in pre-caching file templates
+ }
+
+ $cache = BSApp::$db->query("SELECT * FROM " . self::$dbCacheTable . " WHERE filename IN ('" . implode("', '", $namearray) . "')");
+ while ($tpl = $cache->fetchArray())
+ {
+ self::$cache[$tpl['filename']] = $tpl;
+ }
}
/**
- * Sets the name of the table to access for the datbase cache
- *
- * @param string DB table name
+ * Fluent interface-compatible constructor
*/
- public function setDatabaseCache($table)
+ public static function fetch()
{
- $this->dbCacheTable = $table;
+ $obj = new ReflectionClass(__CLASS__);
+ $args = func_get_args();
+ return $obj->newInstanceArgs($args);
}
/**
- * Sets the pre-parse hook method which is called before any other
- * processing is done on the template.
- *
- * @param string Method name
+ * Constructor
+ *
+ * @param string File name
*/
- public function setPreParseHook($hook)
+ public function __construct($path)
{
- $this->preParseHook = $hook;
+ $this->file = $path;
+
+ // checks to see if the template has been cached
+ if (isset(self::$cache[$this->file]))
+ {
+ if (!self::$dbCacheTable || filemtime(sprintf(self::$templatePath, $this->file)) <= self::$cache[$this->file]['timestamp'])
+ {
+ $this->template = self::$cache[$this->file]['template'];
+ return;
+ }
+ }
+
+ // it hasn't been cached
+ $path = sprintf(self::$templatePath, $this->file);
+ if (!is_file($path) || !is_readable($path))
+ {
+ throw new Exception("Could not load the template $path");
+ }
+ $this->template = $this->_parseTemplate(file_get_contents($path));
+ self::$cache[$this->file]['template'] = $this->template;
+
+ // store the template in the database
+ if (self::$dbCacheTable)
+ {
+ BSApp::$db->query("REPLACE INTO " . self::$dbCacheTable . " SET template = '" . BSApp::$db->escapeString($this->template) . "', timestamp = " . TIMENOW . ", filename = '" . $this->file . "'");
+ self::$cache[$this->file]['time'] = TIMENOW;
+ }
}
/**
- * Takes an array of template names, loads them, and then stores a
- * parsed version for optimum speed.
+ * Returns the template data
*
- * @param array List of template names to be cached
+ * @return string Final template data
*/
- public function cache($namearray)
+ public function getTemplate()
{
- if (sizeof($this->cache) > 0)
- {
- throw new Exception('You cannot cache templates more than once per initialization');
- }
- else
- {
- $dbCache = array();
- if ($this->dbCacheTable)
- {
- $db =& BSApp::$db;
- $cache = $db->query("SELECT * FROM {$this->dbCacheTable} WHERE filename IN ('" . implode("', '", $namearray) . "')");
- while ($tpl = $cache->fetchArray())
- {
- $time = filemtime($this->templateDir . $tpl['filename'] . '.' . $this->extension);
- $template = $tpl['template'];
- if ($time > $tpl['timestamp'])
- {
- $template = $this->_parseTemplate($this->_loadTemplate($tpl['filename']));
- $db->query("UPDATE {$this->dbCacheTable} SET template = '" . $db->escapeString($template) . "', timestamp = " . TIMENOW . " WHERE filename = '" . $tpl['filename'] . "'");
- $tpl['template'] = $template;
- }
- $dbCache["$tpl[filename]"] = $template;
- }
- }
- foreach ($namearray as $name)
- {
- if ($this->dbCacheTable)
- {
- if (isset($dbCache["$name"]))
- {
- $template = $dbCache["$name"];
- }
- else
- {
- $template = $this->_parseTemplate($this->_loadTemplate($name));
- $db->query("INSERT INTO {$this->dbCacheTable} (filename, template, timestamp) VALUES ('$name', '" . $db->escapeString($template) . "', " . TIMENOW . ")");
- }
- }
- else
- {
- $template = $this->_parseTemplate($this->_loadTemplate($name));
- }
-
- $this->cache[$name] = $template;
- }
- }
+ return $this->template;
}
/**
- * Loads a template from the cache or the _load function and stores the
- * parsed version of it
+ * This function globalizes/extracts the assigned variables and then
+ * returns the output buffer
+ *
+ * @param string Unevaluated template
*
- * @param string The name of the template
- *
- * @return string A parsed and loaded template
+ * @return fluent interface
*/
- public function fetch($name)
+ public function evaluate()
{
- if (isset($this->cache[$name]))
- {
- $template = $this->cache[$name];
- }
- else
- {
- $this->uncached[$name] = (isset($this->uncached[$name]) ? $this->uncached[$name] + 1 : 0);
- BSApp::debug("Manually loading template '$name'");
- $template = $this->_loadTemplate($name);
- $template = $this->_parseTemplate($template);
- }
+ extract($this->vars);
- return $template;
+ ob_start();
+ $this->template = str_replace(array('$this->', 'self::'), 'null', $this->template); // don't want internal access coming from a template
+ $this->template = '?>' . $this->template;
+ eval($this->template);
+ $this->template = ob_get_clean();
+ ob_end_clean();
+
+ return $this;
}
/**
* Output a template fully compiled to the browser
- *
- * @param string Compiled and ready template
*/
- public function flush($template)
+ public function flush()
{
ob_start();
- if (empty($template))
+ if (empty($this->template))
{
- throw new Exception('There was no output to print');
+ throw new Exception('There is no output to print');
}
- if ($this->doneflush)
- {
- throw new Exception('A template has already been sent to the output buffer');
- }
+ $template = $this->template;
$debugBlock = '';
- if (BSApp::get_debug())
- {
+ if (BSApp::get_debug() && strpos($template, '</body>') !== false)
+ {
$debugBlock .= "\n<div align=\"center\">Executed in " . round(BSFunctions::fetch_microtime_diff('0 ' . $_SERVER['REQUEST_TIME']), 10) . ' seconds</div>';
$debugBlock .= "\n<br /><div align=\"center\">" . BSApp::get_debug_list() . "</div>";
-
- if (sizeof($this->uncached) > 0)
- {
- foreach ($this->uncached as $name => $count)
- {
- $tpls[] = $name . "($count)";
- }
- $debugBlock .= "<br /><div style=\"color: red\" align=\"center\"><strong>Uncached Templates:</strong>" . implode(', ', $tpls) . " )</div>\n";
- }
-
+
if (BSApp::$db)
{
$queries = BSApp::$db->getHistory();
print($template);
}
- /**
- * Loads an additional template from the database
- *
- * @param string The name of the template
- *
- * @return string Template data from the database
- */
- protected function _loadTemplate($name)
- {
- $path = $this->templateDir . $name . '.' . $this->extension;
- if (is_file($path) && is_readable($path))
- {
- return @file_get_contents($path);
- }
- else
- {
- throw new Exception("Could not load the template '$path'");
- }
- }
-
/**
* A wrapper for all the parsing functions and compiling functins
*
*/
protected function _parseTemplate($template)
{
- $template = str_replace('"', '\"', $template);
-
- if (function_exists($this->preParseHook))
+ if (function_exists(self::$preParseHook))
{
- $template = call_user_func($this->preParseHook, $template);
+ $template = call_user_func(self::$preParseHook, $template);
}
- $template = $this->_parseBlocksAndTokens($template);
- $template = $this->_parsePhrases($template);
- $template = $this->_parseConditionals($template);
+ $template = $this->_parseTokens($template);
return $template;
}
/**
- * Parses anything with curly braces {} (including phrases)
+ * Parses tokens <% %>
*
* @param string Template data
*
* @return string Parsed template data
*/
- protected function _parseBlocksAndTokens($template)
+ protected function _parseTokens($template)
{
$stack = array();
$tokens = array();
- while (1)
+ for ($i = 0; $i < strlen($template); $i++)
{
- for ($i = 0; $i < strlen($template); $i++)
+ // opening tag
+ if ($template[$i] == '<' && $template[$i + 1] == '%')
{
- // we've run through the template and there's nothing in the stack--done
- if ($i == strlen($template) - 1 && sizeof($stack) == 0)
- {
- return $template;
- }
-
- if ($template[$i] == '{')
- {
- // ignore escaped sequences
- if ($template[$i - 1] != '\\')
- {
- array_push($stack, $i);
- }
- }
- else if ($template[$i] == '}')
- {
- // there's no stack so it was probably escaped
- if (sizeof($stack) == 0)
- {
- continue;
- }
- // we're good and nested
- else if (sizeof($stack) == 1)
- {
- $open = array_pop($stack);
- $token = substr($template, $open, $i - $open + 1);
- $template = str_replace($token, $this->_parseToken($token), $template);
- break;
- }
- // just pop it off
- else
- {
- array_pop($stack);
- }
- }
+ array_push($stack, $i);
}
- }
- }
-
- /**
- * Parses a curly brace token {}
- *
- * @param string Token
- *
- * @return string Parsed value
- */
- protected function _parseToken($token)
- {
- // knock of the braces
- $token = substr($token, 1, strlen($token) - 2);
-
- // language token
- if ($token[0] == '@' && $token[1] == '\\' && $token[2] == '"')
- {
- return '" . ' . $this->langcall . '(\'' . str_replace(array('\\\"', "'"), array('"', "\'"), substr($token, 3, strlen($token) - 5)) . '\')' . ' . "';
- }
- // normal PHP code
- else
- {
- return '" . (' . $token . ') . "';
- }
- }
-
- /**
- * Prepares language and locale information inside templates
- *
- * @param string Template data to be processed
- *
- * @return string Language-ready template data
- */
- protected function _parsePhrases($template)
- {
- $tagStart = '<lang ';
- $tagEnd = '</lang>';
-
- $start = -1; // start of open tag
- $end = -1; // start of the close tag
- $varEnd = -1; // end of the open tag
-
- while ($start <= strlen($template))
- {
- // reset
- $varMap = array(); // storage for all the substitution indices
-
- // Find the start language object tag
- $start = strpos($template, $tagStart, $end + 1);
- if ($start === false)
- {
- break;
- }
-
- // look ahead to parse out all the variables
- $i = $start + strlen($tagStart); // current position
- $capture = ''; // current capture
- $capturePos = $i; // the place to start capturing
- $varNum = -1; // variable placeholder index
- while ($i < strlen($template))
+ // closing tag
+ else if ($template[$i] == '%' && $template[$i + 1] == '>')
{
- if ($template[$i] == '=')
+ // there's no stack, so it's a bad template
+ if (sizeof($stack) == 0)
{
- // backtrack to find the previous variable substitution
- $backPos = $i;
- while ($backPos >= $start)
- {
- if ($template[$backPos] == '"')
- {
- // startPosition + length(startTag) + length(=\")
- $varMap[intval($varNum)] = BSFunctions::substring($template, $capturePos + 3, $backPos - 1);
- // remove our old substitution from the capture
- $capture = BSFunctions::substring($template, $backPos + 1, $i);
- break;
- }
- $backPos--;
- }
-
- // do we have a valid index?
- if (intval($capture) > 0)
- {
- // set aside the index and restart capturing
- $varNum = $capture;
- $capture = '';
- $capturePos = $i;
- }
- else
- {
- throw new Exception('Invalid language variable index "' . $capture . '"');
- }
+ throw new Exception('Malformed template data: unexpected closing substitution tag');
}
- else if ($template[$i] == '>' && $template[$i - 1] == '"')
+ // we're good and nested
+ else if (sizeof($stack) == 1)
{
- // the final variable substitution
- $varMap[intval($varNum)] = BSFunctions::substring($template, $capturePos + 3, $i - 2);
- $varEnds = $i;
- break;
+ $open = array_pop($stack);
+ $replace = '<?php ' . BSFunctions::substring($template, $open + 2, $i) . ' ?>';
+ $template = substr_replace($template, $replace, $open, ($i + 2) - $open);
}
-
- $capture .= $template[$i];
- $i++;
- }
-
- // locate the end tag
- $end = strpos($template, $tagEnd, $i);
- if ($end === false)
- {
- break;
- }
-
- // this is the string that gets variable replacement
- $str = BSFunctions::substring($template, $varEnds + 1, $end);
-
- // create the complete varmap
-
- for ($i = max(array_keys($varMap)); $i > 0; $i--)
- {
- if (!isset($varMap[$i]))
+ // just pop it off
+ else
{
- $varMap[$i] = '<strong>[MISSING SUBSTITUTION INDEX: ' . $i . ']</strong>';
- }
- }
-
- // put all the keys in corresponding argument order
- ksort($varMap);
-
- // FINALLY, construct the call to sprintf()
- $template = substr_replace($template, '" . ' . $this->langconst . '(\'' . $str . '\', "' . implode('", "', $varMap) . '") . "', $start, ($end + strlen($tagEnd)) - $start);
- }
-
- return $template;
- }
-
- /**
- * Parser for in-line template conditionals
- *
- * @param string Template data awaiting processing
- *
- * @return string Parsed template data
- */
- protected function _parseConditionals($template)
- {
- // tag data
- $tag_start = '<if condition=\"';
- $tag_start_end = '\">';
- $tag_else = '<else />';
- $tag_end = '</if>';
+ array_pop($stack);
+ } // end else
+ } // end if
+ } // end for
- // tag stack
- $stack = array();
-
- // the information about the current active tag
- $tag_full = array();
- $parsed = array();
-
- // start at 0
- $offset = 0;
-
- while (1)
- {
- if (strpos($template, $tag_start) === false)
- {
- break;
- }
-
- for ($i = $offset; $i < strlen($template); $i++)
- {
- // we've found ourselves a conditional!
- if (substr($template, $i, strlen($tag_start)) == $tag_start)
- {
- // push the position into the tag stack
- if ($tag_full)
- {
- array_push($stack, $i);
- }
- else
- {
- $tag_full['posi'] = $i;
- }
- }
- // locate else tags
- else if (substr($template, $i, strlen($tag_else)) == $tag_else)
- {
- if (sizeof($stack) == 0 && !isset($tag_full['else']))
- {
- $tag_full['else'] = $i;
- }
- }
- // do we have an end tag?
- else if (substr($template, $i, strlen($tag_end)) == $tag_end)
- {
- if (sizeof($stack) != 0)
- {
- array_pop($stack);
- continue;
- }
-
- // calculate the position of the end tag
- $tag_full['posf'] = $i + strlen($tag_end) - 1;
-
- // extract the entire conditional from the template
- $fullspread = substr($template, $tag_full['posi'], $tag_full['posf'] - $tag_full['posi'] + 1);
-
- // remove the beginning tag
- $conditional = substr($fullspread, strlen($tag_start));
-
- // find the end of the expression
- $temp_end = strpos($conditional, $tag_start_end);
-
- // save the expression
- $parsed[0] = stripslashes(substr($conditional, 0, $temp_end));
-
- // remove the expression from the conditional
- $conditional = substr($conditional, strlen($parsed[0]) + strlen($tag_start_end));
-
- // remove the tailing end tag
- $conditional = substr($conditional, 0, strlen($conditional) - strlen($tag_end));
-
- // handle the else
- if (isset($tag_full['else']))
- {
- // now relative to the start of the <if>
- $relpos = $tag_full['else'] - $tag_full['posi'];
-
- // calculate the length of the expression and opening tag
- $length = strlen($parsed[0]) + strlen($tag_start) + strlen($tag_start_end);
-
- // relative to the start of iftrue
- $elsepos = $relpos - $length;
-
- $parsed[1] = substr($conditional, 0, $elsepos);
- $parsed[2] = substr($conditional, $elsepos + strlen($tag_else));
- }
- // no else to handle
- else
- {
- $parsed[1] = $conditional;
- $parsed[2] = '';
- }
-
- // final parsed output
- $parsed = '" . ((' . stripslashes($parsed[0]) . ') ? "' . $parsed[1] . '" : "' . $parsed[2] . '") . "';
-
- // replace the conditional
- $template = str_replace($fullspread, $parsed, $template);
-
- // reset the parser
- $offset = $tag_full['posi'] + strlen($tag_start) + strlen($tag_start_end);
- $tag_full = array();
- $stack = array();
- $parsed = array();
- unset($fullspread, $conditional, $temp_end, $relpos, $length, $elsepos);
- break;
- }
- }
- }
-
return $template;
}
}
class TemplateTest extends PHPUnit_Framework_TestCase
{
- private $fixture;
private $db;
public function setUp()
require_once ISSO . '/App.php';
require_once ISSO . '/Template.php';
- $this->fixture = new BSTemplate();
- $this->fixture->setTemplateDirectory(TEST_TEMPLATE_PATH);
- $this->fixture->setExtension('test.tpl');
+ BSTemplate::$templatePath = TEST_TEMPLATE_PATH . '/%s.test.tpl';
if ($this->db == null)
{
{
try
{
- $this->fixture->fetch('--invalid--');
+ new BSTemplate('--invalid--');
$this->fail('exception expected');
}
catch (Exception $e)
public function testFetch()
{
- $result = $this->fixture->fetch('fetch.lang');
- $this->assertEquals('this is a test of " . gettext(\'language\') . " strings', $result);
+ $result = BSTemplate::fetch('fetch.lang');
+ $this->assertEquals('this is a test of <?php T(\'language\') ?> strings', $result->getTemplate());
- $result = $this->fixture->fetch('fetch.if');
- $this->assertEquals('this " . (($a == $b) ? "is cool" : "sucks") . "!', $result);
+ $result = BSTemplate::fetch('fetch.if');
+ $this->assertEquals('this <?php if ($a == $b): ?>is cool<?php else: ?>sucks<?php endif; ?>!', $result->getTemplate());
- $result = $this->fixture->fetch('fetch.php');
- $this->assertEquals('this is " . (date(\'Y\', time()) . " today\'s year', $result);
+ $result = BSTemplate::fetch('fetch.php');
+ $this->assertEquals('this is <?php date(\'Y\', time() ?> today\'s year', $result->getTemplate());
- // TODO: pass test
- // $result = $this->fixture->fetch('fetch.php.nested');
- // $this->assertEquals('this is a " . strpos(\'somestr{\', \'}\') . " nested token', $result);
-
- $result = $this->fixture->fetch('fetch.lang.tag');
- $this->assertEquals('this is a " . sprintf(\'" . gettext(\'a %1$s b %2$s\') . "\', "hello", "there") . " test', $result);
-
- $result = $this->fixture->fetch('fetch.if.nested');
- $this->assertEquals('this " . (($c == $d) ? "foo " . (($e == $f) ? "e" : "f") . "" : "moo " . (($g == $h) ? "g" : "h") . "") . " rules!', $result);
-
- $result = $this->fixture->fetch('fetch.if.noelse');
- $this->assertEquals('this is a test " . (($foo != \'moo\') ? "without else" : "") . "!', $result);
-
- try
- {
- $this->fixture->fetch('fetch.lang.invalid');
- $this->fail('exception expected');
- }
- catch (Exception $e)
- {}
-
- $result = $this->fixture->fetch('fetch.lang.indexmissing');
- $this->assertEquals('missing " . sprintf(\'" . gettext(\'1 %1$s 2 %2$s 3 %3$s\') . "\', "a", "<strong>[MISSING SUBSTITUTION INDEX: 2]</strong>", "b") . " index', $result);
+ $result = BSTemplate::fetch('fetch.if.nested');
+ $this->assertEquals('this <?php if ($c == $d): ?>foo <?php if ($e == $f): ?>e<?php else: ?>f<?php endif; ?><?php else: ?>moo <?php if ($g == $h): ?>g<?php else: ?>h<?php endif; ?><?php endif; ?> rules!', $result->getTemplate());
}
public function testPreParseHook()
{
$func = create_function('$tpl', 'return "this template is now cleared";');
- $this->fixture->setPreParseHook($func);
+ BSTemplate::$preParseHook = $func;
- $result = $this->fixture->fetch('hook');
- $this->assertEquals('this template is now cleared', $result);
+ $result = new BSTemplate('hook');
+ $this->assertEquals('this template is now cleared', $result->getTemplate());
+ BSTemplate::$preParseHook = null;
}
public function testStandardCache()
{
file_put_contents(TEST_TEMPLATE_PATH . '/cache.test.tpl', 'this file is retreived from the cache');
- $this->fixture->cache(array('cache'));
+ BSTemplate::fetch('cache');
unlink(TEST_TEMPLATE_PATH . '/cache.test.tpl');
try
{
- $result = $this->fixture->fetch('cache');
- $this->assertEquals('this file is retreived from the cache', $result);
+ $result = BSTemplate::fetch('cache');
}
catch (Exception $e)
{
- $this->fixture('unexpected exception');
+ $this->fail('unexpected exception');
}
+ $this->assertEquals('this file is retreived from the cache', $result->getTemplate());
try
{
- $this->fixture->cache(array('hook'));
+ BSTemplate::cache(array('hook'));
$this->fail('exception expected');
}
catch (Exception $e)
}
public function testDbCache()
- {
- $this->fixture->setDatabaseCache('template');
+ {
+ BSTemplate::$dbCacheTable = 'template';
file_put_contents(TEST_TEMPLATE_PATH . '/db.cache.test.tpl', 'store in the database');
- $this->fixture->cache(array('db.cache'));
+ BSTemplate::fetch('db.cache');
$template = $this->db->queryFirst("SELECT * FROM template");
$this->assertNotEquals(null, $template);
- $this->setUp();
- $this->fixture->setDatabaseCache('template');
-
- $this->fixture->cache(array('db.cache'));
- $this->assertEquals('store in the database', $this->fixture->fetch('db.cache'));
+ BSTemplate::cache(array('db.cache'));
+ $this->assertEquals('store in the database', BSTemplate::fetch('db.cache')->getTemplate());
file_put_contents(TEST_TEMPLATE_PATH . '/db.cache.test.tpl', 'store in the database, retouched');
sleep(1); // give the file system some time
touch(TEST_TEMPLATE_PATH . '/db.cache.test.tpl');
clearstatcache();
- $this->setUp();
- $this->fixture->setDatabaseCache('template');
- $this->fixture->cache(array('db.cache'));
- $this->setUp();
- $this->fixture->setDatabaseCache('template');
- $this->fixture->cache(array('db.cache'));
- $this->assertEquals('store in the database, retouched', $this->fixture->fetch('db.cache'));
+ $this->assertEquals('store in the database, retouched', BSTemplate::fetch('db.cache')->getTemplate());
+
+ BSTemplate::$dbCacheTable = null;
}
public function testFlush()
{
- try
- {
- $this->fixture->flush('');
- $this->fail('exception expected');
- }
- catch (Exception $e)
- {}
-
$a = 'foo';
ob_start();
- $this->fixture->flush($this->fixture->fetch('flush'));
+ BSTemplate::fetch('flush')->flush();
$data = ob_get_contents();
ob_end_clean();
$this->assertEquals('this is a $a test', $data);
-
- try
- {
- $this->fixture->flush($this->fixture->fetch('flush'));
- $this->fail('exception expected');
- }
- catch (Exception $e)
- {}
}
}