Merge pull request #16552 from eileenmcnaughton/part_form
[civicrm-core.git] / CRM / Event / Form / SelfSvcUpdate.php
CommitLineData
97d8187a 1<?php
97d8187a
DG
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
97d8187a 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
97d8187a
DG
9 +--------------------------------------------------------------------+
10 */
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
97d8187a
DG
16 * $Id$
17 *
18 */
19
20/**
21 * This class generates form components to allow an Event to be cancelled or transferred from an email link
22 *
23 */
24class CRM_Event_Form_SelfSvcUpdate extends CRM_Core_Form {
25 /**
26 * particpant id
27 *
28 * @var string
29 *
30 */
31 protected $_participant_id;
32 /**
33 * contact id
34 *
35 * @var string
36 *
37 */
38 protected $_contact_id;
39 /**
40 * name of the particpant
41 *
42 * @var string
43 *
44 */
45 protected $_contact_name;
46 /**
47 * email of participant
48 *
49 * @var string
50 */
51 protected $_contact_email;
52 /**
53 * event to be cancelled/transferred
54 *
55 * @var string
56 */
57 protected $_event_id;
58 /**
59 * event title
60 *
61 * @var string
62 */
63 protected $_event_title;
64 /**
65 * event title
66 *
67 * @var string
68 */
69 protected $_event_start_date;
70 /**
71 * action
72 *
73 * @var string
74 */
3a936dab 75 public $_action;
97d8187a
DG
76 /**
77 * participant object
78 *
79 * @var string
80 */
be2fb01f 81 protected $_participant = [];
97d8187a
DG
82 /**
83 * particpant values
84 *
85 * @var string
86 */
87 protected $_part_values;
88 /**
89 * details of event registration values
90 *
91 * @var array
92 */
be2fb01f 93 protected $_details = [];
e219d53b 94 /**
95 * Is backoffice form?
96 *
90b461f1 97 * @var bool
e219d53b 98 */
99 protected $isBackoffice = FALSE;
90b461f1 100
97d8187a
DG
101 /**
102 * Set variables up before form is built based on participant ID from URL
103 *
104 * @return void
105 */
106 public function preProcess() {
107 $config = CRM_Core_Config::singleton();
108 $session = CRM_Core_Session::singleton();
109 $this->_userContext = $session->readUserContext();
be2fb01f 110 $participant = $values = [];
97d8187a 111 $this->_participant_id = CRM_Utils_Request::retrieve('pid', 'Positive', $this, FALSE, NULL, 'REQUEST');
af29aaac 112 $this->_userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this, FALSE, NULL, 'REQUEST');
e219d53b 113 $this->isBackoffice = CRM_Utils_Request::retrieve('is_backoffice', 'String', $this, FALSE, NULL, 'REQUEST');
be2fb01f 114 $params = ['id' => $this->_participant_id];
97d8187a
DG
115 $this->_participant = CRM_Event_BAO_Participant::getValues($params, $values, $participant);
116 $this->_part_values = $values[$this->_participant_id];
117 $this->set('values', $this->_part_values);
118 //fetch Event by event_id, verify that this event can still be xferred/cancelled
119 $this->_event_id = $this->_part_values['event_id'];
af29aaac 120 $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}");
97d8187a 121 $this->_contact_id = $this->_part_values['participant_contact_id'];
af29aaac 122 $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($this->_contact_id, $this->_userChecksum);
e3b510fe 123 if (!$validUser && !CRM_Core_Permission::check('edit all events')) {
124 CRM_Core_Error::statusBounce(ts('You do not have sufficient permission to transfer/cancel this participant.'), $url);
125 }
97d8187a
DG
126 $this->assign('action', $this->_action);
127 if ($this->_participant_id) {
128 $this->assign('participantId', $this->_participant_id);
129 }
be2fb01f 130 $event = [];
97d8187a
DG
131 $daoName = 'title';
132 $this->_event_title = CRM_Event_BAO_Event::getFieldValue('CRM_Event_DAO_Event', $this->_event_id, $daoName);
133 $daoName = 'start_date';
134 $this->_event_start_date = CRM_Event_BAO_Event::getFieldValue('CRM_Event_DAO_Event', $this->_event_id, $daoName);
135 list($displayName, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contact_id);
136 $this->_contact_name = $displayName;
137 $this->_contact_email = $email;
be2fb01f 138 $details = [];
97d8187a 139 $details = CRM_Event_BAO_Participant::participantDetails($this->_participant_id);
4abc4ee1 140 $optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'participant_role', 'id', 'name');
141 $contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_participant_id, 'contribution_id', 'participant_id');
142 $this->assign('contributionId', $contributionId);
97d8187a 143 $query = "
974bdb44 144 SELECT cpst.name as status, cov.name as role, cp.fee_level, cp.fee_amount, cp.register_date, cp.status_id, civicrm_event.start_date
97d8187a
DG
145 FROM civicrm_participant cp
146 LEFT JOIN civicrm_participant_status_type cpst ON cpst.id = cp.status_id
4abc4ee1 147 LEFT JOIN civicrm_option_value cov ON cov.value = cp.role_id and cov.option_group_id = {$optionGroupId}
974bdb44 148 LEFT JOIN civicrm_event ON civicrm_event.id = cp.event_id
97d8187a 149 WHERE cp.id = {$this->_participant_id}";
33621c4f 150 $dao = CRM_Core_DAO::executeQuery($query);
97d8187a
DG
151 while ($dao->fetch()) {
152 $details['status'] = $dao->status;
153 $details['role'] = $dao->role;
e219d53b 154 $details['fee_level'] = trim($dao->fee_level, CRM_Core_DAO::VALUE_SEPARATOR);
97d8187a
DG
155 $details['fee_amount'] = $dao->fee_amount;
156 $details['register_date'] = $dao->register_date;
0d21c8b1 157 $details['event_start_date'] = $dao->start_date;
97d8187a
DG
158 }
159 //verify participant status is still Registered
160 if ($details['status'] != "Registered") {
8b9023b8
DG
161 $status = "You cannot transfer or cancel your registration for " . $this->_event_title . ' as you are not currently registered for this event.';
162 CRM_Core_Session::setStatus($status, ts('Sorry'), 'alert');
4abc4ee1 163 CRM_Utils_System::redirect($url);
97d8187a
DG
164 }
165 $query = "select start_date as start, selfcancelxfer_time as time from civicrm_event where id = " . $this->_event_id;
33621c4f 166 $dao = CRM_Core_DAO::executeQuery($query);
97d8187a
DG
167 while ($dao->fetch()) {
168 $time_limit = $dao->time;
169 $start_date = $dao->start;
170 }
4abc4ee1 171 $start_time = new Datetime($start_date);
172 $timenow = new Datetime();
e219d53b 173 if (!$this->isBackoffice && !empty($start_time) && $start_time < $timenow) {
8b9023b8
DG
174 $status = ts("Registration for this event cannot be cancelled or transferred once the event has begun. Contact the event organizer if you have questions.");
175 CRM_Core_Error::statusBounce($status, $url, ts('Sorry'));
4abc4ee1 176 }
e219d53b 177 if (!$this->isBackoffice && !empty($time_limit) && $time_limit > 0) {
97d8187a
DG
178 $interval = $timenow->diff($start_time);
179 $days = $interval->format('%d');
180 $hours = $interval->format('%h');
181 if ($hours <= $time_limit && $days < 1) {
be2fb01f 182 $status = ts("Registration for this event cannot be cancelled or transferred less than %1 hours prior to the event's start time. Contact the event organizer if you have questions.", [1 => $time_limit]);
8b9023b8 183 CRM_Core_Error::statusBounce($status, $url, ts('Sorry'));
97d8187a
DG
184 }
185 }
186 $this->assign('details', $details);
187 $this->selfsvcupdateUrl = CRM_Utils_System::url('civicrm/event/selfsvcupdate', "reset=1&id={$this->_participant_id}&id=0");
188 $this->selfsvcupdateText = ts('Update');
189 $this->selfsvcupdateButtonText = ts('Update');
190 // Based on those ids retrieve event and verify it is eligible
191 // for self update (event.start_date > today, event can be 'self_updated'
192 // retrieve contact name and email, and let user verify his/her identity
193 }
90b461f1 194
97d8187a
DG
195 /**
196 * buildQuickForm -populate input variables for source Event
197 * to cancel or transfer to another person
198 *
199 * return @void
200 */
201 public function buildQuickForm() {
be2fb01f
CW
202 $this->add('select', 'action', ts('Transfer or Cancel Registration'), [ts('-select-'), ts('Transfer'), ts('Cancel')], TRUE);
203 $this->addButtons([
204 [
97d8187a
DG
205 'type' => 'submit',
206 'name' => ts('Submit'),
be2fb01f
CW
207 ],
208 ]);
209 $this->addFormRule(['CRM_Event_Form_SelfSvcUpdate', 'formRule'], $this);
97d8187a
DG
210 parent::buildQuickForm();
211 }
974bdb44 212
97d8187a
DG
213 /**
214 * Set default values for contact
215 *
216 * return @void
217 */
218 public function setDefaultValues() {
be2fb01f 219 $this->_defaults = [];
97d8187a
DG
220 $this->_defaults['details'] = $this->_details;
221 return $this->_defaults;
222 }
974bdb44 223
e3b510fe 224 /**
225 * Validate action input
226 * @param array $fields
227 * Posted fields of the form.
228 * @param $files
229 * @param $self
230 *
231 * @return array
232 * list of errors to be posted back to the form
233 */
234 public static function formRule($fields, $files, $self) {
be2fb01f 235 $errors = [];
e3b510fe 236 if (empty($fields['action'])) {
237 $errors['action'] = ts("Please select Transfer OR Cancel action.");
238 }
239 return empty($errors) ? TRUE : $errors;
240 }
241
97d8187a
DG
242 /**
243 * Process submit form - based on user selection of action
244 * transfer or cancel the event
245 *
246 * return @void
247 */
248 public function postProcess() {
249 //if selection is cancel, cancel this participant' registration, process refund
250 //if transfer, process form to allow selection of transferree
251 $params = $this->controller->exportValues($this->_name);
252 $action = $params['action'];
253 if ($action == "1") {
254 $action = "Transfer Event";
255 $this->transferParticipant($params);
256 }
257 elseif ($action == "2") {
258 $action = "Cancel Event";
259 $this->cancelParticipant($params);
260 }
261 }
974bdb44 262
97d8187a
DG
263 /**
264 * Transfer to a new form, allowing selection of a new contact
265 * based on email and name. The Event will be transferred to this new participant
266 *
267 * return @void
268 */
269 public function transferParticipant($params) {
e219d53b 270 CRM_Utils_System::redirect(CRM_Utils_System::url(
271 'civicrm/event/selfsvctransfer',
be2fb01f 272 [
e219d53b 273 'reset' => 1,
274 'action' => 'add',
275 'pid' => $this->_participant_id,
276 'cs' => $this->_userChecksum,
cb98c7f9 277 'is_backoffice' => $this->isBackoffice,
be2fb01f 278 ]
e219d53b 279 ));
97d8187a 280 }
974bdb44 281
97d8187a
DG
282 /**
283 * Cancel this participant and finish, send cancellation email. At this point no
284 * auto-cancellation of payment is handled, so payment needs to be manually cancelled
285 *
286 * return @void
287 */
288 public function cancelParticipant($params) {
289 //set participant record status to Cancelled, refund payment if possible
290 // send email to participant and admin, and log Activity
be2fb01f 291 $value = [];
97d8187a
DG
292 $value['id'] = $this->_participant_id;
293 $cancelledId = array_search('Cancelled',
294 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'"));
295 $value['status_id'] = $cancelledId;
296 CRM_Event_BAO_Participant::create($value);
be2fb01f 297 $domainValues = [];
97d8187a 298 $domain = CRM_Core_BAO_Domain::getDomain();
be2fb01f 299 $tokens = [
97d8187a 300 'domain' =>
be2fb01f 301 [
97d8187a
DG
302 'name',
303 'phone',
304 'address',
305 'email',
be2fb01f 306 ],
97d8187a 307 'contact' => CRM_Core_SelectValues::contactTokens(),
be2fb01f 308 ];
97d8187a
DG
309 foreach ($tokens['domain'] as $token) {
310 $domainValues[$token] = CRM_Utils_Token::getDomainTokenReplacement($token, $domain);
311 }
be2fb01f 312 $participantRoles = [];
97d8187a 313 $participantRoles = CRM_Event_PseudoConstant::participantRole();
be2fb01f 314 $participantDetails = [];
97d8187a
DG
315 $query = "SELECT * FROM civicrm_participant WHERE id = {$this->_participant_id}";
316 $dao = CRM_Core_DAO::executeQuery($query);
317 while ($dao->fetch()) {
be2fb01f 318 $participantDetails[$dao->id] = [
97d8187a
DG
319 'id' => $dao->id,
320 'role' => $participantRoles[$dao->role_id],
321 'is_test' => $dao->is_test,
322 'event_id' => $dao->event_id,
323 'status_id' => $dao->status_id,
324 'fee_amount' => $dao->fee_amount,
325 'contact_id' => $dao->contact_id,
326 'register_date' => $dao->register_date,
327 'registered_by_id' => $dao->registered_by_id,
be2fb01f 328 ];
97d8187a 329 }
be2fb01f
CW
330 $eventDetails = [];
331 $eventParams = ['id' => $this->_event_id];
97d8187a
DG
332 CRM_Event_BAO_Event::retrieve($eventParams, $eventDetails[$this->_event_id]);
333 //get default participant role.
334 $eventDetails[$this->_event_id]['participant_role'] = CRM_Utils_Array::value($eventDetails[$this->_event_id]['default_role_id'], $participantRoles);
335 //get the location info
be2fb01f 336 $locParams = ['entity_id' => $this->_event_id, 'entity_table' => 'civicrm_event'];
97d8187a
DG
337 $eventDetails[$this->_event_id]['location'] = CRM_Core_BAO_Location::getValues($locParams, TRUE);
338 //get contact details
339 $contactIds[$this->_contact_id] = $this->_contact_id;
340 list($currentContactDetails) = CRM_Utils_Token::getTokenDetails($contactIds, NULL,
be2fb01f 341 FALSE, FALSE, NULL, [],
97d8187a
DG
342 'CRM_Event_BAO_Participant'
343 );
344 foreach ($currentContactDetails as $contactId => $contactValues) {
345 $contactDetails[$this->_contact_id] = $contactValues;
346 }
347 //send a 'cancelled' email to user, and cc the event's cc_confirm email
348 $mail = CRM_Event_BAO_Participant::sendTransitionParticipantMail($this->_participant_id,
349 $participantDetails[$this->_participant_id],
350 $eventDetails[$this->_event_id],
351 $contactDetails[$this->_contact_id],
352 $domainValues,
353 "Cancelled",
354 ""
355 );
be2fb01f
CW
356 $statusMsg = ts('Event registration information for %1 has been updated.', [1 => $this->_contact_name]);
357 $statusMsg .= ' ' . ts('A cancellation email has been sent to %1.', [1 => $this->_contact_email]);
8b9023b8 358 CRM_Core_Session::setStatus($statusMsg, ts('Thanks'), 'success');
e219d53b 359 if (!empty($this->isBackoffice)) {
360 return;
361 }
4abc4ee1 362 $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}&noFullMsg=true");
363 CRM_Utils_System::redirect($url);
97d8187a
DG
364 }
365
366}