Add Helper implementation.
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Mustache.php.
|
||||
*
|
||||
* (c) 2012 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Mustache;
|
||||
|
||||
/**
|
||||
* A collection of helpers for a Mustache instance.
|
||||
*/
|
||||
class HelperCollection {
|
||||
private $helpers = array();
|
||||
|
||||
/**
|
||||
* Helper Collection constructor.
|
||||
*
|
||||
* Optionally accepts an array (or \Traversable) of `$name => $helper` pairs.
|
||||
*
|
||||
* @throws \InvalidArgumentException if the $helpers argument isn't an array or \Traversable
|
||||
*
|
||||
* @param array|Traversable $helpers (default: null)
|
||||
*/
|
||||
public function __construct($helpers = null) {
|
||||
if ($helpers !== null) {
|
||||
if (!is_array($helpers) && !$helpers instanceof \Traversable) {
|
||||
throw new \InvalidArgumentException('HelperCollection constructor expects an array of helpers');
|
||||
}
|
||||
|
||||
foreach ($helpers as $name => $helper) {
|
||||
$this->add($name, $helper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic mutator.
|
||||
*
|
||||
* @see \Mustache\HelperCollection::add
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $helper
|
||||
*/
|
||||
public function __set($name, $helper) {
|
||||
$this->add($name, $helper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a helper to this collection.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $helper
|
||||
*/
|
||||
public function add($name, $helper) {
|
||||
$this->helpers[$name] = $helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic accessor.
|
||||
*
|
||||
* @see \Mustache\HelperCollection::get
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed Helper
|
||||
*/
|
||||
public function __get($name) {
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a helper by name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed Helper
|
||||
*/
|
||||
public function get($name) {
|
||||
if (!$this->has($name)) {
|
||||
throw new \InvalidArgumentException('Unknown helper: '.$name);
|
||||
}
|
||||
|
||||
return $this->helpers[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset().
|
||||
*
|
||||
* @see \Mustache\HelperCollection::has
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return boolean True if helper is present
|
||||
*/
|
||||
public function __isset($name) {
|
||||
return $this->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given helper is present in the collection.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return boolean True if helper is present
|
||||
*/
|
||||
public function has($name) {
|
||||
return array_key_exists($name, $this->helpers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic unset().
|
||||
*
|
||||
* @see \Mustache\HelperCollection::remove
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function __unset($name) {
|
||||
$this->remove($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given helper is present in the collection.
|
||||
*
|
||||
* @throws \InvalidArgumentException if the requested helper is not present.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function remove($name) {
|
||||
if (!$this->has($name)) {
|
||||
throw new \InvalidArgumentException('Unknown helper: '.$name);
|
||||
}
|
||||
|
||||
unset($this->helpers[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the helper collection.
|
||||
*
|
||||
* Removes all helpers from this collection
|
||||
*/
|
||||
public function clear() {
|
||||
$this->helpers = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the helper collection is empty.
|
||||
*
|
||||
* @return boolean True if the collection is empty
|
||||
*/
|
||||
public function isEmpty() {
|
||||
return empty($this->helpers);
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ class Mustache {
|
||||
private $cache = null;
|
||||
private $loader;
|
||||
private $partialsLoader;
|
||||
private $helpers;
|
||||
private $charset = 'UTF-8';
|
||||
|
||||
/**
|
||||
@@ -63,6 +64,13 @@ class Mustache {
|
||||
* // efficient or lazy as a Filesystem (or database) loader.
|
||||
* 'partials' => array('foo' => file_get_contents(__DIR__.'/views/partials/foo.mustache')),
|
||||
*
|
||||
* // An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order
|
||||
* // sections), or any other valid Mustache context value. They will be prepended to the context stack,
|
||||
* // so they will be available in any template loaded by this Mustache instance.
|
||||
* 'helpers' => array('i18n' => function($text) {
|
||||
* // do something translatey here...
|
||||
* }),
|
||||
*
|
||||
* // character set for `htmlspecialchars`. Defaults to 'UTF-8'
|
||||
* 'charset' => 'ISO-8859-1',
|
||||
* );
|
||||
@@ -90,6 +98,10 @@ class Mustache {
|
||||
$this->setPartials($options['partials']);
|
||||
}
|
||||
|
||||
if (isset($options['helpers'])) {
|
||||
$this->setHelpers($options['helpers']);
|
||||
}
|
||||
|
||||
if (isset($options['charset'])) {
|
||||
$this->charset = $options['charset'];
|
||||
}
|
||||
@@ -187,6 +199,93 @@ class Mustache {
|
||||
$loader->setTemplates($partials);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array of Mustache helpers.
|
||||
*
|
||||
* An array of 'helpers'. Helpers can be global variables or objects, closures (e.g. for higher order sections), or
|
||||
* any other valid Mustache context value. They will be prepended to the context stack, so they will be available in
|
||||
* any template loaded by this Mustache instance.
|
||||
*
|
||||
* @throws \InvalidArgumentException if $helpers is not an array or \Traversable
|
||||
*
|
||||
* @param array|Traversable $helpers
|
||||
*/
|
||||
public function setHelpers($helpers) {
|
||||
if (!is_array($helpers) && !$helpers instanceof \Traversable) {
|
||||
throw new \InvalidArgumentException('setHelpers expects an array of helpers');
|
||||
}
|
||||
|
||||
$this->getHelpers()->clear();
|
||||
|
||||
foreach ($helpers as $name => $helper) {
|
||||
$this->addHelper($name, $helper);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current set of Mustache helpers.
|
||||
*
|
||||
* @see \Mustache\Mustache::setHelpers
|
||||
*
|
||||
* @return \Mustache\HelperCollection
|
||||
*/
|
||||
public function getHelpers() {
|
||||
if (!isset($this->helpers)) {
|
||||
$this->helpers = new HelperCollection;
|
||||
}
|
||||
|
||||
return $this->helpers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Mustache helper.
|
||||
*
|
||||
* @see \Mustache\Mustache::setHelpers
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $helper
|
||||
*/
|
||||
public function addHelper($name, $helper) {
|
||||
$this->getHelpers()->add($name, $helper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Mustache helper by name.
|
||||
*
|
||||
* @see \Mustache\Mustache::setHelpers
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed Helper
|
||||
*/
|
||||
public function getHelper($name) {
|
||||
return $this->getHelpers()->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this Mustache instance has a helper.
|
||||
*
|
||||
* @see \Mustache\Mustache::setHelpers
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return boolean True if the helper is present
|
||||
*/
|
||||
public function hasHelper($name) {
|
||||
return $this->getHelpers()->has($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a helper by name.
|
||||
*
|
||||
* @see \Mustache\Mustache::setHelpers
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function removeHelper($name) {
|
||||
$this->getHelpers()->remove($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Mustache Tokenizer instance.
|
||||
*
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class Template {
|
||||
* @return string Rendered template
|
||||
*/
|
||||
public function render($context = array()) {
|
||||
return $this->renderInternal(new Context($context));
|
||||
return $this->renderInternal($this->prepareContextStack($context));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,4 +119,27 @@ abstract class Template {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to prepare the Context stack.
|
||||
*
|
||||
* Adds the Mustache HelperCollection to the stack's top context frame if helpers are present.
|
||||
*
|
||||
* @param mixed $context Optional first context frame (default: null)
|
||||
*
|
||||
* @return \Mustache\Context
|
||||
*/
|
||||
protected function prepareContextStack($context = null) {
|
||||
$stack = new Context;
|
||||
|
||||
$helpers = $this->mustache->getHelpers();
|
||||
if (!$helpers->isEmpty()) {
|
||||
$stack->push($helpers);
|
||||
}
|
||||
|
||||
if (!empty($context)) {
|
||||
$stack->push($context);
|
||||
}
|
||||
|
||||
return $stack;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Mustache.php.
|
||||
*
|
||||
* (c) 2012 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Mustache\Test;
|
||||
|
||||
use Mustache\HelperCollection;
|
||||
|
||||
class HelperCollectionTest extends \PHPUnit_Framework_TestCase {
|
||||
public function testConstructor() {
|
||||
$foo = function() { echo 'foo'; };
|
||||
$bar = 'BAR';
|
||||
|
||||
$helpers = new HelperCollection(array(
|
||||
'foo' => $foo,
|
||||
'bar' => $bar,
|
||||
));
|
||||
|
||||
$this->assertSame($foo, $helpers->get('foo'));
|
||||
$this->assertSame($bar, $helpers->get('bar'));
|
||||
}
|
||||
|
||||
public function testAccessorsAndMutators() {
|
||||
$foo = function() { echo 'foo'; };
|
||||
$bar = 'BAR';
|
||||
|
||||
$helpers = new HelperCollection;
|
||||
$this->assertTrue($helpers->isEmpty());
|
||||
$this->assertFalse($helpers->has('foo'));
|
||||
$this->assertFalse($helpers->has('bar'));
|
||||
|
||||
$helpers->add('foo', $foo);
|
||||
$this->assertFalse($helpers->isEmpty());
|
||||
$this->assertTrue($helpers->has('foo'));
|
||||
$this->assertFalse($helpers->has('bar'));
|
||||
|
||||
$helpers->add('bar', $bar);
|
||||
$this->assertFalse($helpers->isEmpty());
|
||||
$this->assertTrue($helpers->has('foo'));
|
||||
$this->assertTrue($helpers->has('bar'));
|
||||
|
||||
$helpers->remove('foo');
|
||||
$this->assertFalse($helpers->isEmpty());
|
||||
$this->assertFalse($helpers->has('foo'));
|
||||
$this->assertTrue($helpers->has('bar'));
|
||||
}
|
||||
|
||||
public function testMagicMethods() {
|
||||
$foo = function() { echo 'foo'; };
|
||||
$bar = 'BAR';
|
||||
|
||||
$helpers = new HelperCollection;
|
||||
$this->assertTrue($helpers->isEmpty());
|
||||
$this->assertFalse($helpers->has('foo'));
|
||||
$this->assertFalse($helpers->has('bar'));
|
||||
$this->assertFalse(isset($helpers->foo));
|
||||
$this->assertFalse(isset($helpers->bar));
|
||||
|
||||
$helpers->foo = $foo;
|
||||
$this->assertFalse($helpers->isEmpty());
|
||||
$this->assertTrue($helpers->has('foo'));
|
||||
$this->assertFalse($helpers->has('bar'));
|
||||
$this->assertTrue(isset($helpers->foo));
|
||||
$this->assertFalse(isset($helpers->bar));
|
||||
|
||||
$helpers->bar = $bar;
|
||||
$this->assertFalse($helpers->isEmpty());
|
||||
$this->assertTrue($helpers->has('foo'));
|
||||
$this->assertTrue($helpers->has('bar'));
|
||||
$this->assertTrue(isset($helpers->foo));
|
||||
$this->assertTrue(isset($helpers->bar));
|
||||
|
||||
unset($helpers->foo);
|
||||
$this->assertFalse($helpers->isEmpty());
|
||||
$this->assertFalse($helpers->has('foo'));
|
||||
$this->assertTrue($helpers->has('bar'));
|
||||
$this->assertFalse(isset($helpers->foo));
|
||||
$this->assertTrue(isset($helpers->bar));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getInvalidHelperArguments
|
||||
*/
|
||||
public function testHelperCollectionIsntAfraidToThrowExceptions($helpers = array(), $actions = array(), $exception = null) {
|
||||
if ($exception) {
|
||||
$this->setExpectedException($exception);
|
||||
}
|
||||
|
||||
$helpers = new HelperCollection($helpers);
|
||||
|
||||
foreach ($actions as $method => $args) {
|
||||
call_user_func_array(array($helpers, $method), $args);
|
||||
}
|
||||
}
|
||||
|
||||
public function getInvalidHelperArguments() {
|
||||
return array(
|
||||
array(
|
||||
'not helpers',
|
||||
array(),
|
||||
'\InvalidArgumentException',
|
||||
),
|
||||
array(
|
||||
array(),
|
||||
array('get' => array('foo')),
|
||||
'\InvalidArgumentException',
|
||||
),
|
||||
array(
|
||||
array('foo' => 'FOO'),
|
||||
array('get' => array('foo')),
|
||||
null,
|
||||
),
|
||||
array(
|
||||
array('foo' => 'FOO'),
|
||||
array('get' => array('bar')),
|
||||
'\InvalidArgumentException',
|
||||
),
|
||||
array(
|
||||
array('foo' => 'FOO'),
|
||||
array(
|
||||
'add' => array('bar', 'BAR'),
|
||||
'get' => array('bar'),
|
||||
),
|
||||
null,
|
||||
),
|
||||
array(
|
||||
array('foo' => 'FOO'),
|
||||
array(
|
||||
'get' => array('foo'),
|
||||
'remove' => array('foo'),
|
||||
),
|
||||
null,
|
||||
),
|
||||
array(
|
||||
array('foo' => 'FOO'),
|
||||
array(
|
||||
'remove' => array('foo'),
|
||||
'get' => array('foo'),
|
||||
),
|
||||
'\InvalidArgumentException',
|
||||
),
|
||||
array(
|
||||
array(),
|
||||
array('remove' => array('foo')),
|
||||
'\InvalidArgumentException',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,10 @@ class MustacheTest extends \PHPUnit_Framework_TestCase {
|
||||
'partials' => array(
|
||||
'foo' => '{{ foo }}',
|
||||
),
|
||||
'helpers' => array(
|
||||
'foo' => function() { return 'foo'; },
|
||||
'bar' => 'BAR',
|
||||
),
|
||||
'charset' => 'ISO-8859-1',
|
||||
));
|
||||
|
||||
@@ -51,6 +55,9 @@ class MustacheTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
|
||||
$this->assertContains('__whot__', $mustache->getTemplateClassName('{{ foo }}'));
|
||||
$this->assertEquals('ISO-8859-1', $mustache->getCharset());
|
||||
$this->assertTrue($mustache->hasHelper('foo'));
|
||||
$this->assertTrue($mustache->hasHelper('bar'));
|
||||
$this->assertFalse($mustache->hasHelper('baz'));
|
||||
}
|
||||
|
||||
public function testRender() {
|
||||
@@ -144,6 +151,49 @@ class MustacheTest extends \PHPUnit_Framework_TestCase {
|
||||
$mustache->setPartials(array('foo' => '{{ foo }}'));
|
||||
}
|
||||
|
||||
public function testHelpers() {
|
||||
$foo = function() { return 'foo'; };
|
||||
$bar = 'BAR';
|
||||
$mustache = new Mustache(array('helpers' => array(
|
||||
'foo' => $foo,
|
||||
'bar' => $bar,
|
||||
)));
|
||||
|
||||
$helpers = $mustache->getHelpers();
|
||||
$this->assertTrue($mustache->hasHelper('foo'));
|
||||
$this->assertTrue($mustache->hasHelper('bar'));
|
||||
$this->assertTrue($helpers->has('foo'));
|
||||
$this->assertTrue($helpers->has('bar'));
|
||||
$this->assertSame($foo, $mustache->getHelper('foo'));
|
||||
$this->assertSame($bar, $mustache->getHelper('bar'));
|
||||
|
||||
$mustache->removeHelper('bar');
|
||||
$this->assertFalse($mustache->hasHelper('bar'));
|
||||
$mustache->addHelper('bar', $bar);
|
||||
$this->assertSame($bar, $mustache->getHelper('bar'));
|
||||
|
||||
$baz = function($text) { return '__'.$text.'__'; };
|
||||
$this->assertFalse($mustache->hasHelper('baz'));
|
||||
$this->assertFalse($helpers->has('baz'));
|
||||
|
||||
$mustache->addHelper('baz', $baz);
|
||||
$this->assertTrue($mustache->hasHelper('baz'));
|
||||
$this->assertTrue($helpers->has('baz'));
|
||||
|
||||
// ... and a functional test
|
||||
$tpl = $mustache->loadTemplate('{{foo}} - {{bar}} - {{#baz}}qux{{/baz}}');
|
||||
$this->assertEquals('foo - BAR - __qux__', $tpl->render());
|
||||
$this->assertEquals('foo - BAR - __qux__', $tpl->render(array('qux' => "won't mess things up")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testSetHelpersThrowsExceptions() {
|
||||
$mustache = new Mustache;
|
||||
$mustache->setHelpers('monkeymonkeymonkey');
|
||||
}
|
||||
|
||||
private static function rmdir($path) {
|
||||
$path = rtrim($path, '/').'/';
|
||||
$handle = opendir($path);
|
||||
|
||||
Reference in New Issue
Block a user