diff --git a/lib/.xmlregistry/channels/channel-phpsavant.com.xml b/lib/.xmlregistry/channels/channel-phpsavant.com.xml new file mode 100644 index 0000000000000000000000000000000000000000..3e15ed16539b2a2b2f112bac0618a27b92fc035e --- /dev/null +++ b/lib/.xmlregistry/channels/channel-phpsavant.com.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<channel version="1.0" xmlns="http://pear.php.net/channel-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd"> + <name>phpsavant.com</name> + <suggestedalias>savant</suggestedalias> + <summary>Savant</summary> + <servers> + <primary> + <rest> + <baseurl type="REST1.0">http://phpsavant.com/rest/</baseurl> + <baseurl type="REST1.1">http://phpsavant.com/rest/</baseurl> + <baseurl type="REST1.3">http://phpsavant.com/rest/</baseurl> + </rest> + </primary> + </servers> +</channel> diff --git a/lib/.xmlregistry/channels/channelalias-savant.txt b/lib/.xmlregistry/channels/channelalias-savant.txt new file mode 100644 index 0000000000000000000000000000000000000000..50601c9682e9872207fe30fb369ab5c6f62087f6 --- /dev/null +++ b/lib/.xmlregistry/channels/channelalias-savant.txt @@ -0,0 +1 @@ +phpsavant.com \ No newline at end of file diff --git a/lib/.xmlregistry/packages/phpsavant.com/Savvy/0.7.3-info.xml b/lib/.xmlregistry/packages/phpsavant.com/Savvy/0.7.3-info.xml new file mode 100644 index 0000000000000000000000000000000000000000..a9e535f7792a1a0dd14bfb3c885a6a6efb9457f1 --- /dev/null +++ b/lib/.xmlregistry/packages/phpsavant.com/Savvy/0.7.3-info.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<package xmlns="http://pear.php.net/dtd/package-2.1" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.1 http://pear.php.net/dtd/package-2.1.xsd" packagerversion="2.0.0"> + <name>Savvy</name> + <channel>phpsavant.com</channel> + <summary>Savvy is a powerful but lightweight object-oriented template system for PHP. +</summary> + <description> +Unlike other template systems, Savvy by default does not compile your +templates into PHP; instead, it uses PHP itself as its template language so you +don't need to learn a new markup system.</description> + <lead> + <name>Brett Bieber</name> + <user>saltybeagle</user> + <email>saltybeagle@php.net</email> + <active>yes</active> + </lead> + <lead> + <name>Gregory Beaver</name> + <user>cellog</user> + <email>cellog@php.net</email> + <active>yes</active> + </lead> + <date>2013-04-29</date> + <time>14:29:53</time> + <version> + <release>0.7.3</release> + <api>0.1.0</api> + </version> + <stability> + <release>alpha</release> + <api>alpha</api> + </stability> + <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license> + <notes>Improve support for proxying arrays: + +* Objects which implement ArrayIterator are now proxied using a compatible object +* Ensure keys are proxied when returned from ArrayObject + + +Package Savvy API release notes for version 0.1.0.</notes> + <contents> + <dir name="/"> + <file role="test" name="tests/test_framework.php.inc" md5sum="d7b66614eef48d4945901a43a9568b14"/> + <file role="test" name="tests/render/string.phpt" md5sum="1a60e68f87d277aa9c653472b8c0ef76"/> + <file role="test" name="tests/render/object.phpt" md5sum="5555262b6c42f604b38f3e3aaf77e974"/> + <file role="test" name="tests/render/Foo.tpl.php" md5sum="2af7ae28b4d35227c53921eaabfaeaad"/> + <file role="test" name="tests/render/fastcompile.phpt" md5sum="923e958a495177f4be567abd6d7d37f6"/> + <file role="test" name="tests/render/echostring.tpl.php" md5sum="138231e0b170c36ff602c09eaaa1690f"/> + <file role="test" name="tests/render/array.phpt" md5sum="3f284e6ec2d710398f4b67378f373de4"/> + <file role="test" name="tests/globals/escape.phpt" md5sum="d1b9276341877c681e62ddad93d2d1dc"/> + <file role="test" name="tests/globals/escape.nestedarrays.phpt" md5sum="7f1e04a1302995ed6c0a43d525ebd73d"/> + <file role="test" name="tests/globals/escape.arrays.phpt" md5sum="20312ab95ea7901b79e21fdd61f5dca4"/> + <file role="test" name="tests/globals/basic.tpl.php" md5sum="7898705f5a0a5792a191cca28501e22e"/> + <file role="test" name="tests/globals/basic.phpt" md5sum="ac2ae80d9f5344694e6f2d90c0417b2c"/> + <file role="test" name="tests/escape/string.phpt" md5sum="4fd594fef7e7621e79cefa341c2439a0"/> + <file role="test" name="tests/escape/raw.tpl.php" md5sum="2e7b87c466f106a575d6740258356109"/> + <file role="test" name="tests/escape/object.phpt" md5sum="7012a6b97c7cb20391bde8243b582e1b"/> + <file role="test" name="tests/escape/Foo.tpl.php" md5sum="d960fd1fa4867a04702db10cda65d772"/> + <file role="test" name="tests/escape/echostring.tpl.php" md5sum="a45c7c6b67b56e43935d844f358f080b"/> + <file role="php" name="src/Savvy/UnexpectedValueException.php" md5sum="bc88ee83b651bea0cb3190c4785be447"/> + <file role="php" name="src/Savvy/TemplateException.php" md5sum="0dcf725a67d3db2457f4f9793654e8d1"/> + <file role="php" name="src/Savvy/ObjectProxy/Traversable.php" md5sum="d8ecfde88e9de6d70e051ac27c1f5952"/> + <file role="php" name="src/Savvy/ObjectProxy/ArrayObject.php" md5sum="e8e70b5189d19163132d07292233fa87"/> + <file role="php" name="src/Savvy/ObjectProxy/ArrayIterator.php" md5sum="6e3b437bb6f98b38b309e82ea9c0c3de"/> + <file role="php" name="src/Savvy/ObjectProxy/ArrayAccess.php" md5sum="eadebc4221a22f59b14c31c19af03638"/> + <file role="php" name="src/Savvy/ObjectProxy.php" md5sum="9990f3eae842039b9e3d2570d859afd2"/> + <file role="php" name="src/Savvy/MapperInterface.php" md5sum="127c43a259b071872044a492d101faca"/> + <file role="php" name="src/Savvy/FilterAbstract.php" md5sum="dc9abe43fa8f2a7ec038d8bc4e2fd0da"/> + <file role="php" name="src/Savvy/FastCompilerInterface.php" md5sum="213b589107a0b18d2074167f2d0fe864"/> + <file role="php" name="src/Savvy/Exception.php" md5sum="1e05784e2648c5daf2bf8848f302290d"/> + <file role="php" name="src/Savvy/CompilerInterface.php" md5sum="45622fa0a1eea84981eb8265b43ce2da"/> + <file role="php" name="src/Savvy/CompilerException.php" md5sum="05e9107fb803c7f54d512a4daee8cd30"/> + <file role="php" name="src/Savvy/ClassToTemplateMapper.php" md5sum="fd04a4a3f7bb2e2317bc32e5451b56a3"/> + <file role="php" name="src/Savvy/BasicFastCompiler.php" md5sum="313d6d9ac280509c7f0e072e6841d80d"/> + <file role="php" name="src/Savvy/BadMethodCallException.php" md5sum="e5d06612d101d72bc82709df7ae0426e"/> + <file role="php" name="src/Savvy/Autoload.php" md5sum="c0ee9b9628bed191991bc641721a39d8"/> + <file role="php" name="src/Savvy.php" md5sum="15a9925335b9d9e2065526d89f7a6660"/> + <file role="doc" name="examples/templates/StringView.tpl.php" md5sum="b4746d9c4e29624cb75c4bbf74600371"/> + <file role="doc" name="examples/templates/stdClass.tpl.php" md5sum="ecb083ab102eac7b1bc6d5306092b36d"/> + <file role="doc" name="examples/templates/MyTemplate.tpl.php" md5sum="b7004c1f5eed19602e5c7afe97dbbd27"/> + <file role="doc" name="examples/basic.php" md5sum="74ae4c065f1920ecfb59e9a9ad6e3746"/> + <file role="doc" name="examples/baseball/PartialSeason.tpl.php" md5sum="028f2aa4e14931455bf1c2b89407def3"/> + <file role="doc" name="examples/baseball/ListItem.tpl.php" md5sum="606d5c6b9e5987776d70f5eb4431783d"/> + <file role="doc" name="examples/baseball/index.php" md5sum="3a7e6408b0fc2ad9a2ff6fcbeee4a43a"/> + <file role="doc" name="examples/baseball/BaseballTeam.tpl.php" md5sum="dd3d25e88626d358a05050b3a5b22f78"/> + <file role="doc" name="examples/baseball/BaseballPlayer.tpl.php" md5sum="ff0ddb3f097ac934f71c442d6893bece"/> + </dir> + </contents> + <dependencies> + <required> + <php> + <min>5.2.0</min> + </php> + <pearinstaller> + <min>1.4.0</min> + </pearinstaller> + </required> + </dependencies> + <phprelease/> +</package> diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballPlayer.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballPlayer.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..b19f414fa7038c2d711081074f059a3cc2bd86d1 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballPlayer.tpl.php @@ -0,0 +1,5 @@ +<h2>Player :: <?php echo $context->name; ?></h2> +<p>Years on team:</p> +<ul> + <?php echo $savvy->render($context->years_on_team, 'ListItem.tpl.php'); ?> +</ul> \ No newline at end of file diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballTeam.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballTeam.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..f95a97bbeddf25479dcd093ef5f70b3afe1d3dfc --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballTeam.tpl.php @@ -0,0 +1,9 @@ +<html> +<head> + <title><?php echo $context->name; ?></title> +</head> +<body> + <h1><?php echo $context->name; ?></h1> + <?php echo $savvy->render($context->output); ?> +</body> +</html> \ No newline at end of file diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/ListItem.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/ListItem.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..23604d5edaad4a04a710f7b7c2dc18571f46bbd2 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/ListItem.tpl.php @@ -0,0 +1 @@ +<li><?php echo $savvy->render($context); ?></li> \ No newline at end of file diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/PartialSeason.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/PartialSeason.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..1eb04a091234ab493df7e30a69651942663a2f7e --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/PartialSeason.tpl.php @@ -0,0 +1 @@ +<?php echo $context->start; ?>—<?php echo $context->end; ?> \ No newline at end of file diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/index.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/index.php new file mode 100644 index 0000000000000000000000000000000000000000..fcfef095a2b55f7ace2b49b93cf9e778cdf83c61 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/index.php @@ -0,0 +1,58 @@ +<?php +ini_set('display_errors',true); +error_reporting(E_ALL^E_STRICT); +require_once dirname(__FILE__).'/../../src/Savvy/Autoload.php'; +$classLoader = new Savvy_Autoload(); +$classLoader->register(); + +class BaseballTeam +{ + protected $view = 'player'; + + protected $view_map = array( + 'player' => 'BaseballPlayer' + ); + + public $name; + + public $output; + + function __construct($options = array()) + { + if (isset($options['view'], $this->view_map[$options['view']])) { + $this->view = $options['view']; + } + $this->output = new $this->view_map[$this->view](); + } +} + +class BaseballPlayer +{ + public $name = 'Joseph Baseball <AKA: Joey B>'; + public $years_on_team = array(2005, 2008); + function __construct() + { + $this->years_on_team[] = new PartialSeason(date('Y')); + } +} + +class PartialSeason +{ + public $start; + public $end; + + function __construct($start, $end = null) + { + $this->start = $start; + if ($end) { + $this->end = $end; + } + } +} + +$team = new BaseballTeam(); +$team->name = 'Phillies'; + +$savvy = new Savvy(); +$savvy->setEscape('htmlspecialchars'); +echo $savvy->render($team); \ No newline at end of file diff --git a/lib/docs/phpsavant.com/Savvy/examples/basic.php b/lib/docs/phpsavant.com/Savvy/examples/basic.php new file mode 100644 index 0000000000000000000000000000000000000000..0f4b21a78ed75ca6a59ac558ce3983116e720795 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/basic.php @@ -0,0 +1,40 @@ +<?php +ini_set('display_errors',true); +error_reporting(E_ALL^E_STRICT); +require_once dirname(__FILE__).'/../src/Savvy/Autoload.php'; +$classLoader = new Savvy_Autoload(); +$classLoader->register(); + +// Set up a view object we'd like to display +$class = new stdClass(); +$class->var1 = '<p>This is var1 inside a standard class</p>'; + +$savvy = new Savvy(); +$savvy->addTemplatePath(__DIR__ . '/templates'); + +// Display a simple string +echo $savvy->render('<h1>Welcome to the Savvy Demo</h1>'); + +// Display a string, in a custom template +echo $savvy->render('mystring', 'StringView.tpl.php'); + +// Display an array +echo $savvy->render(array('<ul>', '<li>This is an array</li>', '</ul>')); + +// Display an object using a default class name to template mapping function +echo $savvy->render($class); + +// Display the object using a specific template +echo $savvy->render($class, 'MyTemplate.tpl.php'); + +echo $savvy->render('<h2>Output Filtering</h2>'); +$savvy->addFilters('htmlspecialchars'); + +// Now show an entire template with htmlspecialchars +echo $savvy->render($class); + +// Ok, now remove the output filters +$savvy->setFilters(); + +highlight_file(__FILE__); + diff --git a/lib/docs/phpsavant.com/Savvy/examples/templates/MyTemplate.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/templates/MyTemplate.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..23e7ad593ac73289dcaebf0c25b6fdf8087aa563 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/templates/MyTemplate.tpl.php @@ -0,0 +1,2 @@ +<h2>This is MyTemplate.tpl.php</h2> +<p>This represents using a custom output template for an object.</p> diff --git a/lib/docs/phpsavant.com/Savvy/examples/templates/StringView.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/templates/StringView.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..36d1493312e1d7be129759545e6cbb097a349004 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/templates/StringView.tpl.php @@ -0,0 +1 @@ +<p>We're in the string view template, the data is: <?php echo $context; ?></p> \ No newline at end of file diff --git a/lib/docs/phpsavant.com/Savvy/examples/templates/stdClass.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/templates/stdClass.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..1f649fe6fd9981b815acee679a6d34c220b76419 --- /dev/null +++ b/lib/docs/phpsavant.com/Savvy/examples/templates/stdClass.tpl.php @@ -0,0 +1,6 @@ +<h2>This is stdClass.tpl.php</h2> +<p>This represents the default mapping of class name to template.</p> +<p>The class of this context is: <?php echo get_class($context); ?></p> +<p>The $context object contains the stdClass object with access to all the member +variables and functions, such as $context->var1</p> +<?php echo $context->var1; ?> \ No newline at end of file diff --git a/lib/php/Savvy.php b/lib/php/Savvy.php new file mode 100644 index 0000000000000000000000000000000000000000..484bdc884b30d68a6897d05911eac040e2ca741f --- /dev/null +++ b/lib/php/Savvy.php @@ -0,0 +1,986 @@ +<?php +/** + * Savvy + * + * PHP version 5 + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @copyright 2010 Brett Bieber + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version SVN: $Id$ + * @link http://svn.php.net/repository/pear2/Savvy + */ + +/** + * Main class for Savvy + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @copyright 2010 Brett Bieber + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @link http://svn.php.net/repository/pear2/Savvy + */ +class Savvy +{ + /** + * + * Array of configuration parameters. + * + * @access protected + * + * @var array + * + */ + + protected $__config = array( + 'compiler' => null, + 'filters' => array(), + 'escape' => null, + ); + + /** + * Parameters for escaping. + * + * @var array + */ + protected $_escape = array( + 'quotes' => ENT_COMPAT, + 'charset' => 'UTF-8', + ); + + /** + * The output template to render using + * + * @var string + */ + protected $template; + + /** + * stack of templates, so we can access the parent template + * + * @var array + */ + protected $templateStack = array(); + + /** + * To avoid stats on locating templates, populate this array with + * full path => 1 for any existing templates + * + * @var array + */ + protected $templateMap = array(); + + /** + * An array of paths to look for template files in. + * + * @var array + */ + protected $template_path = array('./'); + + /** + * The current controller to use + * + * @var string + */ + protected $selected_controller; + + /** + * How class names are translated to templates + * + * @var MapperInterface + */ + protected $class_to_template; + + /** + * Array of globals available within every template + * + * @var array + */ + protected $globals = array(); + // ----------------------------------------------------------------- + // + // Constructor and magic methods + // + // ----------------------------------------------------------------- + + + /** + * + * Constructor. + * + * @access public + * + * @param array $config An associative array of configuration keys for + * the Main object. Any, or none, of the keys may be set. + * + * @return Savvy A Savvy instance. + * + */ + + public function __construct($config = null) + { + $savvy = $this; + + $this->selected_controller = 'basic'; + + // set the default template search path + if (isset($config['template_path'])) { + // user-defined dirs + $this->setTemplatePath($config['template_path']); + } + + // set the output escaping callbacks + if (isset($config['escape'])) { + $this->setEscape($config['escape']); + } + + // set the default filter callbacks + if (isset($config['filters'])) { + $this->addFilters($config['filters']); + } + } + + /** + * Basic output controller + * + * @param mixed $context The context passed to the template + * @param mixed $parent Parent template with context and parents $parent->context + * @param mixed $file The filename to include + * @param Savvy $savvy The Savvy templating system + * + * @return string + */ + protected static function basicOutputController($context, $parent, $file, $savvy) + { + foreach ($savvy->getGlobals() as $__name => $__value) { + $$__name = $__value; + } + unset($__name, $__value); + ob_start(); + include $file; + return ob_get_clean(); + } + + /** + * Basic output controller + * + * @param mixed $context The context passed to the template + * @param mixed $parent Parent template with context and parents $parent->context + * @param mixed $file The filename to include + * @param Savvy $savvy The Savvy templating system + * + * @return string + */ + protected static function filterOutputController($context, $parent, $file, $savvy) + { + foreach ($savvy->getGlobals() as $__name => $__value) { + $$__name = $__value; + } + unset($__name, $__value); + ob_start(); + include $file; + return $savvy->applyFilters(ob_get_clean()); + } + + /** + * Basic output controller + * + * @param mixed $context The context passed to the template + * @param mixed $parent Parent template with context and parents $parent->context + * @param mixed $file The filename to include + * @param Savvy $savvy The Savvy templating system + * + * @return string + */ + protected static function basicCompiledOutputController($context, $parent, $file, $savvy) + { + foreach ($savvy->getGlobals() as $__name => $__value) { + $$__name = $__value; + } + unset($__name, $__value); + ob_start(); + include $savvy->template($file); + return ob_get_clean(); + } + + /** + * Basic output controller + * + * @param mixed $context The context passed to the template + * @param mixed $parent Parent template with context and parents $parent->context + * @param mixed $file The filename to include + * @param Savvy $savvy The Savvy templating system + * + * @return string + */ + protected static function filterCompiledOutputController($context, $parent, $file, $savvy) + { + foreach ($savvy->getGlobals() as $__name => $__value) { + $$__name = $__value; + } + unset($__name, $__value); + ob_start(); + include $savvy->template($file); + return $savvy->applyFilters(ob_get_clean()); + } + + /** + * Basic output controller + * + * @param mixed $context The context passed to the template + * @param mixed $parent Parent template with context and parents $parent->context + * @param mixed $file The filename to include + * @param Savvy $savvy The Savvy templating system + * + * @return string + */ + protected static function basicFastCompiledOutputController($context, $parent, $file, $savvy) + { + return include $savvy->template($file); + } + + /** + * Basic output controller + * + * @param mixed $context The context passed to the template + * @param mixed $parent Parent template with context and parents $parent->context + * @param mixed $file The filename to include + * @param Savvy $savvy The Savvy templating system + * + * @return string + */ + protected static function filterFastCompiledOutputController($context, $parent, $file, $savvy) + { + return $savvy->applyFilters(include $savvy->template($file)); + } + + /** + * Add a global variable which will be available inside every template + * + * @param string $var The global variable name + * @param mixed $value The value + * + * @return void + */ + function addGlobal($name, $value) + { + switch ($name) { + case 'context': + case 'parent': + case 'template': + case 'savvy': + case 'this': + throw new Savvy_BadMethodCallException('Invalid global variable name'); + } + + if ($this->__config['escape']) { + switch (gettype($value)) { + case 'object': + if (!$value instanceof Savvy_ObjectProxy) { + $value = Savvy_ObjectProxy::factory($value, $this); + } + break; + case 'string': + case 'int': + case 'double': + $value = $this->escape($value); + break; + case 'array': + $value = new Savvy_ObjectProxy_ArrayIterator($value, $this); + break; + } + } + + $this->globals[$name] = $value; + } + + /** + * Get the array of assigned globals + * + * @return array + */ + function getGlobals() + { + return $this->globals; + } + + /** + * Return the current template set (if any) + * + * @return string + */ + function getTemplate() + { + return $this->template; + } + + + // ----------------------------------------------------------------- + // + // Public configuration management (getters and setters). + // + // ----------------------------------------------------------------- + + + /** + * + * Returns a copy of the Savvy configuration parameters. + * + * @access public + * + * @param string $key The specific configuration key to return. If null, + * returns the entire configuration array. + * + * @return mixed A copy of the $this->__config array. + * + */ + + public function getConfig($key = null) + { + if (is_null($key)) { + // no key requested, return the entire config array + return $this->__config; + } elseif (empty($this->__config[$key])) { + // no such key + return null; + } else { + // return the requested key + return $this->__config[$key]; + } + } + + + /** + * + * Sets a custom compiler/pre-processor callback for template sources. + * + * By default, Savvy does not use a compiler; use this to set your + * own custom compiler (pre-processor) for template sources. + * + * @access public + * + * @param mixed $compiler A compiler callback value suitable for the + * first parameter of call_user_func(). Set to null/false/empty to + * use PHP itself as the template markup (i.e., no compiling). + * + * @return void + * + */ + + public function setCompiler(Savvy_CompilerInterface $compiler) + { + $this->__config['compiler'] = $compiler; + if ($compiler instanceof Savvy_FastCompilerInterface) { + switch ($this->selected_controller) { + case 'basic' : + case 'basiccompiled'; + $this->selected_controller = 'basicfastcompiled'; + break; + case 'filter' : + case 'filtercompiled' : + $this->selected_controller = 'filterfastcompiled'; + break; + } + return; + } + if (!strpos($this->selected_controller, 'compiled')) { + $this->selected_controller .= 'compiled'; + } + } + + /** + * Set the class to template mapper. + * + * @see MapperInterface + * + * @param MapperInterface $mapper The mapper interface to use + * + * @return Main + */ + function setClassToTemplateMapper(Savvy_MapperInterface $mapper) + { + $this->class_to_template = $mapper; + return $this; + } + + /** + * Get the class to template mapper. + * + * @return MapperInterface + */ + function getClassToTemplateMapper() + { + if (!isset($this->class_to_template)) { + $this->setClassToTemplateMapper(new Savvy_ClassToTemplateMapper()); + } + return $this->class_to_template; + } + + + // ----------------------------------------------------------------- + // + // Output escaping and management. + // + // ----------------------------------------------------------------- + + + /** + * + * Clears then sets the callbacks to use when calling $this->escape(). + * + * Each parameter passed to this function is treated as a separate + * callback. For example: + * + * <code> + * $savvy->setEscape( + * 'stripslashes', + * 'htmlspecialchars', + * array('StaticClass', 'method'), + * array($object, $method) + * ); + * </code> + * + * @access public + * + * @return Main + * + */ + + public function setEscape() + { + $this->__config['escape'] = @func_get_args(); + return $this; + } + + + /** + * + * Gets the array of output-escaping callbacks. + * + * @access public + * + * @return array The array of output-escaping callbacks. + * + */ + + public function getEscape() + { + return $this->__config['escape']; + } + + + /** + * Escapes a value for output in a view script. + * + * If escaping mechanism is one of htmlspecialchars or htmlentities, uses + * {@link $_encoding} setting. + * + * @param mixed $var The output to escape. + * + * @return mixed The escaped value. + */ + public function escape($var) + { + foreach ($this->__config['escape'] as $escape) { + if (in_array($escape, + array('htmlspecialchars', 'htmlentities'), true)) { + $var = call_user_func($escape, + $var, + $this->_escape['quotes'], + $this->_escape['charset']); + } else { + $var = call_user_func($escape, $var); + } + } + return $var; + } + + + // ----------------------------------------------------------------- + // + // File management + // + // ----------------------------------------------------------------- + + /** + * Get the template path. + * + * @return array + */ + function getTemplatePath() + { + return $this->template_path; + } + + /** + * + * Sets an entire array of search paths for templates or resources. + * + * @access public + * + * @param string|array $path The new set of search paths. If null or + * false, resets to the current directory only. + * + * @return Main + * + */ + + public function setTemplatePath($path = null) + { + // clear out the prior search dirs, add default + $this->template_path = array('./'); + + // actually add the user-specified directories + $this->addTemplatePath($path); + return $this; + } + + + /** + * + * Adds to the search path for templates and resources. + * + * @access public + * + * @param string|array $path The directory or stream to search. + * + * @return Main + * + */ + + public function addTemplatePath($path) + { + // convert from path string to array of directories + if (is_string($path) && !strpos($path, '://')) { + + // the path config is a string, and it's not a stream + // identifier (the "://" piece). add it as a path string. + $path = explode(PATH_SEPARATOR, $path); + + // typically in path strings, the first one is expected + // to be searched first. however, Savvy uses a stack, + // so the first would be last. reverse the path string + // so that it behaves as expected with path strings. + $path = array_reverse($path); + + } else { + + // just force to array + settype($path, 'array'); + + } + + // loop through the path directories + foreach ($path as $dir) { + + // no surrounding spaces allowed! + $dir = trim($dir); + + // add trailing separators as needed + if (strpos($dir, '://')) { + if (substr($dir, -1) != '/') { + // stream + $dir .= '/'; + } + } elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) { + if (false !== strpos($dir, '..')) { + // checking for weird paths here removes directory traversal threat + throw new Savvy_UnexpectedValueException('upper directory reference .. cannot be used in template path'); + } + // directory + $dir .= DIRECTORY_SEPARATOR; + } + + // add to the top of the search dirs + array_unshift( + $this->template_path, + $dir + ); + } + } + + + /** + * + * Searches the directory paths for a given file. + * + * @param string $file The file name to look for. + * + * @return string|bool The full path and file name for the target file, + * or boolean false if the file is not found in any of the paths. + * + */ + + public function findTemplateFile($file) + { + if (false !== strpos($file, '..')) { + // checking for weird path here removes directory traversal threat + throw new Savvy_UnexpectedValueException('upper directory reference .. cannot be used in template filename'); + } + + // start looping through the path set + foreach ($this->template_path as $path) { + // get the path to the file + $fullname = $path . $file; + + if (isset($this->templateMap[$fullname])) { + return $fullname; + } + + if (!@is_readable($fullname)) { + continue; + } + + return $fullname; + } + + // could not find the file in the set of paths + throw new Savvy_TemplateException('Could not find the template ' . $file); + } + + + // ----------------------------------------------------------------- + // + // Template processing + // + // ----------------------------------------------------------------- + + /** + * Render context data through a template. + * + * This method allows you to render data through a template. Typically one + * will pass the model they wish to display through an optional template. + * If no template is specified, the ClassToTemplateMapper::map() method + * will be called which should return the name of a template to render. + * + * Arrays will be looped over and rendered through the template specified. + * + * Strings, ints, and doubles will returned if no template parameter is + * present. + * + * Within templates, two variables will be available, $context and $savvy. + * The $context variable will contain the data passed to the render method, + * the $savvy object will be an instance of the Main class with which you + * can render nested data through partial templates. + * + * @param mixed $mixed Data to display through the template. + * @param string $template A template to display data in. + * + * @return string The template output + */ + function render($mixed = null, $template = null) + { + $method = 'render'.gettype($mixed); + return $this->$method($mixed, $template); + } + + /** + * Called when a resource is rendered + * + * @param resource $resouce The resources + * @param string $template Template + * + * @return void + * + * @throws UnexpectedValueException + */ + protected function renderResource($resouce, $template = null) + { + throw new Savvy_UnexpectedValueException('No way to render a resource!'); + } + + protected function renderBoolean($bool, $template = null) + { + return $this->renderString((string)$bool, $template); + } + + protected function renderDouble($double, $template = null) + { + return $this->renderString($double, $template); + } + + protected function renderInteger($int, $template = null) + { + return $this->renderString($int, $template); + } + + /** + * Render string of data + * + * @param string $string String of data + * @param string $template A template to display the string in + * + * @return string + */ + protected function renderString($string, $template = null) + { + if ($this->__config['escape']) { + $string = $this->escape($string); + } + + if ($template) { + return $this->fetch($string, $template); + } + + if (!$this->__config['filters']) { + return $string; + } + return $this->applyFilters($string); + } + + /** + * Used to render context array + * + * @param array $array Data to render + * @param string $template Template to render + * + * @return string Rendered output + */ + protected function renderArray(array $array, $template = null) + { + $output = ''; + foreach ($array as $mixed) { + $output .= $this->render($mixed, $template); + } + return $output; + } + + /** + * Render an associative array of data through a template. + * + * Three parameters will be passed to the closure, the array key, value, + * and selective third parameter. + * + * @param array $array Associative array of data + * @param mixed $selected Optional parameter to pass + * @param Closure $template A closure that will be called + * + * @return string + */ + public function renderAssocArray(array $array, $selected = false, Closure $template) + { + $ret = ''; + foreach ($array as $key => $element) { + $ret .= $template($key, $element, $selected); + } + return $ret; + } + + protected function renderArrayAccess(ArrayAccess $array, $template = null) + { + $ret = ''; + foreach ($array as $key => $element) { + $ret .= $this->render($element, $template); + } + return $ret; + } + + /** + * Render an if else conditional template output. + * + * @param mixed $condition The conditional to evaluate + * @param mixed $render Context data to render if condition is true + * @param mixed $else Context data to render if condition is false + * @param string $rendertemplate If true, render using this template + * @param string $elsetemplate If false, render using this template + * + * @return string + */ + public function renderElse($condition, $render, $else, $rendertemplate = null, $elsetemplate = null) + { + if ($condition) { + $this->render($render, $rendertemplate); + } else { + $this->render($else, $elsetemplate); + } + } + + /** + * Used to render an object through a template. + * + * @param object $object Model containing data + * @param string $template Template to render data through + * + * @return string Rendered output + */ + protected function renderObject($object, $template = null) + { + if ($this->__config['escape']) { + + if (!$object instanceof Savvy_ObjectProxy) { + $object = Savvy_ObjectProxy::factory($object, $this); + } + + if ($object instanceof Savvy_ObjectProxy_ArrayIterator) { + return $this->renderArrayAccess($object); + } + } + return $this->fetch($object, $template); + } + + /** + * Used to render null through an optional template + * + * @param null $null The null var + * @param string $template Template to render null through + * + * @return string Rendered output + */ + protected function renderNULL($null, $template = null) + { + if ($template) { + return $this->fetch(null, $template); + } + } + + protected function fetch($mixed, $template = null) + { + if ($template) { + $this->template = $template; + } else { + if ($mixed instanceof Savvy_ObjectProxy) { + $class = $mixed->__getClass(); + } else { + $class = get_class($mixed); + } + $this->template = $this->getClassToTemplateMapper()->map($class); + } + $current = new stdClass; + $current->file = $this->findTemplateFile($this->template); + $current->context = $mixed; + $current->parent = null; + if (count($this->templateStack)) { + $current->parent = $this->templateStack[count($this->templateStack)-1]; + } + $this->templateStack[] = $current; + $ret = call_user_func(array($this, $this->selected_controller.'OutputController'), $current->context, $current->parent, $current->file, $this); + array_pop($this->templateStack); + return $ret; + } + + /** + * + * Compiles a template and returns path to compiled script. + * + * By default, Savvy does not compile templates, it uses PHP as the + * markup language, so the "compiled" template is the same as the source + * template. + * + * If a compiler is specific, this method is used to look up the compiled + * template script name + * + * @param string $tpl The template source name to look for. + * + * @return string The full path to the compiled template script. + * + * @throws Savvy_UnexpectedValueException + * @throws Savvy_Exception + * + */ + + public function template($tpl = null) + { + // find the template source. + $file = $this->findTemplateFile($tpl); + + // are we compiling source into a script? + if ($this->__config['compiler']) { + // compile the template source and get the path to the + // compiled script (will be returned instead of the + // source path) + $result = $this->__config['compiler']->compile($file, $this); + } else { + // no compiling requested, use the source path + $result = $file; + } + + // is there a script from the compiler? + if (!$result) { + // return an error, along with any error info + // generated by the compiler. + throw new Savvy_TemplateException('Compiler error for template '.$tpl.'. '.$result ); + + } else { + // no errors, the result is a path to a script + return $result; + } + } + + + // ----------------------------------------------------------------- + // + // Filter management and processing + // + // ----------------------------------------------------------------- + + + /** + * + * Resets the filter stack to the provided list of callbacks. + * + * @access protected + * + * @param array An array of filter callbacks. + * + * @return void + * + */ + + public function setFilters() + { + $this->__config['filters'] = (array) @func_get_args(); + if (!$this->__config['filters']) { + $this->selected_controller = 'basic'; + } else { + $this->selected_controller = 'filter'; + } + } + + + /** + * + * Adds filter callbacks to the stack of filters. + * + * @access protected + * + * @param array An array of filter callbacks. + * + * @return void + * + */ + + public function addFilters() + { + // add the new filters to the static config variable + // via the reference + foreach ((array) @func_get_args() as $callback) { + $this->__config['filters'][] = $callback; + $this->selected_controller = 'filter'; + } + } + + + /** + * + * Runs all filter callbacks on buffered output. + * + * @access protected + * + * @param string The template output. + * + * @return void + * + */ + + public function applyFilters($buffer) + { + foreach ($this->__config['filters'] as $callback) { + $buffer = call_user_func($callback, $buffer); + } + return $buffer; + } + +} diff --git a/lib/php/Savvy/Autoload.php b/lib/php/Savvy/Autoload.php new file mode 100644 index 0000000000000000000000000000000000000000..a3ab8d26f98f01eb3ab0d2833d39d1c3f4342294 --- /dev/null +++ b/lib/php/Savvy/Autoload.php @@ -0,0 +1,139 @@ +<?php +/** +* SplClassLoader implementation that implements the technical interoperability +* standards for PHP 5.3 namespaces and class names. +* +* http://groups.google.com/group/php-standards/web/final-proposal +* +* // Example which loads classes for the Doctrine Common package in the +* // Doctrine\Common namespace. +* $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine'); +* $classLoader->register(); +* +* @author Jonathan H. Wage <jonwage@gmail.com> +* @author Roman S. Borschel <roman@code-factory.org> +* @author Matthew Weier O'Phinney <matthew@zend.com> +* @author Kris Wallsmith <kris.wallsmith@gmail.com> +* @author Fabien Potencier <fabien.potencier@symfony-project.org> +*/ +class Savvy_Autoload +{ + private $_fileExtension = '.php'; + private $_namespace; + private $_includePath; + private $_namespaceSeparator = '\\'; + + /** + * Creates a new <tt>SplClassLoader</tt> that loads classes of the + * specified namespace. + * + * @param string $ns The namespace to use. + */ + public function __construct($ns = null, $includePath = null) + { + $this->_namespace = $ns; + if ($includePath) { + $this->_includePath = $includePath; + } else { + $this->_includePath = dirname(dirname(__FILE__)); + } + } + + /** + * Sets the namespace separator used by classes in the namespace of this class loader. + * + * @param string $sep The separator to use. + */ + public function setNamespaceSeparator($sep) + { + $this->_namespaceSeparator = $sep; + } + + /** + * Gets the namespace seperator used by classes in the namespace of this class loader. + * + * @return void + */ + public function getNamespaceSeparator() + { + return $this->_namespaceSeparator; + } + + /** + * Sets the base include path for all class files in the namespace of this class loader. + * + * @param string $includePath + */ + public function setIncludePath($includePath) + { + $this->_includePath = $includePath; + } + + /** + * Gets the base include path for all class files in the namespace of this class loader. + * + * @return string $includePath + */ + public function getIncludePath() + { + return $this->_includePath; + } + + /** + * Sets the file extension of class files in the namespace of this class loader. + * + * @param string $fileExtension + */ + public function setFileExtension($fileExtension) + { + $this->_fileExtension = $fileExtension; + } + + /** + * Gets the file extension of class files in the namespace of this class loader. + * + * @return string $fileExtension + */ + public function getFileExtension() + { + return $this->_fileExtension; + } + + /** + * Installs this class loader on the SPL autoload stack. + */ + public function register() + { + spl_autoload_register(array($this, 'loadClass')); + } + + /** + * Uninstalls this class loader from the SPL autoloader stack. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $className The name of the class to load. + * @return void + */ + public function loadClass($className) + { + if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) { + $fileName = ''; + $namespace = ''; + if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) { + $namespace = substr($className, 0, $lastNsPos); + $className = substr($className, $lastNsPos + 1); + $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; + } + $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension; + + require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName; + } + } +} diff --git a/lib/php/Savvy/BadMethodCallException.php b/lib/php/Savvy/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..1722ba7194d94435763527461df5e5cdf7983be0 --- /dev/null +++ b/lib/php/Savvy/BadMethodCallException.php @@ -0,0 +1,2 @@ +<?php +class Savvy_BadMethodCallException extends BadMethodCallException implements Savvy_Exception {} \ No newline at end of file diff --git a/lib/php/Savvy/BasicFastCompiler.php b/lib/php/Savvy/BasicFastCompiler.php new file mode 100644 index 0000000000000000000000000000000000000000..227850870c949d83dcc2451922d8f73419fb8479 --- /dev/null +++ b/lib/php/Savvy/BasicFastCompiler.php @@ -0,0 +1,51 @@ +<?php +class Savvy_BasicFastCompiler implements Savvy_FastCompilerInterface +{ + /** + * Directory where compiled templates will be stored + * + * @var string + */ + protected $compiledtemplatedir; + + /** + * Constructor for the BasicFastCompiler + * + * @param string $compiledtemplatedir Where to store compiled templates + * + * @throws UnexpectedValueException + */ + function __construct($compiledtemplatedir) + { + $this->compiledtemplatedir = realpath($compiledtemplatedir); + if (!$this->compiledtemplatedir && !is_writable($this->compiledtemplatedir)) { + throw new Savvy_UnexpectedValueException('Unable to compile templates into ' . + $compiledtemplatedir . ', directory does not exist ' . + 'or is unwritable'); + } + $this->compiledtemplatedir .= DIRECTORY_SEPARATOR; + } + + /** + * Compile a template. + * + * @param string $name Template to compile + * @param Main $savvy Savvy main object + * + * @return string Name of the compiled template file. + */ + function compile($name, $savvy) + { + $cname = $this->compiledtemplatedir . md5($name); + if (file_exists($cname)) { + if (filemtime($name) == filemtime($cname)) { + return $cname; + } + } + $a = file_get_contents($name); + $a = "<?php return '" . str_replace(array('<?php echo', '?>'), array('\' . ', ' . \''), $a) . "';"; + file_put_contents($cname, $a); + touch($cname, filemtime($name)); + return $cname; + } +} \ No newline at end of file diff --git a/lib/php/Savvy/ClassToTemplateMapper.php b/lib/php/Savvy/ClassToTemplateMapper.php new file mode 100644 index 0000000000000000000000000000000000000000..b8d8c92243a26315d452cb537eb83fd5a77cb85a --- /dev/null +++ b/lib/php/Savvy/ClassToTemplateMapper.php @@ -0,0 +1,101 @@ +<?php +/** + * Savvy_ClassToTemplateMapper + * + * PHP version 5 + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @copyright 2010 Brett Bieber + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version SVN: $Id$ + * @link http://svn.php.net/repository/pear2/Savvy + */ + +/** + * Savvy_ClassToTemplateMapper class for Savvy + * + * This class allows class names to be mapped to template names though a simple + * scheme. + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @copyright 2010 Brett Bieber + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @link http://svn.php.net/repository/pear2/Savvy + */ +class Savvy_ClassToTemplateMapper implements Savvy_MapperInterface +{ + /** + * Default template mapping can be temporarily overridden by + * assigning a direct template name. + * + * ClassToTemplateMapper::$output_template['My_Class'] = 'My/Class_rss.tpl.php'; + * + * @var array + */ + static $output_template = array(); + + /** + * What character to use as a directory separator when mapping class names + * to templates. + * + * @var string + */ + static $directory_separator = '_'; + + /** + * Strip something out of class names before mapping them to templates. + * + * This can be useful if your class names are very long, and you don't + * want empty subdirectories within your templates directory. + * + * @var string + */ + static $classname_replacement = ''; + + /** + * The file extension to use + * + * @var string + */ + static $template_extension = '.tpl.php'; + + /** + * Maps class names to template filenames. + * + * Underscores and namespace separators in class names are replaced with + * directory separators. + * + * Examples: + * Class => Class.tpl.php + * Other_Class => Other/Class.tpl.php + * namespace\Class => namespace/Class.tpl.php + * + * @param string $class Class name to map to a template + * + * @return string Template file name + */ + function map($class) + { + if (isset(self::$output_template[$class])) { + $class = self::$output_template[$class]; + } + + $class = str_replace(array(self::$classname_replacement, + self::$directory_separator, + '\\'), + array('', + DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR), + $class); + + $templatefile = $class . self::$template_extension; + + return $templatefile; + } + +} +?> \ No newline at end of file diff --git a/lib/php/Savvy/CompilerException.php b/lib/php/Savvy/CompilerException.php new file mode 100644 index 0000000000000000000000000000000000000000..1489a2b50e41c9ce15011238ad6e19845adebd87 --- /dev/null +++ b/lib/php/Savvy/CompilerException.php @@ -0,0 +1,3 @@ +<?php +class Savvy_CompilerException extends Exception implements Savvy_Exception {} +?> \ No newline at end of file diff --git a/lib/php/Savvy/CompilerInterface.php b/lib/php/Savvy/CompilerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..29b1c07fc472423f4030bb5b1c76d37cd7dce019 --- /dev/null +++ b/lib/php/Savvy/CompilerInterface.php @@ -0,0 +1,6 @@ +<?php + +interface Savvy_CompilerInterface +{ + function compile($savvy, $name); +} \ No newline at end of file diff --git a/lib/php/Savvy/Exception.php b/lib/php/Savvy/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..1aac0b7dc0230c06cd826e2f6c7776d7bccb1c13 --- /dev/null +++ b/lib/php/Savvy/Exception.php @@ -0,0 +1,6 @@ +<?php +interface Savvy_Exception +{ + +} +?> \ No newline at end of file diff --git a/lib/php/Savvy/FastCompilerInterface.php b/lib/php/Savvy/FastCompilerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..49cace38837e0e7a68242673a4ace91d864a479c --- /dev/null +++ b/lib/php/Savvy/FastCompilerInterface.php @@ -0,0 +1,5 @@ +<?php + +interface Savvy_FastCompilerInterface extends Savvy_CompilerInterface +{ +} \ No newline at end of file diff --git a/lib/php/Savvy/FilterAbstract.php b/lib/php/Savvy/FilterAbstract.php new file mode 100644 index 0000000000000000000000000000000000000000..c1a0be689eee13137671356ca51342a4dd324ff7 --- /dev/null +++ b/lib/php/Savvy/FilterAbstract.php @@ -0,0 +1,85 @@ +<?php + +/** +* +* Abstract Savvy_Filter class. +* +* @package Savvy +* +* @author Paul M. Jones <pmjones@ciaweb.net> +* +* @license http://www.gnu.org/copyleft/lesser.html LGPL +* +* @version $Id: Filter.php,v 1.5 2005/04/29 16:23:50 pmjones Exp $ +* +*/ + +/** +* +* Abstract Savvy_Filter class. +* +* You have to extend this class for it to be useful; e.g., "class +* Savvy_Filter_example extends Savvy_Filter". +* +* @package Savvy +* +* @author Paul M. Jones <pmjones@ciaweb.net> +* +*/ +abstract class Savvy_FilterAbstract +{ + + + /** + * + * Optional reference to the calling Savvy object. + * + * @access protected + * + * @var object + * + */ + + protected $savvy = null; + + + /** + * + * Constructor. + * + * @access public + * + * @param array $conf An array of configuration keys and values for + * this filter. + * + * @return void + * + */ + + public function __construct($conf = null) + { + settype($conf, 'array'); + foreach ($conf as $key => $val) { + $this->$key = $val; + } + } + + + /** + * + * Stub method for extended behaviors. + * + * @access public + * + * @param string $text The text buffer to filter. + * + * @return string The text buffer after it has been filtered. + * + */ + + public static function filter($text) + { + return $text; + } +} +?> \ No newline at end of file diff --git a/lib/php/Savvy/MapperInterface.php b/lib/php/Savvy/MapperInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..82d6b86be505a59b5dfff7837cbfbf165fa5ff93 --- /dev/null +++ b/lib/php/Savvy/MapperInterface.php @@ -0,0 +1,6 @@ +<?php + +interface Savvy_MapperInterface +{ + function map($name); +} \ No newline at end of file diff --git a/lib/php/Savvy/ObjectProxy.php b/lib/php/Savvy/ObjectProxy.php new file mode 100644 index 0000000000000000000000000000000000000000..a9803d046327c05357d96e50d43422867273a457 --- /dev/null +++ b/lib/php/Savvy/ObjectProxy.php @@ -0,0 +1,222 @@ +<?php +/** + * Savvy_ObjectProxy + * + * PHP version 5 + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @copyright 2010 Brett Bieber + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version SVN: $Id$ + * @link http://svn.php.net/repository/pear2/Savvy + */ + +/** + * ObjectProxy class for Savvy + * + * The ObjectProxy acts as an intermediary between an object and a template. + * The $context variable will be an ObjectProxy which proxies member variable + * access so escaping can be applied. + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @copyright 2010 Brett Bieber + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @link https://github.com/saltybeagle/Savvy + */ +class Savvy_ObjectProxy implements Countable +{ + /** + * The internal object + * + * @var mixed + */ + protected $object; + + /** + * The savvy templating system + * + * @var Savvy + */ + protected $savvy; + + /** + * Construct a new object proxy + * + * @param mixed $object The object + * @param Main $savvy The savvy templating system + */ + function __construct($object, $savvy) + { + $this->object = $object; + $this->savvy = $savvy; + } + + /** + * Magic method for retrieving data. + * + * String data will be escaped with $savvy->escape() before it is returned + * + * @return mixed + */ + function __get($var) + { + return $this->filterVar($this->object->$var); + } + + /** + * Returns a variable, after it has been filtered. + * + * @param mixed $var + * + * @return string|Savvy_ObjectProxy + */ + protected function filterVar($var) + { + switch(gettype($var)) { + case 'object': + if ($var instanceof ArrayIterator) { + return new Savvy_ObjectProxy_ArrayIterator($var, $this->savvy); + } + if ($var instanceof ArrayAccess) { + return new Savvy_ObjectProxy_ArrayAccess($var, $this->savvy); + } + return self::factory($var, $this->savvy); + case 'string': + case 'int': + case 'double': + return $this->savvy->escape($var); + case 'array': + return new Savvy_ObjectProxy_ArrayObject( + new \ArrayObject($var), + $this->savvy + ); + } + return $var; + } + + /** + * Allows direct access to the entire object for situations where the proxy + * interferes. + * + * @return mixed The raw object + */ + function getRawObject() + { + return $this->object; + } + + /** + * Allows access to the raw member variables of the internal object. + * + * @return mixed + */ + function getRaw($var) + { + return $this->object->$var; + } + + function __set($var, $value) + { + $this->object->$var = $value; + } + + /** + * Magic method for checking if a property is set. + * + * @param string $var The var + * + * @return bool + */ + function __isset($var) + { + return isset($this->object->$var); + } + + /** + * Unset a property. + * + * @param string $var The var + * + * @return void + */ + function __unset($var) + { + unset($this->object->$var); + } + + /** + * Magic method which will call methods on the object. + * + * @return mixed + */ + function __call($name, $arguments) + { + return $this->filterVar( + call_user_func_array( + array($this->object, $name), + $arguments + ) + ); + } + + /** + * Gets the class of the internal object + * + * When using the ClassToTemplateMapper this method will be called to + * determine the class of the object. + * + * @return string + */ + function __getClass() + { + return get_class($this->object); + } + + /** + * Constructs an ObjectProxy for the given object. + * + * @param mixed $object The object to proxy + * @param Main $savvy The main savvy instance + * + * @return Savvy_ObjectProxy + */ + public static function factory($object, $savvy) + { + if ($object instanceof Traversable) { + return new Savvy_ObjectProxy_Traversable($object, $savvy); + } + if ($object instanceof ArrayAccess) { + return new Savvy_ObjectProxy_ArrayAccess($object, $savvy); + } + if ($object instanceof ArrayIterator) { + return new Savvy_ObjectProxy_ArrayIterator($object, $savvy); + } + return new self($object, $savvy); + } + + function __toString() + { + if (method_exists($this->object, '__toString')) { + return $this->savvy->escape($this->object->__toString()); + } + throw new Savvy_BadMethodCallException( + 'Object of class ' . $this->__getClass() + . ' could not be converted to string' + ); + } + + /** + * Returns the number of elements if the object has implemented Countable, + * otherwise 1 is returned. + * + * @return int + */ + function count() + { + return count($this->object); + } +} diff --git a/lib/php/Savvy/ObjectProxy/ArrayAccess.php b/lib/php/Savvy/ObjectProxy/ArrayAccess.php new file mode 100644 index 0000000000000000000000000000000000000000..71109eac757345fd880ed6cfd32bc42f104a11e5 --- /dev/null +++ b/lib/php/Savvy/ObjectProxy/ArrayAccess.php @@ -0,0 +1,23 @@ +<?php +class Savvy_ObjectProxy_ArrayAccess extends Savvy_ObjectProxy implements ArrayAccess +{ + function offsetExists($offset) + { + return $this->object->offsetExists($offset); + } + + function offsetGet($offset) + { + return $this->filterVar($this->object->offsetGet($offset)); + } + + function offsetSet($offset, $value) + { + $this->object->offsetSet($offset, $value); + } + + function offsetUnset($offset) + { + $this->object->offsetUnset($offset); + } +} diff --git a/lib/php/Savvy/ObjectProxy/ArrayIterator.php b/lib/php/Savvy/ObjectProxy/ArrayIterator.php new file mode 100644 index 0000000000000000000000000000000000000000..22e5d12cba785185449f091966ff46b28ffcc7fa --- /dev/null +++ b/lib/php/Savvy/ObjectProxy/ArrayIterator.php @@ -0,0 +1,68 @@ +<?php +class Savvy_ObjectProxy_ArrayIterator extends Savvy_ObjectProxy implements Iterator, ArrayAccess, SeekableIterator, Countable +{ + + /** + * Construct a new object proxy + * + * @param array $array The array + * @param Main $savant The savant templating system + */ + function __construct($array, $savvy) + { + if (!($array instanceof ArrayIterator)) { + $array = new ArrayIterator($array); + } + parent::__construct($array, $savvy); + } + + function current() + { + return $this->filterVar($this->object->current()); + } + + function next() + { + return $this->object->next(); + } + + function key() + { + return $this->filterVar($this->object->key()); + } + + function valid() + { + return $this->object->valid(); + } + + function rewind() + { + return $this->object->rewind(); + } + + function seek($offset) + { + return $this->object->seek($offset); + } + + function offsetExists($offset) + { + return $this->object->offsetExists($offset); + } + + function offsetGet($offset) + { + return $this->filterVar($this->object->offsetGet($offset)); + } + + function offsetSet($offset, $value) + { + $this->object->offsetSet($offset, $value); + } + + function offsetUnset($offset) + { + $this->object->offsetUnset($offset); + } +} diff --git a/lib/php/Savvy/ObjectProxy/ArrayObject.php b/lib/php/Savvy/ObjectProxy/ArrayObject.php new file mode 100644 index 0000000000000000000000000000000000000000..f4792639176656b9b9c28af10cbd5745d790e7a6 --- /dev/null +++ b/lib/php/Savvy/ObjectProxy/ArrayObject.php @@ -0,0 +1,82 @@ +<?php + +/** + * Savvy_ObjectProxy_ArrayObject + * + * PHP version 5 + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @author Michael Gauthier <mike@silverorange.com> + * @copyright 2009 Brett Bieber, 2011 Michael Gauthier + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version SVN: $Id$ + * @link https://github.com/saltybeagle/Savvy + */ + +/** + * Proxies ArrayObject objects + * + * Filters on array access or on traversal. + * + * @category Templates + * @package Savvy + * @author Brett Bieber <saltybeagle@php.net> + * @author Michael Gauthier <mike@silverorange.com> + * @copyright 2009 Brett Bieber, 2011 Michael Gauthier + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @link https://github.com/saltybeagle/Savvy + */ +class Savvy_ObjectProxy_ArrayObject + extends Savvy_ObjectProxy_ArrayAccess + implements ArrayAccess, Countable, Serializable, IteratorAggregate +{ + public function getIterator() + { + return $this->object->getIterator(); + } + + public function next() + { + $this->object->next(); + } + + public function key() + { + return $this->filterVar($this->object->key()); + } + + public function valid() + { + return $this->object->valid(); + } + + public function rewind() + { + $this->object->rewind(); + } + + public function current() + { + return $this->filterVar($this->object->current()); + } + + public function count() + { + return count($this->object); + } + + public function serialize() + { + return serialize($this->object); + } + + public function unserialize($string) + { + $object = unserialize($string); + if ($object !== false) { + $this->object = $object; + } + } +} diff --git a/lib/php/Savvy/ObjectProxy/Traversable.php b/lib/php/Savvy/ObjectProxy/Traversable.php new file mode 100644 index 0000000000000000000000000000000000000000..56c7608c4b28a937bc6401d2bc1f417c5891a8db --- /dev/null +++ b/lib/php/Savvy/ObjectProxy/Traversable.php @@ -0,0 +1,34 @@ +<?php +class Savvy_ObjectProxy_Traversable extends Savvy_ObjectProxy implements Iterator +{ + + function getIterator() + { + return $this->object; + } + + function next() + { + $this->object->next(); + } + + function key() + { + return $this->object->key(); + } + + function valid() + { + return $this->object->valid(); + } + + function rewind() + { + $this->object->rewind(); + } + + function current() + { + return $this->filterVar($this->object->current()); + } +} \ No newline at end of file diff --git a/lib/php/Savvy/TemplateException.php b/lib/php/Savvy/TemplateException.php new file mode 100644 index 0000000000000000000000000000000000000000..fb44d2e8ae6fd96ae8625e250354a1f5390db0d7 --- /dev/null +++ b/lib/php/Savvy/TemplateException.php @@ -0,0 +1,3 @@ +<?php +class Savvy_TemplateException extends Exception implements Savvy_Exception {} +?> \ No newline at end of file diff --git a/lib/php/Savvy/UnexpectedValueException.php b/lib/php/Savvy/UnexpectedValueException.php new file mode 100644 index 0000000000000000000000000000000000000000..c8c0174a0f08d6070b57ba47c0b2cf259273c14d --- /dev/null +++ b/lib/php/Savvy/UnexpectedValueException.php @@ -0,0 +1,5 @@ +<?php +class Savvy_UnexpectedValueException extends UnexpectedValueException implements Savvy_Exception +{ + +} diff --git a/lib/tests/phpsavant.com/Savvy/escape/Foo.tpl.php b/lib/tests/phpsavant.com/Savvy/escape/Foo.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..48c5e528a1ec7f8ea2671d3ed73c003995b00679 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/escape/Foo.tpl.php @@ -0,0 +1,3 @@ +<?php +echo $context->var1; +?> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/escape/echostring.tpl.php b/lib/tests/phpsavant.com/Savvy/escape/echostring.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..7833ffb8b27e6b43e4c282ce4ca7a951b86f7fd7 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/escape/echostring.tpl.php @@ -0,0 +1,3 @@ +<?php +echo $context; +?> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/escape/object.phpt b/lib/tests/phpsavant.com/Savvy/escape/object.phpt new file mode 100644 index 0000000000000000000000000000000000000000..f0e37efac8112e330b1a3a4ec70c9512aa4b5bd9 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/escape/object.phpt @@ -0,0 +1,24 @@ +--TEST-- +Savvy::addEscape() object variable escaping test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); +$savvy->setEscape('htmlspecialchars'); + +class Foo +{ + public $var1; +} + +$object = new Foo(); +$object->var1 = '<p></p>'; + +$test->assertEquals(htmlspecialchars($object->var1), $savvy->render($object), 'render object with variable escaping'); + +$test->assertEquals($object->var1, $savvy->render($object, 'raw.tpl.php'), 'render object with raw variable access'); +?> +===DONE=== +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/escape/raw.tpl.php b/lib/tests/phpsavant.com/Savvy/escape/raw.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..d020c83bbf9158afb2adbb27eb84ab735461d279 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/escape/raw.tpl.php @@ -0,0 +1,3 @@ +<?php +echo $context->getRaw('var1'); +?> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/escape/string.phpt b/lib/tests/phpsavant.com/Savvy/escape/string.phpt new file mode 100644 index 0000000000000000000000000000000000000000..80abcc09c3aabc0d6d49d201566be30c4a6e1c68 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/escape/string.phpt @@ -0,0 +1,19 @@ +--TEST-- +Savvy::render() string with addEscape() test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); +$savvy->setEscape('htmlspecialchars'); + +$string = 'test'; +$test->assertEquals($string, $savvy->escape($string), 'render'); + +$string = '<p></p>'; +$test->assertEquals(htmlspecialchars($string), $savvy->escape($string), 'render string with special chars'); + +?> +===DONE=== +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/globals/basic.phpt b/lib/tests/phpsavant.com/Savvy/globals/basic.phpt new file mode 100644 index 0000000000000000000000000000000000000000..2cb2f6cef3507a8a65cf83f332ac1d2cae43f3c4 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/globals/basic.phpt @@ -0,0 +1,15 @@ +--TEST-- +Savvy::addGlobal() basic test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +$savvy->addGlobal('foo', true); + +echo $savvy->render(null, 'basic.tpl.php'); + +?> +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/globals/basic.tpl.php b/lib/tests/phpsavant.com/Savvy/globals/basic.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..5df37bdc279a53291d1adecf40b3cd4da930d011 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/globals/basic.tpl.php @@ -0,0 +1,6 @@ +<?php + if (isset($foo) + && true === $foo) { + echo '===DONE==='; + } +?> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/globals/escape.arrays.phpt b/lib/tests/phpsavant.com/Savvy/globals/escape.arrays.phpt new file mode 100644 index 0000000000000000000000000000000000000000..a34ac672c8a260f0cae8d4da1eb8492af8464f4e --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/globals/escape.arrays.phpt @@ -0,0 +1,23 @@ +--TEST-- +Savvy::addGlobal() Escape added global array +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +$savvy->setEscape('htmlspecialchars'); + +$unescaped = array( + '<a href="Blah">Blah</a>' +); + +$savvy->addGlobal('foo', $unescaped); + +$escaped = $savvy->getGlobals(); + +echo $escaped['foo'][0]; + +?> +--EXPECT-- +<a href="Blah">Blah</a> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/globals/escape.nestedarrays.phpt b/lib/tests/phpsavant.com/Savvy/globals/escape.nestedarrays.phpt new file mode 100644 index 0000000000000000000000000000000000000000..b50b6528d84300c92cdb46838883844579f596ae --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/globals/escape.nestedarrays.phpt @@ -0,0 +1,23 @@ +--TEST-- +Savvy::addGlobal() Escape added global array +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +$savvy->setEscape('htmlspecialchars'); + +$unescaped = array( + '<a href="Blah">Blah</a>' +); + +$savvy->addGlobal('foo', array($unescaped)); + +$escaped = $savvy->getGlobals(); + +echo $escaped['foo'][0][0]; + +?> +--EXPECT-- +<a href="Blah">Blah</a> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/globals/escape.phpt b/lib/tests/phpsavant.com/Savvy/globals/escape.phpt new file mode 100644 index 0000000000000000000000000000000000000000..c8190bc2222cd30a0efe62051c3e24cdaa1dedfc --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/globals/escape.phpt @@ -0,0 +1,21 @@ +--TEST-- +Savvy::addGlobal() Escape added globals test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +function myEscape($var) +{ + echo '===DONE==='; + return $var; +} + +$savvy->setEscape('myEscape'); + +$savvy->addGlobal('foo', 'lalalala'); + +?> +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/render/Foo.tpl.php b/lib/tests/phpsavant.com/Savvy/render/Foo.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..83c9b5f0f2bc819bf1028d81dbfc98dc95dd9f32 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/render/Foo.tpl.php @@ -0,0 +1,2 @@ +<?php echo get_class($context) ?> +<?php echo $context->var1 ?> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/render/array.phpt b/lib/tests/phpsavant.com/Savvy/render/array.phpt new file mode 100644 index 0000000000000000000000000000000000000000..a049a9330242f049725daa353904709cb43c99c2 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/render/array.phpt @@ -0,0 +1,18 @@ +--TEST-- +Savvy::render() array test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +$array = array(1,2,3); +$test->assertEquals('123', $savvy->render($array), 'render array'); + +$array = array(1,2,3); +$test->assertEquals('123', $savvy->render($array, 'echostring.tpl.php'), 'render array through custom template'); + +?> +===DONE=== +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/render/echostring.tpl.php b/lib/tests/phpsavant.com/Savvy/render/echostring.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..8bad12826e19a8978bbef856df16e7091b42d332 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/render/echostring.tpl.php @@ -0,0 +1 @@ +<?php echo $context ?> \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/render/fastcompile.phpt b/lib/tests/phpsavant.com/Savvy/render/fastcompile.phpt new file mode 100644 index 0000000000000000000000000000000000000000..1025ef2a17050768190e058393d3ff0f099d0e21 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/render/fastcompile.phpt @@ -0,0 +1,49 @@ +--TEST-- +Savvy::render() fast compiler test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +class Foo +{ + public $var1; + function __toString() + { + return 'test'; + } +} + +$object = new Foo(); +$object->var1 = ' is my class'; + +$savvy->setEscape(); +mkdir(__DIR__ . '/compiled'); +$compiler = new Savvy_BasicFastCompiler(__DIR__ . DIRECTORY_SEPARATOR . 'compiled'); +$savvy->setCompiler($compiler); + +$test->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR . + md5('.' . DIRECTORY_SEPARATOR . 'Foo.tpl.php'), $savvy->template('Foo.tpl.php'), + 'verify compiler is called'); +$test->assertEquals("<?php return '' . get_class(\$context) . ' +' . \$context->var1 . '';", file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR . + md5('.' . DIRECTORY_SEPARATOR . 'Foo.tpl.php')), 'compiled template'); + +$test->assertEquals('Foo is my class', $savvy->render($object), 'render object'); + +$test->assertEquals('test', $savvy->render($object, 'echostring.tpl.php'), 'render object with custom template'); + +?> +===DONE=== +--CLEAN-- +<?php +$a = opendir(__DIR__ . '/compiled'); +while (false !== ($b = readdir($a))) { + if (is_dir(__DIR__ . '/compiled/' . $b)) continue; + unlink(__DIR__ . '/compiled/' . $b); +} +rmdir(__DIR__ . '/compiled'); +?> +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/render/object.phpt b/lib/tests/phpsavant.com/Savvy/render/object.phpt new file mode 100644 index 0000000000000000000000000000000000000000..d7d11d5abb75d4e890cb27e405ab4983c65b7338 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/render/object.phpt @@ -0,0 +1,30 @@ +--TEST-- +Savvy::render() object test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); + +class Foo +{ + public $var1; + function __toString() + { + return 'test'; + } +} + +$object = new Foo(); +$object->var1 = ' is my class'; + +$savvy->setEscape(); + +$test->assertEquals('Foo is my class', $savvy->render($object), 'render object'); + +$test->assertEquals('test', $savvy->render($object, 'echostring.tpl.php'), 'render object with custom template'); + +?> +===DONE=== +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/render/string.phpt b/lib/tests/phpsavant.com/Savvy/render/string.phpt new file mode 100644 index 0000000000000000000000000000000000000000..1fee2313cd0afd9630547cfd7509061e20943630 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/render/string.phpt @@ -0,0 +1,24 @@ +--TEST-- +Savvy::render() string test +--FILE-- +<?php +require dirname(__FILE__) . '/../test_framework.php.inc'; +chdir(__DIR__); +$savvy = new Savvy(); +$savvy->setEscape('htmlspecialchars'); + +$string = 'test'; +$test->assertEquals($string, $savvy->render($string), 'render'); + +$string = '<p></p>'; +$test->assertEquals(htmlspecialchars($string), $savvy->render($string), 'render string with special chars'); + +$string = 'test'; +$test->assertEquals($string, $savvy->render($string, 'echostring.tpl.php'), 'render string through template'); + +$string = '<p></p>'; +$test->assertEquals(htmlspecialchars($string), $savvy->render($string, 'echostring.tpl.php'), 'render string with special chars through template'); +?> +===DONE=== +--EXPECT-- +===DONE=== \ No newline at end of file diff --git a/lib/tests/phpsavant.com/Savvy/test_framework.php.inc b/lib/tests/phpsavant.com/Savvy/test_framework.php.inc new file mode 100644 index 0000000000000000000000000000000000000000..c072c9d6ec1f6eae23de09a5a6b7fa915389b714 --- /dev/null +++ b/lib/tests/phpsavant.com/Savvy/test_framework.php.inc @@ -0,0 +1,212 @@ +<?php +$__e = error_reporting(); +error_reporting(E_ERROR|E_NOTICE|E_WARNING); +require_once dirname(__FILE__) . '/../src/Savvy/Autoload.php'; +$classLoader = new Savvy_Autoload(); +$classLoader->register(); +@include_once 'Text/Diff.php'; +@include_once 'Text/Diff/Renderer.php'; +@include_once 'Text/Diff/Renderer/unified.php'; +error_reporting($__e); +class PEAR2_PHPT +{ + var $_diffonly; + function __construct($diffonly = false) + { + $this->_diffonly = $diffonly; + $this->_errors = array(); + } + + function assertTrue($test, $message) + { + if ($test === true) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-true value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertIsa($control, $test, $message) + { + if (is_a($test, $control)) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-$control object: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNull($test, $message) + { + if ($test === null) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-null value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNotNull($test, $message) + { + if ($test !== null) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected null: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertSame($test, $test1, $message) + { + if ($test === $test1) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpectedly two vars are not the same thing: \n"; + echo "\n'$message'\n"; + return false; + } + + function assertNotSame($test, $test1, $message) + { + if ($test !== $test1) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpectedly two vars are the same thing: \n"; + echo "\n'$message'\n"; + return false; + } + + function assertFalse($test, $message) + { + if ($test === false) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected non-false value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNotTrue($test, $message) + { + if (!$test) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected loose true value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertNotFalse($test, $message) + { + if ($test) { + return true; + } + $this->_failTest(debug_backtrace(), $message); + echo "Unexpected loose false value: \n"; + var_export($test); + echo "\n'$message'\n"; + return false; + } + + function assertRegex($regex, $test, $message) + { + if (!preg_match($regex, $test)) { + $this->_failTest(debug_backtrace(), $message); + echo "Expecting:\nText Matching Regular Expression $regex\n"; + echo "\nReceived:\n"; + var_export($test); + echo "\n"; + return false; + } + return true; + } + + function assertException($exception, $class, $emessage, $message) + { + if (!($exception instanceof $class)) { + $this->_failTest(debug_backtrace(), $message); + echo "Expecting class $class, got ", get_class($exception); + } + $this->assertEquals($emessage, $exception->getMessage(), $message, debug_backtrace()); + } + + function assertEquals($control, $test, $message, $trace = null) + { + if (!$trace) { + $trace = debug_backtrace(); + } + if (str_replace(array("\r", "\n"), array('', ''), + var_export($control, true)) != str_replace(array("\r", "\n"), array('', ''), + var_export($test, true))) { + $this->_failTest($trace, $message); + if (class_exists('Text_Diff', false)) { + echo "Diff of expecting/received:\n"; + $diff = new Text_Diff( + explode("\n", var_export($control, true)), + explode("\n", var_export($test, true))); + + // Output the diff in unified format. + $renderer = new Text_Diff_Renderer_unified(); + echo $renderer->render($diff); + if ($this->_diffonly) { + return false; + } + } + echo "Expecting:\n"; + var_export($control); + echo "\nReceived:\n"; + var_export($test); + echo "\n"; + return false; + } + return true; + } + + function assertFileExists($fname, $message) + { + if (!@file_exists($fname)) { + $this->_failTest(debug_backtrace(), $message); + echo "File '$fname' does not exist, and should\n"; + return false; + } + return true; + } + + function assertFileNotExists($fname, $message) + { + if (@file_exists($fname)) { + $this->_failTest(debug_backtrace(), $message); + echo "File '$fname' exists, and should not\n"; + return false; + } + return true; + } + + function _failTest($trace, $message) + { + echo 'Test Failure: "' . $message . "\"\n in " . $trace[0]['file'] . ' line ' . + $trace[0]['line'] . "\n"; + } + + function showAll() + { + $this->_diffonly = false; + } +} +$test = new PEAR2_PHPT(); +?>