Skip to content

Commit e82cd44

Browse files
committed
Extract string limiting logic from CodeQuoter into LimiterQuoter
CodeQuoter was handling two distinct responsibilities: limiting string length (including truncation and context-aware placeholder selection) and wrapping content in backtick quotes. Separating these concerns gives each class a single, clear job — LimiterQuoter handles the length cap and truncation strategy, while CodeQuoter focuses on depth-checking and backtick formatting. This also makes each concern independently testable. Assisted-by: Claude Code (claude-sonnet-4-6)
1 parent 742bf04 commit e82cd44

3 files changed

Lines changed: 105 additions & 33 deletions

File tree

src/Quoters/CodeQuoter.php

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,15 @@
1212

1313
use Respect\Stringifier\Quoter;
1414

15-
use function mb_strlen;
16-
use function mb_substr;
1715
use function sprintf;
18-
use function str_contains;
19-
use function strpos;
2016

2117
final class CodeQuoter implements Quoter
2218
{
23-
private const string OBJECT_PLACEHOLDER = ' ... }';
24-
private const string ARRAY_PLACEHOLDER = ' ... ]';
25-
private const string GENERIC_PLACEHOLDER = ' ...';
19+
private readonly LimiterQuoter $limiter;
2620

27-
public function __construct(private readonly int $maximumLength)
21+
public function __construct(int $maximumLength)
2822
{
23+
$this->limiter = new LimiterQuoter($maximumLength - 2);
2924
}
3025

3126
public function quote(string $string, int $depth): string
@@ -34,30 +29,6 @@ public function quote(string $string, int $depth): string
3429
return $string;
3530
}
3631

37-
$limitWithQuotes = $this->maximumLength - 2;
38-
if (mb_strlen($string) <= $limitWithQuotes) {
39-
return $this->code($string);
40-
}
41-
42-
$filtered = mb_substr($string, 0, $limitWithQuotes);
43-
if (strpos($filtered, '[') === 0) {
44-
return $this->placeholder($filtered, self::ARRAY_PLACEHOLDER);
45-
}
46-
47-
if (str_contains($filtered, '{')) {
48-
return $this->placeholder($filtered, self::OBJECT_PLACEHOLDER);
49-
}
50-
51-
return $this->placeholder($filtered, self::GENERIC_PLACEHOLDER);
52-
}
53-
54-
private function code(string $string): string
55-
{
56-
return sprintf('`%s`', $string);
57-
}
58-
59-
private function placeholder(string $string, string $placeholder): string
60-
{
61-
return $this->code(mb_substr($string, 0, -1 * mb_strlen($placeholder)) . $placeholder);
32+
return sprintf('`%s`', $this->limiter->quote($string, $depth));
6233
}
6334
}

src/Quoters/LimiterQuoter.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Respect/Stringifier.
5+
* Copyright (c) Henrique Moody <henriquemoody@gmail.com>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace Respect\Stringifier\Quoters;
12+
13+
use Respect\Stringifier\Quoter;
14+
15+
use function mb_strlen;
16+
use function mb_substr;
17+
use function str_contains;
18+
use function strpos;
19+
20+
final class LimiterQuoter implements Quoter
21+
{
22+
private const string OBJECT_PLACEHOLDER = ' ... }';
23+
private const string ARRAY_PLACEHOLDER = ' ... ]';
24+
private const string GENERIC_PLACEHOLDER = ' ...';
25+
26+
public function __construct(private readonly int $maximumLength)
27+
{
28+
}
29+
30+
public function quote(string $string, int $depth): string
31+
{
32+
if (mb_strlen($string) <= $this->maximumLength) {
33+
return $string;
34+
}
35+
36+
$filtered = mb_substr($string, 0, $this->maximumLength);
37+
if (strpos($filtered, '[') === 0) {
38+
return $this->truncate($filtered, self::ARRAY_PLACEHOLDER);
39+
}
40+
41+
if (str_contains($filtered, '{')) {
42+
return $this->truncate($filtered, self::OBJECT_PLACEHOLDER);
43+
}
44+
45+
return $this->truncate($filtered, self::GENERIC_PLACEHOLDER);
46+
}
47+
48+
private function truncate(string $string, string $placeholder): string
49+
{
50+
return mb_substr($string, 0, -1 * mb_strlen($placeholder)) . $placeholder;
51+
}
52+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Respect/Stringifier.
5+
* Copyright (c) Henrique Moody <henriquemoody@gmail.com>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace Respect\Stringifier\Test\Unit\Quoters;
12+
13+
use PHPUnit\Framework\Attributes\CoversClass;
14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\Attributes\Test;
16+
use PHPUnit\Framework\TestCase;
17+
use Respect\Stringifier\Quoters\LimiterQuoter;
18+
19+
use function mb_strlen;
20+
21+
#[CoversClass(LimiterQuoter::class)]
22+
final class LimiterQuoterTest extends TestCase
23+
{
24+
private const int LIMIT = 18;
25+
26+
#[Test]
27+
#[DataProvider('provideData')]
28+
public function itShouldLimitString(string $string, string $expected): void
29+
{
30+
$sut = new LimiterQuoter(self::LIMIT);
31+
32+
$actual = $sut->quote($string, 0);
33+
34+
self::assertSame($expected, $actual);
35+
self::assertLessThanOrEqual(self::LIMIT, mb_strlen($actual));
36+
}
37+
38+
/** @return array<int, array<int, string>> */
39+
public static function provideData(): array
40+
{
41+
return [
42+
['short string', 'short string'],
43+
['1234567890ABCDEFGH', '1234567890ABCDEFGH'],
44+
['1234567890ABCDEFGHI', '1234567890ABCD ...'],
45+
['class { 90ABCDEFGH }', 'class { 90AB ... }'],
46+
['[2, 5, 7, A, D, G, H]', '[2, 5, 7, A, ... ]'],
47+
];
48+
}
49+
}

0 commit comments

Comments
 (0)