phpcs - Fix error, "Expected 1 newline at end of file; XXX found".
[civicrm-core.git] / CRM / Campaign / Form / Petition / Signature.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * This class generates form components for processing a petition signature
38 *
39 */
40class CRM_Campaign_Form_Petition_Signature extends CRM_Core_Form {
7da04cde 41 const EMAIL_THANK = 1, EMAIL_CONFIRM = 2, MODE_CREATE = 4;
6a488035
TO
42
43 protected $_mode;
44
45 /**
100fef9d 46 * The id of the contact associated with this signature
6a488035
TO
47 *
48 * @var int
6a488035
TO
49 */
50 public $_contactId;
51
52 /**
53 * Is this a logged in user
54 *
55 * @var int
56 */
57 protected $_loggedIn = FALSE;
58
59 /**
60 * The contact type
61 *
62 * @var string ("Individual"/"Household"/"Organization"). Never been tested for something else than Individual
63 */
64 protected $_ctype = 'Individual';
65
66 /**
67 * The contact profile id attached with this petition
68 *
69 * @var int
70 */
71 protected $_contactProfileId;
72
73 /**
100fef9d 74 * The contact profile fields used for this petition
6a488035
TO
75 *
76 * @var array
77 */
78 public $_contactProfileFields;
79
80 /**
81 * The activity profile id attached with this petition
82 *
83 * @var int
84 */
85 protected $_activityProfileId;
86
87 /**
100fef9d 88 * The activity profile fields used for this petition
6a488035
TO
89 *
90 * @var array
91 */
92 public $_activityProfileFields;
93
94 /**
100fef9d 95 * The id of the survey (petition) we are proceessing
6a488035
TO
96 *
97 * @var int
6a488035
TO
98 */
99 public $_surveyId;
100
101 /**
102 * The tag id used to set against contacts with unconfirmed email
103 *
104 * @var int
105 */
106 protected $_tagId;
107
108 /**
100fef9d 109 * Values to use for custom profiles
6a488035
TO
110 *
111 * @var array
6a488035
TO
112 */
113 public $_values;
114
115 /**
116 * The params submitted by the form
117 *
118 * @var array
6a488035
TO
119 */
120 protected $_params;
121
122 /**
100fef9d 123 * Which email send mode do we use
6a488035
TO
124 *
125 * @var int
126 * EMAIL_THANK = 1,
127 * connected user via login/pwd - thank you
128 * or dedupe contact matched who doesn't have a tag CIVICRM_TAG_UNCONFIRMED - thank you
129 * or login using fb connect - thank you + click to add msg to fb wall
130 * EMAIL_CONFIRM = 2;
131 * send a confirmation request email
132 */
133 protected $_sendEmailMode;
134
135 protected $_image_URL;
136
430ae6dd
TO
137 protected $_defaults = NULL;
138
30c4e065
EM
139 /**
140 *
141 */
00be9182 142 public function __construct() {
6a488035
TO
143 parent::__construct();
144 // this property used by civicrm_fb module and if true, forces thank you email to be sent
145 // for users signing in via Facebook connect; also sets Fb email to check against
146 $this->forceEmailConfirmed['flag'] = FALSE;
147 $this->forceEmailConfirmed['email'] = '';
148 }
149
30c4e065
EM
150 /**
151 * @return mixed
152 */
00be9182 153 public function getContactID() {
6a488035
TO
154 $tempID = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
155
156 // force to ignore the authenticated user
157 if ($tempID === '0') {
158 return $tempID;
159 }
160
161 //check if this is a checksum authentication
162 $userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this);
163 if ($userChecksum) {
164 //check for anonymous user.
165 $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($tempID, $userChecksum);
166 if ($validUser) {
167 return $tempID;
168 }
169 }
170
171 // check if the user is registered and we have a contact ID
172 $session = CRM_Core_Session::singleton();
173 return $session->get('userID');
174 }
175
176 public function preProcess() {
177 $this->bao = new CRM_Campaign_BAO_Petition();
178 $this->_mode = self::MODE_CREATE;
179
180 //get the survey id
181 $this->_surveyId = CRM_Utils_Request::retrieve('sid', 'Positive', $this);
182
183 //some sanity checks
184 if (!$this->_surveyId) {
185 CRM_Core_Error::fatal('Petition id is not valid. (it needs a "sid" in the url).');
186 return;
187 }
188 //check petition is valid and active
189 $params['id'] = $this->_surveyId;
190 $this->petition = array();
191 CRM_Campaign_BAO_Survey::retrieve($params, $this->petition);
192 if (empty($this->petition)) {
193 CRM_Core_Error::fatal('Petition doesn\'t exist.');
194 }
195 if ($this->petition['is_active'] == 0) {
196 CRM_Core_Error::fatal('Petition is no longer active.');
197 }
198
199 //get userID from session
200 $session = CRM_Core_Session::singleton();
201
202 //get the contact id for this user if logged in
203 $this->_contactId = $this->getContactId();
204 if (isset($this->_contactId)) {
205 $this->_loggedIn = TRUE;
206 }
207
208 // add the custom contact and activity profile fields to the signature form
209
210 $ufJoinParams = array(
211 'entity_id' => $this->_surveyId,
212 'entity_table' => 'civicrm_survey',
213 'module' => 'CiviCampaign',
214 'weight' => 2,
215 );
216
217 $this->_contactProfileId = CRM_Core_BAO_UFJoin::findUFGroupId($ufJoinParams);
218 if ($this->_contactProfileId) {
219 $this->_contactProfileFields = CRM_Core_BAO_UFGroup::getFields($this->_contactProfileId, FALSE, CRM_Core_Action::ADD);
220 }
221 if (!isset($this->_contactProfileFields['email-Primary'])) {
222 CRM_Core_Error::fatal('The contact profile needs to contain the primary email address field');
223 }
224
225
226 $ufJoinParams['weight'] = 1;
227 $this->_activityProfileId = CRM_Core_BAO_UFJoin::findUFGroupId($ufJoinParams);
228
229 if ($this->_activityProfileId) {
230 $this->_activityProfileFields = CRM_Core_BAO_UFGroup::getFields($this->_activityProfileId, FALSE, CRM_Core_Action::ADD);
231 }
232
233 $this->setDefaultValues();
234 CRM_Utils_System::setTitle($this->petition['title']);
235 }
236
237 /**
c490a46a 238 * Set default values for the form.
6a488035 239 *
6a488035 240 *
355ba699 241 * @return void
6a488035 242 */
00be9182 243 public function setDefaultValues() {
6a488035
TO
244 $this->_defaults = array();
245 if ($this->_contactId) {
246 CRM_Core_BAO_UFGroup::setProfileDefaults($this->_contactId, $this->_contactProfileFields, $this->_defaults, TRUE);
247 if ($this->_activityProfileId) {
248 CRM_Core_BAO_UFGroup::setProfileDefaults($this->_contactId, $this->_activityProfileFields, $this->_defaults, TRUE);
249 }
250 }
251
252 //set custom field defaults
253
254 foreach ($this->_contactProfileFields as $name => $field) {
255 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
256 $htmlType = $field['html_type'];
257
258 if (!isset($this->_defaults[$name])) {
259 CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID,
260 $name,
261 $this->_defaults,
262 $this->_contactId,
263 $this->_mode
264 );
265 }
266 }
267 }
268
269 if ($this->_activityProfileFields) {
270 foreach ($this->_activityProfileFields as $name => $field) {
271 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
272 $htmlType = $field['html_type'];
273
274 if (!isset($this->_defaults[$name])) {
275 CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID,
276 $name,
277 $this->_defaults,
278 $this->_contactId,
279 $this->_mode
280 );
281 }
282 }
283 }
284 }
285
286 $this->setDefaults($this->_defaults);
287 }
288
289 public function buildQuickForm() {
290 $this->assign('survey_id', $this->_surveyId);
291 $this->assign('petitionTitle', $this->petition['title']);
292 if (isset($_COOKIE['signed_' . $this->_surveyId])) {
293 if (isset($_COOKIE['confirmed_' . $this->_surveyId])) {
294 $this->assign('duplicate', "confirmed");
295 }
296 else {
297 $this->assign('duplicate', "unconfirmed");
298 }
299 return;
300 }
301
302 $this->applyFilter('__ALL__', 'trim');
303
304 $this->buildCustom($this->_contactProfileId, 'petitionContactProfile');
305 if ($this->_activityProfileId) {
306 $this->buildCustom($this->_activityProfileId, 'petitionActivityProfile');
307 }
308 // add buttons
309 $this->addButtons(array(
310 array(
311 'type' => 'next',
312 'name' => ts('Sign the Petition'),
313 'isDefault' => TRUE,
314 ),
315 )
316 );
317 }
318
319 /**
320 * This function is used to add the rules (mainly global rules) for form.
321 * All local rules are added near the element
322 *
da6b46f4
EM
323 * @param $fields
324 * @param $files
325 * @param $errors
326 *
355ba699 327 * @return void
6a488035
TO
328 * @see valid_date
329 */
330
00be9182 331 public static function formRule($fields, $files, $errors) {
6a488035
TO
332 $errors = array();
333
334 return empty($errors) ? TRUE : $errors;
335 }
336
337 /**
338 * Form submission of petition signature
339 *
6a488035 340 *
355ba699 341 * @return void
6a488035
TO
342 */
343 public function postProcess() {
344 $tag_name = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CAMPAIGN_PREFERENCES_NAME,
345 'tag_unconfirmed'
346 );
347
348
349 if ($tag_name) {
350 // Check if contact 'email confirmed' tag exists, else create one
351 // This should be in the petition module initialise code to create a default tag for this
352 $tag_params['name'] = $tag_name;
353 $tag_params['version'] = 3;
354 $tag = civicrm_api('tag', 'get', $tag_params);
355 if ($tag['count'] == 0) {
356 //create tag
357 $tag_params['description'] = $tag_name;
358 $tag_params['is_reserved'] = 1;
359 $tag_params['used_for'] = 'civicrm_contact';
360 $tag = civicrm_api('tag', 'create', $tag_params);
361 }
362 $this->_tagId = $tag['id'];
363 }
364
365 // export the field values to be used for saving the profile form
366 $params = $this->controller->exportValues($this->_name);
367
368 $session = CRM_Core_Session::singleton();
369 // format params
370 $params['last_modified_id'] = $session->get('userID');
371 $params['last_modified_date'] = date('YmdHis');
372
373 if ($this->_action & CRM_Core_Action::ADD) {
374 $params['created_id'] = $session->get('userID');
375 $params['created_date'] = date('YmdHis');
376 }
377
378 if (isset($this->_surveyId)) {
379 $params['sid'] = $this->_surveyId;
380 }
381
382 if (isset($this->_contactId)) {
383 $params['contactId'] = $this->_contactId;
384 }
385
386 // if logged in user, skip dedupe
387 if ($this->_loggedIn) {
388 $ids[0] = $this->_contactId;
389 }
390 else {
391 // dupeCheck - check if contact record already exists
392 // code modified from api/v2/Contact.php-function civicrm_contact_check_params()
393 $params['contact_type'] = $this->_ctype;
394 //TODO - current dedupe finds soft deleted contacts - adding param is_deleted not working
395 // ignore soft deleted contacts
396 //$params['is_deleted'] = 0;
397 $dedupeParams = CRM_Dedupe_Finder::formatParams($params, $params['contact_type']);
398 $dedupeParams['check_permission'] = '';
399
400 //dupesByParams($params, $ctype, $level = 'Unsupervised', $except = array())
401 $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $params['contact_type']);
402 }
403
404 $petition_params['id'] = $this->_surveyId;
405 $petition = array();
406 CRM_Campaign_BAO_Survey::retrieve($petition_params, $petition);
407
408 switch (count($ids)) {
409 case 0:
410 //no matching contacts - create a new contact
411 // Add a source for this new contact
412 $params['source'] = ts('Petition Signature') . ' ' . $this->petition['title'];
413
414 if ($this->petition['bypass_confirm']) {
415 // send thank you email directly, bypassing confirmation
416 $this->_sendEmailMode = self::EMAIL_THANK;
417 // Set status for signature activity to completed
418 $params['statusId'] = 2;
419 }
420 else {
421 $this->_sendEmailMode = self::EMAIL_CONFIRM;
422
423 // Set status for signature activity to scheduled until email is verified
424 $params['statusId'] = 1;
425 }
426 break;
427
428 case 1:
429 $this->_contactId = $params['contactId'] = $ids[0];
430
431 // check if user has already signed this petition - redirects to Thank You if true
432 $this->redirectIfSigned($params);
433
434 if ($this->petition['bypass_confirm']) {
435 // send thank you email directly, bypassing confirmation
436 $this->_sendEmailMode = self::EMAIL_THANK;
437 // Set status for signature activity to completed
438 $params['statusId'] = 2;
439 break;
440 }
441
442 // dedupe matched single contact, check for 'unconfirmed' tag
443 if ($tag_name) {
444 $tag = new CRM_Core_DAO_EntityTag();
445 $tag->entity_id = $this->_contactId;
446 $tag->tag_id = $this->_tagId;
447
448 if (!($tag->find())) {
449 // send thank you email directly, the user is known and validated
450 $this->_sendEmailMode = self::EMAIL_THANK;
451 // Set status for signature activity to completed
452 $params['statusId'] = 2;
453 }
454 else {
455 // send email verification email
456 $this->_sendEmailMode = self::EMAIL_CONFIRM;
457 // Set status for signature activity to scheduled until email is verified
458 $params['statusId'] = 1;
459 }
460 }
461 break;
462
463 default:
464 // more than 1 matching contact
465 // for time being, take the first matching contact (not sure that's the best strategy, but better than creating another duplicate)
466 $this->_contactId = $params['contactId'] = $ids[0];
467
468 // check if user has already signed this petition - redirects to Thank You if true
469 $this->redirectIfSigned($params);
470
471 if ($this->petition['bypass_confirm']) {
472 // send thank you email directly, bypassing confirmation
473 $this->_sendEmailMode = self::EMAIL_THANK;
474 // Set status for signature activity to completed
475 $params['statusId'] = 2;
476 break;
477 }
478
479 if ($tag_name) {
480 $tag = new CRM_Core_DAO_EntityTag();
481 $tag->entity_id = $this->_contactId;
482 $tag->tag_id = $this->_tagId;
483
484 if (!($tag->find())) {
485 // send thank you email
486 $this->_sendEmailMode = self::EMAIL_THANK;
487 // Set status for signature activity to completed
488 $params['statusId'] = 2;
489 }
490 else {
491 // send email verification email
492 $this->_sendEmailMode = self::EMAIL_CONFIRM;
493 // Set status for signature activity to scheduled until email is verified
494 $params['statusId'] = 1;
495 }
496 }
497 break;
498 }
499
500
501
502 $transaction = new CRM_Core_Transaction();
503
504 $addToGroupID = isset($this->_addToGroupID) ? $this->_addToGroupID : NULL;
505 $this->_contactId = CRM_Contact_BAO_Contact::createProfileContact($params, $this->_contactProfileFields,
506 $this->_contactId, $addToGroupID,
507 $this->_contactProfileId, $this->_ctype,
508 TRUE
509 );
510
511 // get additional custom activity profile field data
512 // to save with new signature activity record
513 $surveyInfo = $this->bao->getSurveyInfo($this->_surveyId);
514 $customActivityFields = CRM_Core_BAO_CustomField::getFields('Activity', FALSE, FALSE,
515 $surveyInfo['activity_type_id']
516 );
517 $customActivityFields = CRM_Utils_Array::crmArrayMerge($customActivityFields,
518 CRM_Core_BAO_CustomField::getFields('Activity', FALSE, FALSE,
519 NULL, NULL, TRUE
520 )
521 );
522
523 $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params,
524 $customActivityFields,
525 NULL,
526 'Activity'
527 );
528
529 // create the signature activity record
530 $params['contactId'] = $this->_contactId;
43427a24 531 $params['activity_campaign_id'] = CRM_Utils_Array::value('campaign_id', $this->petition);
6a488035
TO
532 $result = $this->bao->createSignature($params);
533
534 // send thank you or email verification emails
535
536 // if logged in using Facebook connect and email on form matches Fb email,
537 // no need for email confirmation, send thank you email
538 if ($this->forceEmailConfirmed['flag'] &&
539 ($this->forceEmailConfirmed['email'] == $params['email-Primary'])
540 ) {
541 $this->_sendEmailMode = self::EMAIL_THANK;
542 }
543
544 switch ($this->_sendEmailMode) {
545 case self::EMAIL_THANK:
546 // mark the signature activity as completed and set confirmed cookie
547 $this->bao->confirmSignature($result->id, $this->_contactId, $this->_surveyId);
548 break;
549
550 case self::EMAIL_CONFIRM:
551 // set 'Unconfirmed' tag for this new contact
552 if ($tag_name) {
553 unset($tag_params);
554 $tag_params['contact_id'] = $this->_contactId;
555 $tag_params['tag_id'] = $this->_tagId;
83b0a3cc 556 $tag_params['version'] = 3;
6a488035
TO
557 $tag_value = civicrm_api('entity_tag', 'create', $tag_params);
558 }
559 break;
560 }
561
562 //send email
563 $params['activityId'] = $result->id;
564 $params['tagId'] = $this->_tagId;
6a488035
TO
565
566 $transaction->commit();
567
83b0a3cc 568 $this->bao->sendEmail($params, $this->_sendEmailMode);
569
6a488035
TO
570 if ($result) {
571 // call the hook before we redirect
572 $this->postProcessHook();
573
574 // set the template to thank you
575 $url =
576 CRM_Utils_System::url(
577 'civicrm/petition/thankyou',
578 'pid=' . $this->_surveyId . '&id=' . $this->_sendEmailMode . '&reset=1'
579 );
580 CRM_Utils_System::redirect($url);
581 }
582 }
583
584 /**
100fef9d 585 * Build the petition profile form
6a488035 586 *
100fef9d
CW
587 * @param int $id
588 * @param string $name
2a6da8d7
EM
589 * @param bool $viewOnly
590 *
355ba699 591 * @return void
6a488035 592 */
00be9182 593 public function buildCustom($id, $name, $viewOnly = FALSE) {
6a488035
TO
594 if ($id) {
595 $session = CRM_Core_Session::singleton();
596 $this->assign("petition", $this->petition);
597 //$contactID = $this->_contactId;
598 $contactID = NULL;
599 $this->assign('contact_id', $this->_contactId);
600
601 $fields = NULL;
602 // TODO: contactID is never set (commented above)
603 if ($contactID) {
604 if (CRM_Core_BAO_UFGroup::filterUFGroups($id, $contactID)) {
605 $fields = CRM_Core_BAO_UFGroup::getFields($id, FALSE, CRM_Core_Action::ADD);
606 }
607 }
608 else {
609 $fields = CRM_Core_BAO_UFGroup::getFields($id, FALSE, CRM_Core_Action::ADD);
610 }
611
612 if ($fields) {
613 /*
614 // unset any email-* fields since we already collect it, CRM-2888
615 foreach ( array_keys( $fields ) as $fieldName ) {
616 if ( substr( $fieldName, 0, 6 ) == 'email-' ) {
617 unset( $fields[$fieldName] );
618 }
619 }
620 */
621
622
623 $this->assign($name, $fields);
624
625 $addCaptcha = FALSE;
626 foreach ($fields as $key => $field) {
627 if ($viewOnly &&
628 isset($field['data_type']) &&
629 $field['data_type'] == 'File' || ($viewOnly && $field['name'] == 'image_URL')
630 ) {
631 // ignore file upload fields
632 continue;
633 }
2efcf0c2 634
635 // if state or country in the profile, create map
2c6b0601 636 list($prefixName, $index) = CRM_Utils_System::explode('-', $key, 2);
6a488035
TO
637
638 CRM_Core_BAO_UFGroup::buildProfile($this, $field, CRM_Profile_Form::MODE_CREATE, $contactID, TRUE);
639 $this->_fields[$key] = $field;
71fc6ea4
DG
640 // CRM-11316 Is ReCAPTCHA enabled for this profile AND is this an anonymous visitor
641 if ($field['add_captcha'] && !$this->_contactId) {
6a488035
TO
642 $addCaptcha = TRUE;
643 }
644 }
645
71fc6ea4 646 if ($addCaptcha && !$viewOnly) {
6a488035
TO
647 $captcha = CRM_Utils_ReCAPTCHA::singleton();
648 $captcha->add($this);
649 $this->assign("isCaptcha", TRUE);
650 }
651 }
652 }
653 }
654
30c4e065
EM
655 /**
656 * @return string
657 */
00be9182 658 public function getTemplateFileName() {
6a488035
TO
659 if (isset($this->thankyou)) {
660 return ('CRM/Campaign/Page/Petition/ThankYou.tpl');
661 }
662 else {}
663 return parent::getTemplateFileName();
664 }
665
666 // check if user has already signed this petition
30c4e065 667 /**
c490a46a 668 * @param array $params
30c4e065 669 */
00be9182 670 public function redirectIfSigned($params) {
6a488035
TO
671 $signature = $this->bao->checkSignature($this->_surveyId, $this->_contactId);
672 //TODO: error case when more than one signature found for this petition and this contact
673 if (!empty($signature) && (count($signature) == 1)) {
674 $signature_id = array_keys($signature);
675 switch ($signature[$signature_id[0]]['status_id']) {
676 case 1:
677 //status is scheduled - email is unconfirmed
678 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/petition/thankyou', 'pid=' . $this->_surveyId . '&id=4&reset=1'));
679 break;
680
681 case 2:
682 //status is completed
683 $this->bao->sendEmail($params, 1);
684 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/petition/thankyou', 'pid=' . $this->_surveyId . '&id=5&reset=1'));
685 break;
686 }
687 }
688 }
689}