Skip to content

Commit 28ead3e

Browse files
committed
feature symfony#57243 [String] Add TruncateMode mode to truncate methods (Korbeil)
This PR was merged into the 7.2 branch. Discussion ---------- [String] Add `TruncateMode` mode to `truncate` methods | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | | License | MIT When using truncate we had two behaviors: ```php u("Lorem ipsum dolor sit amet")->truncate(14, cut: true); // outputs: Lorem ipsum do u("Lorem ipsum dolor sit amet")->truncate(14, cut: false); // outputs: Lorem ipsum dolor ``` But sometimes, I want the truncate to fit within 14 chars while keeping all complete words, so I changed truncate method to have a new mode "WordBefore" and switch the `cut` parameter to use a new enum so we can choose which mode is better. Now: ```php u("Lorem ipsum dolor sit amet")->truncate(14, cut: TruncateMode::Char); // outputs: Lorem ipsum do u("Lorem ipsum dolor sit amet")->truncate(14, cut: TruncateMode::WordAfter); // outputs: Lorem ipsum dolor u("Lorem ipsum dolor sit amet")->truncate(14, cut: TruncateMode::WordBefore); // outputs: Lorem ipsum ``` Commits ------- c3136a0 [String] Add WORD_STRICT mode to truncate method
2 parents d18d9dd + c3136a0 commit 28ead3e

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed

UPGRADE-7.2.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ Yaml
1717
----
1818

1919
* Deprecate parsing duplicate mapping keys whose value is `null`
20+
21+
String
22+
------
23+
24+
* `truncate` method now also accept `TruncateMode` enum instead of a boolean:
25+
* `TruncateMode::Char` is equivalent to `true` value ;
26+
* `TruncateMode::WordAfter` is equivalent to `true` value ;
27+
* `TruncateMode::Word` is a new mode that will cut the sentence on the last word before the limit is reached.

src/Symfony/Component/String/AbstractString.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ public function trimSuffix($suffix): static
605605
return $str;
606606
}
607607

608-
public function truncate(int $length, string $ellipsis = '', bool $cut = true): static
608+
public function truncate(int $length, string $ellipsis = '', bool|TruncateMode $cut = TruncateMode::Char): static
609609
{
610610
$stringLength = $this->length();
611611

@@ -619,7 +619,8 @@ public function truncate(int $length, string $ellipsis = '', bool $cut = true):
619619
$ellipsisLength = 0;
620620
}
621621

622-
if (!$cut) {
622+
$desiredLength = $length;
623+
if (TruncateMode::WordAfter === $cut || TruncateMode::WordBefore === $cut || !$cut) {
623624
if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) {
624625
return clone $this;
625626
}
@@ -629,6 +630,14 @@ public function truncate(int $length, string $ellipsis = '', bool $cut = true):
629630

630631
$str = $this->slice(0, $length - $ellipsisLength);
631632

633+
if (TruncateMode::WordBefore === $cut) {
634+
if (0 === $ellipsisLength && $desiredLength === $this->indexOf([' ', "\r", "\n", "\t"], $length)) {
635+
return $str;
636+
}
637+
638+
$str = $str->beforeLast([' ', "\r", "\n", "\t"]);
639+
}
640+
632641
return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
633642
}
634643

src/Symfony/Component/String/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.2
5+
---
6+
7+
* Add `TruncateMode` enum to handle more truncate methods
8+
49
7.1
510
---
611

src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\String\ByteString;
1717
use Symfony\Component\String\CodePointString;
1818
use Symfony\Component\String\Exception\InvalidArgumentException;
19+
use Symfony\Component\String\TruncateMode;
1920
use Symfony\Component\String\UnicodeString;
2021

2122
abstract class AbstractAsciiTestCase extends TestCase
@@ -1505,22 +1506,24 @@ public static function providePadStart()
15051506
/**
15061507
* @dataProvider provideTruncate
15071508
*/
1508-
public function testTruncate(string $expected, string $origin, int $length, string $ellipsis, bool $cut = true)
1509+
public function testTruncate(string $expected, string $origin, int $length, string $ellipsis, bool|TruncateMode $cut = TruncateMode::Char)
15091510
{
15101511
$instance = static::createFromString($origin)->truncate($length, $ellipsis, $cut);
15111512

15121513
$this->assertEquals(static::createFromString($expected), $instance);
15131514
}
15141515

1515-
public static function provideTruncate()
1516+
public static function provideTruncate(): array
15161517
{
15171518
return [
15181519
['', '', 3, ''],
15191520
['', 'foo', 0, '...'],
15201521
['foo', 'foo', 0, '...', false],
1522+
['foo', 'foo', 0, '...', TruncateMode::WordAfter],
15211523
['fo', 'foobar', 2, ''],
15221524
['foobar', 'foobar', 10, ''],
15231525
['foobar', 'foobar', 10, '...', false],
1526+
['foobar', 'foobar', 10, '...', TruncateMode::WordAfter],
15241527
['foo', 'foo', 3, '...'],
15251528
['fo', 'foobar', 2, '...'],
15261529
['...', 'foobar', 3, '...'],
@@ -1529,6 +1532,14 @@ public static function provideTruncate()
15291532
['foobar...', 'foobar foo', 7, '...', false],
15301533
['foobar foo...', 'foobar foo a', 10, '...', false],
15311534
['foobar foo aar', 'foobar foo aar', 12, '...', false],
1535+
['foobar...', 'foobar foo', 6, '...', TruncateMode::WordAfter],
1536+
['foobar...', 'foobar foo', 7, '...', TruncateMode::WordAfter],
1537+
['foobar foo...', 'foobar foo a', 10, '...', TruncateMode::WordAfter],
1538+
['foobar foo aar', 'foobar foo aar', 12, '...', TruncateMode::WordAfter],
1539+
['foobar foo', 'foobar foo aar', 10, '', TruncateMode::WordBefore],
1540+
['foobar...', 'foobar foo aar', 10, '...', TruncateMode::WordBefore],
1541+
['Lorem ipsum', 'Lorem ipsum dolor sit amet', 14, '', TruncateMode::WordBefore],
1542+
['Lorem...', 'Lorem ipsum dolor sit amet', 10, '...', TruncateMode::WordBefore],
15321543
];
15331544
}
15341545

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\String;
13+
14+
enum TruncateMode
15+
{
16+
/**
17+
* Will cut exactly at given length.
18+
*
19+
* Length: 14
20+
* Source: Lorem ipsum dolor sit amet
21+
* Output: Lorem ipsum do
22+
*/
23+
case Char;
24+
25+
/**
26+
* Returns the string up to the last complete word containing the specified length.
27+
*
28+
* Length: 14
29+
* Source: Lorem ipsum dolor sit amet
30+
* Output: Lorem ipsum
31+
*/
32+
case WordBefore;
33+
34+
/**
35+
* Returns the string up to the complete word after or at the given length.
36+
*
37+
* Length: 14
38+
* Source: Lorem ipsum dolor sit amet
39+
* Output: Lorem ipsum dolor
40+
*/
41+
case WordAfter;
42+
}

0 commit comments

Comments
 (0)