Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
Changelog
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
11 / 11
21
100.00% covered (success)
100.00%
1 / 1
 getPrologue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPrologue
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEpilogue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setEpilogue
100.00% covered (success)
100.00%
2 / 2
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
 setEntries
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 getLatestEntry
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addEntry
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getVersions
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 jsonSerialize
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 jsonUnserialize
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2/**
3 * Class representing a changelog.
4 *
5 * @package automattic/jetpack-changelogger
6 */
7
8namespace Automattic\Jetpack\Changelog;
9
10use InvalidArgumentException;
11use JsonSerializable;
12
13/**
14 * Class representing a changelog.
15 */
16class Changelog implements JsonSerializable {
17
18    /**
19     * Content before the changelog itself.
20     *
21     * @var string
22     */
23    protected $prologue = '';
24
25    /**
26     * Content after the changelog itself.
27     *
28     * @var string
29     */
30    protected $epilogue = '';
31
32    /**
33     * Changelog entries, one per version.
34     *
35     * @var ChangelogEntry[]
36     */
37    protected $entries = array();
38
39    /**
40     * Get the prologue content.
41     *
42     * @return string
43     */
44    public function getPrologue() {
45        return $this->prologue;
46    }
47
48    /**
49     * Set the prologue content.
50     *
51     * @param string $prologue Prologue content to set.
52     * @return $this
53     */
54    public function setPrologue( $prologue ) {
55        $this->prologue = (string) $prologue;
56        return $this;
57    }
58
59    /**
60     * Get the epilogue content.
61     *
62     * @return string
63     */
64    public function getEpilogue() {
65        return $this->epilogue;
66    }
67
68    /**
69     * Set the epilogue content.
70     *
71     * @param string $epilogue Epilogue content to set.
72     * @return $this
73     */
74    public function setEpilogue( $epilogue ) {
75        $this->epilogue = (string) $epilogue;
76        return $this;
77    }
78
79    /**
80     * Get the list of changelog entries.
81     *
82     * @return ChangelogEntry[]
83     */
84    public function getEntries() {
85        return $this->entries;
86    }
87
88    /**
89     * Set the list of changelog entries.
90     *
91     * This replaces all existing entries.
92     *
93     * @param ChangelogEntry[] $entries Changelog entries.
94     * @return $this
95     * @throws InvalidArgumentException If an argument is invalid.
96     */
97    public function setEntries( array $entries ) {
98        foreach ( $entries as $i => $entry ) {
99            if ( ! $entry instanceof ChangelogEntry ) {
100                $what = is_object( $entry ) ? get_class( $entry ) : gettype( $entry );
101                throw new InvalidArgumentException( __METHOD__ . ": Expected a ChangelogEntry, got $what at index $i" );
102            }
103        }
104        $this->entries = array_values( $entries );
105        return $this;
106    }
107
108    /**
109     * Get the latest changelog entry.
110     *
111     * @return ChangelogEntry|null
112     */
113    public function getLatestEntry() {
114        return $this->entries[0] ?? null;
115    }
116
117    /**
118     * Add a new entry as the latest.
119     *
120     * @param ChangelogEntry $entry New entry.
121     * @return $this
122     */
123    public function addEntry( ChangelogEntry $entry ) {
124        array_unshift( $this->entries, $entry );
125        return $this;
126    }
127
128    /**
129     * Get the list of versions in the changelog.
130     *
131     * @return string[]
132     */
133    public function getVersions() {
134        $ret = array();
135        foreach ( $this->entries as $entry ) {
136            $ret[] = $entry->getVersion();
137        }
138        return $ret;
139    }
140
141    /**
142     * Return data for serializing to JSON.
143     *
144     * @return array
145     */
146    #[\ReturnTypeWillChange]
147    public function jsonSerialize() {
148        return array(
149            '__class__' => static::class,
150            'prologue'  => $this->prologue,
151            'epilogue'  => $this->epilogue,
152            'entries'   => $this->entries,
153        );
154    }
155
156    /**
157     * Unserialize from JSON.
158     *
159     * @param array $data JSON data as returned by self::jsonSerialize().
160     * @return static
161     * @throws InvalidArgumentException If the data is invalid.
162     */
163    public static function jsonUnserialize( $data ) {
164        $data = (array) $data;
165        if ( ! isset( $data['__class__'] ) ) {
166            throw new InvalidArgumentException( 'Invalid data' );
167        }
168        $class = $data['__class__'];
169        unset( $data['__class__'] );
170        if ( ! class_exists( $class ) || ! is_a( $class, static::class, true ) ) {
171            throw new InvalidArgumentException( "Cannot instantiate $class via " . static::class . '::' . __FUNCTION__ );
172        }
173        $ret = new $class();
174        if ( isset( $data['prologue'] ) ) {
175            $ret->setPrologue( $data['prologue'] );
176        }
177        if ( isset( $data['epilogue'] ) ) {
178            $ret->setEpilogue( $data['epilogue'] );
179        }
180        if ( isset( $data['entries'] ) ) {
181            $ret->setEntries( array_map( array( ChangelogEntry::class, 'jsonUnserialize' ), $data['entries'] ) );
182        }
183        return $ret;
184    }
185}