Browse code

Merge branch '1.x' into 2.x

* 1.x:
fixed batch filter clobbers array keys when fill parameter is used
added preserveKeys support for the batch filter
removed dead code
fixed "embed" support when used from "template_from_string"
fixed CS

Fabien Potencier authored on 12/03/2019 10:07:16
Showing 9 changed files
... ...
@@ -163,6 +163,9 @@
163 163
 
164 164
 * 1.38.0 (2019-XX-XX)
165 165
 
166
+ * fixed batch filter clobbers array keys when fill parameter is used
167
+ * added preserveKeys support for the batch filter
168
+ * fixed "embed" support when used from "template_from_string"
166 169
  * added the possibility to pass a TemplateWrapper to Twig\Environment::load()
167 170
  * improved the performance of the sandbox
168 171
  * added a spaceless filter
... ...
@@ -299,7 +299,7 @@ class Environment
299 299
     {
300 300
         $key = $this->getLoader()->getCacheKey($name).$this->optionsHash;
301 301
 
302
-        return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index);
302
+        return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '___'.$index);
303 303
     }
304 304
 
305 305
     /**
... ...
@@ -379,9 +379,17 @@ class Environment
379 379
      */
380 380
     public function loadTemplate($name, $index = null)
381 381
     {
382
-        $cls = $mainCls = $this->getTemplateClass($name);
382
+        return $this->loadClass($this->getTemplateClass($name), $name, $index);
383
+    }
384
+
385
+    /**
386
+     * @internal
387
+     */
388
+    public function loadClass($cls, $name, $index = null)
389
+    {
390
+        $mainCls = $cls;
383 391
         if (null !== $index) {
384
-            $cls .= '_'.$index;
392
+            $cls .= '___'.$index;
385 393
         }
386 394
 
387 395
         if (isset($this->loadedTemplates[$cls])) {
... ...
@@ -411,7 +419,7 @@ class Environment
411 419
                 }
412 420
 
413 421
                 if (!class_exists($cls, false)) {
414
-                    throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.', $name, $index), -1, $source);
422
+                    throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source);
415 423
                 }
416 424
             }
417 425
         }
... ...
@@ -1469,23 +1469,22 @@ function twig_constant_is_defined($constant, $object = null)
1469 1469
  *
1470 1470
  * @return array
1471 1471
  */
1472
-function twig_array_batch($items, $size, $fill = null)
1472
+function twig_array_batch($items, $size, $fill = null, $preserveKeys = true)
1473 1473
 {
1474 1474
     if ($items instanceof \Traversable) {
1475
-        $items = iterator_to_array($items, false);
1475
+        $items = iterator_to_array($items, $preserveKeys);
1476 1476
     }
1477 1477
 
1478 1478
     $size = ceil($size);
1479 1479
 
1480
-    $result = array_chunk($items, $size, true);
1480
+    $result = array_chunk($items, $size, $preserveKeys);
1481 1481
 
1482
-    if (null !== $fill && !empty($result)) {
1482
+    if (null !== $fill && $result) {
1483 1483
         $last = \count($result) - 1;
1484 1484
         if ($fillCount = $size - \count($result[$last])) {
1485
-            $result[$last] = array_merge(
1486
-                $result[$last],
1487
-                array_fill(0, $fillCount, $fill)
1488
-            );
1485
+            for ($i = 0; $i < $fillCount; $i++) {
1486
+                $result[$last][] = $fill;
1487
+            }
1489 1488
         }
1490 1489
     }
1491 1490
 
... ...
@@ -39,10 +39,6 @@ final class NodeTraverser
39 39
 
40 40
     public function addVisitor(NodeVisitorInterface $visitor)
41 41
     {
42
-        if (!isset($this->visitors[$visitor->getPriority()])) {
43
-            $this->visitors[$visitor->getPriority()] = [];
44
-        }
45
-
46 42
         $this->visitors[$visitor->getPriority()][] = $visitor;
47 43
     }
48 44
 
... ...
@@ -309,6 +309,15 @@ abstract class Template
309 309
                 return $template;
310 310
             }
311 311
 
312
+            if ($template === $this->getTemplateName()) {
313
+                $class = get_class($this);
314
+                if (false !== $pos = strrpos($class, '___', -1)) {
315
+                    $class = substr($class, 0, $pos);
316
+                }
317
+
318
+                return $this->env->loadClass($class, $template, $index);
319
+            }
320
+
312 321
             return $this->env->loadTemplate($template, $index);
313 322
         } catch (Error $e) {
314 323
             if (!$e->getSourceContext()) {
... ...
@@ -364,7 +364,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
364 364
 
365 365
     /**
366 366
      * @expectedException \Twig\Error\RuntimeError
367
-     * @expectedExceptionMessage Failed to load Twig template "testFailLoadTemplate.twig", index "abc": cache is corrupted in "testFailLoadTemplate.twig".
367
+     * @expectedExceptionMessage Failed to load Twig template "testFailLoadTemplate.twig", index "abc": cache might be corrupted in "testFailLoadTemplate.twig".
368 368
      */
369 369
     public function testFailLoadTemplate()
370 370
     {
... ...
@@ -1,8 +1,8 @@
1 1
 --TEST--
2 2
 "batch" filter preserves array keys
3 3
 --TEMPLATE--
4
-{{ {'foo': 'bar', 'key': 'value'}|batch(4)|first|keys|join(',')  }}
5
-{{ {'foo': 'bar', 'key': 'value'}|batch(4, 'fill')|first|keys|join(',')  }}
4
+{{ {'foo': 'bar', 'key': 'value'}|batch(4)|first|keys|join(',') }}
5
+{{ {'foo': 'bar', 'key': 'value'}|batch(4, 'fill')|first|keys|join(',') }}
6 6
 --DATA--
7 7
 return []
8 8
 --EXPECT--
9 9
new file mode 100644
... ...
@@ -0,0 +1,23 @@
1
+--TEST--
2
+"batch" filter
3
+--TEMPLATE--
4
+{% for row in items|batch(3, 'fill') %}
5
+  <div class=row>
6
+  {% for key, column in row %}
7
+    <div class={{ key }}>{{ column }}</div>
8
+  {% endfor %}
9
+  </div>
10
+{% endfor %}
11
+--DATA--
12
+return ['items' => ['a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', '123' => 'e']]
13
+--EXPECT--
14
+<div class=row>
15
+      <div class=a>a</div>
16
+      <div class=b>b</div>
17
+      <div class=c>c</div>
18
+    </div>
19
+  <div class=row>
20
+      <div class=d>d</div>
21
+      <div class=123>e</div>
22
+      <div class=124>fill</div>
23
+    </div>
0 24
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+--TEST--
2
+"template_from_string" function works in an "include"
3
+--TEMPLATE--
4
+{% set embed = '{% embed "embed.twig" %}{% endembed %}' %}
5
+{{ include(template_from_string(embed)) }}
6
+--TEMPLATE(embed.twig)--
7
+Cool
8
+--DATA--
9
+return []
10
+--EXPECT--
11
+Cool