Skip to content

Commit a2ec874

Browse files
committed
[String] Add WORD_STRICT mode to truncate method
1 parent 9f77ba3 commit a2ec874

File tree

4 files changed

+75
-10
lines changed

4 files changed

+75
-10
lines changed

src/Symfony/Component/String/AbstractString.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,12 @@ 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|TruncateCut $cut = TruncateCut::Char): static
609609
{
610+
if (\is_bool($cut)) {
611+
$cut = $cut ? TruncateCut::Char : TruncateCut::WordAfterWord;
612+
}
613+
610614
$stringLength = $this->length();
611615

612616
if ($stringLength <= $length) {
@@ -619,7 +623,8 @@ public function truncate(int $length, string $ellipsis = '', bool $cut = true):
619623
$ellipsisLength = 0;
620624
}
621625

622-
if (!$cut) {
626+
$desiredLength = $length;
627+
if (TruncateCut::WordAfterWord === $cut || TruncateCut::Word === $cut) {
623628
if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) {
624629
return clone $this;
625630
}
@@ -629,6 +634,14 @@ public function truncate(int $length, string $ellipsis = '', bool $cut = true):
629634

630635
$str = $this->slice(0, $length - $ellipsisLength);
631636

637+
if (TruncateCut::Word === $cut) {
638+
if (0 === $ellipsisLength && $desiredLength === $this->indexOf([' ', "\r", "\n", "\t"], $length)) {
639+
return $str;
640+
}
641+
642+
$str = $str->beforeLast([' ', "\r", "\n", "\t"]);
643+
}
644+
632645
return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
633646
}
634647

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 `TruncateCut::Word` mode to truncate method
8+
49
7.1
510
---
611

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

Lines changed: 13 additions & 8 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\TruncateCut;
1920
use Symfony\Component\String\UnicodeString;
2021

2122
abstract class AbstractAsciiTestCase extends TestCase
@@ -1498,30 +1499,34 @@ public static function providePadStart()
14981499
/**
14991500
* @dataProvider provideTruncate
15001501
*/
1501-
public function testTruncate(string $expected, string $origin, int $length, string $ellipsis, bool $cut = true)
1502+
public function testTruncate(string $expected, string $origin, int $length, string $ellipsis, TruncateCut $cut = TruncateCut::Char)
15021503
{
15031504
$instance = static::createFromString($origin)->truncate($length, $ellipsis, $cut);
15041505

15051506
$this->assertEquals(static::createFromString($expected), $instance);
15061507
}
15071508

1508-
public static function provideTruncate()
1509+
public static function provideTruncate(): array
15091510
{
15101511
return [
15111512
['', '', 3, ''],
15121513
['', 'foo', 0, '...'],
1513-
['foo', 'foo', 0, '...', false],
1514+
['foo', 'foo', 0, '...', TruncateCut::WordAfterWord],
15141515
['fo', 'foobar', 2, ''],
15151516
['foobar', 'foobar', 10, ''],
1516-
['foobar', 'foobar', 10, '...', false],
1517+
['foobar', 'foobar', 10, '...', TruncateCut::WordAfterWord],
15171518
['foo', 'foo', 3, '...'],
15181519
['fo', 'foobar', 2, '...'],
15191520
['...', 'foobar', 3, '...'],
15201521
['fo...', 'foobar', 5, '...'],
1521-
['foobar...', 'foobar foo', 6, '...', false],
1522-
['foobar...', 'foobar foo', 7, '...', false],
1523-
['foobar foo...', 'foobar foo a', 10, '...', false],
1524-
['foobar foo aar', 'foobar foo aar', 12, '...', false],
1522+
['foobar...', 'foobar foo', 6, '...', TruncateCut::WordAfterWord],
1523+
['foobar...', 'foobar foo', 7, '...', TruncateCut::WordAfterWord],
1524+
['foobar foo...', 'foobar foo a', 10, '...', TruncateCut::WordAfterWord],
1525+
['foobar foo aar', 'foobar foo aar', 12, '...', TruncateCut::WordAfterWord],
1526+
['foobar foo', 'foobar foo aar', 10, '', TruncateCut::Word],
1527+
['foobar...', 'foobar foo aar', 10, '...', TruncateCut::Word],
1528+
['Lorem ipsum', 'Lorem ipsum dolor sit amet', 14, '', TruncateCut::Word],
1529+
['Lorem...', 'Lorem ipsum dolor sit amet', 10, '...', TruncateCut::Word],
15251530
];
15261531
}
15271532

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 TruncateCut
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+
* Will cut at given length, if length is onto a word, will cut before it.
27+
*
28+
* Length: 14
29+
* Source: Lorem ipsum dolor sit amet
30+
* Output: Lorem ipsum
31+
*/
32+
case Word;
33+
34+
/**
35+
* Will cut at given length until the end of the current word if length is onto a word.
36+
*
37+
* Length: 14
38+
* Source: Lorem ipsum dolor sit amet
39+
* Output: Lorem ipsum dolor
40+
*/
41+
case WordAfterWord;
42+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy