Passed
Push — master ( f250ce...3ee825 )
by Alexander
12:51
created

MultipleScopePreservingFormatter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 7
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 4
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Vasoft\VersionIncrement\Changelog;
6
7
use Vasoft\VersionIncrement\Commits\Commit;
8
use Vasoft\VersionIncrement\Contract\ScopeInterpreterInterface;
9
10
/**
11
 * A changelog formatter that handles commits with multiple scopes separated by a source delimiter.
12
 *
13
 * This formatter splits the commit's scope string (e.g., 'api|db|frontend') using the source separator,
14
 * processes each individual scope against the list of preserved scopes (which can include interpreters
15
 * or literal strings), filters out non-preserved ones, joins the processed scopes using the destination
16
 * separator, and finally applies an overall template to the resulting string.
17
 *
18
 * It bypasses the parent's 'outputTemplate' logic. Formatting is controlled solely by the
19
 * 'overallTemplate' applied to the final joined scope string.
20
 *
21
 * Example:
22
 * - Commit scope: 'api|db'
23
 * - Preserved scopes: ['api', 'db'] (or interpreters)
24
 * - Source separator: '|'
25
 * - Destination separator: '|'
26
 * - Overall template: '%s: '
27
 * - Result: 'api|db: commit message'
28
 *
29
 * Example with interpreters:
30
 * - Commit scope: 'api|task123'
31
 * - Preserved scopes: [new SinglePreservedScopeInterpreter(...), new RegexpScopeInterpreter(...)]
32
 * - Assume 'api' maps to 'API' and 'task123' maps to '[TASK-123]' via interpreters
33
 * - Overall template: '%s - '
34
 * - Result: 'API|[TASK-123] - commit message'
35
 */
36
class MultipleScopePreservingFormatter extends ScopePreservingFormatter
37
{
38
    /**
39
     * Constructs a new MultipleScopePreservingFormatter instance.
40
     *
41
     * @param array<ScopeInterpreterInterface|string> $preservedScopes an array of scope names or interpreters
42
     *                                                                 used to determine which scopes are preserved
43
     *                                                                 and how they are formatted
44
     * @param string                                  $srcSeparator    The delimiter used to split the original commit scope string. Defaults to '|'.
45
     * @param string                                  $dstSeparator    The delimiter used to join the processed, preserved scopes. Defaults to '|'.
46
     * @param string                                  $overallTemplate The template applied to the final joined scope string. Defaults to '%s'.
47
     *                                                                 The '%s' placeholder will be replaced by the string resulting from
48
     *                                                                 joining the processed, preserved scopes.
49
     *                                                                 Example: if joined result is 'api|db' and template is '%s: ',
50
     *                                                                 the final output for scopes will be 'api|db: '.
51
     */
52 4
    public function __construct(
53
        array $preservedScopes,
54
        private readonly string $srcSeparator = '|',
55
        private readonly string $dstSeparator = '|',
56
        private readonly string $overallTemplate = '%s ',
57
    ) {
58 4
        parent::__construct($preservedScopes);
59
    }
60
61 4
    protected function getScopeForCommit(Commit $commit): string
62
    {
63 4
        $scopes = explode($this->srcSeparator, $commit->scope);
64 4
        $result = [];
65 4
        foreach ($scopes as $scope) {
66 4
            $formatted = $this->processScope(trim($scope));
67 4
            if ('' !== $formatted) {
68 4
                $result[] = $formatted;
69
            }
70
        }
71
72 4
        return empty($result) ? '' : sprintf($this->overallTemplate, implode($this->dstSeparator, $result));
73
    }
74
75 4
    private function processScope(string $commitScope): string
76
    {
77 4
        $scopes = $this->config?->getScopes() ?? [];
78 4
        foreach ($this->preservedScopes as $scope) {
79 4
            if ($scope instanceof ScopeInterpreterInterface) {
80 4
                $result = $scope->interpret($commitScope);
81 4
                if (null !== $result) {
82 4
                    return $result;
83
                }
84 4
            } elseif ($commitScope === $scope) {
85 3
                return $scopes[$commitScope] ?? $commitScope;
86
            }
87
        }
88
89 3
        return '';
90
    }
91
}
92