Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
12256 views
1
<?php
2
3
final class PhabricatorCalendarEventEditor
4
extends PhabricatorApplicationTransactionEditor {
5
6
private $oldIsAllDay;
7
private $newIsAllDay;
8
9
public function getEditorApplicationClass() {
10
return 'PhabricatorCalendarApplication';
11
}
12
13
public function getEditorObjectsDescription() {
14
return pht('Calendar');
15
}
16
17
public function getCreateObjectTitle($author, $object) {
18
return pht('%s created this event.', $author);
19
}
20
21
public function getCreateObjectTitleForFeed($author, $object) {
22
return pht('%s created %s.', $author, $object);
23
}
24
25
protected function shouldApplyInitialEffects(
26
PhabricatorLiskDAO $object,
27
array $xactions) {
28
return true;
29
}
30
31
public function getOldIsAllDay() {
32
return $this->oldIsAllDay;
33
}
34
35
public function getNewIsAllDay() {
36
return $this->newIsAllDay;
37
}
38
39
protected function applyInitialEffects(
40
PhabricatorLiskDAO $object,
41
array $xactions) {
42
43
$actor = $this->requireActor();
44
if ($object->getIsStub()) {
45
$this->materializeStub($object);
46
}
47
48
// Before doing anything, figure out if the event will be an all day event
49
// or not after the edit. This affects how we store datetime values, and
50
// whether we render times or not.
51
$old_allday = $object->getIsAllDay();
52
$new_allday = $old_allday;
53
$type_allday = PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE;
54
foreach ($xactions as $xaction) {
55
if ($xaction->getTransactionType() != $type_allday) {
56
continue;
57
}
58
$new_allday = (bool)$xaction->getNewValue();
59
}
60
61
$this->oldIsAllDay = $old_allday;
62
$this->newIsAllDay = $new_allday;
63
}
64
65
private function materializeStub(PhabricatorCalendarEvent $event) {
66
if (!$event->getIsStub()) {
67
throw new Exception(
68
pht('Can not materialize an event stub: this event is not a stub.'));
69
}
70
71
$actor = $this->getActor();
72
73
$invitees = $event->getInvitees();
74
75
$event->copyFromParent($actor);
76
$event->setIsStub(0);
77
78
$event->openTransaction();
79
$event->save();
80
foreach ($invitees as $invitee) {
81
$invitee
82
->setEventPHID($event->getPHID())
83
->save();
84
}
85
$event->saveTransaction();
86
87
$event->attachInvitees($invitees);
88
}
89
90
public function getTransactionTypes() {
91
$types = parent::getTransactionTypes();
92
93
$types[] = PhabricatorTransactions::TYPE_COMMENT;
94
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
95
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
96
97
return $types;
98
}
99
100
protected function adjustObjectForPolicyChecks(
101
PhabricatorLiskDAO $object,
102
array $xactions) {
103
104
$copy = parent::adjustObjectForPolicyChecks($object, $xactions);
105
foreach ($xactions as $xaction) {
106
switch ($xaction->getTransactionType()) {
107
case PhabricatorCalendarEventHostTransaction::TRANSACTIONTYPE:
108
$copy->setHostPHID($xaction->getNewValue());
109
break;
110
case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
111
PhabricatorPolicyRule::passTransactionHintToRule(
112
$copy,
113
new PhabricatorCalendarEventInviteesPolicyRule(),
114
array_fuse($xaction->getNewValue()));
115
break;
116
}
117
}
118
119
return $copy;
120
}
121
122
123
protected function applyFinalEffects(
124
PhabricatorLiskDAO $object,
125
array $xactions) {
126
127
// Clear the availability caches for users whose availability is affected
128
// by this edit.
129
130
$phids = mpull($object->getInvitees(), 'getInviteePHID');
131
$phids = array_fuse($phids);
132
133
$invalidate_all = false;
134
$invalidate_phids = array();
135
foreach ($xactions as $xaction) {
136
switch ($xaction->getTransactionType()) {
137
case PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE:
138
case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE:
139
case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE:
140
case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE:
141
case PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE:
142
// For these kinds of changes, we need to invalidate the availabilty
143
// caches for all attendees.
144
$invalidate_all = true;
145
break;
146
case PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE:
147
case PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE:
148
$acting_phid = $this->getActingAsPHID();
149
$invalidate_phids[$acting_phid] = $acting_phid;
150
break;
151
case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
152
foreach ($xaction->getOldValue() as $phid) {
153
// Add the possibly un-invited user to the list of potentially
154
// affected users if they are't already present.
155
$phids[$phid] = $phid;
156
157
$invalidate_phids[$phid] = $phid;
158
}
159
160
foreach ($xaction->getNewValue() as $phid) {
161
$invalidate_phids[$phid] = $phid;
162
}
163
break;
164
}
165
}
166
167
if (!$invalidate_all) {
168
$phids = array_select_keys($phids, $invalidate_phids);
169
}
170
171
if ($phids) {
172
$object->applyViewerTimezone($this->getActor());
173
174
$user = new PhabricatorUser();
175
$conn_w = $user->establishConnection('w');
176
queryfx(
177
$conn_w,
178
'UPDATE %T SET availabilityCacheTTL = NULL
179
WHERE phid IN (%Ls)',
180
$user->getTableName(),
181
$phids);
182
}
183
184
return $xactions;
185
}
186
187
188
protected function validateAllTransactions(
189
PhabricatorLiskDAO $object,
190
array $xactions) {
191
192
$start_date_xaction =
193
PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE;
194
$end_date_xaction =
195
PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE;
196
$is_recurrence_xaction =
197
PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE;
198
$recurrence_end_xaction =
199
PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE;
200
201
$start_date = $object->getStartDateTimeEpoch();
202
$end_date = $object->getEndDateTimeEpoch();
203
$recurrence_end = $object->getUntilDateTimeEpoch();
204
$is_recurring = $object->getIsRecurring();
205
206
$errors = array();
207
208
foreach ($xactions as $xaction) {
209
if ($xaction->getTransactionType() == $start_date_xaction) {
210
$start_date = $xaction->getNewValue()->getEpoch();
211
} else if ($xaction->getTransactionType() == $end_date_xaction) {
212
$end_date = $xaction->getNewValue()->getEpoch();
213
} else if ($xaction->getTransactionType() == $recurrence_end_xaction) {
214
$recurrence_end = $xaction->getNewValue()->getEpoch();
215
} else if ($xaction->getTransactionType() == $is_recurrence_xaction) {
216
$is_recurring = $xaction->getNewValue();
217
}
218
}
219
220
if ($start_date > $end_date) {
221
$errors[] = new PhabricatorApplicationTransactionValidationError(
222
$end_date_xaction,
223
pht('Invalid'),
224
pht('End date must be after start date.'),
225
null);
226
}
227
228
if ($recurrence_end && !$is_recurring) {
229
$errors[] = new PhabricatorApplicationTransactionValidationError(
230
$recurrence_end_xaction,
231
pht('Invalid'),
232
pht('Event must be recurring to have a recurrence end date.').
233
null);
234
}
235
236
return $errors;
237
}
238
239
protected function shouldPublishFeedStory(
240
PhabricatorLiskDAO $object,
241
array $xactions) {
242
243
if ($object->isImportedEvent()) {
244
return false;
245
}
246
247
return true;
248
}
249
250
protected function supportsSearch() {
251
return true;
252
}
253
254
protected function shouldSendMail(
255
PhabricatorLiskDAO $object,
256
array $xactions) {
257
258
if ($object->isImportedEvent()) {
259
return false;
260
}
261
262
return true;
263
}
264
265
protected function getMailSubjectPrefix() {
266
return pht('[Calendar]');
267
}
268
269
protected function getMailTo(PhabricatorLiskDAO $object) {
270
$phids = array();
271
272
if ($object->getHostPHID()) {
273
$phids[] = $object->getHostPHID();
274
}
275
$phids[] = $this->getActingAsPHID();
276
277
$invitees = $object->getInvitees();
278
foreach ($invitees as $invitee) {
279
$status = $invitee->getStatus();
280
if ($status === PhabricatorCalendarEventInvitee::STATUS_ATTENDING
281
|| $status === PhabricatorCalendarEventInvitee::STATUS_INVITED) {
282
$phids[] = $invitee->getInviteePHID();
283
}
284
}
285
286
$phids = array_unique($phids);
287
288
return $phids;
289
}
290
291
public function getMailTagsMap() {
292
return array(
293
PhabricatorCalendarEventTransaction::MAILTAG_CONTENT =>
294
pht(
295
"An event's name, status, invite list, ".
296
"icon, and description changes."),
297
PhabricatorCalendarEventTransaction::MAILTAG_RESCHEDULE =>
298
pht(
299
"An event's start and end date ".
300
"and cancellation status changes."),
301
PhabricatorCalendarEventTransaction::MAILTAG_OTHER =>
302
pht('Other event activity not listed above occurs.'),
303
);
304
}
305
306
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
307
return id(new PhabricatorCalendarReplyHandler())
308
->setMailReceiver($object);
309
}
310
311
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
312
$name = $object->getName();
313
$monogram = $object->getMonogram();
314
315
return id(new PhabricatorMetaMTAMail())
316
->setSubject("{$monogram}: {$name}");
317
}
318
319
protected function buildMailBody(
320
PhabricatorLiskDAO $object,
321
array $xactions) {
322
323
$body = parent::buildMailBody($object, $xactions);
324
325
$description = $object->getDescription();
326
if ($this->getIsNewObject()) {
327
if (strlen($description)) {
328
$body->addRemarkupSection(
329
pht('EVENT DESCRIPTION'),
330
$description);
331
}
332
}
333
334
$body->addLinkSection(
335
pht('EVENT DETAIL'),
336
PhabricatorEnv::getProductionURI($object->getURI()));
337
338
$ics_attachment = $this->newICSAttachment($object);
339
$body->addAttachment($ics_attachment);
340
341
return $body;
342
}
343
344
protected function shouldApplyHeraldRules(
345
PhabricatorLiskDAO $object,
346
array $xactions) {
347
return true;
348
}
349
350
protected function buildHeraldAdapter(
351
PhabricatorLiskDAO $object,
352
array $xactions) {
353
354
return id(new PhabricatorCalendarEventHeraldAdapter())
355
->setObject($object);
356
}
357
358
private function newICSAttachment(
359
PhabricatorCalendarEvent $event) {
360
$actor = $this->getActor();
361
362
$ics_data = id(new PhabricatorCalendarICSWriter())
363
->setViewer($actor)
364
->setEvents(array($event))
365
->writeICSDocument();
366
367
$ics_attachment = new PhabricatorMailAttachment(
368
$ics_data,
369
$event->getICSFilename(),
370
'text/calendar');
371
372
return $ics_attachment;
373
}
374
375
}
376
377