diff --git a/ViewRenderer.php b/ViewRenderer.php index ca78371b6..9fd6a5055 100644 --- a/ViewRenderer.php +++ b/ViewRenderer.php @@ -230,26 +230,26 @@ public function setLexerOptions($options) */ private function _addCustom($classType, $elements) { - $classFunction = 'Twig_' . $classType . '_Function'; + $classFunction = 'Twig_Simple' . $classType; foreach ($elements as $name => $func) { $twigElement = null; switch ($func) { - // Just a name of function - case is_string($func): - $twigElement = new $classFunction($func); + // Callable (including just a name of function). + case is_callable($func): + $twigElement = new $classFunction($name, $func); break; - // Name of function + options array - case is_array($func) && is_string($func[0]) && isset($func[1]) && is_array($func[1]): - $twigElement = new $classFunction($func[0], $func[1]); + // Callable (including just a name of function) + options array. + case is_array($func) && is_callable($func[0]): + $twigElement = new $classFunction($name, $func[0], (!empty($func[1]) && is_array($func[1])) ? $func[1] : []); break; + case $func instanceof \Twig_SimpleFunction || $func instanceof \Twig_SimpleFilter: + $twigElement = $func; } if ($twigElement !== null) { - $this->twig->{'add'.$classType}($name, $twigElement); - } elseif ($func instanceof \Twig_SimpleFunction || $func instanceof \Twig_SimpleFilter) { - $this->twig->{'add'.$classType}($func); + $this->twig->{'add'.$classType}($twigElement); } else { throw new \Exception("Incorrect options for \"$classType\" $name."); } diff --git a/docs/guide/additional-configuration.md b/docs/guide/additional-configuration.md index ba9ad1c8a..6af9e59ba 100644 --- a/docs/guide/additional-configuration.md +++ b/docs/guide/additional-configuration.md @@ -36,7 +36,13 @@ You can define additional functions like the following: new \Twig_SimpleFunction('rot14', 'str_rot13'), new \Twig_SimpleFunction('add_*', function ($symbols, $val) { return $val . $symbols; - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + 'callable_add_*' => function ($symbols, $val) { + return $val . $symbols; + }, + 'sum' => function ($a, $b) { + return $a + $b; + } ], ``` @@ -47,6 +53,8 @@ In template they could be used like the following: `{{ truncate(post.text, 100) }}` `{{ rot14('test') }}` `{{ add_42('answer') }}` +`{{ callable_add_42('test') }}` +`{{ sum(1, 2) }}` ``` ## Filters @@ -59,7 +67,13 @@ Additional filters may be added via the application configuration's `filters` op new \Twig_SimpleFilter('rot13', 'str_rot13'), new \Twig_SimpleFilter('add_*', function ($symbols, $val) { return $val . $symbols; - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + 'callable_rot13' => function($string) { + return str_rot13($string); + }, + 'callable_add_*' => function ($symbols, $val) { + return $val . $symbols; + } ], ``` @@ -69,4 +83,6 @@ Then in the template you can apply filter using the following syntax: {{ model|jsonEncode }} {{ 'test'|rot13 }} {{ 'answer'|add_42 }} +{{ 'test'|callable_rot13 }} +{{ 'answer'|callable_add_42 }} ``` diff --git a/tests/ViewRendererTest.php b/tests/ViewRendererTest.php index 98025a8f3..fb05691fc 100644 --- a/tests/ViewRendererTest.php +++ b/tests/ViewRendererTest.php @@ -117,6 +117,12 @@ public function testSimpleFilters() $this->assertEquals($content, 'Gjvt'); $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFilters2.twig'); $this->assertEquals($content, 'val42'); + $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFilters3.twig'); + $this->assertEquals($content, 'Gjvt'); + $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFilters4.twig'); + $this->assertEquals($content, 'val42'); + $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFilters5.twig'); + $this->assertEquals($content, 'Gjvt'); } public function testSimpleFunctions() @@ -126,6 +132,12 @@ public function testSimpleFunctions() $this->assertEquals($content, 'Gjvt'); $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFunctions2.twig'); $this->assertEquals($content, 'val43'); + $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFunctions3.twig'); + $this->assertEquals($content, 'Gjvt'); + $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFunctions4.twig'); + $this->assertEquals($content, 'val43'); + $content = $view->renderFile('@yiiunit/extensions/twig/views/simpleFunctions5.twig'); + $this->assertEquals($content, '6'); } /** @@ -151,13 +163,29 @@ protected function mockView() new \Twig_SimpleFunction('rot13', 'str_rot13'), new \Twig_SimpleFunction('add_*', function ($symbols, $val) { return $val . $symbols; - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + 'callable_rot13' => function($string) { + return str_rot13($string); + }, + 'callable_add_*' => function ($symbols, $val) { + return $val . $symbols; + }, + 'callable_sum' => function ($a, $b) { + return $a + $b; + } ], 'filters' => [ + 'string_rot13' => 'str_rot13', new \Twig_SimpleFilter('rot13', 'str_rot13'), new \Twig_SimpleFilter('add_*', function ($symbols, $val) { return $val . $symbols; - }, ['is_safe' => ['html']]) + }, ['is_safe' => ['html']]), + 'callable_rot13' => function($string) { + return str_rot13($string); + }, + 'callable_add_*' => function ($symbols, $val) { + return $val . $symbols; + } ], 'lexerOptions' => [ 'tag_comment' => [ '{*', '*}' ], diff --git a/tests/views/simpleFilters3.twig b/tests/views/simpleFilters3.twig new file mode 100644 index 000000000..dfa4ac495 --- /dev/null +++ b/tests/views/simpleFilters3.twig @@ -0,0 +1 @@ +{{ 'Twig'|callable_rot13 }} \ No newline at end of file diff --git a/tests/views/simpleFilters4.twig b/tests/views/simpleFilters4.twig new file mode 100644 index 000000000..ae59b3841 --- /dev/null +++ b/tests/views/simpleFilters4.twig @@ -0,0 +1 @@ +{{ 'val'|callable_add_42 }} \ No newline at end of file diff --git a/tests/views/simpleFilters5.twig b/tests/views/simpleFilters5.twig new file mode 100644 index 000000000..9dc4cd722 --- /dev/null +++ b/tests/views/simpleFilters5.twig @@ -0,0 +1 @@ +{{ 'Twig'|string_rot13 }} \ No newline at end of file diff --git a/tests/views/simpleFunctions3.twig b/tests/views/simpleFunctions3.twig new file mode 100644 index 000000000..0fd489de8 --- /dev/null +++ b/tests/views/simpleFunctions3.twig @@ -0,0 +1 @@ +{{ callable_rot13('Twig') }} \ No newline at end of file diff --git a/tests/views/simpleFunctions4.twig b/tests/views/simpleFunctions4.twig new file mode 100644 index 000000000..cd1b03d82 --- /dev/null +++ b/tests/views/simpleFunctions4.twig @@ -0,0 +1 @@ +{{ callable_add_43('val') }} \ No newline at end of file diff --git a/tests/views/simpleFunctions5.twig b/tests/views/simpleFunctions5.twig new file mode 100644 index 000000000..31359d47b --- /dev/null +++ b/tests/views/simpleFunctions5.twig @@ -0,0 +1 @@ +{{ callable_sum(2, 4) }} \ No newline at end of file