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