diff --git a/doc/filters/join.rst b/doc/filters/join.rst index 2fab94528..d919c85bd 100644 --- a/doc/filters/join.rst +++ b/doc/filters/join.rst @@ -16,8 +16,17 @@ define it with the optional first parameter: {{ [1, 2, 3]|join('|') }} {# outputs 1|2|3 #} + +A second parameter can also be provided that will be the separator used +between the last two items of the sequence: +.. code-block:: jinja + + {{ [1, 2, 3]|join(', ', ' and ') }} + {# outputs 1, 2 and 3 #} + Arguments --------- * ``glue``: The separator +* ``and``: The separator for the last pair of input items diff --git a/lib/Twig/Extension/Core.php b/lib/Twig/Extension/Core.php index 9d408e178..0f8b581aa 100644 --- a/lib/Twig/Extension/Core.php +++ b/lib/Twig/Extension/Core.php @@ -717,9 +717,12 @@ function twig_last(Twig_Environment $env, $item) /** * Joins the values to a string. * - * The separator between elements is an empty string per default, you can define it with the optional parameter. + * The separators between elements are empty strings per default, you can define them with the optional parameters. * *
+ * {{ [1, 2, 3]|join(', ', ' and ') }}
+ * {# returns 1, 2 and 3 #}
+ *
* {{ [1, 2, 3]|join('|') }}
* {# returns 1|2|3 #}
*
@@ -727,18 +730,29 @@ function twig_last(Twig_Environment $env, $item)
* {# returns 123 #}
*
*
- * @param array $value An array
- * @param string $glue The separator
+ * @param array $value An array
+ * @param string $glue The separator
+ * @param string|null $and The separator for the last pair
*
* @return string The concatenated string
*/
-function twig_join_filter($value, $glue = '')
+function twig_join_filter($value, $glue = '', $and = null)
{
if ($value instanceof Traversable) {
$value = iterator_to_array($value, false);
+ } else {
+ $value = (array) $value;
}
- return implode($glue, (array) $value);
+ if (empty( $value ) || null === $and || $and === $glue) {
+ return implode($glue, $value);
+ }
+ $last = array_values( array_slice( $value, -1 ) )[0];
+ $value = array_slice( $value, 0, -1 );
+ if( $value ) {
+ return implode($glue, $value) . $and . $last;
+ }
+ return $last;
}
/**
diff --git a/test/Twig/Tests/Fixtures/filters/join.test b/test/Twig/Tests/Fixtures/filters/join.test
index b342c174c..ad9f887ed 100644
--- a/test/Twig/Tests/Fixtures/filters/join.test
+++ b/test/Twig/Tests/Fixtures/filters/join.test
@@ -4,9 +4,35 @@
{{ ["foo", "bar"]|join(', ') }}
{{ foo|join(', ') }}
{{ bar|join(', ') }}
+
+{{ ["foo", "bar"]|join(', ', ' and ') }}
+{{ foo|join(', ', ' and ') }}
+{{ bar|join(', ', ' and ') }}
+{{ ["one", "two", "three"]|join(', ', ' and ') }}
+{{ ["a", "b", "c"]|join('','-') }}
+{{ ["a", "b", "c"]|join('-','-') }}
+{{ ["a", "b", "c"]|join('-','') }}
+{{ ["hello"]|join('|','-') }}
+
+{{ {"a": "w", "b": "x", "c": "y", "d": "z"}|join }}
+{{ {"a": "w", "b": "x", "c": "y", "d": "z"}|join(',') }}
+{{ {"a": "w", "b": "x", "c": "y", "d": "z"}|join(',','-') }}
--DATA--
return array('foo' => new TwigTestFoo(), 'bar' => new ArrayObject(array(3, 4)))
--EXPECT--
foo, bar
1, 2
3, 4
+
+foo and bar
+1 and 2
+3 and 4
+one, two and three
+ab-c
+a-b-c
+a-bc
+hello
+
+wxyz
+w,x,y,z
+w,x,y-z