Completed
Push — add/changelog-tooling ( b30521...fa9ac3 )
by
unknown
1097:09 queued 1086:59
created

ChangelogEntry::insertEntry()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 2
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
2
/**
3
 * Class representing a changelog entry.
4
 *
5
 * @package automattic/jetpack-changelogger
6
 */
7
8
// phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
9
10
namespace Automattic\Jetpack\Changelog;
11
12
use DateTime;
13
use InvalidArgumentException;
14
15
/**
16
 * Class representing a changelog entry.
17
 */
18
class ChangelogEntry {
19
20
	/**
21
	 * Entry version.
22
	 *
23
	 * @var string
24
	 */
25
	protected $version;
26
27
	/**
28
	 * Entry link.
29
	 *
30
	 * @var string|null
31
	 */
32
	protected $link = null;
33
34
	/**
35
	 * Entry timestamp.
36
	 *
37
	 * @var DateTime
38
	 */
39
	protected $timestamp;
40
41
	/**
42
	 * Content before the changes themselves.
43
	 *
44
	 * @var string
45
	 */
46
	protected $prologue = '';
47
48
	/**
49
	 * Content after the changes themselves.
50
	 *
51
	 * @var string
52
	 */
53
	protected $epilogue = '';
54
55
	/**
56
	 * Changes.
57
	 *
58
	 * @var ChangeEntry[]
59
	 */
60
	protected $changes = array();
61
62
	/**
63
	 * Constructor.
64
	 *
65
	 * @param string $version Version for the new entry.
66
	 * @param array  $data Data for other entry fields. Keys correspond to the setters, e.g. key 'link' calls `setLink()`.
67
	 * @throws InvalidArgumentException If an argument is invalid.
68
	 */
69 View Code Duplication
	public function __construct( $version, array $data = array() ) {
70
		$data = array( 'version' => $version ) + $data + array( 'timestamp' => 'now' );
71
		foreach ( $data as $k => $v ) {
72
			$func = array( $this, 'set' . ucfirst( $k ) );
73
			if ( is_callable( $func ) ) {
74
				$func( $v );
75
			} else {
76
				throw new InvalidArgumentException( __METHOD__ . ": Unrecognized data item \"$k\"." );
77
			}
78
		}
79
	}
80
81
	/**
82
	 * Get the version.
83
	 *
84
	 * @return string
85
	 */
86
	public function getVersion() {
87
		return $this->version;
88
	}
89
90
	/**
91
	 * Set the version.
92
	 *
93
	 * @param string $version Version to set.
94
	 * @returns $this
95
	 * @throws InvalidArgumentException If an argument is invalid.
96
	 */
97
	public function setVersion( $version ) {
98
		$version = (string) $version;
99
		if ( '' === $version ) {
100
			throw new InvalidArgumentException( __METHOD__ . ': Version may not be empty' );
101
		}
102
		$this->version = (string) $version;
103
		return $this;
104
	}
105
106
	/**
107
	 * Get the link.
108
	 *
109
	 * @return string|null
110
	 */
111
	public function getLink() {
112
		return $this->link;
113
	}
114
115
	/**
116
	 * Set the link.
117
	 *
118
	 * @param string|null $link Link to set.
119
	 * @returns $this
120
	 * @throws InvalidArgumentException If an argument is invalid.
121
	 */
122
	public function setLink( $link ) {
123
		if ( '' === $link ) {
124
			$link = null;
125
		} elseif ( null !== $link ) {
126
			$link = filter_var( $link, FILTER_VALIDATE_URL );
127
			if ( ! is_string( $link ) ) {
128
				throw new InvalidArgumentException( __METHOD__ . ': Invalid URL' );
129
			}
130
		}
131
		$this->link = $link;
132
		return $this;
133
	}
134
135
	/**
136
	 * Get the timestamp.
137
	 *
138
	 * @return DateTime
139
	 */
140
	public function getTimestamp() {
141
		return $this->timestamp;
142
	}
143
144
	/**
145
	 * Set the timestamp.
146
	 *
147
	 * @param DateTime|string $timestamp Timestamp to set.
148
	 * @returns $this
149
	 * @throws InvalidArgumentException If an argument is invalid.
150
	 */
151 View Code Duplication
	public function setTimestamp( $timestamp ) {
152
		if ( ! $timestamp instanceof DateTime ) {
153
			try {
154
				$timestamp = new DateTime( $timestamp );
155
			} catch ( \Exception $ex ) {
156
				throw new InvalidArgumentException( __METHOD__ . ': Invalid timestamp', 0, $ex );
157
			}
158
		}
159
		$this->timestamp = $timestamp;
160
		return $this;
161
	}
162
163
	/**
164
	 * Get the prologue content.
165
	 *
166
	 * @return string
167
	 */
168
	public function getPrologue() {
169
		return $this->prologue;
170
	}
171
172
	/**
173
	 * Set the prologue content.
174
	 *
175
	 * @param string $prologue Prologue content to set.
176
	 * @return $this
177
	 */
178
	public function setPrologue( $prologue ) {
179
		$this->prologue = (string) $prologue;
180
		return $this;
181
	}
182
183
	/**
184
	 * Get the epilogue content.
185
	 *
186
	 * @return string
187
	 */
188
	public function getEpilogue() {
189
		return $this->epilogue;
190
	}
191
192
	/**
193
	 * Set the epilogue content.
194
	 *
195
	 * @param string $epilogue Epilogue content to set.
196
	 * @return $this
197
	 */
198
	public function setEpilogue( $epilogue ) {
199
		$this->epilogue = (string) $epilogue;
200
		return $this;
201
	}
202
203
	/**
204
	 * Get the list of changes.
205
	 *
206
	 * @return ChangeEntry[]
207
	 */
208
	public function getChanges() {
209
		return $this->changes;
210
	}
211
212
	/**
213
	 * Set the list of changes.
214
	 *
215
	 * This replaces all existing changes. The caller is responsible
216
	 * for making sure the changes are sorted properly.
217
	 *
218
	 * @param ChangeEntry[] $changes Changes.
219
	 * @return $this
220
	 * @throws InvalidArgumentException If an argument is invalid.
221
	 */
222 View Code Duplication
	public function setChanges( array $changes ) {
223
		foreach ( $changes as $i => $change ) {
224
			if ( ! $change instanceof ChangeEntry ) {
225
				$what = is_object( $change ) ? get_class( $change ) : gettype( $change );
226
				throw new InvalidArgumentException( __METHOD__ . ": Expected a ChangeEntry, got $what at index $i" );
227
			}
228
		}
229
		$this->changes = array_values( $changes );
230
		return $this;
231
	}
232
233
	/**
234
	 * Add a new change.
235
	 *
236
	 * The new change is inserted before the first existing change where
237
	 * `ChangeEntry::compare()` says the existing change should come after.
238
	 *
239
	 * @param ChangeEntry $change New change.
240
	 * @param array       $compareconfig Comparison config, see `ChangeEntry::compare()`.
241
	 * @return $this
242
	 */
243
	public function insertChange( ChangeEntry $change, $compareconfig = array() ) {
244
		foreach ( $this->changes as $i => $e ) {
245
			if ( ChangeEntry::compare( $change, $e, $compareconfig ) < 0 ) {
246
				array_splice( $this->changes, $i, 0, array( $change ) );
247
				return $this;
248
			}
249
		}
250
		$this->changes[] = $change;
251
		return $this;
252
	}
253
254
	/**
255
	 * Append a new change.
256
	 *
257
	 * @param ChangeEntry $change New change.
258
	 * @return $this
259
	 */
260
	public function appendChange( ChangeEntry $change ) {
261
		$this->changes[] = $change;
262
		return $this;
263
	}
264
265
	/**
266
	 * Get the changes grouped by subheading.
267
	 *
268
	 * @param string|null $subheading Subheading to retrieve.
269
	 * @return ChangeEntry[]|ChangeEntry[][] An array of changes with the
270
	 *   heading if `$subheading` was passed, or an array keyed by subheading of
271
	 *   arrays of changes if it was null.
272
	 */
273
	public function getChangesBySubheading( $subheading = null ) {
274
		$ret = array();
275
		foreach ( $this->changes as $entry ) {
276
			$ret[ $entry->getSubheading() ][] = $entry;
277
		}
278
279
		return null === $subheading
280
			? $ret
281
			: ( isset( $ret[ $subheading ] ) ? $ret[ $subheading ] : array() );
282
	}
283
284
}
285