Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
ChangelogRelease
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
10 / 10
14
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getVersion
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isUnreleased
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEntries
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEntriesFor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasEntries
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 withEntry
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 withEntries
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 withDate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
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\Document;
21
22use FastForward\DevTools\Changelog\Entry\ChangelogEntryType;
23
24/**
25 * Represents one Keep a Changelog release section.
26 */
27 class ChangelogRelease
28{
29    /**
30     * @var array<string, list<string>>
31     */
32    private array $entries = [];
33
34    /**
35     * @param array<string, list<string>> $entries
36     * @param string $version
37     * @param ?string $date
38     */
39    public function __construct(
40        private  string $version,
41        private  ?string $date = null,
42        array $entries = [],
43    ) {
44        foreach (ChangelogEntryType::ordered() as $type) {
45            $this->entries[$type->value] = array_values(array_unique($entries[$type->value] ?? []));
46        }
47    }
48
49    /**
50     * Returns the section version label.
51     */
52    public function getVersion(): string
53    {
54        return $this->version;
55    }
56
57    /**
58     * Returns the release date when present.
59     */
60    public function getDate(): ?string
61    {
62        return $this->date;
63    }
64
65    /**
66     * Returns whether this section is the active Unreleased section.
67     */
68    public function isUnreleased(): bool
69    {
70        return ChangelogDocument::UNRELEASED_VERSION === $this->version;
71    }
72
73    /**
74     * Returns all entries keyed by changelog category.
75     *
76     * @return array<string, list<string>>
77     */
78    public function getEntries(): array
79    {
80        return $this->entries;
81    }
82
83    /**
84     * Returns the entries for a specific changelog category.
85     *
86     * @param ChangelogEntryType $type
87     *
88     * @return list<string>
89     */
90    public function getEntriesFor(ChangelogEntryType $type): array
91    {
92        return $this->entries[$type->value];
93    }
94
95    /**
96     * Returns whether the section contains at least one meaningful entry.
97     */
98    public function hasEntries(): bool
99    {
100        foreach ($this->entries as $entries) {
101            if ([] !== $entries) {
102                return true;
103            }
104        }
105
106        return false;
107    }
108
109    /**
110     * Returns a copy with an additional entry appended to the given category.
111     *
112     * @param ChangelogEntryType $type
113     * @param string $entry
114     */
115    public function withEntry(ChangelogEntryType $type, string $entry): self
116    {
117        $entries = $this->entries;
118        $entry = trim($entry);
119
120        if ('' === $entry) {
121            return $this;
122        }
123
124        $entries[$type->value][] = $entry;
125        $entries[$type->value] = array_values(array_unique($entries[$type->value]));
126
127        return new self($this->version, $this->date, $entries);
128    }
129
130    /**
131     * Returns a copy with all entries replaced by the supplied map.
132     *
133     * @param array<string, list<string>> $entries
134     */
135    public function withEntries(array $entries): self
136    {
137        return new self($this->version, $this->date, $entries);
138    }
139
140    /**
141     * Returns a copy with the release date replaced.
142     *
143     * @param ?string $date
144     */
145    public function withDate(?string $date): self
146    {
147        return new self($this->version, $date, $this->entries);
148    }
149}