Update Copywrite year to be 2019
[civicrm-core.git] / CRM / Event / Form / SelfSvcTransfer.php
CommitLineData
97d8187a
DG
1<?php
2
3/*
4 +--------------------------------------------------------------------+
fee14197 5 | CiviCRM version 5 |
97d8187a 6 +--------------------------------------------------------------------+
6b83d5bd 7 | Copyright CiviCRM LLC (c) 2004-2019 |
97d8187a
DG
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
10 | |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public |
21 | License and the CiviCRM Licensing Exception along |
22 | with this program; if not, contact CiviCRM LLC |
23 | at info[AT]civicrm[DOT]org. If you have questions about the |
24 | GNU Affero General Public License or the licensing of CiviCRM, |
25 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
26 +--------------------------------------------------------------------+
27 */
28
29/**
30 *
31 * @package CRM
6b83d5bd 32 * @copyright CiviCRM LLC (c) 2004-2019
97d8187a
DG
33 * $Id$
34 *
35 */
36
37/**
38 * This class generates form components to transfer an Event to another participant
39 *
40 */
41class CRM_Event_Form_SelfSvcTransfer extends CRM_Core_Form {
42 /**
43 * from particpant id
44 *
45 * @var string
46 *
47 */
48 protected $_from_participant_id;
49 /**
50 * from contact id
51 *
52 * @var string
53 *
54 */
55 protected $_from_contact_id;
56 /**
57 * last name of the particpant to transfer to
58 *
59 * @var string
60 *
61 */
62 protected $_to_contact_last_name;
63 /**
64 * first name of the particpant to transfer to
65 *
66 * @var string
67 *
68 */
69 protected $_to_contact_first_name;
70 /**
71 * email of participant
72 *
73 *
74 * @var string
75 */
76 protected $_to_contact_email;
77 /**
78 * _to_contact_id
79 *
80 * @var string
81 */
82 protected $_to_contact_id;
83 /**
84 * event to be cancelled/transferred
85 *
86 * @var string
87 */
88 protected $_event_id;
89 /**
90 * event title
91 *
92 * @var string
93 */
94 protected $_event_title;
95 /**
96 * event title
97 *
98 * @var string
99 */
100 protected $_event_start_date;
101 /**
102 * action
103 *
104 * @var string
105 */
3a936dab 106 public $_action;
97d8187a
DG
107 /**
108 * participant object
109 *
110 * @var string
111 */
112 protected $_participant = array();
113 /**
114 * particpant values
115 *
116 * @array string
117 */
118 protected $_part_values;
119 /**
120 * details
121 *
122 * @array string
123 */
124 protected $_details = array();
125 /**
126 * line items
127 *
128 * @array string
129 */
130 protected $_line_items = array();
131 /**
132 * contact_id
133 *
134 * @array string
135 */
136 protected $contact_id;
974bdb44 137
e219d53b 138 /**
139 * Is backoffice form?
140 *
141 * @array bool
142 */
143 protected $isBackoffice = FALSE;
144
97d8187a
DG
145 /**
146 * Get source values for transfer based on participant id in URL. Line items will
147 * be transferred to this participant - at this point no transaction changes processed
148 *
149 * return @void
150 */
151 public function preProcess() {
152 $config = CRM_Core_Config::singleton();
153 $session = CRM_Core_Session::singleton();
154 $this->_userContext = $session->readUserContext();
155 $this->_from_participant_id = CRM_Utils_Request::retrieve('pid', 'Positive', $this, FALSE, NULL, 'REQUEST');
af29aaac 156 $this->_userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this, FALSE, NULL, 'REQUEST');
e219d53b 157 $this->isBackoffice = CRM_Utils_Request::retrieve('is_backoffice', 'String', $this, FALSE, NULL, 'REQUEST');
97d8187a
DG
158 $params = array('id' => $this->_from_participant_id);
159 $participant = $values = array();
160 $this->_participant = CRM_Event_BAO_Participant::getValues($params, $values, $participant);
161 $this->_part_values = $values[$this->_from_participant_id];
162 $this->set('values', $this->_part_values);
163 $this->_event_id = $this->_part_values['event_id'];
af29aaac 164 $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}");
97d8187a 165 $this->_from_contact_id = $this->_part_values['participant_contact_id'];
af29aaac 166 $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($this->_from_contact_id, $this->_userChecksum);
167 if (!$validUser && !CRM_Core_Permission::check('edit all events')) {
168 CRM_Core_Error::statusBounce(ts('You do not have sufficient permission to transfer/cancel this participant.'), $url);
169 }
97d8187a
DG
170 $this->assign('action', $this->_action);
171 if ($this->_from_participant_id) {
172 $this->assign('participantId', $this->_from_participant_id);
173 }
174 $event = array();
175 $daoName = 'title';
176 $this->_event_title = CRM_Event_BAO_Event::getFieldValue('CRM_Event_DAO_Event', $this->_event_id, $daoName);
177 $daoName = 'start_date';
178 $this->_event_start_date = CRM_Event_BAO_Event::getFieldValue('CRM_Event_DAO_Event', $this->_event_id, $daoName);
179 list($displayName, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_from_contact_id);
180 $this->_contact_name = $displayName;
181 $this->_contact_email = $email;
182 $details = array();
183 $details = CRM_Event_BAO_Participant::participantDetails($this->_from_participant_id);
4abc4ee1 184 $optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'participant_role', 'id', 'name');
97d8187a 185 $query = "
974bdb44 186 SELECT cpst.name as status, cov.name as role, cp.fee_level, cp.fee_amount, cp.register_date, civicrm_event.start_date
97d8187a
DG
187 FROM civicrm_participant cp
188 LEFT JOIN civicrm_participant_status_type cpst ON cpst.id = cp.status_id
4abc4ee1 189 LEFT JOIN civicrm_option_value cov ON cov.value = cp.role_id and cov.option_group_id = {$optionGroupId}
974bdb44 190 LEFT JOIN civicrm_event ON civicrm_event.id = cp.event_id
97d8187a 191 WHERE cp.id = {$this->_from_participant_id}";
33621c4f 192 $dao = CRM_Core_DAO::executeQuery($query);
97d8187a
DG
193 while ($dao->fetch()) {
194 $details['status'] = $dao->status;
195 $details['role'] = $dao->role;
196 $details['fee_level'] = $dao->fee_level;
197 $details['fee_amount'] = $dao->fee_amount;
198 $details['register_date'] = $dao->register_date;
0d21c8b1 199 $details['event_start_date'] = $dao->start_date;
97d8187a
DG
200 }
201 $this->assign('details', $details);
202 //This participant row will be cancelled. Get line item(s) to cancel
203 $this->selfsvctransferUrl = CRM_Utils_System::url('civicrm/event/selfsvcupdate',
204 "reset=1&id={$this->_from_participant_id}&id=0");
205 $this->selfsvctransferText = ts('Update');
206 $this->selfsvctransferButtonText = ts('Update');
207 }
974bdb44 208
97d8187a
DG
209 /**
210 * Build form for input of transferree email, name
211 *
212 * return @void
213 */
214 public function buildQuickForm() {
e219d53b 215 // use entityRef select field for contact when this form is used by staff/admin user
216 if ($this->isBackoffice) {
217 $this->addEntityRef("contact_id", ts('Select Contact'), array('create' => TRUE), TRUE);
218 }
219 // for front-end user show and use the basic three fields used to create a contact
220 else {
221 $this->add('text', 'email', ts('To Email'), ts($this->_contact_email), TRUE);
222 $this->add('text', 'last_name', ts('To Last Name'), ts($this->_to_contact_last_name), TRUE);
223 $this->add('text', 'first_name', ts('To First Name'), ts($this->_to_contact_first_name), TRUE);
224 }
225
97d8187a
DG
226 $this->addButtons(array(
227 array(
228 'type' => 'submit',
974bdb44 229 'name' => ts('Transfer Registration'),),
97d8187a
DG
230 )
231 );
232 $this->addFormRule(array('CRM_Event_Form_SelfSvcTransfer', 'formRule'), $this);
233 parent::buildQuickForm();
234 }
974bdb44 235
97d8187a
DG
236 /**
237 * Set defaults
238 *
239 * return @array _defaults
240 */
241 public function setDefaultValues() {
242 $this->_defaults = array();
243 return $this->_defaults;
244 }
974bdb44 245
97d8187a
DG
246 /**
247 * Validate email and name input
248 *
249 * return array $errors
250 */
251 public static function formRule($fields, $files, $self) {
252 $errors = array();
e219d53b 253 if (!empty($fields['contact_id'])) {
254 $to_contact_id = $fields['contact_id'];
255 }
256 else {
257 //check that either an email or firstname+lastname is included in the form(CRM-9587)
258 $to_contact_id = self::checkProfileComplete($fields, $errors, $self);
259 }
97d8187a 260 //To check if the user is already registered for the event(CRM-2426)
e219d53b 261 if (!empty($to_contact_id)) {
e3b510fe 262 self::checkRegistration($fields, $self, $to_contact_id, $errors);
263 }
97d8187a
DG
264 //return parent::formrule($fields, $files, $self);
265 return empty($errors) ? TRUE : $errors;
266 }
974bdb44 267
97d8187a
DG
268 /**
269 * Check whether profile (name, email) is complete
270 *
271 * return $contact_id
272 */
273 public static function checkProfileComplete($fields, &$errors, $self) {
274 $email = '';
275 foreach ($fields as $fieldname => $fieldvalue) {
276 if (substr($fieldname, 0, 5) == 'email' && $fieldvalue) {
277 $email = $fieldvalue;
278 }
279 }
280 if (!$email && !(CRM_Utils_Array::value('first_name', $fields) &&
281 CRM_Utils_Array::value('last_name', $fields))) {
282 $defaults = $params = array('id' => $eventId);
283 CRM_Event_BAO_Event::retrieve($params, $defaults);
284 $message = ts("Mandatory fields (first name and last name, OR email address) are missing from this form.");
285 $errors['_qf_default'] = $message;
286 }
287 $contact = CRM_Contact_BAO_Contact::matchContactOnEmail($email, "");
288 $contact_id = empty($contact->contact_id) ? NULL : $contact->contact_id;
e3b510fe 289 if (!CRM_Utils_Rule::email($fields['email'])) {
290 $errors['email'] = ts('Enter valid email address.');
291 }
292 if (empty($errors) && empty($contact_id)) {
97d8187a
DG
293 $params = array(
294 'email-Primary' => CRM_Utils_Array::value('email', $fields, NULL),
295 'first_name' => CRM_Utils_Array::value('first_name', $fields, NULL),
296 'last_name' => CRM_Utils_Array::value('last_name', $fields, NULL),
297 'is_deleted' => CRM_Utils_Array::value('is_deleted', $fields, FALSE),);
298 //create new contact for this name/email pair
299 //if new contact, no need to check for contact already registered
300 $contact_id = CRM_Contact_BAO_Contact::createProfileContact($params, $fields, $contact_id);
301 }
302 return $contact_id;
303 }
974bdb44 304
97d8187a
DG
305 /**
306 * Check contact details
307 *
308 * return @void
309 */
4abc4ee1 310 public static function checkRegistration($fields, $self, $contact_id, &$errors) {
97d8187a 311 // verify whether this contact already registered for this event
97d8187a
DG
312 $contact_details = CRM_Contact_BAO_Contact::getContactDetails($contact_id);
313 $display_name = $contact_details[0];
314 $query = "select event_id from civicrm_participant where contact_id = " . $contact_id;
33621c4f 315 $dao = CRM_Core_DAO::executeQuery($query);
97d8187a
DG
316 while ($dao->fetch()) {
317 $to_event_id[] = $dao->event_id;
318 }
319 if (!empty($to_event_id)) {
320 foreach ($to_event_id as $id) {
321 if ($id == $self->_event_id) {
4abc4ee1 322 $errors['email'] = $display_name . ts(" is already registered for this event");
97d8187a
DG
323 }
324 }
325 }
326 }
974bdb44 327
97d8187a
DG
328 /**
329 * Process transfer - first add the new participant to the event, then cancel
330 * source participant - send confirmation email to transferee
331 */
332 public function postProcess() {
333 //For transfer, process form to allow selection of transferree
334 $params = $this->controller->exportValues($this->_name);
e219d53b 335 if (!empty($params['contact_id'])) {
336 $contact_id = $params['contact_id'];
337 }
338 else {
339 //cancel 'from' participant row
340 $query = "select contact_id from civicrm_email where email = '" . $params['email'] . "'";
341 $dao = CRM_Core_DAO::executeQuery($query);
342 while ($dao->fetch()) {
343 $contact_id = $dao->contact_id;
344 }
97d8187a
DG
345 }
346 $from_participant = $params = array();
347 $query = "select role_id, source, fee_level, is_test, is_pay_later, fee_amount, discount_id, fee_currency,campaign_id, discount_amount from civicrm_participant where id = " . $this->_from_participant_id;
33621c4f 348 $dao = CRM_Core_DAO::executeQuery($query);
97d8187a
DG
349 $value_to = array();
350 while ($dao->fetch()) {
351 $value_to['role_id'] = $dao->role_id;
352 $value_to['source'] = $dao->source;
353 $value_to['fee_level'] = $dao->fee_level;
354 $value_to['is_test'] = $dao->is_test;
355 $value_to['is_pay_later'] = $dao->is_pay_later;
356 $value_to['fee_amount'] = $dao->fee_amount;
357 }
358 $value_to['contact_id'] = $contact_id;
359 $value_to['event_id'] = $this->_event_id;
360 $value_to['status_id'] = 1;
361 $value_to['register_date'] = date("Y-m-d");
362 //first create the new participant row -don't set registered_by yet or email won't be sent
363 $participant = CRM_Event_BAO_Participant::create($value_to);
364 //send a confirmation email to the new participant
e3b510fe 365 $this->participantTransfer($participant);
97d8187a
DG
366 //now update registered_by_id
367 $query = "UPDATE civicrm_participant cp SET cp.registered_by_id = %1 WHERE cp.id = ({$participant->id})";
368 $params = array(1 => array($this->_from_participant_id, 'Integer'));
369 $dao = CRM_Core_DAO::executeQuery($query, $params);
370 //copy line items to new participant
371 $line_items = CRM_Price_BAO_LineItem::getLineItems($this->_from_participant_id);
372 foreach ($line_items as $item) {
373 $item['entity_id'] = $participant->id;
374 $item['id'] = NULL;
375 $item['entity_table'] = "civicrm_participant";
376 $new_item = CRM_Price_BAO_LineItem::create($item);
377 }
378 //now cancel the from participant record, leaving the original line-item(s)
379 $value_from = array();
380 $value_from['id'] = $this->_from_participant_id;
381 $tansferId = array_search('Transferred', CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'"));
382 $value_from['status_id'] = $tansferId;
383 $value_from['transferred_to_contact_id'] = $contact_id;
384 $contact_details = CRM_Contact_BAO_Contact::getContactDetails($contact_id);
385 $display_name = current($contact_details);
386 $this->assign('to_participant', $display_name);
387 CRM_Event_BAO_Participant::create($value_from);
388 $this->sendCancellation();
389 list($displayName, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contact_id);
390 $statusMsg = ts('Event registration information for %1 has been updated.', array(1 => $displayName));
391 $statusMsg .= ' ' . ts('A confirmation email has been sent to %1.', array(1 => $email));
974bdb44 392 CRM_Core_Session::setStatus($statusMsg, ts('Registration Transferred'), 'success');
e219d53b 393 if ($this->isBackoffice) {
394 return;
395 }
e3b510fe 396 $url = CRM_Utils_System::url('civicrm/event/info', "reset=1&id={$this->_event_id}");
397 CRM_Utils_System::redirect($url);
97d8187a 398 }
974bdb44 399
97d8187a
DG
400 /**
401 * Based on input, create participant row for transferee and send email
402 *
403 * return @ void
404 */
405 public function participantTransfer($participant) {
406 $contactDetails = array();
407 $contactIds[] = $participant->contact_id;
408 list($currentContactDetails) = CRM_Utils_Token::getTokenDetails($contactIds, NULL,
409 FALSE, FALSE, NULL, array(), 'CRM_Event_BAO_Participant');
410 foreach ($currentContactDetails as $contactId => $contactValues) {
411 $contactDetails[$contactId] = $contactValues;
412 }
413 $participantRoles = CRM_Event_PseudoConstant::participantRole();
414 $participantDetails = array();
415 $query = "SELECT * FROM civicrm_participant WHERE id = " . $participant->id;
416 $dao = CRM_Core_DAO::executeQuery($query);
417 while ($dao->fetch()) {
418 $participantDetails[$dao->id] = array(
419 'id' => $dao->id,
420 'role' => $participantRoles[$dao->role_id],
421 'is_test' => $dao->is_test,
422 'event_id' => $dao->event_id,
423 'status_id' => $dao->status_id,
424 'fee_amount' => $dao->fee_amount,
425 'contact_id' => $dao->contact_id,
426 'register_date' => $dao->register_date,
427 'registered_by_id' => $dao->registered_by_id,
428 );
429 }
430 $domainValues = array();
431 if (empty($domainValues)) {
432 $domain = CRM_Core_BAO_Domain::getDomain();
433 $tokens = array(
434 'domain' =>
435 array(
436 'name',
437 'phone',
438 'address',
439 'email',
440 ),
441 'contact' => CRM_Core_SelectValues::contactTokens(),
442 );
443 foreach ($tokens['domain'] as $token) {
444 $domainValues[$token] = CRM_Utils_Token::getDomainTokenReplacement($token, $domain);
445 }
446 }
447 $eventDetails = array();
448 $eventParams = array('id' => $participant->event_id);
e3b510fe 449 CRM_Event_BAO_Event::retrieve($eventParams, $eventDetails);
97d8187a 450 //get default participant role.
e3b510fe 451 $eventDetails['participant_role'] = CRM_Utils_Array::value($eventDetails['default_role_id'], $participantRoles);
97d8187a
DG
452 //get the location info
453 $locParams = array(
454 'entity_id' => $participant->event_id,
455 'entity_table' => 'civicrm_event',
456 );
e3b510fe 457 $eventDetails['location'] = CRM_Core_BAO_Location::getValues($locParams, TRUE);
458 $toEmail = CRM_Utils_Array::value('email', $contactDetails[$participant->contact_id]);
459 if ($toEmail) {
460 //take a receipt from as event else domain.
461 $receiptFrom = $domainValues['name'] . ' <' . $domainValues['email'] . '>';
462 if (!empty($eventDetails['confirm_from_name']) && !empty($eventDetails['confirm_from_email'])) {
463 $receiptFrom = $eventDetails['confirm_from_name'] . ' <' . $eventDetails['confirm_from_email'] . '>';
464 }
465 $participantName = $contactDetails[$participant->contact_id]['display_name'];
466 $tplParams = array(
467 'event' => $eventDetails,
468 'participant' => $participantDetails[$participant->id],
469 'participantID' => $participant->id,
470 'participant_status' => 'Registered',
471 );
472
473 $sendTemplateParams = array(
474 'groupName' => 'msg_tpl_workflow_event',
475 'valueName' => 'event_online_receipt',
476 'contactId' => $participantDetails[$participant->id]['contact_id'],
477 'tplParams' => $tplParams,
478 'from' => $receiptFrom,
479 'toName' => $participantName,
480 'toEmail' => $toEmail,
481 'cc' => CRM_Utils_Array::value('cc_confirm', $eventDetails),
482 'bcc' => CRM_Utils_Array::value('bcc_confirm', $eventDetails),
483 );
484 CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams);
485 }
97d8187a 486 }
974bdb44 487
97d8187a
DG
488 /**
489 * Send confirmation of cancellation to source participant
490 *
491 * return @ void
492 */
493 public function sendCancellation() {
494 $domainValues = array();
495 $domain = CRM_Core_BAO_Domain::getDomain();
496 $tokens = array(
497 'domain' =>
498 array(
499 'name',
500 'phone',
501 'address',
502 'email',
503 ),
504 'contact' => CRM_Core_SelectValues::contactTokens(),
505 );
506 foreach ($tokens['domain'] as $token) {
507 $domainValues[$token] = CRM_Utils_Token::getDomainTokenReplacement($token, $domain);
508 }
509 $participantRoles = array();
510 $participantRoles = CRM_Event_PseudoConstant::participantRole();
511 $participantDetails = array();
512 $query = "SELECT * FROM civicrm_participant WHERE id = {$this->_from_participant_id}";
513 $dao = CRM_Core_DAO::executeQuery($query);
514 while ($dao->fetch()) {
515 $participantDetails[$dao->id] = array(
516 'id' => $dao->id,
517 'role' => $participantRoles[$dao->role_id],
518 'is_test' => $dao->is_test,
519 'event_id' => $dao->event_id,
520 'status_id' => $dao->status_id,
521 'fee_amount' => $dao->fee_amount,
522 'contact_id' => $dao->contact_id,
523 'register_date' => $dao->register_date,
524 'registered_by_id' => $dao->registered_by_id,
525 );
526 }
527 $eventDetails = array();
528 $eventParams = array('id' => $this->_event_id);
529 CRM_Event_BAO_Event::retrieve($eventParams, $eventDetails[$this->_event_id]);
530 //get default participant role.
531 $eventDetails[$this->_event_id]['participant_role'] = CRM_Utils_Array::value($eventDetails[$this->_event_id]['default_role_id'], $participantRoles);
532 //get the location info
533 $locParams = array('entity_id' => $this->_event_id, 'entity_table' => 'civicrm_event');
534 $eventDetails[$this->_event_id]['location'] = CRM_Core_BAO_Location::getValues($locParams, TRUE);
535 //get contact details
536 $contactIds[$this->_from_contact_id] = $this->_from_contact_id;
537 list($currentContactDetails) = CRM_Utils_Token::getTokenDetails($contactIds, NULL,
538 FALSE, FALSE, NULL, array(),
539 'CRM_Event_BAO_Participant'
540 );
541 foreach ($currentContactDetails as $contactId => $contactValues) {
542 $contactDetails[$this->_from_contact_id] = $contactValues;
543 }
544 //send a 'cancelled' email to user, and cc the event's cc_confirm email
545 $mail = CRM_Event_BAO_Participant::sendTransitionParticipantMail($this->_from_participant_id,
546 $participantDetails[$this->_from_participant_id],
547 $eventDetails[$this->_event_id],
548 $contactDetails[$this->_from_contact_id],
549 $domainValues,
550 "Transferred",
551 ""
552 );
553 $statusMsg = ts('Event registration information for %1 has been updated.', array(1 => $this->_contact_name));
554 $statusMsg .= ' ' . ts('A cancellation email has been sent to %1.', array(1 => $this->_contact_email));
8b9023b8 555 CRM_Core_Session::setStatus($statusMsg, ts('Thanks'), 'success');
97d8187a
DG
556 }
557
558}