|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Charcoal\Cms; |
|
4
|
|
|
|
|
5
|
|
|
use DateTime; |
|
6
|
|
|
use DateTimeInterface; |
|
7
|
|
|
use InvalidArgumentException; |
|
8
|
|
|
|
|
9
|
|
|
|
|
10
|
|
|
// From 'charcoal-object' |
|
11
|
|
|
use Charcoal\Object\Content; |
|
12
|
|
|
use Charcoal\Object\CategorizableTrait; |
|
13
|
|
|
use Charcoal\Object\PublishableTrait; |
|
14
|
|
|
use Charcoal\Object\RoutableTrait; |
|
15
|
|
|
|
|
16
|
|
|
// From 'charcoal-translator' |
|
17
|
|
|
use Charcoal\Translator\Translation; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* |
|
21
|
|
|
*/ |
|
22
|
|
|
abstract class AbstractEvent extends Content implements EventInterface |
|
23
|
|
|
{ |
|
24
|
|
|
use CategorizableTrait; |
|
25
|
|
|
use MetatagTrait; |
|
26
|
|
|
use PublishableTrait; |
|
27
|
|
|
use RoutableTrait; |
|
28
|
|
|
use SearchableTrait; |
|
29
|
|
|
use TemplateableTrait; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* @var Translation|string|null |
|
33
|
|
|
*/ |
|
34
|
|
|
private $title; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* @var Translation|string|null |
|
38
|
|
|
*/ |
|
39
|
|
|
private $subtitle; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* @var Translation|string|null |
|
43
|
|
|
*/ |
|
44
|
|
|
private $summary; |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* @var Translation|string|null |
|
48
|
|
|
*/ |
|
49
|
|
|
private $content; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* @var Translation|string|null |
|
53
|
|
|
*/ |
|
54
|
|
|
private $image; |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* @var DateTimeInterface|null |
|
58
|
|
|
*/ |
|
59
|
|
|
private $startDate; |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* @var DateTimeInterface|null |
|
63
|
|
|
*/ |
|
64
|
|
|
private $endDate; |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* @var Translation|string|null |
|
68
|
|
|
*/ |
|
69
|
|
|
private $infoUrl; |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* @var string |
|
73
|
|
|
*/ |
|
74
|
|
|
private $infoPhone; |
|
75
|
|
|
|
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* @var float|null |
|
79
|
|
|
*/ |
|
80
|
|
|
private $ticketPriceMin; |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* @var float|null |
|
84
|
|
|
*/ |
|
85
|
|
|
private $ticketPriceMax; |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* @var Translation|string|null |
|
89
|
|
|
*/ |
|
90
|
|
|
private $ticketSummary; |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* @var Translation|string|null |
|
94
|
|
|
*/ |
|
95
|
|
|
private $ticketUrl; |
|
96
|
|
|
|
|
97
|
|
|
/** |
|
98
|
|
|
* @var string |
|
99
|
|
|
*/ |
|
100
|
|
|
private $ticketPhone; |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* @var array |
|
104
|
|
|
*/ |
|
105
|
|
|
protected $keywords; |
|
106
|
|
|
|
|
107
|
|
|
/** |
|
108
|
|
|
* Section constructor. |
|
109
|
|
|
* @param array $data The data. |
|
110
|
|
|
*/ |
|
111
|
|
|
public function __construct(array $data = null) |
|
112
|
|
|
{ |
|
113
|
|
|
parent::__construct($data); |
|
114
|
|
|
|
|
115
|
|
|
if (is_callable([ $this, 'defaultData' ])) { |
|
116
|
|
|
$this->setData($this->defaultData()); |
|
117
|
|
|
} |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
/** |
|
121
|
|
|
* @see MetataTrait::canonicalUrl |
|
122
|
|
|
* @return string |
|
123
|
|
|
*/ |
|
124
|
|
|
public function canonicalUrl() |
|
125
|
|
|
{ |
|
126
|
|
|
return ''; |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* Some dates cannot be null |
|
131
|
|
|
* @return void |
|
132
|
|
|
*/ |
|
133
|
|
|
public function verifyDates() |
|
134
|
|
|
{ |
|
135
|
|
|
if (!$this->startDate()) { |
|
136
|
|
|
$this->setStartDate('now'); |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
if (!$this->endDate()) { |
|
140
|
|
|
$this->setEndDate($this->startDate()); |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
if (!$this->publishDate()) { |
|
144
|
|
|
$this->setPublishDate('now'); |
|
145
|
|
|
} |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
/** |
|
149
|
|
|
* @return string The date filtered for admin dual select input and others. |
|
150
|
|
|
*/ |
|
151
|
|
|
public function adminDateFilter() |
|
152
|
|
|
{ |
|
153
|
|
|
$start = $this->startDate()->format('Y-m-d'); |
|
154
|
|
|
$end = $this->endDate()->format('Y-m-d'); |
|
155
|
|
|
|
|
156
|
|
|
if ($start === $end) { |
|
157
|
|
|
$date = $start; |
|
158
|
|
|
} else { |
|
159
|
|
|
$date = $start.' - '.$end; |
|
160
|
|
|
} |
|
161
|
|
|
|
|
162
|
|
|
return $date; |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
/** |
|
166
|
|
|
* @param mixed $title The event title (localized). |
|
167
|
|
|
* @return self |
|
168
|
|
|
*/ |
|
169
|
|
|
public function setTitle($title) |
|
170
|
|
|
{ |
|
171
|
|
|
$this->title = $this->translator()->translation($title); |
|
172
|
|
|
|
|
173
|
|
|
return $this; |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* @return Translation|string|null |
|
178
|
|
|
*/ |
|
179
|
|
|
public function title() |
|
180
|
|
|
{ |
|
181
|
|
|
return $this->title; |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
|
|
/** |
|
185
|
|
|
* @param mixed $subtitle The event subtitle (localized). |
|
186
|
|
|
* @return self |
|
187
|
|
|
*/ |
|
188
|
|
|
public function setSubtitle($subtitle) |
|
189
|
|
|
{ |
|
190
|
|
|
$this->subtitle = $this->translator()->translation($subtitle); |
|
191
|
|
|
|
|
192
|
|
|
return $this; |
|
193
|
|
|
} |
|
194
|
|
|
|
|
195
|
|
|
/** |
|
196
|
|
|
* @return Translation|string|null |
|
197
|
|
|
*/ |
|
198
|
|
|
public function subtitle() |
|
199
|
|
|
{ |
|
200
|
|
|
return $this->subtitle; |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
/** |
|
204
|
|
|
* @param mixed $summary The news summary (localized). |
|
205
|
|
|
* @return self |
|
206
|
|
|
*/ |
|
207
|
|
|
public function setSummary($summary) |
|
208
|
|
|
{ |
|
209
|
|
|
$this->summary = $this->translator()->translation($summary); |
|
210
|
|
|
|
|
211
|
|
|
return $this; |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
/** |
|
215
|
|
|
* @return Translation|string|null |
|
216
|
|
|
*/ |
|
217
|
|
|
public function summary() |
|
218
|
|
|
{ |
|
219
|
|
|
return $this->summary; |
|
220
|
|
|
} |
|
221
|
|
|
|
|
222
|
|
|
/** |
|
223
|
|
|
* @param mixed $content The event content (localized). |
|
224
|
|
|
* @return self |
|
225
|
|
|
*/ |
|
226
|
|
|
public function setContent($content) |
|
227
|
|
|
{ |
|
228
|
|
|
$this->content = $this->translator()->translation($content); |
|
229
|
|
|
|
|
230
|
|
|
return $this; |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
|
|
/** |
|
234
|
|
|
* @return Translation|string|null |
|
235
|
|
|
*/ |
|
236
|
|
|
public function content() |
|
237
|
|
|
{ |
|
238
|
|
|
return $this->content; |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
/** |
|
242
|
|
|
* @param mixed $image The section main image (localized). |
|
243
|
|
|
* @return self |
|
244
|
|
|
*/ |
|
245
|
|
|
public function setImage($image) |
|
246
|
|
|
{ |
|
247
|
|
|
$this->image = $this->translator()->translation($image); |
|
248
|
|
|
|
|
249
|
|
|
return $this; |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
/** |
|
253
|
|
|
* @return Translation|string|null |
|
254
|
|
|
*/ |
|
255
|
|
|
public function image() |
|
256
|
|
|
{ |
|
257
|
|
|
return $this->image; |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
/** |
|
261
|
|
|
* @param string|DateTimeInterface|null $startDate Event starting date. |
|
262
|
|
|
* @throws InvalidArgumentException If the timestamp is invalid. |
|
263
|
|
|
* @return self |
|
264
|
|
|
*/ |
|
265
|
|
View Code Duplication |
public function setStartDate($startDate) |
|
|
|
|
|
|
266
|
|
|
{ |
|
267
|
|
|
if ($startDate === null || $startDate === '') { |
|
268
|
|
|
$this->startDate = null; |
|
269
|
|
|
|
|
270
|
|
|
return $this; |
|
271
|
|
|
} |
|
272
|
|
|
if (is_string($startDate)) { |
|
273
|
|
|
$startDate = new DateTime($startDate); |
|
274
|
|
|
} |
|
275
|
|
|
if (!($startDate instanceof DateTimeInterface)) { |
|
276
|
|
|
throw new InvalidArgumentException( |
|
277
|
|
|
'Invalid "Start Date" value. Must be a date/time string or a DateTime object.' |
|
278
|
|
|
); |
|
279
|
|
|
} |
|
280
|
|
|
$this->startDate = $startDate; |
|
281
|
|
|
|
|
282
|
|
|
return $this; |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
/** |
|
286
|
|
|
* @return DateTimeInterface|null |
|
287
|
|
|
*/ |
|
288
|
|
|
public function startDate() |
|
289
|
|
|
{ |
|
290
|
|
|
return $this->startDate; |
|
291
|
|
|
} |
|
292
|
|
|
|
|
293
|
|
|
/** |
|
294
|
|
|
* @param string|DateTimeInterface|null $endDate Event end date. |
|
295
|
|
|
* @throws InvalidArgumentException If the timestamp is invalid. |
|
296
|
|
|
* @return self |
|
297
|
|
|
*/ |
|
298
|
|
View Code Duplication |
public function setEndDate($endDate) |
|
|
|
|
|
|
299
|
|
|
{ |
|
300
|
|
|
if ($endDate === null || $endDate === '') { |
|
301
|
|
|
$this->endDate = null; |
|
302
|
|
|
|
|
303
|
|
|
return $this; |
|
304
|
|
|
} |
|
305
|
|
|
if (is_string($endDate)) { |
|
306
|
|
|
$endDate = new DateTime($endDate); |
|
307
|
|
|
} |
|
308
|
|
|
if (!($endDate instanceof DateTimeInterface)) { |
|
309
|
|
|
throw new InvalidArgumentException( |
|
310
|
|
|
'Invalid "End Date" value. Must be a date/time string or a DateTime object.' |
|
311
|
|
|
); |
|
312
|
|
|
} |
|
313
|
|
|
$this->endDate = $endDate; |
|
314
|
|
|
|
|
315
|
|
|
return $this; |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
/** |
|
319
|
|
|
* @return DateTimeInterface|null |
|
320
|
|
|
*/ |
|
321
|
|
|
public function endDate() |
|
322
|
|
|
{ |
|
323
|
|
|
return $this->endDate; |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
/** |
|
327
|
|
|
* @param mixed $url The information URL (localized). |
|
328
|
|
|
* @return self |
|
329
|
|
|
*/ |
|
330
|
|
|
public function setInfoUrl($url) |
|
331
|
|
|
{ |
|
332
|
|
|
$this->infoUrl = $this->translator()->translation($url); |
|
333
|
|
|
return $this; |
|
334
|
|
|
} |
|
335
|
|
|
|
|
336
|
|
|
/** |
|
337
|
|
|
* @return Translation|null|string |
|
338
|
|
|
*/ |
|
339
|
|
|
public function infoUrl() |
|
340
|
|
|
{ |
|
341
|
|
|
return $this->infoUrl; |
|
342
|
|
|
} |
|
343
|
|
|
|
|
344
|
|
|
/** |
|
345
|
|
|
* @param mixed $phone General information phone number. |
|
346
|
|
|
* @return self |
|
347
|
|
|
*/ |
|
348
|
|
|
public function setInfoPhone($phone) |
|
349
|
|
|
{ |
|
350
|
|
|
$this->infoPhone = $phone; |
|
351
|
|
|
return $this; |
|
352
|
|
|
} |
|
353
|
|
|
|
|
354
|
|
|
/** |
|
355
|
|
|
* @return string|null |
|
356
|
|
|
*/ |
|
357
|
|
|
public function infoPhone() |
|
358
|
|
|
{ |
|
359
|
|
|
return $this->infoPhone; |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
/** |
|
363
|
|
|
* @param float $price The minimum ticket price. |
|
364
|
|
|
* @return self |
|
365
|
|
|
*/ |
|
366
|
|
|
public function setTicketPriceMin($price) |
|
367
|
|
|
{ |
|
368
|
|
|
$this->ticketPriceMin = (float)$price; |
|
369
|
|
|
return $this; |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
/** |
|
373
|
|
|
* @return float|null |
|
374
|
|
|
*/ |
|
375
|
|
|
public function ticketPriceMin() |
|
376
|
|
|
{ |
|
377
|
|
|
return $this->ticketPriceMin; |
|
378
|
|
|
} |
|
379
|
|
|
|
|
380
|
|
|
/** |
|
381
|
|
|
* @param float $price The maximum ticket price. |
|
382
|
|
|
* @return self |
|
383
|
|
|
*/ |
|
384
|
|
|
public function setTicketPriceMax($price) |
|
385
|
|
|
{ |
|
386
|
|
|
$this->ticketPriceMax = (float)$price; |
|
387
|
|
|
return $this; |
|
388
|
|
|
} |
|
389
|
|
|
|
|
390
|
|
|
/** |
|
391
|
|
|
* @return float|null |
|
392
|
|
|
*/ |
|
393
|
|
|
public function ticketPriceMax() |
|
394
|
|
|
{ |
|
395
|
|
|
return $this->ticketPriceMax; |
|
396
|
|
|
} |
|
397
|
|
|
|
|
398
|
|
|
/** |
|
399
|
|
|
* @param mixed $summary The ticket summary / information (localized). |
|
400
|
|
|
* @return self |
|
401
|
|
|
*/ |
|
402
|
|
|
public function setTicketSummary($summary) |
|
403
|
|
|
{ |
|
404
|
|
|
$this->ticketSummary = $this->translator()->translation($summary); |
|
405
|
|
|
return $this; |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
/** |
|
409
|
|
|
* @return Translation|null |
|
410
|
|
|
*/ |
|
411
|
|
|
public function ticketSummary() |
|
412
|
|
|
{ |
|
413
|
|
|
return $this->ticketSummary; |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
/** |
|
417
|
|
|
* @param mixed $url The ticket URL (localized). |
|
418
|
|
|
* @return self |
|
419
|
|
|
*/ |
|
420
|
|
|
public function setTicketUrl($url) |
|
421
|
|
|
{ |
|
422
|
|
|
$this->ticketUrl = $this->translator()->translation($url); |
|
423
|
|
|
return $this; |
|
424
|
|
|
} |
|
425
|
|
|
|
|
426
|
|
|
/** |
|
427
|
|
|
* @return Translation|null |
|
428
|
|
|
*/ |
|
429
|
|
|
public function ticketUrl() |
|
430
|
|
|
{ |
|
431
|
|
|
return $this->ticketUrl; |
|
432
|
|
|
} |
|
433
|
|
|
|
|
434
|
|
|
/** |
|
435
|
|
|
* @param string|null $phone Tickets phone number. |
|
436
|
|
|
* @return self |
|
437
|
|
|
*/ |
|
438
|
|
|
public function setTicketPhone($phone) |
|
439
|
|
|
{ |
|
440
|
|
|
$this->ticketPhone = $phone; |
|
441
|
|
|
return $this; |
|
442
|
|
|
} |
|
443
|
|
|
|
|
444
|
|
|
/** |
|
445
|
|
|
* @return string|null |
|
446
|
|
|
*/ |
|
447
|
|
|
public function ticketPhone() |
|
448
|
|
|
{ |
|
449
|
|
|
return $this->ticketPhone; |
|
450
|
|
|
} |
|
451
|
|
|
|
|
452
|
|
|
/** |
|
453
|
|
|
* @return Translation|null |
|
454
|
|
|
*/ |
|
455
|
|
|
public function defaultMetaTitle() |
|
456
|
|
|
{ |
|
457
|
|
|
return $this->title(); |
|
458
|
|
|
} |
|
459
|
|
|
|
|
460
|
|
|
/** |
|
461
|
|
|
* @return Translation|string|null |
|
462
|
|
|
*/ |
|
463
|
|
View Code Duplication |
public function defaultMetaDescription() |
|
|
|
|
|
|
464
|
|
|
{ |
|
465
|
|
|
$content = $this->translator()->translation($this->content()); |
|
466
|
|
|
if ($content instanceof Translation) { |
|
467
|
|
|
$desc = []; |
|
468
|
|
|
foreach ($content->data() as $lang => $text) { |
|
469
|
|
|
$desc[$lang] = strip_tags($text); |
|
470
|
|
|
} |
|
471
|
|
|
|
|
472
|
|
|
return $this->translator()->translation($desc); |
|
473
|
|
|
} |
|
474
|
|
|
|
|
475
|
|
|
return null; |
|
476
|
|
|
} |
|
477
|
|
|
|
|
478
|
|
|
/** |
|
479
|
|
|
* @return Translation|string|null |
|
480
|
|
|
*/ |
|
481
|
|
|
public function defaultMetaImage() |
|
482
|
|
|
{ |
|
483
|
|
|
return $this->image(); |
|
484
|
|
|
} |
|
485
|
|
|
|
|
486
|
|
|
/** |
|
487
|
|
|
* Retrieve the object's keywords. |
|
488
|
|
|
* |
|
489
|
|
|
* @return string[] |
|
490
|
|
|
*/ |
|
491
|
|
|
public function keywords() |
|
492
|
|
|
{ |
|
493
|
|
|
return $this->keywords; |
|
494
|
|
|
} |
|
495
|
|
|
|
|
496
|
|
|
/** |
|
497
|
|
|
* GenericRoute checks if the route is active. |
|
498
|
|
|
* Default in RoutableTrait. |
|
499
|
|
|
* |
|
500
|
|
|
* @return boolean |
|
501
|
|
|
*/ |
|
502
|
|
|
public function isActiveRoute() |
|
503
|
|
|
{ |
|
504
|
|
|
return ( |
|
505
|
|
|
$this->active() && |
|
506
|
|
|
$this->isPublished() |
|
507
|
|
|
); |
|
508
|
|
|
} |
|
509
|
|
|
|
|
510
|
|
|
/** |
|
511
|
|
|
* {@inheritdoc} |
|
512
|
|
|
* |
|
513
|
|
|
* @return boolean |
|
514
|
|
|
*/ |
|
515
|
|
|
protected function preSave() |
|
516
|
|
|
{ |
|
517
|
|
|
$this->verifyDates(); |
|
518
|
|
|
$this->setSlug($this->generateSlug()); |
|
519
|
|
|
|
|
520
|
|
|
return parent::preSave(); |
|
521
|
|
|
} |
|
522
|
|
|
|
|
523
|
|
|
/** |
|
524
|
|
|
* {@inheritdoc} |
|
525
|
|
|
* |
|
526
|
|
|
* @param array $properties Optional properties to update. |
|
527
|
|
|
* @return boolean |
|
528
|
|
|
*/ |
|
529
|
|
|
protected function preUpdate(array $properties = null) |
|
530
|
|
|
{ |
|
531
|
|
|
$this->verifyDates(); |
|
532
|
|
|
$this->setSlug($this->generateSlug()); |
|
533
|
|
|
|
|
534
|
|
|
return parent::preUpdate($properties); |
|
535
|
|
|
} |
|
536
|
|
|
|
|
537
|
|
|
/** |
|
538
|
|
|
* @return boolean Parent postSave(). |
|
539
|
|
|
*/ |
|
540
|
|
|
protected function postSave() |
|
541
|
|
|
{ |
|
542
|
|
|
// RoutableTrait |
|
543
|
|
|
$this->generateObjectRoute($this->slug()); |
|
544
|
|
|
|
|
545
|
|
|
return parent::postSave(); |
|
546
|
|
|
} |
|
547
|
|
|
|
|
548
|
|
|
/** |
|
549
|
|
|
* @param array|null $properties Properties. |
|
550
|
|
|
* @return boolean |
|
551
|
|
|
*/ |
|
552
|
|
|
protected function postUpdate(array $properties = null) |
|
553
|
|
|
{ |
|
554
|
|
|
// RoutableTrait |
|
555
|
|
|
$this->generateObjectRoute($this->slug()); |
|
556
|
|
|
|
|
557
|
|
|
return parent::postUpdate($properties); |
|
|
|
|
|
|
558
|
|
|
} |
|
559
|
|
|
} |
|
560
|
|
|
|
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.