Skip to content

Commit

Permalink
feature twigphp#1503 Use LimitIterator on Iterable objects within the…
Browse files Browse the repository at this point in the history
… slice filter (Anthony Sterling)

This PR was merged into the 1.16-dev branch.

Discussion
----------

Use LimitIterator on Iterable objects within the slice filter

Previously the `slice` filter would create an array of items if the subject to be sliced implemented Traversable, this PR instead passes the subject to LimitIterator first - but only if `$start` and `$length` are positive values as LimitIterator does not support the "n'th from end" behaviour.

Our use case is that we have an API client, which we pass to slice, that implements Traversable but lazy loads the items to be returned via an API when `Iterator::current()` is called. Here a quick example:-

```
{% for item in client.items | slice(0,5) %}
    {{ item.name }}
{% endfor %}

<img src="/assets/useless-sodding-banner.jpg" />

{% for item in client.items | slice(5,10) %}
    {{ item.name }}
{% endfor %}
```

Current behaviour would mean that the client would issue 15 requests to the API, 5 for the first block, and 10 for the second (but only return items 5 to 10). This PR means only 10 requests are made, 5 in each block.

I'd imagine this would lower memory usage too.

Commits
-------

fdddb1c Use LimitIterator on Iterable objects within the splice filter
  • Loading branch information
fabpot committed Oct 1, 2014
2 parents 0a179e8 + fdddb1c commit 1ed333b
Showing 1 changed file with 10 additions and 1 deletion.
11 changes: 10 additions & 1 deletion lib/Twig/Extension/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,16 @@ function twig_array_merge($arr1, $arr2)
function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
{
if ($item instanceof Traversable) {
$item = iterator_to_array($item, false);

if ($item instanceof IteratorAggregate) {
$item = $item->getIterator();
}

if ($start >= 0 && $length >= 0) {
return iterator_to_array(new LimitIterator($item, $start, $length), $preserveKeys);
}

$item = iterator_to_array($item, $preserveKeys);
}

if (is_array($item)) {
Expand Down

0 comments on commit 1ed333b

Please sign in to comment.