1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Charcoal\Object; |
4
|
|
|
|
5
|
|
|
use DateTime; |
6
|
|
|
use DateTimeInterface; |
7
|
|
|
use InvalidArgumentException; |
8
|
|
|
use UnexpectedValueException; |
9
|
|
|
use Exception; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Publishable Object |
13
|
|
|
* |
14
|
|
|
* A full implementation, as trait, of the {@see \Charcoal\Object\PublishableInterface}. |
15
|
|
|
*/ |
16
|
|
|
trait PublishableTrait |
17
|
|
|
{ |
18
|
|
|
/** |
19
|
|
|
* The publication date. |
20
|
|
|
* |
21
|
|
|
* @var DateTimeInterface $publishDate |
22
|
|
|
*/ |
23
|
|
|
protected $publishDate; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* The expiration date. |
27
|
|
|
* |
28
|
|
|
* @var DateTimeInterface $expiryDate |
29
|
|
|
*/ |
30
|
|
|
protected $expiryDate; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* The publication status. |
34
|
|
|
* |
35
|
|
|
* @var string|null |
36
|
|
|
*/ |
37
|
|
|
protected $publishStatus; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Set the object's publication date. |
41
|
|
|
* |
42
|
|
|
* @param string|DateTimeInterface|null $time The date/time value. |
43
|
|
|
* @throws UnexpectedValueException If the date/time value is invalid. |
44
|
|
|
* @throws InvalidArgumentException If the value is not a date/time instance. |
45
|
|
|
* @return PublishableInterface Chainable |
46
|
|
|
*/ |
47
|
|
View Code Duplication |
public function setPublishDate($time) |
|
|
|
|
48
|
|
|
{ |
49
|
|
|
if ($time === null || $time === '') { |
50
|
|
|
$this->publishDate = null; |
51
|
|
|
return $this; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
if (is_string($time)) { |
55
|
|
|
try { |
56
|
|
|
$time = new DateTime($time); |
57
|
|
|
} catch (Exception $e) { |
58
|
|
|
throw new UnexpectedValueException(sprintf( |
59
|
|
|
'Invalid Publication Date: %s', |
60
|
|
|
$e->getMessage() |
61
|
|
|
), $e->getCode(), $e); |
62
|
|
|
} |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
if (!$time instanceof DateTimeInterface) { |
66
|
|
|
throw new InvalidArgumentException( |
67
|
|
|
'Publication Date must be a date/time string or an instance of DateTimeInterface' |
68
|
|
|
); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
$this->publishDate = $time; |
72
|
|
|
|
73
|
|
|
return $this; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Retrieve the object's publication date. |
78
|
|
|
* |
79
|
|
|
* @return DateTimeInterface|null |
80
|
|
|
*/ |
81
|
|
|
public function getPublishDate() |
82
|
|
|
{ |
83
|
|
|
return $this->publishDate; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Set the object's expiration date. |
88
|
|
|
* |
89
|
|
|
* @param string|DateTimeInterface|null $time The date/time value. |
90
|
|
|
* @throws UnexpectedValueException If the date/time value is invalid. |
91
|
|
|
* @throws InvalidArgumentException If the value is not a date/time instance. |
92
|
|
|
* @return PublishableInterface Chainable |
93
|
|
|
*/ |
94
|
|
View Code Duplication |
public function setExpiryDate($time) |
|
|
|
|
95
|
|
|
{ |
96
|
|
|
if ($time === null || $time === '') { |
97
|
|
|
$this->expiryDate = null; |
98
|
|
|
return $this; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
if (is_string($time)) { |
102
|
|
|
try { |
103
|
|
|
$time = new DateTime($time); |
104
|
|
|
} catch (Exception $e) { |
105
|
|
|
throw new UnexpectedValueException(sprintf( |
106
|
|
|
'Invalid Expiration Date: %s', |
107
|
|
|
$e->getMessage() |
108
|
|
|
), $e->getCode(), $e); |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
if (!$time instanceof DateTimeInterface) { |
113
|
|
|
throw new InvalidArgumentException( |
114
|
|
|
'Expiration Date must be a date/time string or an instance of DateTimeInterface' |
115
|
|
|
); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$this->expiryDate = $time; |
119
|
|
|
|
120
|
|
|
return $this; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Retrieve the object's expiration date. |
125
|
|
|
* |
126
|
|
|
* @return DateTimeInterface|null |
127
|
|
|
*/ |
128
|
|
|
public function getExpiryDate() |
129
|
|
|
{ |
130
|
|
|
return $this->expiryDate; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Set the object's publication status. |
135
|
|
|
* |
136
|
|
|
* @param string $status A publication status. |
137
|
|
|
* @throws InvalidArgumentException If the status is invalid. |
138
|
|
|
* @return PublishableInterface Chainable |
139
|
|
|
*/ |
140
|
|
|
public function setPublishStatus($status) |
141
|
|
|
{ |
142
|
|
|
if ($status === null || $status === '') { |
143
|
|
|
$this->publishStatus = null; |
144
|
|
|
return $this; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$specialStatus = [ |
148
|
|
|
static::STATUS_EXPIRED => static::STATUS_PUBLISHED, |
149
|
|
|
static::STATUS_UPCOMING => static::STATUS_PUBLISHED |
150
|
|
|
]; |
151
|
|
|
|
152
|
|
|
/** Resolve any special statuses */ |
153
|
|
|
if (isset($specialStatus[$status])) { |
154
|
|
|
$status = $specialStatus[$status]; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
$validStatus = [ |
158
|
|
|
static::STATUS_DRAFT, |
159
|
|
|
static::STATUS_PENDING, |
160
|
|
|
static::STATUS_PUBLISHED |
161
|
|
|
]; |
162
|
|
|
|
163
|
|
|
if (!in_array($status, $validStatus)) { |
164
|
|
|
throw new InvalidArgumentException(sprintf( |
165
|
|
|
'Status "%s" is not a valid publish status.', |
166
|
|
|
$status |
167
|
|
|
)); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$this->publishStatus = $status; |
171
|
|
|
|
172
|
|
|
return $this; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Retrieve the object's publication status. |
177
|
|
|
* |
178
|
|
|
* @return string|null |
179
|
|
|
*/ |
180
|
|
|
public function getPublishStatus() |
181
|
|
|
{ |
182
|
|
|
return $this->publishStatus; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Retrieve the object's publication status based on publication and expiration dates. |
187
|
|
|
* |
188
|
|
|
* - If the publication status is not "published", that status is returned (e.g., "draft", "pending", NULL). |
189
|
|
|
* - If no publication date is set, then it's assumed to be always published (or "expired"). |
190
|
|
|
* - If no expiration date is set, then it's assumed to never expire. |
191
|
|
|
* - If a publication date is set to a future date, then it's assumed to be scheduled to be published ("upcoming"). |
192
|
|
|
* |
193
|
|
|
* @return string|null |
194
|
|
|
*/ |
195
|
|
|
public function publishDateStatus() |
196
|
|
|
{ |
197
|
|
|
$now = new DateTime(); |
198
|
|
|
$publish = $this['publishDate']; |
199
|
|
|
$expiry = $this['expiryDate']; |
200
|
|
|
$status = $this['publishStatus']; |
201
|
|
|
|
202
|
|
|
if ($status !== static::STATUS_PUBLISHED) { |
203
|
|
|
return $status; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
if (!$publish) { |
207
|
|
|
if (!$expiry || $now < $expiry) { |
208
|
|
|
return static::STATUS_PUBLISHED; |
209
|
|
|
} else { |
210
|
|
|
return static::STATUS_EXPIRED; |
211
|
|
|
} |
212
|
|
|
} else { |
213
|
|
|
if ($now < $publish) { |
214
|
|
|
return static::STATUS_UPCOMING; |
215
|
|
|
} else { |
216
|
|
|
if (!$expiry || $now < $expiry) { |
217
|
|
|
return static::STATUS_PUBLISHED; |
218
|
|
|
} else { |
219
|
|
|
return static::STATUS_EXPIRED; |
220
|
|
|
} |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Determine if the object is published. |
227
|
|
|
* |
228
|
|
|
* @return boolean |
229
|
|
|
*/ |
230
|
|
|
public function isPublished() |
231
|
|
|
{ |
232
|
|
|
return ($this->publishDateStatus() === static::STATUS_PUBLISHED); |
233
|
|
|
} |
234
|
|
|
} |
235
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.