mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-13 19:06:40 +00:00
Merge branch '2.x' into 3.x
* 2.x: Restrict callables to closures in filters Fix CS Update html_to_markdown.rst
This commit is contained in:
@@ -375,6 +375,7 @@
|
||||
* Fix PHP 8 compatibility
|
||||
* Drop PHP 5.5 5.6, and 7.0 support
|
||||
* Fix ambiguous syntax parsing
|
||||
* In sandbox, the `filter`, `map` and `reduce` filters require Closures in `arrow` parameter
|
||||
|
||||
# 1.42.5 (2020-02-11)
|
||||
|
||||
|
||||
@@ -11,21 +11,7 @@ The ``html_to_markdown`` filter converts a block of HTML to Markdown:
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
You can also add some options by passing them as an argument to the filter:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply html_to_markdown({hard_break: false}) %}
|
||||
<html>
|
||||
<h1>Hello!</h1>
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
.. note::
|
||||
|
||||
The options are the ones provided by the ``league/html-to-markdown`` package.
|
||||
|
||||
You can also use the filter on an included file:
|
||||
You can also use the filter on an entire template which you ``include``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
@@ -40,8 +26,14 @@ You can also use the filter on an included file:
|
||||
|
||||
$ composer req twig/markdown-extra
|
||||
|
||||
Then, use the ``twig/extra-bundle`` on Symfony projects or add the extension
|
||||
explicitly on the Twig environment::
|
||||
On Symfony projects, you can automatically enable it by installing the
|
||||
``twig/extra-bundle``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ composer req twig/extra-bundle
|
||||
|
||||
Or add the extension explicitly on the Twig environment::
|
||||
|
||||
use Twig\Extra\Markdown\MarkdownExtension;
|
||||
|
||||
@@ -61,3 +53,22 @@ You can also use the filter on an included file:
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
``html_to_markdown`` is just a frontend; the actual conversion is done by one of
|
||||
the following compatible libraries, from which you can choose:
|
||||
|
||||
* [erusev/parsedown](https://github.com/erusev/parsedown)
|
||||
* [thephpleague/html-to-markdown](https://github.com/thephpleague/html-to-markdown)
|
||||
* [michelf/php-markdown](https://github.com/michelf/php-markdown)
|
||||
|
||||
Depending on the library, you can also add some options by passing them as an argument
|
||||
to the filter. Example for ``league/html-to-markdown``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% apply html_to_markdown({hard_break: false}) %}
|
||||
<html>
|
||||
<h1>Hello!</h1>
|
||||
</html>
|
||||
{% endapply %}
|
||||
|
||||
|
||||
@@ -205,9 +205,9 @@ final class CoreExtension extends AbstractExtension
|
||||
new TwigFilter('merge', 'twig_array_merge'),
|
||||
new TwigFilter('batch', 'twig_array_batch'),
|
||||
new TwigFilter('column', 'twig_array_column'),
|
||||
new TwigFilter('filter', 'twig_array_filter'),
|
||||
new TwigFilter('map', 'twig_array_map'),
|
||||
new TwigFilter('reduce', 'twig_array_reduce'),
|
||||
new TwigFilter('filter', 'twig_array_filter', ['needs_environment' => true]),
|
||||
new TwigFilter('map', 'twig_array_map', ['needs_environment' => true]),
|
||||
new TwigFilter('reduce', 'twig_array_reduce', ['needs_environment' => true]),
|
||||
|
||||
// string/array filters
|
||||
new TwigFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]),
|
||||
@@ -1569,12 +1569,16 @@ function twig_array_column($array, $name, $index = null): array
|
||||
return array_column($array, $name, $index);
|
||||
}
|
||||
|
||||
function twig_array_filter($array, $arrow)
|
||||
function twig_array_filter(Environment $env, $array, $arrow)
|
||||
{
|
||||
if (!twig_test_iterable($array)) {
|
||||
throw new RuntimeError(sprintf('The "filter" filter expects an array or "Traversable", got "%s".', \is_object($array) ? \get_class($array) : \gettype($array)));
|
||||
}
|
||||
|
||||
if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
|
||||
throw new RuntimeError('The callable passed to "filter" filter must be a Closure in sandbox mode.');
|
||||
}
|
||||
|
||||
if (\is_array($array)) {
|
||||
return array_filter($array, $arrow, \ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
@@ -1583,8 +1587,12 @@ function twig_array_filter($array, $arrow)
|
||||
return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow);
|
||||
}
|
||||
|
||||
function twig_array_map($array, $arrow)
|
||||
function twig_array_map(Environment $env, $array, $arrow)
|
||||
{
|
||||
if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
|
||||
throw new RuntimeError('The callable passed to the "map" filter must be a Closure in sandbox mode.');
|
||||
}
|
||||
|
||||
$r = [];
|
||||
foreach ($array as $k => $v) {
|
||||
$r[$k] = $arrow($v, $k);
|
||||
@@ -1593,8 +1601,12 @@ function twig_array_map($array, $arrow)
|
||||
return $r;
|
||||
}
|
||||
|
||||
function twig_array_reduce($array, $arrow, $initial = null)
|
||||
function twig_array_reduce(Environment $env, $array, $arrow, $initial = null)
|
||||
{
|
||||
if (!$arrow instanceof Closure && $env->hasExtension('\Twig\Extension\SandboxExtension') && $env->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed()) {
|
||||
throw new RuntimeError('The callable passed to the "reduce" filter must be a Closure in sandbox mode.');
|
||||
}
|
||||
|
||||
if (!\is_array($array)) {
|
||||
$array = iterator_to_array($array);
|
||||
}
|
||||
|
||||
@@ -320,6 +320,30 @@ EOF
|
||||
$this->assertFalse($twig->getExtension(SandboxExtension::class)->isSandboxed(), 'Sandboxed include() function call should not leave Sandbox enabled when an error occurs.');
|
||||
}
|
||||
|
||||
public function testSandboxWithNoClosureFilter()
|
||||
{
|
||||
$this->expectException('\Twig\Error\RuntimeError');
|
||||
$this->expectExceptionMessage('The callable passed to "filter" filter must be a Closure in sandbox mode in "index" at line 1.');
|
||||
|
||||
|
||||
$twig = $this->getEnvironment(true, ['autoescape' => 'html'], ['index' => <<<EOF
|
||||
{{ ["foo", "bar", ""]|filter("trim")|join(", ") }}
|
||||
EOF
|
||||
], [], ['escape', 'filter', 'join']);
|
||||
|
||||
$twig->load('index')->render([]);
|
||||
}
|
||||
|
||||
public function testSandboxWithClosureFilter()
|
||||
{
|
||||
$twig = $this->getEnvironment(true, ['autoescape' => 'html'], ['index' => <<<EOF
|
||||
{{ ["foo", "bar", ""]|filter(v => v != "")|join(", ") }}
|
||||
EOF
|
||||
], [], ['escape', 'filter', 'join']);
|
||||
|
||||
$this->assertSame('foo, bar', $twig->load('index')->render([]));
|
||||
}
|
||||
|
||||
protected function getEnvironment($sandboxed, $options, $templates, $tags = [], $filters = [], $methods = [], $properties = [], $functions = [])
|
||||
{
|
||||
$loader = new ArrayLoader($templates);
|
||||
|
||||
Reference in New Issue
Block a user