Inline isCallable and isTruthy into compiled templates
~3-5% performance gain.
This commit is contained in:
@@ -140,14 +140,14 @@ class Compiler {
|
||||
|
||||
const SECTION = '
|
||||
private function section%s(\Mustache\Buffer $buffer, \Mustache\Context $context, $value) {
|
||||
if ($context->isCallable($value)) {
|
||||
if (!is_string($value) && is_callable($value)) {
|
||||
$source = %s;
|
||||
$buffer->write(
|
||||
$this->mustache
|
||||
->loadLambda((string) call_user_func($value, $source)%s)
|
||||
->renderInternal($context, $buffer->getIndent())
|
||||
);
|
||||
} elseif ($context->isTruthy($value)) {
|
||||
} elseif (!empty($value)) {
|
||||
$values = $context->isIterable($value) ? $value : array($value);
|
||||
foreach ($values as $value) {
|
||||
$context->push($value);%s
|
||||
@@ -191,7 +191,8 @@ class Compiler {
|
||||
|
||||
const INVERTED_SECTION = '
|
||||
// %s inverted section
|
||||
if (!$context->isTruthy($context->%s(%s))) {
|
||||
$value = $context->%s(%s);
|
||||
if (empty($value)) {
|
||||
%s
|
||||
}';
|
||||
|
||||
@@ -232,7 +233,7 @@ class Compiler {
|
||||
|
||||
const VARIABLE = '
|
||||
$value = $context->%s(%s);
|
||||
if ($context->isCallable($value)) {
|
||||
if (!is_string($value) && is_callable($value)) {
|
||||
$value = $this->mustache
|
||||
->loadLambda((string) call_user_func($value))
|
||||
->renderInternal($context, $buffer->getIndent());
|
||||
|
||||
@@ -28,36 +28,6 @@ class Context {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to test whether a value is 'truthy'.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return boolean True if the value is 'truthy'
|
||||
*/
|
||||
public function isTruthy($value) {
|
||||
return !empty($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Higher order sections helper: tests whether a value is a valid callback.
|
||||
*
|
||||
* In Mustache.php, a variable is considered 'callable' if the variable is:
|
||||
*
|
||||
* 1. An anonymous function.
|
||||
* 2. An object and the name of a public function, e.g. `array($someObject, 'methodName')`
|
||||
* 3. A class name and the name of a public static function, e.g. `array('SomeClass', 'methodName')`
|
||||
*
|
||||
* Note that this specifically excludes strings, which PHP would normally consider 'callable'.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return boolean True if the value is 'callable'
|
||||
*/
|
||||
public function isCallable($value) {
|
||||
return !is_string($value) && is_callable($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a value should be iterated over (e.g. in a section context).
|
||||
*
|
||||
|
||||
@@ -36,57 +36,6 @@ class ContextTest extends \PHPUnit_Framework_TestCase {
|
||||
$this->assertEquals('NAME', $three->find('name'));
|
||||
}
|
||||
|
||||
public function testIsTruthy() {
|
||||
$context = new Context;
|
||||
|
||||
$this->assertTrue($context->isTruthy('string'));
|
||||
$this->assertTrue($context->isTruthy(new \StdClass));
|
||||
$this->assertTrue($context->isTruthy(1));
|
||||
$this->assertTrue($context->isTruthy(array('a', 'b')));
|
||||
|
||||
$this->assertFalse($context->isTruthy(null));
|
||||
$this->assertFalse($context->isTruthy(''));
|
||||
$this->assertFalse($context->isTruthy(0));
|
||||
$this->assertFalse($context->isTruthy(array()));
|
||||
}
|
||||
|
||||
public function testIsCallable() {
|
||||
$dummy = new TestDummy;
|
||||
$context = new Context;
|
||||
|
||||
$this->assertTrue($context->isCallable(function() {
|
||||
return null;
|
||||
}));
|
||||
$this->assertTrue($context->isCallable(array('\Mustache\Test\TestDummy', 'foo')));
|
||||
$this->assertTrue($context->isCallable(array($dummy, 'bar')));
|
||||
$this->assertTrue($context->isCallable($dummy));
|
||||
|
||||
$this->assertFalse($context->isCallable('count'));
|
||||
$this->assertFalse($context->isCallable('TestDummy::foo'));
|
||||
$this->assertFalse($context->isCallable(array('\Mustache\Test\TestDummy', 'name')));
|
||||
$this->assertFalse($context->isCallable(array('NotReallyAClass', 'foo')));
|
||||
$this->assertFalse($context->isCallable(array($dummy, 'name')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getIterables
|
||||
*/
|
||||
public function testIsIterable($value, $iterable) {
|
||||
$context = new Context;
|
||||
$this->assertEquals($iterable, $context->isIterable($value));
|
||||
}
|
||||
|
||||
public function getIterables() {
|
||||
return array(
|
||||
array(array(0 => 'a', 1 => 'b'), true),
|
||||
array(array(0 => 'a', 2 => 'b'), false),
|
||||
array(array(1 => 'a', 2 => 'b'), false),
|
||||
array(array('a' => 0, 'b' => 1), false),
|
||||
array('some string', false),
|
||||
array(new \ArrayIterator, true),
|
||||
);
|
||||
}
|
||||
|
||||
public function testPushPopAndLast() {
|
||||
$context = new Context;
|
||||
$this->assertFalse($context->last());
|
||||
|
||||
Reference in New Issue
Block a user