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