Merge pull request #15641 from eileenmcnaughton/cont_clean
[civicrm-core.git] / CRM / Activity / Form / Activity.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
6b83d5bd 31 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
32 */
33
34/**
b6c94f42 35 * This class generates form components for Activity.
6a488035
TO
36 */
37class CRM_Activity_Form_Activity extends CRM_Contact_Form_Task {
38
39 /**
40 * The id of the object being edited / created
41 *
42 * @var int
43 */
44 public $_activityId;
45
52c7b3a2 46 /**
fe482240 47 * Store activity ids when multiple activities are created.
52c7b3a2
KJ
48 *
49 * @var int
50 */
96f94695 51 public $_activityIds = [];
52c7b3a2 52
6a488035 53 /**
fe482240 54 * The id of activity type.
6a488035
TO
55 *
56 * @var int
57 */
58 public $_activityTypeId;
59
60 /**
fe482240 61 * The name of activity type.
6a488035
TO
62 *
63 * @var string
64 */
65 public $_activityTypeName;
66
67 /**
fe482240 68 * The id of currently viewed contact.
6a488035
TO
69 *
70 * @var int
71 */
72 public $_currentlyViewedContactId;
73
74 /**
fe482240 75 * The id of source contact and target contact.
6a488035
TO
76 *
77 * @var int
78 */
79 protected $_sourceContactId;
80 protected $_targetContactId;
81 protected $_asigneeContactId;
82
83 protected $_single;
84
85 public $_context;
86 public $_compContext;
87 public $_action;
88 public $_activityTypeFile;
89
90 /**
91 * The id of the logged in user, used when add / edit
92 *
93 * @var int
94 */
95 public $_currentUserId;
96
97 /**
fe482240 98 * The array of form field attributes.
6a488035
TO
99 *
100 * @var array
101 */
102 public $_fields;
103
104 /**
105 * The the directory inside CRM, to include activity type file from
106 *
107 * @var string
108 */
109 protected $_crmDir = 'Activity';
110
c490a46a 111 /**
fe482240 112 * Survey activity.
c490a46a 113 *
d51c6add 114 * @var bool
c490a46a 115 */
6a488035
TO
116 protected $_isSurveyActivity;
117
96f94695 118 protected $_values = [];
6a488035 119
c087eb82 120 protected $unsavedWarn = TRUE;
d5965a37 121
62d3ee27
SL
122 /**
123 *
53c79877
SM
124 * Is it possible to create separate activities with this form?
125 *
126 * When TRUE, the form will ask whether the user wants to create separate
127 * activities (if the user has specified multiple contacts in the "with"
128 * field).
129 *
130 * When FALSE, the form will create one activity with all contacts together
131 * and won't ask the user anything.
132 *
133 * Note: This is a class property so that child classes can turn off this
134 * behavior (e.g. in CRM_Case_Form_Activity)
135 *
d51c6add 136 * @var bool
62d3ee27 137 *
53c79877
SM
138 */
139 protected $supportsActivitySeparation = TRUE;
140
423616fa
CW
141 public $submitOnce = TRUE;
142
d5965a37 143 /**
6e62b28c 144 * Explicitly declare the entity api name.
7808aae6
SB
145 *
146 * @return string
6e62b28c
TM
147 */
148 public function getDefaultEntity() {
149 return 'Activity';
150 }
59d63f8b 151
6a488035
TO
152 /**
153 * The _fields var can be used by sub class to set/unset/edit the
154 * form fields based on their requirement
6a488035 155 */
00be9182 156 public function setFields() {
056878d2
CW
157 // Remove print document activity type
158 $unwanted = CRM_Core_OptionGroup::values('activity_type', FALSE, FALSE, FALSE, "AND v.name = 'Print PDF Letter'");
159 $activityTypes = array_diff_key(CRM_Core_PseudoConstant::ActivityType(FALSE), $unwanted);
160
96f94695 161 $this->_fields = [
162 'subject' => [
6a488035
TO
163 'type' => 'text',
164 'label' => ts('Subject'),
96f94695 165 'attributes' => CRM_Core_DAO::getAttribute('CRM_Activity_DAO_Activity', 'activity_subject'),
166 ],
167 'duration' => [
4b2fda1e 168 'type' => 'number',
6a488035 169 'label' => ts('Duration'),
96f94695 170 'attributes' => ['class' => 'four', 'min' => 1],
6a488035 171 'required' => FALSE,
96f94695 172 ],
173 'location' => [
6a488035
TO
174 'type' => 'text',
175 'label' => ts('Location'),
9d72cede 176 'attributes' => CRM_Core_DAO::getAttribute('CRM_Activity_DAO_Activity', 'location'),
21dfd5f5 177 'required' => FALSE,
96f94695 178 ],
179 'details' => [
6a488035
TO
180 'type' => 'wysiwyg',
181 'label' => ts('Details'),
96f94695 182 'attributes' => ['class' => 'huge'],
21dfd5f5 183 'required' => FALSE,
96f94695 184 ],
185 'status_id' => [
6a488035 186 'type' => 'select',
475e9f44 187 'required' => TRUE,
96f94695 188 ],
189 'priority_id' => [
6a488035 190 'type' => 'select',
475e9f44 191 'required' => TRUE,
96f94695 192 ],
193 'source_contact_id' => [
c27ebe4e 194 'type' => 'entityRef',
6a488035 195 'label' => ts('Added By'),
21dfd5f5 196 'required' => FALSE,
96f94695 197 ],
198 'target_contact_id' => [
c27ebe4e
CW
199 'type' => 'entityRef',
200 'label' => ts('With Contact'),
96f94695 201 'attributes' => ['multiple' => TRUE, 'create' => TRUE],
202 ],
203 'assignee_contact_id' => [
c27ebe4e 204 'type' => 'entityRef',
3bd48a28 205 'label' => ts('Assigned to'),
96f94695 206 'attributes' => [
353ffa53
TO
207 'multiple' => TRUE,
208 'create' => TRUE,
96f94695 209 'api' => ['params' => ['is_deceased' => 0]],
210 ],
211 ],
212 'activity_date_time' => [
d104311a
CW
213 'type' => 'datepicker',
214 'label' => ts('Date'),
215 'required' => TRUE,
96f94695 216 ],
217 'followup_assignee_contact_id' => [
c27ebe4e 218 'type' => 'entityRef',
3bd48a28 219 'label' => ts('Assigned to'),
96f94695 220 'attributes' => [
353ffa53
TO
221 'multiple' => TRUE,
222 'create' => TRUE,
96f94695 223 'api' => ['params' => ['is_deceased' => 0]],
224 ],
225 ],
226 'followup_activity_type_id' => [
6a488035
TO
227 'type' => 'select',
228 'label' => ts('Followup Activity'),
96f94695 229 'attributes' => ['' => '- ' . ts('select activity') . ' -'] + $activityTypes,
230 'extra' => ['class' => 'crm-select2'],
231 ],
6a488035 232 // Add optional 'Subject' field for the Follow-up Activiity, CRM-4491
96f94695 233 'followup_activity_subject' => [
6a488035
TO
234 'type' => 'text',
235 'label' => ts('Subject'),
96f94695 236 'attributes' => CRM_Core_DAO::getAttribute('CRM_Activity_DAO_Activity', 'subject'),
237 ],
238 ];
6a488035
TO
239 }
240
241 /**
fe482240 242 * Build the form object.
6a488035 243 */
00be9182 244 public function preProcess() {
b334d9ad 245 CRM_Core_Form_RecurringEntity::preProcess('civicrm_activity');
6a488035
TO
246 $this->_atypefile = CRM_Utils_Array::value('atypefile', $_GET);
247 $this->assign('atypefile', FALSE);
248 if ($this->_atypefile) {
249 $this->assign('atypefile', TRUE);
250 }
251
252 $session = CRM_Core_Session::singleton();
3bdcd4ec 253 $this->_currentUserId = CRM_Core_Session::getLoggedInContactID();
6a488035
TO
254
255 $this->_currentlyViewedContactId = $this->get('contactId');
256 if (!$this->_currentlyViewedContactId) {
257 $this->_currentlyViewedContactId = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
258 }
259 $this->assign('contactId', $this->_currentlyViewedContactId);
260
7808aae6 261 // Give the context.
6a488035 262 if (!isset($this->_context)) {
edc80cda 263 $this->_context = CRM_Utils_Request::retrieve('context', 'Alphanumeric', $this);
6a488035
TO
264 if (CRM_Contact_Form_Search::isSearchContext($this->_context)) {
265 $this->_context = 'search';
266 }
0d48f1cc 267 elseif (!in_array($this->_context, ['dashlet', 'case', 'dashletFullscreen'])
6a488035
TO
268 && $this->_currentlyViewedContactId
269 ) {
270 $this->_context = 'activity';
271 }
272 $this->_compContext = CRM_Utils_Request::retrieve('compContext', 'String', $this);
273 }
274
275 $this->assign('context', $this->_context);
276
277 $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this);
278
279 if ($this->_action & CRM_Core_Action::DELETE) {
280 if (!CRM_Core_Permission::check('delete activities')) {
2b795b1f 281 CRM_Core_Error::statusBounce(ts('You do not have permission to access this page.'));
6a488035
TO
282 }
283 }
284
7808aae6
SB
285 // CRM-6957
286 // When we come from contact search, activity id never comes.
287 // So don't try to get from object, it might gives you wrong one.
6a488035
TO
288
289 // if we're not adding new one, there must be an id to
290 // an activity we're trying to work on.
291 if ($this->_action != CRM_Core_Action::ADD &&
292 get_class($this->controller) != 'CRM_Contact_Controller_Search'
293 ) {
294 $this->_activityId = CRM_Utils_Request::retrieve('id', 'Positive', $this);
295 }
296
297 $this->_activityTypeId = CRM_Utils_Request::retrieve('atype', 'Positive', $this);
298 $this->assign('atype', $this->_activityTypeId);
299
5b7581f1
CW
300 $this->assign('activityId', $this->_activityId);
301
7808aae6 302 // Check for required permissions, CRM-6264.
6a488035 303 if ($this->_activityId &&
96f94695 304 in_array($this->_action, [
19fc6ae4 305 CRM_Core_Action::UPDATE,
21dfd5f5 306 CRM_Core_Action::VIEW,
96f94695 307 ]) &&
6a488035
TO
308 !CRM_Activity_BAO_Activity::checkPermission($this->_activityId, $this->_action)
309 ) {
2b795b1f 310 CRM_Core_Error::statusBounce(ts('You do not have permission to access this page.'));
6a488035
TO
311 }
312 if (($this->_action & CRM_Core_Action::VIEW) &&
313 CRM_Activity_BAO_Activity::checkPermission($this->_activityId, CRM_Core_Action::UPDATE)
314 ) {
315 $this->assign('permission', 'edit');
55806731 316 $this->assign('allow_edit_inbound_emails', CRM_Activity_BAO_Activity::checkEditInboundEmailsPermissions());
6a488035
TO
317 }
318
319 if (!$this->_activityTypeId && $this->_activityId) {
320 $this->_activityTypeId = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity',
321 $this->_activityId,
322 'activity_type_id'
323 );
324 }
325
c6bbfc3a 326 $this->assignActivityType();
6a488035 327
7808aae6
SB
328 // Check the mode when this form is called either single or as
329 // search task action.
6a488035
TO
330 if ($this->_activityTypeId ||
331 $this->_context == 'standalone' ||
332 $this->_currentlyViewedContactId
333 ) {
334 $this->_single = TRUE;
335 $this->assign('urlPath', 'civicrm/activity');
336 }
337 else {
7808aae6 338 // Set the appropriate action.
6a488035
TO
339 $url = CRM_Utils_System::currentPath();
340 $urlArray = explode('/', $url);
50237bc9 341 $searchPath = array_pop($urlArray);
6a488035
TO
342 $searchType = 'basic';
343 $this->_action = CRM_Core_Action::BASIC;
50237bc9 344 switch ($searchPath) {
6a488035 345 case 'basic':
50237bc9 346 $searchType = $searchPath;
6a488035
TO
347 $this->_action = CRM_Core_Action::BASIC;
348 break;
349
350 case 'advanced':
50237bc9 351 $searchType = $searchPath;
6a488035
TO
352 $this->_action = CRM_Core_Action::ADVANCED;
353 break;
354
355 case 'builder':
50237bc9 356 $searchType = $searchPath;
6a488035
TO
357 $this->_action = CRM_Core_Action::PROFILE;
358 break;
359
360 case 'custom':
361 $this->_action = CRM_Core_Action::COPY;
50237bc9 362 $searchType = $searchPath;
6a488035
TO
363 break;
364 }
365
366 parent::preProcess();
367 $this->_single = FALSE;
368
369 $this->assign('urlPath', "civicrm/contact/search/$searchType");
370 $this->assign('urlPathVar', "_qf_Activity_display=true&qfKey={$this->controller->_key}");
371 }
372
373 $this->assign('single', $this->_single);
374 $this->assign('action', $this->_action);
375
376 if ($this->_action & CRM_Core_Action::VIEW) {
7808aae6 377 // Get the tree of custom fields.
0b330e6d 378 $this->_groupTree = CRM_Core_BAO_CustomGroup::getTree('Activity', NULL,
6a488035
TO
379 $this->_activityId, 0, $this->_activityTypeId
380 );
381 }
382
383 if ($this->_activityTypeId) {
7808aae6 384 // Set activity type name and description to template.
6a488035
TO
385 list($this->_activityTypeName, $activityTypeDescription) = CRM_Core_BAO_OptionValue::getActivityTypeDetails($this->_activityTypeId);
386 $this->assign('activityTypeName', $this->_activityTypeName);
387 $this->assign('activityTypeDescription', $activityTypeDescription);
388 }
389
390 // set user context
391 $urlParams = $urlString = NULL;
9479d7d0
DS
392 $qfKey = CRM_Utils_Request::retrieve('key', 'String', $this);
393 if (!$qfKey) {
394 $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this);
395 }
6a488035 396
7808aae6 397 // Validate the qfKey.
6a488035
TO
398 if (!CRM_Utils_Rule::qfKey($qfKey)) {
399 $qfKey = NULL;
400 }
401
402 if ($this->_context == 'fulltext') {
19fc6ae4 403 $keyName = '&qfKey';
6a488035
TO
404 $urlParams = 'force=1';
405 $urlString = 'civicrm/contact/search/custom';
406 if ($this->_action == CRM_Core_Action::UPDATE) {
407 $keyName = '&key';
408 $urlParams .= '&context=fulltext&action=view';
409 $urlString = 'civicrm/contact/view/activity';
410 }
411 if ($qfKey) {
412 $urlParams .= "$keyName=$qfKey";
413 }
414 $this->assign('searchKey', $qfKey);
415 }
96f94695 416 elseif (in_array($this->_context, [
19fc6ae4 417 'standalone',
418 'home',
419 'dashlet',
21dfd5f5 420 'dashletFullscreen',
96f94695 421 ])
19fc6ae4 422 ) {
6a488035
TO
423 $urlParams = 'reset=1';
424 $urlString = 'civicrm/dashboard';
425 }
426 elseif ($this->_context == 'search') {
427 $urlParams = 'force=1';
428 if ($qfKey) {
429 $urlParams .= "&qfKey=$qfKey";
430 }
7964ef53 431 $path = CRM_Utils_System::currentPath();
481a74f4 432 if ($this->_compContext == 'advanced') {
6a488035
TO
433 $urlString = 'civicrm/contact/search/advanced';
434 }
a26bae24 435 elseif ($path == 'civicrm/group/search'
353ffa53 436 || $path == 'civicrm/contact/search'
d31f1ab3 437 || $path == 'civicrm/contact/search/advanced'
7a60b836 438 || $path == 'civicrm/contact/search/custom'
353ffa53 439 || $path == 'civicrm/group/search'
7974a65a 440 || $path == 'civicrm/contact/search/builder'
353ffa53 441 ) {
d31f1ab3
AH
442 $urlString = $path;
443 }
6a488035 444 else {
d31f1ab3 445 $urlString = 'civicrm/activity/search';
6a488035
TO
446 }
447 $this->assign('searchKey', $qfKey);
448 }
449 elseif ($this->_context != 'caseActivity') {
450 $urlParams = "action=browse&reset=1&cid={$this->_currentlyViewedContactId}&selectedChild=activity";
451 $urlString = 'civicrm/contact/view';
452 }
453
454 if ($urlString) {
455 $session->pushUserContext(CRM_Utils_System::url($urlString, $urlParams));
456 }
457
458 // hack to retrieve activity type id from post variables
459 if (!$this->_activityTypeId) {
460 $this->_activityTypeId = CRM_Utils_Array::value('activity_type_id', $_POST);
461 }
462
463 // when custom data is included in this page
2fcb4a7f 464 $this->assign('cid', $this->_currentlyViewedContactId);
a7488080 465 if (!empty($_POST['hidden_custom'])) {
7808aae6 466 // We need to set it in the session for the code below to work.
6a488035 467 // CRM-3014
7808aae6 468 // Need to assign custom data subtype to the template.
6a488035
TO
469 $this->set('type', 'Activity');
470 $this->set('subType', $this->_activityTypeId);
471 $this->set('entityId', $this->_activityId);
c5366541 472 CRM_Custom_Form_CustomData::preProcess($this, NULL, $this->_activityTypeId, 1, 'Activity', $this->_activityId);
6a488035
TO
473 CRM_Custom_Form_CustomData::buildQuickForm($this);
474 CRM_Custom_Form_CustomData::setDefaultValues($this);
475 }
476
477 // add attachments part
478 CRM_Core_BAO_File::buildAttachment($this, 'civicrm_activity', $this->_activityId, NULL, TRUE);
479
480 // figure out the file name for activity type, if any
481 if ($this->_activityTypeId &&
6c552737 482 $this->_activityTypeFile = CRM_Activity_BAO_Activity::getFileForActivityTypeId($this->_activityTypeId, $this->_crmDir)
6a488035
TO
483 ) {
484 $this->assign('activityTypeFile', $this->_activityTypeFile);
485 $this->assign('crmDir', $this->_crmDir);
486 }
487
488 $this->setFields();
489
490 if ($this->_activityTypeFile) {
0e6e8724
DL
491 $className = "CRM_{$this->_crmDir}_Form_Activity_{$this->_activityTypeFile}";
492 $className::preProcess($this);
6a488035
TO
493 }
494
495 $this->_values = $this->get('values');
496 if (!is_array($this->_values)) {
96f94695 497 $this->_values = [];
6a488035 498 if (isset($this->_activityId) && $this->_activityId) {
96f94695 499 $params = ['id' => $this->_activityId];
6a488035
TO
500 CRM_Activity_BAO_Activity::retrieve($params, $this->_values);
501 }
ee90a98c 502
6a488035
TO
503 $this->set('values', $this->_values);
504 }
59d63f8b 505
78fe87e6 506 if ($this->_action & CRM_Core_Action::UPDATE) {
ee90a98c 507 // We filter out alternatives, in case this is a stored e-mail, before sending to front-end
40e67970
SL
508 if (isset($this->_values['details'])) {
509 $this->_values['details'] = CRM_Utils_String::stripAlternatives($this->_values['details']) ?: '';
510 }
ee90a98c
CR
511
512 if ($this->_activityTypeName === 'Inbound Email' &&
513 !CRM_Core_Permission::check('edit inbound email basic information and content')
514 ) {
515 $this->_fields['details']['type'] = 'static';
516 }
517
8cec51b0 518 CRM_Core_Form_RecurringEntity::preProcess('civicrm_activity');
78fe87e6 519 }
234fa48a
NH
520
521 if ($this->_action & CRM_Core_Action::VIEW) {
522 $url = CRM_Utils_System::url(implode("/", $this->urlPath), "reset=1&id={$this->_activityId}&action=view&cid={$this->_values['source_contact_id']}");
443f35e1 523 CRM_Utils_Recent::add(CRM_Utils_Array::value('subject', $this->_values, ts('(no subject)')),
234fa48a
NH
524 $url,
525 $this->_values['id'],
526 'Activity',
527 $this->_values['source_contact_id'],
528 $this->_values['source_contact']
529 );
530 }
6a488035 531 }
59d63f8b 532
6a488035 533 /**
b6c94f42 534 * Set default values for the form.
6a488035 535 *
b6c94f42 536 * For edit/view mode the default values are retrieved from the database.
7808aae6
SB
537 *
538 * @return array
6a488035 539 */
00be9182 540 public function setDefaultValues() {
6a488035 541
d2a4c29b 542 $defaults = $this->_values + CRM_Core_Form_RecurringEntity::setDefaultValues();
6a488035
TO
543 // if we're editing...
544 if (isset($this->_activityId)) {
6a488035 545
6a488035
TO
546 if ($this->_context != 'standalone') {
547 $this->assign('target_contact_value',
548 CRM_Utils_Array::value('target_contact_value', $defaults)
549 );
550 $this->assign('assignee_contact_value',
551 CRM_Utils_Array::value('assignee_contact_value', $defaults)
552 );
6a488035
TO
553 }
554
c27ebe4e 555 // Fixme: why are we getting the wrong keys from upstream?
28ded762
JP
556 $defaults['target_contact_id'] = CRM_Utils_Array::value('target_contact', $defaults);
557 $defaults['assignee_contact_id'] = CRM_Utils_Array::value('assignee_contact', $defaults);
c27ebe4e 558
6a488035 559 // set default tags if exists
b733747a 560 $defaults['tag'] = implode(',', CRM_Core_BAO_EntityTag::getTag($this->_activityId, 'civicrm_activity'));
6a488035
TO
561 }
562 else {
563 // if it's a new activity, we need to set default values for associated contact fields
6a488035
TO
564 $this->_sourceContactId = $this->_currentUserId;
565 $this->_targetContactId = $this->_currentlyViewedContactId;
6a488035 566
f7305cbc 567 $defaults['source_contact_id'] = $this->_sourceContactId;
c27ebe4e 568 $defaults['target_contact_id'] = $this->_targetContactId;
d104311a 569 }
6a488035 570
d104311a
CW
571 if (empty($defaults['activity_date_time'])) {
572 $defaults['activity_date_time'] = date('Y-m-d H:i:s');
6a488035
TO
573 }
574
575 if ($this->_activityTypeId) {
576 $defaults['activity_type_id'] = $this->_activityTypeId;
577 }
578
ab911378
PJ
579 if (!$this->_single && !empty($this->_contactIds)) {
580 $defaults['target_contact_id'] = $this->_contactIds;
581 }
582
b44e3f84 583 // CRM-15472 - 50 is around the practical limit of how many items a select2 entityRef can handle
531d3b28 584 if ($this->_action == CRM_Core_Action::UPDATE && !empty($defaults['target_contact_id'])) {
33913af6
CW
585 $count = count(is_array($defaults['target_contact_id']) ? $defaults['target_contact_id'] : explode(',', $defaults['target_contact_id']));
586 if ($count > 50) {
96f94695 587 $this->freeze(['target_contact_id']);
33913af6
CW
588 }
589 }
590
6a488035
TO
591 if ($this->_action & (CRM_Core_Action::DELETE | CRM_Core_Action::RENEW)) {
592 $this->assign('delName', CRM_Utils_Array::value('subject', $defaults));
593 }
594
595 if ($this->_activityTypeFile) {
0e6e8724
DL
596 $className = "CRM_{$this->_crmDir}_Form_Activity_{$this->_activityTypeFile}";
597 $defaults += $className::setDefaultValues($this);
6a488035 598 }
a7488080 599 if (empty($defaults['priority_id'])) {
cbf48754 600 $priority = CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id');
6a488035
TO
601 $defaults['priority_id'] = array_search('Normal', $priority);
602 }
a7488080 603 if (empty($defaults['status_id'])) {
343d84fa
DG
604 $defaults['status_id'] = CRM_Core_OptionGroup::getDefaultValue('activity_status');
605 }
6a488035
TO
606 return $defaults;
607 }
608
d51c6add 609 /**
610 * Build Quick form.
611 *
612 * @throws \CRM_Core_Exception
613 * @throws \CiviCRM_API3_Exception
614 */
6a488035
TO
615 public function buildQuickForm() {
616 if ($this->_action & (CRM_Core_Action::DELETE | CRM_Core_Action::RENEW)) {
617 //enable form element (ActivityLinks sets this true)
618 $this->assign('suppressForm', FALSE);
619
620 $button = ts('Delete');
621 if ($this->_action & CRM_Core_Action::RENEW) {
622 $button = ts('Restore');
623 }
96f94695 624 $this->addButtons([
625 [
19fc6ae4 626 'type' => 'next',
627 'name' => $button,
628 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
21dfd5f5 629 'isDefault' => TRUE,
96f94695 630 ],
631 [
19fc6ae4 632 'type' => 'cancel',
21dfd5f5 633 'name' => ts('Cancel'),
96f94695 634 ],
635 ]);
6a488035
TO
636 return;
637 }
638
7808aae6 639 // Build other activity links.
cfcb7676 640 CRM_Activity_Form_ActivityLinks::commonBuildQuickForm($this);
6a488035 641
7808aae6 642 // Enable form element (ActivityLinks sets this true).
6a488035
TO
643 $this->assign('suppressForm', FALSE);
644
353ffa53 645 $element = &$this->add('select', 'activity_type_id', ts('Activity Type'),
96f94695 646 ['' => '- ' . ts('select') . ' -'] + $this->_fields['followup_activity_type_id']['attributes'],
647 FALSE, [
2fcb4a7f 648 'onchange' => "CRM.buildCustomData( 'Activity', this.value, false, false, false, false, false, false, {$this->_currentlyViewedContactId});",
ba6e6f51 649 'class' => 'crm-select2 required',
96f94695 650 ]
6a488035
TO
651 );
652
7808aae6 653 // Freeze for update mode.
6a488035
TO
654 if ($this->_action & CRM_Core_Action::UPDATE) {
655 $element->freeze();
b334d9ad 656 }
657
7808aae6 658 // Call to RecurringEntity buildQuickForm for add/update mode.
b334d9ad 659 if ($this->_action & (CRM_Core_Action::UPDATE | CRM_Core_Action::ADD)) {
78fe87e6 660 CRM_Core_Form_RecurringEntity::buildQuickForm($this);
6a488035
TO
661 }
662
663 foreach ($this->_fields as $field => $values) {
a7488080 664 if (!empty($this->_fields[$field])) {
475e9f44
CW
665 $attribute = CRM_Utils_Array::value('attributes', $values);
666 $required = !empty($values['required']);
6a488035 667
13d9bc82 668 if ($values['type'] == 'select' && empty($attribute)) {
96f94695 669 $this->addSelect($field, ['entity' => 'activity'], $required);
c27ebe4e
CW
670 }
671 elseif ($values['type'] == 'entityRef') {
672 $this->addEntityRef($field, $values['label'], $attribute, $required);
475e9f44 673 }
c27ebe4e 674 else {
5e72d8ae 675 $this->add($values['type'], $field, $values['label'], $attribute, $required, CRM_Utils_Array::value('extra', $values));
6a488035
TO
676 }
677 }
678 }
679
7808aae6 680 // CRM-7362 --add campaigns.
6a488035
TO
681 CRM_Campaign_BAO_Campaign::addCampaign($this, CRM_Utils_Array::value('campaign_id', $this->_values));
682
7808aae6 683 // Add engagement level CRM-7775
6a488035
TO
684 $buildEngagementLevel = FALSE;
685 if (CRM_Campaign_BAO_Campaign::isCampaignEnable() &&
686 CRM_Campaign_BAO_Campaign::accessCampaign()
687 ) {
688 $buildEngagementLevel = TRUE;
96f94695 689 $this->addSelect('engagement_level', ['entity' => 'activity']);
6a488035
TO
690 $this->addRule('engagement_level',
691 ts('Please enter the engagement index as a number (integers only).'),
692 'positiveInteger'
693 );
694 }
695 $this->assign('buildEngagementLevel', $buildEngagementLevel);
696
697 // check for survey activity
698 $this->_isSurveyActivity = FALSE;
699
700 if ($this->_activityId && CRM_Campaign_BAO_Campaign::isCampaignEnable() &&
701 CRM_Campaign_BAO_Campaign::accessCampaign()
702 ) {
703
704 $this->_isSurveyActivity = CRM_Campaign_BAO_Survey::isSurveyActivity($this->_activityId);
705 if ($this->_isSurveyActivity) {
706 $surveyId = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity',
707 $this->_activityId,
708 'source_record_id'
709 );
710 $responseOptions = CRM_Campaign_BAO_Survey::getResponsesOptions($surveyId);
711 if ($responseOptions) {
712 $this->add('select', 'result', ts('Result'),
96f94695 713 ['' => ts('- select -')] + array_combine($responseOptions, $responseOptions)
6a488035
TO
714 );
715 }
716 $surveyTitle = NULL;
717 if ($surveyId) {
718 $surveyTitle = CRM_Core_DAO::getFieldValue('CRM_Campaign_DAO_Survey', $surveyId, 'title');
719 }
720 $this->assign('surveyTitle', $surveyTitle);
721 }
722 }
723 $this->assign('surveyActivity', $this->_isSurveyActivity);
724
598e9b75 725 // Add the "Activity Separation" field
03ca7bcb 726 $actionIsAdd = ($this->_action != CRM_Core_Action::UPDATE && $this->_action != CRM_Core_Action::VIEW);
598e9b75
SM
727 $separationIsPossible = $this->supportsActivitySeparation;
728 if ($actionIsAdd && $separationIsPossible) {
a850c3fe
SM
729 $this->addRadio(
730 'separation',
731 ts('Activity Separation'),
96f94695 732 [
a850c3fe
SM
733 'separate' => ts('Create separate activities for each contact'),
734 'combined' => ts('Create one activity with all contacts together'),
96f94695 735 ]
a850c3fe 736 );
52c7b3a2
KJ
737 }
738
6a488035
TO
739 $this->addRule('duration',
740 ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger'
741 );
6a488035 742
7808aae6 743 // Add followup date.
d7c5e6c3 744 $this->add('datepicker', 'followup_date', ts('in'));
6a488035 745
f7305cbc
CW
746 // Only admins and case-workers can change the activity source
747 if (!CRM_Core_Permission::check('administer CiviCRM') && $this->_context != 'caseActivity') {
c27ebe4e 748 $this->getElement('source_contact_id')->freeze();
f7305cbc 749 }
6a488035 750
6a488035
TO
751 //need to assign custom data type and subtype to the template
752 $this->assign('customDataType', 'Activity');
753 $this->assign('customDataSubType', $this->_activityTypeId);
754 $this->assign('entityID', $this->_activityId);
755
b733747a 756 $tags = CRM_Core_BAO_Tag::getColorTags('civicrm_activity');
6a488035
TO
757
758 if (!empty($tags)) {
96f94695 759 $this->add('select2', 'tag', ts('Tags'), $tags, FALSE, [
760 'class' => 'huge',
761 'placeholder' => ts('- select -'),
762 'multiple' => TRUE,
763 ]);
6a488035
TO
764 }
765
766 // we need to hide activity tagset for special activities
96f94695 767 $specialActivities = ['Open Case'];
6a488035
TO
768
769 if (!in_array($this->_activityTypeName, $specialActivities)) {
770 // build tag widget
771 $parentNames = CRM_Core_BAO_Tag::getTagSet('civicrm_activity');
95ef220a 772 CRM_Core_Form_Tag::buildQuickForm($this, $parentNames, 'civicrm_activity', $this->_activityId);
6a488035
TO
773 }
774
775 // if we're viewing, we're assigning different buttons than for adding/editing
776 if ($this->_action & CRM_Core_Action::VIEW) {
777 if (isset($this->_groupTree)) {
080d719e 778 CRM_Core_BAO_CustomGroup::buildCustomDataView($this, $this->_groupTree, FALSE, NULL, NULL, NULL, $this->_activityId);
6a488035 779 }
6a488035
TO
780 // form should be frozen for view mode
781 $this->freeze();
782
e517eb43
MWMC
783 $this->addButtons([
784 [
785 'type' => 'cancel',
786 'name' => ts('Done'),
787 ],
788 ]);
6a488035
TO
789 }
790 else {
e517eb43
MWMC
791 $this->addButtons([
792 [
c5c263ca
AH
793 'type' => 'upload',
794 'name' => ts('Save'),
c5c263ca 795 'isDefault' => TRUE,
e517eb43
MWMC
796 ],
797 [
c5c263ca
AH
798 'type' => 'cancel',
799 'name' => ts('Cancel'),
e517eb43
MWMC
800 ],
801 ]);
6a488035
TO
802 }
803
804 if ($this->_activityTypeFile) {
0e6e8724 805 $className = "CRM_{$this->_crmDir}_Form_Activity_{$this->_activityTypeFile}";
6a488035 806
0e6e8724 807 $className::buildQuickForm($this);
96f94695 808 $this->addFormRule([$className, 'formRule'], $this);
6a488035
TO
809 }
810
96f94695 811 $this->addFormRule(['CRM_Activity_Form_Activity', 'formRule'], $this);
6db7e202 812
96f94695 813 $doNotNotifyAssigneeFor = (array) Civi::settings()
814 ->get('do_not_notify_assignees_for');
815 if (($this->_activityTypeId && in_array($this->_activityTypeId, $doNotNotifyAssigneeFor)) || !Civi::settings()
62d3ee27 816 ->get('activity_assignee_notification')) {
e680ea41 817 $this->assign('activityAssigneeNotification', FALSE);
0086c33d
DL
818 }
819 else {
e680ea41 820 $this->assign('activityAssigneeNotification', TRUE);
6db7e202 821 }
e680ea41 822 $this->assign('doNotNotifyAssigneeFor', $doNotNotifyAssigneeFor);
6a488035
TO
823 }
824
825 /**
fe482240 826 * Global form rule.
6a488035 827 *
041ab3d1
TO
828 * @param array $fields
829 * The input form values.
830 * @param array $files
831 * The uploaded files if any.
2a6da8d7
EM
832 * @param $self
833 *
72b3a70c
CW
834 * @return bool|array
835 * true if no errors, else array of errors
6a488035 836 */
00be9182 837 public static function formRule($fields, $files, $self) {
6a488035
TO
838 // skip form rule if deleting
839 if (CRM_Utils_Array::value('_qf_Activity_next_', $fields) == 'Delete') {
840 return TRUE;
841 }
96f94695 842 $errors = [];
ba6e6f51 843 if ((array_key_exists('activity_type_id', $fields) || !$self->_single) && empty($fields['activity_type_id'])) {
6a488035
TO
844 $errors['activity_type_id'] = ts('Activity Type is a required field');
845 }
846
f47754ac
ML
847 $activity_type_id = CRM_Utils_Array::value('activity_type_id', $fields);
848 $activity_status_id = CRM_Utils_Array::value('status_id', $fields);
849 $scheduled_status_id = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'status_id', 'Scheduled');
850
851 if ($activity_type_id && $activity_status_id == $scheduled_status_id) {
852 if ($activity_type_id == CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Email')) {
853 $errors['status_id'] = ts('You cannot record scheduled email activity.');
854 }
855 elseif ($activity_type_id == CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'SMS')) {
856 $errors['status_id'] = ts('You cannot record scheduled SMS activity');
857 }
6a488035
TO
858 }
859
8cc574cf 860 if (!empty($fields['followup_activity_type_id']) && empty($fields['followup_date'])) {
d7c5e6c3 861 $errors['followup_date'] = ts('Followup date is a required field.');
6a488035 862 }
7808aae6 863 // Activity type is mandatory if subject or follow-up date is specified for an Follow-up activity, CRM-4515.
8cc574cf 864 if ((!empty($fields['followup_activity_subject']) || !empty($fields['followup_date'])) && empty($fields['followup_activity_type_id'])) {
6a488035
TO
865 $errors['followup_activity_subject'] = ts('Follow-up Activity type is a required field.');
866 }
53c79877
SM
867
868 // Check that a value has been set for the "activity separation" field if needed
869 $separationIsPossible = $self->supportsActivitySeparation;
a850c3fe
SM
870 $actionIsAdd = $self->_action == CRM_Core_Action::ADD;
871 $hasMultipleTargetContacts = !empty($fields['target_contact_id']) && strpos($fields['target_contact_id'], ',') !== FALSE;
872 $separationFieldIsEmpty = empty($fields['separation']);
53c79877 873 if ($separationIsPossible && $actionIsAdd && $hasMultipleTargetContacts && $separationFieldIsEmpty) {
a850c3fe
SM
874 $errors['separation'] = ts('Activity Separation is a required field.');
875 }
53c79877 876
6a488035
TO
877 return $errors;
878 }
879
880 /**
fe482240 881 * Process the form submission.
6a488035 882 *
6a488035 883 *
100fef9d 884 * @param array $params
d51c6add 885 *
100fef9d 886 * @return array|null
531d3b28 887 * @throws \CiviCRM_API3_Exception
6a488035
TO
888 */
889 public function postProcess($params = NULL) {
890 if ($this->_action & CRM_Core_Action::DELETE) {
a6ebc13f
KJ
891 // Look up any repeat activities to be deleted.
892 $activityIds = array_column(CRM_Core_BAO_RecurringEntity::getEntitiesFor($this->_activityId, 'civicrm_activity', TRUE, NULL), 'id');
893 if (!$activityIds) {
894 // There are no repeat activities to delete - just this one.
895 $activityIds = [$this->_activityId];
896 }
897
898 // Delete each activity.
899 foreach ($activityIds as $activityId) {
900 $deleteParams = ['id' => $activityId];
901 $moveToTrash = CRM_Case_BAO_Case::isCaseActivity($activityId);
902 CRM_Activity_BAO_Activity::deleteActivity($deleteParams, $moveToTrash);
6a488035 903
a6ebc13f
KJ
904 // delete tags for the entity
905 $tagParams = [
906 'entity_table' => 'civicrm_activity',
907 'entity_id' => $activityId,
908 ];
6a488035 909
a6ebc13f
KJ
910 CRM_Core_BAO_EntityTag::del($tagParams);
911 }
912
913 CRM_Core_Session::setStatus(
914 ts("Selected Activity has been deleted successfully.", ['plural' => '%count Activities have been deleted successfully.', 'count' => count($activityIds)]),
915 ts('Record Deleted', ['plural' => 'Records Deleted', 'count' => count($activityIds)]), 'success'
916 );
6a488035 917
a1a2a83d 918 return NULL;
6a488035
TO
919 }
920
921 // store the submitted values in an array
922 if (!$params) {
923 $params = $this->controller->exportValues($this->_name);
924 }
925
7808aae6 926 // Set activity type id.
a7488080 927 if (empty($params['activity_type_id'])) {
6a488035
TO
928 $params['activity_type_id'] = $this->_activityTypeId;
929 }
930
a7488080 931 if (!empty($params['hidden_custom']) &&
6a488035
TO
932 !isset($params['custom'])
933 ) {
934 $customFields = CRM_Core_BAO_CustomField::getFields('Activity', FALSE, FALSE,
935 $this->_activityTypeId
936 );
937 $customFields = CRM_Utils_Array::crmArrayMerge($customFields,
938 CRM_Core_BAO_CustomField::getFields('Activity', FALSE, FALSE,
939 NULL, NULL, TRUE
940 )
941 );
942 $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params,
6a488035
TO
943 $this->_activityId,
944 'Activity'
945 );
946 }
947
c27ebe4e 948 // format params as arrays
96f94695 949 foreach (['target', 'assignee', 'followup_assignee'] as $name) {
c27ebe4e
CW
950 if (!empty($params["{$name}_contact_id"])) {
951 $params["{$name}_contact_id"] = explode(',', $params["{$name}_contact_id"]);
952 }
953 else {
96f94695 954 $params["{$name}_contact_id"] = [];
c27ebe4e 955 }
6a488035 956 }
6a488035
TO
957
958 // get ids for associated contacts
959 if (!$params['source_contact_id']) {
960 $params['source_contact_id'] = $this->_currentUserId;
961 }
6a488035
TO
962
963 if (isset($this->_activityId)) {
964 $params['id'] = $this->_activityId;
965 }
966
967 // add attachments as needed
968 CRM_Core_BAO_File::formatAttachment($params,
969 $params,
970 'civicrm_activity',
971 $this->_activityId
972 );
973
a850c3fe
SM
974 $params['is_multi_activity'] = CRM_Utils_Array::value('separation', $params) == 'separate';
975
96f94695 976 $activity = [];
a7488080 977 if (!empty($params['is_multi_activity']) &&
52c7b3a2
KJ
978 !CRM_Utils_Array::crmIsEmptyArray($params['target_contact_id'])
979 ) {
980 $targetContacts = $params['target_contact_id'];
19fc6ae4 981 foreach ($targetContacts as $targetContactId) {
96f94695 982 $params['target_contact_id'] = [$targetContactId];
52c7b3a2
KJ
983 // save activity
984 $activity[] = $this->processActivity($params);
985 }
986 }
987 else {
988 // save activity
989 $activity = $this->processActivity($params);
990 }
991
70f3519a
CW
992 // Redirect to contact page or activity view in standalone mode
993 if ($this->_context == 'standalone') {
994 if (count($params['target_contact_id']) == 1) {
995 $url = CRM_Utils_System::url('civicrm/contact/view', ['cid' => CRM_Utils_Array::first($params['target_contact_id']), 'selectedChild' => 'activity']);
996 }
997 else {
998 $url = CRM_Utils_System::url('civicrm/activity', ['action' => 'view', 'reset' => 1, 'id' => $this->_activityId]);
999 }
1000 CRM_Core_Session::singleton()->pushUserContext($url);
1001 }
1002
96f94695 1003 $activityIds = empty($this->_activityIds) ? [$this->_activityId] : $this->_activityIds;
7a4bb524 1004 foreach ($activityIds as $activityId) {
1005 // set params for repeat configuration in create mode
1006 $params['entity_id'] = $activityId;
1007 $params['entity_table'] = 'civicrm_activity';
7a4bb524 1008 if (!empty($params['entity_id']) && !empty($params['entity_table'])) {
1009 $checkParentExistsForThisId = CRM_Core_BAO_RecurringEntity::getParentFor($params['entity_id'], $params['entity_table']);
1010 if ($checkParentExistsForThisId) {
1011 $params['parent_entity_id'] = $checkParentExistsForThisId;
1012 $scheduleReminderDetails = CRM_Core_BAO_RecurringEntity::getReminderDetailsByEntityId($checkParentExistsForThisId, $params['entity_table']);
1013 }
1014 else {
1015 $params['parent_entity_id'] = $params['entity_id'];
1016 $scheduleReminderDetails = CRM_Core_BAO_RecurringEntity::getReminderDetailsByEntityId($params['entity_id'], $params['entity_table']);
1017 }
1018 if (property_exists($scheduleReminderDetails, 'id')) {
1019 $params['schedule_reminder_id'] = $scheduleReminderDetails->id;
1020 }
fe87e754 1021 }
96f94695 1022 $params['dateColumns'] = ['activity_date_time'];
b334d9ad 1023
83f3c8a3
CW
1024 // Set default repetition start if it was not provided.
1025 if (empty($params['repetition_start_date'])) {
1026 $params['repetition_start_date'] = $params['activity_date_time'];
1027 }
1028
7a4bb524 1029 // unset activity id
1030 unset($params['id']);
96f94695 1031 $linkedEntities = [
1032 [
7a4bb524 1033 'table' => 'civicrm_activity_contact',
96f94695 1034 'findCriteria' => [
7a4bb524 1035 'activity_id' => $activityId,
96f94695 1036 ],
1037 'linkedColumns' => ['activity_id'],
7a4bb524 1038 'isRecurringEntityRecord' => FALSE,
96f94695 1039 ],
1040 ];
7a4bb524 1041 CRM_Core_Form_RecurringEntity::postProcess($params, 'civicrm_activity', $linkedEntities);
1042 }
b334d9ad 1043
96f94695 1044 return ['activity' => $activity];
52c7b3a2
KJ
1045 }
1046
1047 /**
fe482240 1048 * Process activity creation.
52c7b3a2 1049 *
041ab3d1
TO
1050 * @param array $params
1051 * Associated array of submitted values.
77b97be7 1052 *
6c552737 1053 * @return self|null|object
52c7b3a2
KJ
1054 */
1055 protected function processActivity(&$params) {
96f94695 1056 $activityAssigned = [];
44f817d4 1057 $activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
034500d4 1058 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
6a488035
TO
1059 // format assignee params
1060 if (!CRM_Utils_Array::crmIsEmptyArray($params['assignee_contact_id'])) {
1061 //skip those assignee contacts which are already assigned
1062 //while sending a copy.CRM-4509.
1063 $activityAssigned = array_flip($params['assignee_contact_id']);
1064 if ($this->_activityId) {
034500d4 1065 $assigneeContacts = CRM_Activity_BAO_ActivityContact::getNames($this->_activityId, $assigneeID);
6a488035
TO
1066 $activityAssigned = array_diff_key($activityAssigned, $assigneeContacts);
1067 }
1068 }
1069
1070 // call begin post process. Idea is to let injecting file do
1071 // any processing before the activity is added/updated.
1072 $this->beginPostProcess($params);
1073
1074 $activity = CRM_Activity_BAO_Activity::create($params);
1075
1076 // add tags if exists
96f94695 1077 $tagParams = [];
6a488035 1078 if (!empty($params['tag'])) {
b733747a
CW
1079 if (!is_array($params['tag'])) {
1080 $params['tag'] = explode(',', $params['tag']);
1081 }
63b7aefc
DB
1082
1083 $tagParams = array_fill_keys($params['tag'], 1);
6a488035
TO
1084 }
1085
7808aae6 1086 // Save static tags.
6a488035
TO
1087 CRM_Core_BAO_EntityTag::create($tagParams, 'civicrm_activity', $activity->id);
1088
7808aae6 1089 // Save free tags.
6a488035
TO
1090 if (isset($params['activity_taglist']) && !empty($params['activity_taglist'])) {
1091 CRM_Core_Form_Tag::postProcess($params['activity_taglist'], $activity->id, 'civicrm_activity', $this);
1092 }
1093
1094 // call end post process. Idea is to let injecting file do any
1095 // processing needed, after the activity has been added/updated.
1096 $this->endPostProcess($params, $activity);
1097
1098 // CRM-9590
a7488080 1099 if (!empty($params['is_multi_activity'])) {
52c7b3a2
KJ
1100 $this->_activityIds[] = $activity->id;
1101 }
1102 else {
1103 $this->_activityId = $activity->id;
1104 }
6a488035
TO
1105
1106 // create follow up activity if needed
1107 $followupStatus = '';
90b05581 1108 $followupActivity = NULL;
a7488080 1109 if (!empty($params['followup_activity_type_id'])) {
90b05581 1110 $followupActivity = CRM_Activity_BAO_Activity::createFollowupActivity($activity->id, $params);
6a488035
TO
1111 $followupStatus = ts('A followup activity has been scheduled.');
1112 }
1113
1114 // send copy to assignee contacts.CRM-4509
1115 $mailStatus = '';
1116
ac983377 1117 if (Civi::settings()->get('activity_assignee_notification')
96f94695 1118 && !in_array($activity->activity_type_id, Civi::settings()
1119 ->get('do_not_notify_assignees_for'))) {
1120 $activityIDs = [$activity->id];
90b05581 1121 if ($followupActivity) {
96f94695 1122 $activityIDs = array_merge($activityIDs, [$followupActivity->id]);
90b05581
DG
1123 }
1124 $assigneeContacts = CRM_Activity_BAO_ActivityAssignment::getAssigneeNames($activityIDs, TRUE, FALSE);
6a488035 1125
90b05581 1126 if (!CRM_Utils_Array::crmIsEmptyArray($params['assignee_contact_id'])) {
96f94695 1127 $mailToContacts = [];
90b05581 1128
7808aae6 1129 // Build an associative array with unique email addresses.
90b05581
DG
1130 foreach ($activityAssigned as $id => $dnc) {
1131 if (isset($id) && array_key_exists($id, $assigneeContacts)) {
1132 $mailToContacts[$assigneeContacts[$id]['email']] = $assigneeContacts[$id];
1133 }
6a488035 1134 }
6a488035 1135
bc883279 1136 $sent = CRM_Activity_BAO_Activity::sendToAssignee($activity, $mailToContacts);
1137 if ($sent) {
1138 $mailStatus .= ts("A copy of the activity has also been sent to assignee contacts(s).");
1139 }
1140 }
77b97be7 1141
90b05581
DG
1142 // Also send email to follow-up activity assignees if set
1143 if ($followupActivity) {
96f94695 1144 $mailToFollowupContacts = [];
90b05581
DG
1145 foreach ($assigneeContacts as $values) {
1146 if ($values['activity_id'] == $followupActivity->id) {
1147 $mailToFollowupContacts[$values['email']] = $values;
1148 }
1149 }
1150
2bbb4a91 1151 $sentFollowup = CRM_Activity_BAO_Activity::sendToAssignee($followupActivity, $mailToFollowupContacts);
bc883279 1152 if ($sentFollowup) {
f3c5a172 1153 $mailStatus .= '<br />' . ts("A copy of the follow-up activity has also been sent to follow-up assignee contacts(s).");
bc883279 1154 }
6a488035
TO
1155 }
1156 }
1157
1158 // set status message
ef89f226 1159 $subject = '';
a7488080 1160 if (!empty($params['subject'])) {
ef89f226 1161 $subject = "'" . $params['subject'] . "'";
6a488035
TO
1162 }
1163
12e2d503 1164 CRM_Core_Session::setStatus(ts('Activity %1 has been saved. %2 %3',
96f94695 1165 [
ef89f226 1166 1 => $subject,
52c7b3a2 1167 2 => $followupStatus,
21dfd5f5 1168 3 => $mailStatus,
96f94695 1169 ]
52c7b3a2 1170 ), ts('Saved'), 'success');
6a488035 1171
52c7b3a2 1172 return $activity;
6a488035
TO
1173 }
1174
1175 /**
1176 * Shorthand for getting id by display name (makes code more readable)
645ee340
EM
1177 * @param $displayName
1178 * @return null|string
6a488035
TO
1179 */
1180 protected function _getIdByDisplayName($displayName) {
1181 return CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
1182 $displayName,
1183 'id',
1184 'sort_name'
1185 );
1186 }
1187
1188 /**
1189 * Shorthand for getting display name by id (makes code more readable)
645ee340
EM
1190 * @param $id
1191 * @return null|string
6a488035
TO
1192 */
1193 protected function _getDisplayNameById($id) {
1194 return CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
1195 $id,
1196 'sort_name',
1197 'id'
1198 );
1199 }
1200
1201 /**
fe482240 1202 * Let injecting activity type file do any processing.
6a488035
TO
1203 * needed, before the activity is added/updated
1204 *
100fef9d 1205 * @param array $params
6a488035 1206 */
00be9182 1207 public function beginPostProcess(&$params) {
6a488035 1208 if ($this->_activityTypeFile) {
0e6e8724
DL
1209 $className = "CRM_{$this->_crmDir}_Form_Activity_{$this->_activityTypeFile}";
1210 $className::beginPostProcess($this, $params);
6a488035
TO
1211 }
1212 }
1213
1214 /**
100fef9d 1215 * Let injecting activity type file do any processing
6a488035
TO
1216 * needed, after the activity has been added/updated
1217 *
100fef9d
CW
1218 * @param array $params
1219 * @param $activity
6a488035 1220 */
00be9182 1221 public function endPostProcess(&$params, &$activity) {
6a488035 1222 if ($this->_activityTypeFile) {
0e6e8724 1223 $className = "CRM_{$this->_crmDir}_Form_Activity_{$this->_activityTypeFile}";
100fef9d 1224 $className::endPostProcess($this, $params, $activity);
6a488035
TO
1225 }
1226 }
96025800 1227
794f8025
D
1228 /**
1229 * For the moment keeping this the same as the original pulled from preProcess(). Also note the "s" at the end of the function name - planning to change that but in baby steps.
1230 *
1231 * @return string[]
1232 */
1233 public function getActivityTypeDisplayLabels() {
1234 return CRM_Core_OptionGroup::values('activity_type', FALSE, FALSE, FALSE, 'AND v.value = ' . $this->_activityTypeId, 'label');
1235 }
1236
c6bbfc3a
D
1237 /**
1238 * For the moment this is just pulled from preProcess
1239 */
1240 public function assignActivityType() {
1241 if ($this->_activityTypeId) {
1242 $activityTypeDisplayLabels = $this->getActivityTypeDisplayLabels();
1243 if ($activityTypeDisplayLabels[$this->_activityTypeId]) {
1244 $this->_activityTypeName = $activityTypeDisplayLabels[$this->_activityTypeId];
11a60382
D
1245
1246 // At the moment this is duplicating other code in this section, but refactoring in small steps.
1247 $activityTypeObj = new CRM_Activity_BAO_ActivityType($this->_activityTypeId);
f692bf33 1248 $this->assign('activityTypeNameAndLabel', $activityTypeObj->getActivityType());
c6bbfc3a
D
1249 }
1250 // Set title.
1251 if (isset($activityTypeDisplayLabels)) {
1252 // FIXME - it's not clear why the if line just above is needed here and why we can't just set this once above and re-use. What is interesting, but can't possibly be the reason, is that the first if block will fail if the label is the string '0', whereas this one won't. But who would have an activity type called '0'?
1253 $activityTypeDisplayLabel = CRM_Utils_Array::value($this->_activityTypeId, $activityTypeDisplayLabels);
1254
1255 if ($this->_currentlyViewedContactId) {
1256 $displayName = CRM_Contact_BAO_Contact::displayName($this->_currentlyViewedContactId);
1257 // Check if this is default domain contact CRM-10482.
1258 if (CRM_Contact_BAO_Contact::checkDomainContact($this->_currentlyViewedContactId)) {
1259 $displayName .= ' (' . ts('default organization') . ')';
1260 }
1261 CRM_Utils_System::setTitle($displayName . ' - ' . $activityTypeDisplayLabel);
1262 }
1263 else {
1264 CRM_Utils_System::setTitle(ts('%1 Activity', [1 => $activityTypeDisplayLabel]));
1265 }
1266 }
1267 }
1268 }
1269
6a488035 1270}