Merge pull request #16541 from bhahumanists/subtype-issue-991
[civicrm-core.git] / CRM / Event / Form / SelfSvcUpdate.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * This class generates form components to allow an Event to be cancelled or transferred from an email link
20 *
21 */
22 class CRM_Event_Form_SelfSvcUpdate extends CRM_Core_Form {
23 /**
24 * particpant id
25 *
26 * @var string
27 *
28 */
29 protected $_participant_id;
30 /**
31 * contact id
32 *
33 * @var string
34 *
35 */
36 protected $_contact_id;
37 /**
38 * name of the particpant
39 *
40 * @var string
41 *
42 */
43 protected $_contact_name;
44 /**
45 * email of participant
46 *
47 * @var string
48 */
49 protected $_contact_email;
50 /**
51 * event to be cancelled/transferred
52 *
53 * @var string
54 */
55 protected $_event_id;
56 /**
57 * event title
58 *
59 * @var string
60 */
61 protected $_event_title;
62 /**
63 * event title
64 *
65 * @var string
66 */
67 protected $_event_start_date;
68 /**
69 * action
70 *
71 * @var string
72 */
73 public $_action;
74 /**
75 * participant object
76 *
77 * @var string
78 */
79 protected $_participant = [];
80 /**
81 * particpant values
82 *
83 * @var string
84 */
85 protected $_part_values;
86 /**
87 * details of event registration values
88 *
89 * @var array
90 */
91 protected $_details = [];
92 /**
93 * Is backoffice form?
94 *
95 * @var bool
96 */
97 protected $isBackoffice = FALSE;
98
99 /**
100 * Set variables up before form is built based on participant ID from URL
101 *
102 * @return void
103 *
104 * @throws \CRM_Core_Exception
105 */
106 public function preProcess() {
107 $config = CRM_Core_Config::singleton();
108 $session = CRM_Core_Session::singleton();
109 $this->_userContext = $session->readUserContext();
110 $participant = $values = [];
111 $this->_participant_id = CRM_Utils_Request::retrieve('pid', 'Positive', $this, FALSE, NULL, 'REQUEST');
112 $this->_userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this, FALSE, NULL, 'REQUEST');
113 $this->isBackoffice = CRM_Utils_Request::retrieve('is_backoffice', 'String', $this, FALSE, NULL, 'REQUEST');
114 $params = ['id' => $this->_participant_id];
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'];
120 $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}");
121 $this->_contact_id = $this->_part_values['participant_contact_id'];
122 $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($this->_contact_id, $this->_userChecksum);
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 }
126 $this->assign('action', $this->_action);
127 if ($this->_participant_id) {
128 $this->assign('participantId', $this->_participant_id);
129 }
130
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;
138
139 $details = CRM_Event_BAO_Participant::participantDetails($this->_participant_id);
140 $contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantPayment', $this->_participant_id, 'contribution_id', 'participant_id');
141 $this->assign('contributionId', $contributionId);
142 $selfServiceDetails = CRM_Event_BAO_Participant::getSelfServiceEligibility($this->_participant_id, $url, $this->isBackoffice);
143 $details = array_merge($details, $selfServiceDetails);
144 $this->assign('details', $details);
145 $this->selfsvcupdateUrl = CRM_Utils_System::url('civicrm/event/selfsvcupdate', "reset=1&id={$this->_participant_id}&id=0");
146 $this->selfsvcupdateText = ts('Update');
147 $this->selfsvcupdateButtonText = ts('Update');
148 // Based on those ids retrieve event and verify it is eligible
149 // for self update (event.start_date > today, event can be 'self_updated'
150 // retrieve contact name and email, and let user verify his/her identity
151 }
152
153 /**
154 * buildQuickForm -populate input variables for source Event
155 * to cancel or transfer to another person
156 *
157 * return @void
158 */
159 public function buildQuickForm() {
160 $this->add('select', 'action', ts('Transfer or Cancel Registration'), [ts('-select-'), ts('Transfer'), ts('Cancel')], TRUE);
161 $this->addButtons([
162 [
163 'type' => 'submit',
164 'name' => ts('Submit'),
165 ],
166 ]);
167 $this->addFormRule(['CRM_Event_Form_SelfSvcUpdate', 'formRule'], $this);
168 parent::buildQuickForm();
169 }
170
171 /**
172 * Set default values for contact
173 *
174 * return @void
175 */
176 public function setDefaultValues() {
177 $this->_defaults = [];
178 $this->_defaults['details'] = $this->_details;
179 return $this->_defaults;
180 }
181
182 /**
183 * Validate action input
184 * @param array $fields
185 * Posted fields of the form.
186 * @param $files
187 * @param $self
188 *
189 * @return array
190 * list of errors to be posted back to the form
191 */
192 public static function formRule($fields, $files, $self) {
193 $errors = [];
194 if (empty($fields['action'])) {
195 $errors['action'] = ts("Please select Transfer OR Cancel action.");
196 }
197 return empty($errors) ? TRUE : $errors;
198 }
199
200 /**
201 * Process submit form - based on user selection of action
202 * transfer or cancel the event
203 *
204 * return @void
205 */
206 public function postProcess() {
207 //if selection is cancel, cancel this participant' registration, process refund
208 //if transfer, process form to allow selection of transferree
209 $params = $this->controller->exportValues($this->_name);
210 $action = $params['action'];
211 if ($action == "1") {
212 $this->transferParticipant($params);
213 }
214 elseif ($action == "2") {
215 $this->cancelParticipant($params);
216 }
217 }
218
219 /**
220 * Transfer to a new form, allowing selection of a new contact
221 * based on email and name. The Event will be transferred to this new participant
222 *
223 * return @void
224 */
225 public function transferParticipant($params) {
226 CRM_Utils_System::redirect(CRM_Utils_System::url(
227 'civicrm/event/selfsvctransfer',
228 [
229 'reset' => 1,
230 'action' => 'add',
231 'pid' => $this->_participant_id,
232 'cs' => $this->_userChecksum,
233 'is_backoffice' => $this->isBackoffice,
234 ]
235 ));
236 }
237
238 /**
239 * Cancel this participant and finish, send cancellation email. At this point no
240 * auto-cancellation of payment is handled, so payment needs to be manually cancelled
241 *
242 * return @void
243 *
244 * @throws \CRM_Core_Exception
245 */
246 public function cancelParticipant($params) {
247 //set participant record status to Cancelled, refund payment if possible
248 // send email to participant and admin, and log Activity
249 $value = [];
250 $value['id'] = $this->_participant_id;
251 $cancelledId = array_search('Cancelled',
252 CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'"));
253 $value['status_id'] = $cancelledId;
254 CRM_Event_BAO_Participant::create($value);
255 $domainValues = [];
256 $domain = CRM_Core_BAO_Domain::getDomain();
257 $tokens = [
258 'domain' =>
259 [
260 'name',
261 'phone',
262 'address',
263 'email',
264 ],
265 'contact' => CRM_Core_SelectValues::contactTokens(),
266 ];
267 foreach ($tokens['domain'] as $token) {
268 $domainValues[$token] = CRM_Utils_Token::getDomainTokenReplacement($token, $domain);
269 }
270
271 $participantRoles = CRM_Event_PseudoConstant::participantRole();
272 $participantDetails = [];
273 $query = "SELECT * FROM civicrm_participant WHERE id = {$this->_participant_id}";
274 $dao = CRM_Core_DAO::executeQuery($query);
275 while ($dao->fetch()) {
276 $participantDetails[$dao->id] = [
277 'id' => $dao->id,
278 'role' => $participantRoles[$dao->role_id],
279 'is_test' => $dao->is_test,
280 'event_id' => $dao->event_id,
281 'status_id' => $dao->status_id,
282 'fee_amount' => $dao->fee_amount,
283 'contact_id' => $dao->contact_id,
284 'register_date' => $dao->register_date,
285 'registered_by_id' => $dao->registered_by_id,
286 ];
287 }
288 $eventDetails = [];
289 $eventParams = ['id' => $this->_event_id];
290 CRM_Event_BAO_Event::retrieve($eventParams, $eventDetails[$this->_event_id]);
291 //get default participant role.
292 $eventDetails[$this->_event_id]['participant_role'] = $participantRoles[$eventDetails[$this->_event_id]['default_role_id']] ?? NULL;
293 //get the location info
294 $locParams = ['entity_id' => $this->_event_id, 'entity_table' => 'civicrm_event'];
295 $eventDetails[$this->_event_id]['location'] = CRM_Core_BAO_Location::getValues($locParams, TRUE);
296 //get contact details
297 $contactIds[$this->_contact_id] = $this->_contact_id;
298 list($currentContactDetails) = CRM_Utils_Token::getTokenDetails($contactIds, NULL,
299 FALSE, FALSE, NULL, [],
300 'CRM_Event_BAO_Participant'
301 );
302 foreach ($currentContactDetails as $contactId => $contactValues) {
303 $contactDetails[$this->_contact_id] = $contactValues;
304 }
305 //send a 'cancelled' email to user, and cc the event's cc_confirm email
306 $mail = CRM_Event_BAO_Participant::sendTransitionParticipantMail($this->_participant_id,
307 $participantDetails[$this->_participant_id],
308 $eventDetails[$this->_event_id],
309 $contactDetails[$this->_contact_id],
310 $domainValues,
311 "Cancelled",
312 ""
313 );
314 $statusMsg = ts('Event registration information for %1 has been updated.', [1 => $this->_contact_name]);
315 $statusMsg .= ' ' . ts('A cancellation email has been sent to %1.', [1 => $this->_contact_email]);
316 CRM_Core_Session::setStatus($statusMsg, ts('Thanks'), 'success');
317 if (!empty($this->isBackoffice)) {
318 return;
319 }
320 $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}&noFullMsg=true");
321 CRM_Utils_System::redirect($url);
322 }
323
324 }