Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
UnreleasedEntryChecker
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
3 / 3
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasPendingChanges
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 flattenEntries
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/**
6 * Fast Forward Development Tools for PHP projects.
7 *
8 * This file is part of fast-forward/dev-tools project.
9 *
10 * @author   Felipe SayĆ£o Lobato Abreu <github@mentordosnerds.com>
11 * @license  https://opensource.org/licenses/MIT MIT License
12 *
13 * @see      https://github.com/php-fast-forward/
14 * @see      https://github.com/php-fast-forward/dev-tools
15 * @see      https://github.com/php-fast-forward/dev-tools/issues
16 * @see      https://php-fast-forward.github.io/dev-tools/
17 * @see      https://datatracker.ietf.org/doc/html/rfc2119
18 */
19
20namespace FastForward\DevTools\Changelog\Checker;
21
22use FastForward\DevTools\Changelog\Document\ChangelogRelease;
23use FastForward\DevTools\Changelog\Entry\ChangelogEntryType;
24use FastForward\DevTools\Filesystem\FilesystemInterface;
25use FastForward\DevTools\Git\GitClientInterface;
26use FastForward\DevTools\Changelog\Parser\ChangelogParserInterface;
27use Throwable;
28use function array_diff;
29use function array_values;
30
31/**
32 * Compares unreleased changelog entries against the current branch or a base ref.
33 */
34  class UnreleasedEntryChecker implements UnreleasedEntryCheckerInterface
35{
36    /**
37     * Constructs a new UnreleasedEntryChecker.
38     *
39     * @param GitClientInterface $gitClient the Git client used for baseline inspection
40     * @param FilesystemInterface $filesystem
41     * @param ChangelogParserInterface $parser
42     */
43    public function __construct(
44        private FilesystemInterface $filesystem,
45        private GitClientInterface $gitClient,
46        private ChangelogParserInterface $parser,
47    ) {}
48
49    /**
50     * Checks if there are pending unreleased entries in the changelog compared to a given reference.
51     *
52     * @param string $file the changelog file path to inspect
53     * @param string|null $againstReference The reference to compare against (e.g., a branch or commit hash).
54     *
55     * @return bool true if there are pending unreleased entries, false otherwise
56     */
57    public function hasPendingChanges(string $file, ?string $againstReference = null): bool
58    {
59        try {
60            $content = $this->filesystem->readFile($file);
61        } catch (Throwable) {
62            return false;
63        }
64
65        $currentEntries = $this->flattenEntries($this->parser->parse($content)->getUnreleased());
66
67        if ([] === $currentEntries) {
68            return false;
69        }
70
71        if (null === $againstReference) {
72            return true;
73        }
74
75        try {
76            $baseline = $this->gitClient->show($againstReference, $file, $this->filesystem->getDirectory($file));
77        } catch (Throwable) {
78            return true;
79        }
80
81        $baselineEntries = $this->flattenEntries($this->parser->parse($baseline)->getUnreleased());
82
83        return [] !== array_values(array_diff($currentEntries, $baselineEntries));
84    }
85
86    /**
87     * Flattens release entries for set comparison.
88     *
89     * @param ChangelogRelease $release
90     *
91     * @return list<string>
92     */
93    private function flattenEntries(ChangelogRelease $release): array
94    {
95        $entries = [];
96
97        foreach (ChangelogEntryType::ordered() as $type) {
98            $entries = [...$entries, ...$release->getEntriesFor($type)];
99        }
100
101        return array_values(array_unique($entries));
102    }
103}