test - flush pseudoconstant on case test, comments
[civicrm-core.git] / CRM / Activity / BAO / Activity.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * This class is for activity functions
38 *
39 */
40class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
41
42 /**
43 * static field for all the activity information that we can potentially export
44 *
45 * @var array
46 * @static
47 */
48 static $_exportableFields = NULL;
49
50 /**
51 * static field for all the activity information that we can potentially import
52 *
53 * @var array
54 * @static
55 */
56 static $_importableFields = NULL;
57
58 /**
59 * Check if there is absolute minimum of data to add the object
60 *
61 * @param array $params (reference ) an assoc array of name/value pairs
62 *
63 * @return boolean
64 * @access public
65 */
66 public static function dataExists(&$params) {
8cc574cf 67 if (!empty($params['source_contact_id']) || !empty($params['id'])) {
6a488035
TO
68 return TRUE;
69 }
70 return FALSE;
71 }
72
73 /**
74 * Takes a bunch of params that are needed to match certain criteria and
75 * retrieves the relevant objects. Typically the valid params are only
76 * contact_id. We'll tweak this function to be more full featured over a period
77 * of time. This is the inverse function of create. It also stores all the retrieved
78 * values in the default array
79 *
1cfa04c4
EM
80 * @param array $params (reference ) an assoc array of name/value pairs
81 * @param array $defaults (reference ) an assoc array to hold the flattened values
82 *
83 * @internal param string $activityType activity type
6a488035
TO
84 *
85 * @return object CRM_Core_BAO_Meeting object
86 * @access public
87 */
88 public static function retrieve(&$params, &$defaults) {
89 $activity = new CRM_Activity_DAO_Activity();
90 $activity->copyValues($params);
91
92 if ($activity->find(TRUE)) {
e7e657f0 93 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
034500d4 94 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
95 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
96 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
97
6a488035
TO
98 // TODO: at some stage we'll have to deal
99 // TODO: with multiple values for assignees and targets, but
100 // TODO: for now, let's just fetch first row
034500d4 101 $defaults['assignee_contact'] = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $assigneeID);
102 $assignee_contact_names = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $assigneeID);
6a488035 103 $defaults['assignee_contact_value'] = implode('; ', $assignee_contact_names);
eb873b6e 104 $sourceContactId = self::getActivityContact($activity->id, $sourceID);
6a488035 105 if ($activity->activity_type_id != CRM_Core_OptionGroup::getValue('activity_type', 'Bulk Email', 'name')) {
034500d4 106 $defaults['target_contact'] = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $targetID);
107 $target_contact_names = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $targetID);
6a488035
TO
108 $defaults['target_contact_value'] = implode('; ', $target_contact_names);
109 }
110 elseif (CRM_Core_Permission::check('access CiviMail') ||
111 (CRM_Mailing_Info::workflowEnabled() &&
112 CRM_Core_Permission::check('create mailings')
113 )
114 ) {
115 $defaults['mailingId'] = CRM_Utils_System::url('civicrm/mailing/report',
eb873b6e 116 "mid={$activity->source_record_id}&reset=1&atype={$activity->activity_type_id}&aid={$activity->id}&cid={$sourceContactId}&context=activity"
6a488035
TO
117 );
118 }
119 else {
120 $defaults['target_contact_value'] = ts('(recipients)');
121 }
b319d00a 122
65ebc887 123 $sourceContactId = self::getActivityContact($activity->id, $sourceID);
ad674e50 124 $defaults['source_contact_id'] = $sourceContactId;
6a488035 125
65ebc887 126 if ($sourceContactId &&
6a488035 127 !CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
65ebc887 128 $sourceContactId,
6a488035
TO
129 'is_deleted'
130 )
131 ) {
132 $defaults['source_contact'] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
65ebc887 133 $sourceContactId,
6a488035
TO
134 'sort_name'
135 );
136 }
137
138 //get case subject
139 $defaults['case_subject'] = CRM_Case_BAO_Case::getCaseSubject($activity->id);
140
141 CRM_Core_DAO::storeValues($activity, $defaults);
142
143 return $activity;
144 }
145 return NULL;
146 }
147
148 /**
149 * Function to delete the activity
150 *
151 * @param array $params associated array
152 *
153 * @return void
154 * @access public
155 *
156 */
157 public static function deleteActivity(&$params, $moveToTrash = FALSE) {
158 // CRM-9137
a7488080 159 if (!empty($params['id']) && !is_array($params['id'])) {
6a488035
TO
160 CRM_Utils_Hook::pre('delete', 'Activity', $params['id'], $params);
161 }
162 else {
163 CRM_Utils_Hook::pre('delete', 'Activity', NULL, $params);
164 }
165
166 $transaction = new CRM_Core_Transaction();
167 if (is_array(CRM_Utils_Array::value('source_record_id', $params))) {
168 $sourceRecordIds = implode(',', $params['source_record_id']);
169 }
170 else {
171 $sourceRecordIds = CRM_Utils_Array::value('source_record_id', $params);
172 }
173
174 $result = NULL;
175 if (!$moveToTrash) {
176 if (!isset($params['id'])) {
177 if (is_array($params['activity_type_id'])) {
178 $activityTypes = implode(',', $params['activity_type_id']);
179 }
180 else {
181 $activityTypes = $params['activity_type_id'];
182 }
183
184 $query = "DELETE FROM civicrm_activity WHERE source_record_id IN ({$sourceRecordIds}) AND activity_type_id IN ( {$activityTypes} )";
185 $dao = CRM_Core_DAO::executeQuery($query);
186 }
187 else {
188 $activity = new CRM_Activity_DAO_Activity();
189 $activity->copyValues($params);
190 $result = $activity->delete();
191
192 // CRM-8708
193 $activity->case_id = CRM_Case_BAO_Case::getCaseIdByActivityId($activity->id);
93bcc9e8
BS
194
195 // CRM-13994 delete activity entity_tag
196 $query = "DELETE FROM civicrm_entity_tag WHERE entity_table = 'civicrm_activity' AND entity_id = {$activity->id}";
197 $dao = CRM_Core_DAO::executeQuery($query);
6a488035
TO
198 }
199 }
200 else {
201 $activity = new CRM_Activity_DAO_Activity();
202 $activity->copyValues($params);
203
204 $activity->is_deleted = 1;
205 $result = $activity->save();
206
93bcc9e8
BS
207 // CRM-4525 log activity delete
208 $logMsg = 'Case Activity deleted for';
209 $msgs = array();
034500d4 210
e7e657f0 211 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
034500d4 212 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
213 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
214 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
215 $sourceContactId = self::getActivityContact($activity->id, $sourceID);
6a488035
TO
216 if ($sourceContactId) {
217 $msgs[] = " source={$sourceContactId}";
218 }
034500d4 219
6a488035 220 //get target contacts.
034500d4 221 $targetContactIds = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $targetID);
6a488035
TO
222 if (!empty($targetContactIds)) {
223 $msgs[] = " target =" . implode(',', array_keys($targetContactIds));
224 }
225 //get assignee contacts.
034500d4 226 $assigneeContactIds = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $assigneeID);
6a488035
TO
227 if (!empty($assigneeContactIds)) {
228 $msgs[] = " assignee =" . implode(',', array_keys($assigneeContactIds));
229 }
230
231 $logMsg .= implode(', ', $msgs);
232
233 self::logActivityAction($activity, $logMsg);
234 }
235
236 // delete the recently created Activity
237 if ($result) {
238 $activityRecent = array(
239 'id' => $activity->id,
240 'type' => 'Activity',
241 );
242 CRM_Utils_Recent::del($activityRecent);
243 }
244
245 $transaction->commit();
246 if (isset($activity)) {
247 // CRM-8708
248 $activity->case_id = CRM_Case_BAO_Case::getCaseIdByActivityId($activity->id);
249 CRM_Utils_Hook::post('delete', 'Activity', $activity->id, $activity);
250 }
251
252 return $result;
253 }
254
255 /**
256 * Delete activity assignment record
257 *
258 * @param int $id activity id
259 *
260 * @return null
261 * @access public
262 */
a24b3694 263 public static function deleteActivityContact($activityId, $recordTypeID = NULL) {
1d85d241
DL
264 $activityContact = new CRM_Activity_BAO_ActivityContact();
265 $activityContact->activity_id = $activityId;
a24b3694 266 if ($recordTypeID) {
267 $activityContact->record_type_id = $recordTypeID;
6a488035 268 }
1d85d241 269 $activityContact->delete();
6a488035
TO
270 }
271
272 /**
273 * Function to process the activities
274 *
1cfa04c4
EM
275 * @param array $params associated array of the submitted values
276 *
277 * @internal param object $form form object
278 * @internal param array $ids array of ids
279 * @internal param string $activityType activity Type
280 * @internal param bool $record true if it is Record Activity
6a488035
TO
281 * @access public
282 *
1cfa04c4 283 * @return $this|null|object
6a488035
TO
284 */
285 public static function create(&$params) {
286 // check required params
287 if (!self::dataExists($params)) {
9af2925b 288 throw new CRM_Core_Exception('Not enough data to create activity object');
6a488035
TO
289 }
290
291 $activity = new CRM_Activity_DAO_Activity();
292
293 if (isset($params['id']) && empty($params['id'])) {
294 unset($params['id']);
295 }
296
8cc574cf 297 if (empty($params['status_id']) && empty($params['activity_status_id']) && empty($params['id'])) {
6a488035
TO
298 if (isset($params['activity_date_time']) &&
299 strcmp($params['activity_date_time'], CRM_Utils_Date::processDate(date('Ymd')) == -1)
300 ) {
301 $params['status_id'] = 2;
302 }
303 else {
304 $params['status_id'] = 1;
305 }
306 }
307
308 //set priority to Normal for Auto-populated activities (for Cases)
309 if (CRM_Utils_Array::value('priority_id', $params) === NULL &&
310 // if not set and not 0
311 !CRM_Utils_Array::value('id', $params)
312 ) {
cbf48754 313 $priority = CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id');
6a488035
TO
314 $params['priority_id'] = array_search('Normal', $priority);
315 }
316
317 if (!empty($params['target_contact_id']) && is_array($params['target_contact_id'])) {
318 $params['target_contact_id'] = array_unique($params['target_contact_id']);
319 }
320 if (!empty($params['assignee_contact_id']) && is_array($params['assignee_contact_id'])) {
321 $params['assignee_contact_id'] = array_unique($params['assignee_contact_id']);
322 }
323
324 // CRM-9137
a7488080 325 if (!empty($params['id'])) {
6a488035
TO
326 CRM_Utils_Hook::pre('edit', 'Activity', $activity->id, $params);
327 }
328 else {
329 CRM_Utils_Hook::pre('create', 'Activity', NULL, $params);
330 }
331
332 $activity->copyValues($params);
333 if (isset($params['case_id'])) {
334 // CRM-8708, preserve case ID even though it's not part of the SQL model
335 $activity->case_id = $params['case_id'];
336 }
337 elseif (is_numeric($activity->id)) {
338 // CRM-8708, preserve case ID even though it's not part of the SQL model
339 $activity->case_id = CRM_Case_BAO_Case::getCaseIdByActivityId($activity->id);
340 }
341
342 // start transaction
343 $transaction = new CRM_Core_Transaction();
344
345 $result = $activity->save();
346
347 if (is_a($result, 'CRM_Core_Error')) {
348 $transaction->rollback();
349 return $result;
350 }
351
352 $activityId = $activity->id;
e7e657f0 353 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
a24b3694 354 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
355 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
356 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
6a488035 357
1d85d241
DL
358 if (isset($params['source_contact_id'])) {
359 $acParams = array(
360 'activity_id' => $activityId,
361 'contact_id' => $params['source_contact_id'],
a24b3694 362 'record_type_id' => $sourceID
1d85d241 363 );
8ea7ce5d 364 self::deleteActivityContact($activityId, $sourceID);
1d85d241
DL
365 CRM_Activity_BAO_ActivityContact::create($acParams);
366 }
367
6a488035
TO
368 // check and attach and files as needed
369 CRM_Core_BAO_File::processAttachment($params, 'civicrm_activity', $activityId);
370
371 // attempt to save activity assignment
372 $resultAssignment = NULL;
a7488080 373 if (!empty($params['assignee_contact_id'])) {
6a488035
TO
374
375 $assignmentParams = array('activity_id' => $activityId);
376
377 if (is_array($params['assignee_contact_id'])) {
378 if (CRM_Utils_Array::value('deleteActivityAssignment', $params, TRUE)) {
379 // first delete existing assignments if any
a24b3694 380 self::deleteActivityContact($activityId, $assigneeID);
6a488035
TO
381 }
382
383 $values = array();
384 foreach ($params['assignee_contact_id'] as $acID) {
385 if ($acID) {
a24b3694 386 $values[] = "( $activityId, $acID, $assigneeID )";
6a488035
TO
387 }
388 }
389 while (!empty($values)) {
390 $input = array_splice($values, 0, CRM_Core_DAO::BULK_INSERT_COUNT);
391 $str = implode(',', $input);
a24b3694 392 $sql = "INSERT IGNORE INTO civicrm_activity_contact ( activity_id, contact_id, record_type_id ) VALUES $str;";
6a488035
TO
393 CRM_Core_DAO::executeQuery($sql);
394 }
395 }
396 else {
b319d00a 397 $assignmentParams['contact_id'] = $params['assignee_contact_id'];
034500d4 398 $assignmentParams['record_type_id'] = $assigneeID;
a7488080 399 if (!empty($params['id'])) {
cc1c86e9 400 $assignment = new CRM_Activity_BAO_ActivityContact();
6a488035 401 $assignment->activity_id = $activityId;
034500d4 402 $assignment->record_type_id = $assigneeID;
6a488035
TO
403 $assignment->find(TRUE);
404
b319d00a 405 if ($assignment->contact_id != $params['assignee_contact_id']) {
6a488035 406 $assignmentParams['id'] = $assignment->id;
034500d4 407 $resultAssignment = CRM_Activity_BAO_ActivityContact::create($assignmentParams);
6a488035
TO
408 }
409 }
410 else {
034500d4 411 $resultAssignment = CRM_Activity_BAO_ActivityContact::create($assignmentParams);
6a488035
TO
412 }
413 }
414 }
415 else {
416 if (CRM_Utils_Array::value('deleteActivityAssignment', $params, TRUE)) {
a24b3694 417 self::deleteActivityContact($activityId, $assigneeID);
6a488035
TO
418 }
419 }
420
421 if (is_a($resultAssignment, 'CRM_Core_Error')) {
422 $transaction->rollback();
423 return $resultAssignment;
424 }
425
426 // attempt to save activity targets
427 $resultTarget = NULL;
a7488080 428 if (!empty($params['target_contact_id'])) {
6a488035
TO
429
430 $targetParams = array('activity_id' => $activityId);
431 $resultTarget = array();
432 if (is_array($params['target_contact_id'])) {
433 if (CRM_Utils_Array::value('deleteActivityTarget', $params, TRUE)) {
434 // first delete existing targets if any
a24b3694 435 self::deleteActivityContact($activityId, $targetID );
6a488035
TO
436 }
437
438 $values = array();
439 foreach ($params['target_contact_id'] as $tid) {
440 if ($tid) {
a24b3694 441 $values[] = "( $activityId, $tid, $targetID )";
6a488035
TO
442 }
443 }
444
445 while (!empty($values)) {
446 $input = array_splice($values, 0, CRM_Core_DAO::BULK_INSERT_COUNT);
447 $str = implode(',', $input);
a24b3694 448 $sql = "INSERT IGNORE INTO civicrm_activity_contact ( activity_id, contact_id, record_type_id ) VALUES $str;";
6a488035
TO
449 CRM_Core_DAO::executeQuery($sql);
450 }
451 }
452 else {
b319d00a 453 $targetParams['contact_id'] = $params['target_contact_id'];
034500d4 454 $targetParams['record_type_id'] = $targetID;
a7488080 455 if (!empty($params['id'])) {
034500d4 456 $target = new CRM_Activity_BAO_ActivityContact();
6a488035 457 $target->activity_id = $activityId;
034500d4 458 $target->record_type_id = $targetID;
6a488035
TO
459 $target->find(TRUE);
460
b319d00a 461 if ($target->contact_id != $params['target_contact_id']) {
6a488035 462 $targetParams['id'] = $target->id;
034500d4 463 $resultTarget = CRM_Activity_BAO_ActivityContact::create($targetParams);
6a488035
TO
464 }
465 }
466 else {
034500d4 467 $resultTarget = CRM_Activity_BAO_ActivityContact::create($targetParams);
6a488035
TO
468 }
469 }
470 }
471 else {
472 if (CRM_Utils_Array::value('deleteActivityTarget', $params, TRUE)) {
a24b3694 473 self::deleteActivityContact($activityId, $targetID );
6a488035
TO
474 }
475 }
476
0a9f61c4 477 // write to changelog before transaction is committed/rolled
6a488035 478 // back (and prepare status to display)
a7488080 479 if (!empty($params['id'])) {
6a488035
TO
480 $logMsg = "Activity (id: {$result->id} ) updated with ";
481 }
482 else {
483 $logMsg = "Activity created for ";
484 }
485
486 $msgs = array();
487 if (isset($params['source_contact_id'])) {
488 $msgs[] = "source={$params['source_contact_id']}";
489 }
490
a7488080 491 if (!empty($params['target_contact_id'])) {
6a488035
TO
492 if (is_array($params['target_contact_id']) && !CRM_Utils_array::crmIsEmptyArray($params['target_contact_id'])) {
493 $msgs[] = "target=" . implode(',', $params['target_contact_id']);
494 // take only first target
495 // will be used for recently viewed display
496 $t = array_slice($params['target_contact_id'], 0, 1);
497 $recentContactId = $t[0];
498 }
9af2925b
EM
499 //is array check fixes warning without degrading functionality but it seems this bit of code may no longer work
500 // as it may always be an array
501 elseif (isset($params['target_contact_id']) && !is_array($params['target_contact_id'])) {
6a488035
TO
502 $msgs[] = "target={$params['target_contact_id']}";
503 // will be used for recently viewed display
504 $recentContactId = $params['target_contact_id'];
505 }
506 }
507 else {
508 // at worst, take source for recently viewed display
509 $recentContactId = CRM_Utils_Array::value('source_contact_id',$params);
510 }
511
512 if (isset($params['assignee_contact_id'])) {
513 if (is_array($params['assignee_contact_id'])) {
514 $msgs[] = "assignee=" . implode(',', $params['assignee_contact_id']);
515 }
516 else {
517 $msgs[] = "assignee={$params['assignee_contact_id']}";
518 }
519 }
520 $logMsg .= implode(', ', $msgs);
521
522 self::logActivityAction($result, $logMsg);
523
a7488080 524 if (!empty($params['custom']) &&
6a488035
TO
525 is_array($params['custom'])
526 ) {
527 CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_activity', $result->id);
528 }
529
530 $transaction->commit();
a7488080 531 if (empty($params['skipRecentView'])) {
6a488035 532 $recentOther = array();
a7488080 533 if (!empty($params['case_id'])) {
6a488035
TO
534 $caseContactID = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseContact', $params['case_id'], 'contact_id', 'case_id');
535 $url = CRM_Utils_System::url('civicrm/case/activity/view',
536 "reset=1&aid={$activity->id}&cid={$caseContactID}&caseID={$params['case_id']}&context=home"
537 );
538 }
539 else {
eb873b6e 540 $q = "action=view&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid={$params['source_contact_id']}&context=home";
6a488035
TO
541 if ($activity->activity_type_id != CRM_Core_OptionGroup::getValue('activity_type', 'Email', 'name')) {
542 $url = CRM_Utils_System::url('civicrm/activity', $q);
543 if ($activity->activity_type_id == CRM_Core_OptionGroup::getValue('activity_type', 'Print PDF Letter', 'name')) {
544 $recentOther['editUrl'] = CRM_Utils_System::url('civicrm/activity/pdf/add',
eb873b6e 545 "action=update&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid={$params['source_contact_id']}&context=home"
6a488035
TO
546 );
547 }
548 else {
549 $recentOther['editUrl'] = CRM_Utils_System::url('civicrm/activity/add',
eb873b6e 550 "action=update&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid={$params['source_contact_id']}&context=home"
6a488035
TO
551 );
552 }
553
554 if (CRM_Core_Permission::check("delete activities")) {
555 $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/activity',
eb873b6e 556 "action=delete&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid={$params['source_contact_id']}&context=home"
6a488035
TO
557 );
558 }
559 }
560 else {
561 $url = CRM_Utils_System::url('civicrm/activity/view', $q);
562 if (CRM_Core_Permission::check('delete activities')) {
563 $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/activity',
eb873b6e 564 "action=delete&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid={$params['source_contact_id']}&context=home"
6a488035
TO
565 );
566 }
567 }
568 }
569
570 if (!isset($activity->parent_id)) {
571 $recentContactDisplay = CRM_Contact_BAO_Contact::displayName($recentContactId);
572 // add the recently created Activity
573 $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE);
574 $activitySubject = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $activity->id, 'subject');
575
576 $title = "";
577 if (isset($activitySubject)) {
578 $title = $activitySubject . ' - ';
579 }
580
581 $title = $title . $recentContactDisplay;
a7488080 582 if (!empty($activityTypes[$activity->activity_type_id])) {
6a488035
TO
583 $title .= ' (' . $activityTypes[$activity->activity_type_id] . ')';
584 }
585
586 CRM_Utils_Recent::add($title,
587 $url,
588 $activity->id,
589 'Activity',
590 $recentContactId,
591 $recentContactDisplay,
592 $recentOther
593 );
594 }
595 }
596
597 // reset the group contact cache since smart groups might be affected due to this
598 CRM_Contact_BAO_GroupContactCache::remove();
599
a7488080 600 if (!empty($params['id'])) {
6a488035
TO
601 CRM_Utils_Hook::post('edit', 'Activity', $activity->id, $activity);
602 }
603 else {
604 CRM_Utils_Hook::post('create', 'Activity', $activity->id, $activity);
605 }
606
607 // if the subject contains a ‘[case #…]’ string, file that activity on the related case (CRM-5916)
608 $matches = array();
609 if (preg_match('/\[case #([0-9a-h]{7})\]/', CRM_Utils_Array::value('subject', $params), $matches)) {
610 $key = CRM_Core_DAO::escapeString(CIVICRM_SITE_KEY);
611 $hash = $matches[1];
612 $query = "SELECT id FROM civicrm_case WHERE SUBSTR(SHA1(CONCAT('$key', id)), 1, 7) = '$hash'";
613 $caseParams = array(
614 'activity_id' => $activity->id,
615 'case_id' => CRM_Core_DAO::singleValueQuery($query),
616 );
617 if ($caseParams['case_id']) {
618 CRM_Case_BAO_Case::processCaseActivity($caseParams);
619 }
620 else {
621 self::logActivityAction($activity, "unknown case hash encountered: $hash");
622 }
623 }
624
625 return $result;
626 }
627
628 public static function logActivityAction($activity, $logMessage = NULL) {
629 $session = CRM_Core_Session::singleton();
630 $id = $session->get('userID');
631 if (!$id) {
e7e657f0 632 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
8a6844b3
DL
633 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
634 $id = self::getActivityContact($activity->id. $sourceID);
6a488035
TO
635 }
636 $logParams = array(
637 'entity_table' => 'civicrm_activity',
638 'entity_id' => $activity->id,
639 'modified_id' => $id,
640 'modified_date' => date('YmdHis'),
641 'data' => $logMessage,
642 );
643 CRM_Core_BAO_Log::add($logParams);
644 return TRUE;
645 }
646
647 /**
0a9f61c4 648 * function to get the list Activities
6a488035
TO
649 *
650 * @param array $input array of parameters
651 * Keys include
0a9f61c4 652 * - contact_id int contact_id whose activities we want to retrieve
6a488035
TO
653 * - offset int which row to start from ?
654 * - rowCount int how many rows to fetch
655 * - sort object|array object or array describing sort order for sql query.
656 * - admin boolean if contact is admin
657 * - caseId int case ID
658 * - context string page on which selector is build
659 * - activity_type_id int|string the activitiy types we want to restrict by
660 *
0a9f61c4 661 * @return array (reference) $values the relevant data object values of open activities
6a488035
TO
662 *
663 * @access public
664 * @static
665 */
666 static function &getActivities($input) {
667 //step 1: Get the basic activity data
2517d079
DL
668 $bulkActivityTypeID = CRM_Core_OptionGroup::getValue(
669 'activity_type',
6a488035
TO
670 'Bulk Email',
671 'name'
672 );
673
674 $config = CRM_Core_Config::singleton();
675
676 $randomNum = md5(uniqid());
677 $activityTempTable = "civicrm_temp_activity_details_{$randomNum}";
678
679 $tableFields = array(
680 'activity_id' => 'int unsigned',
681 'activity_date_time' => 'datetime',
b8cab202 682 'source_record_id' => 'int unsigned',
6a488035
TO
683 'status_id' => 'int unsigned',
684 'subject' => 'varchar(255)',
cec82bce 685 'source_contact_name' => 'varchar(255)',
6a488035
TO
686 'activity_type_id' => 'int unsigned',
687 'activity_type' => 'varchar(128)',
688 'case_id' => 'int unsigned',
689 'case_subject' => 'varchar(255)',
690 'campaign_id' => 'int unsigned',
691 );
692
693 $sql = "CREATE TEMPORARY TABLE {$activityTempTable} ( ";
694 $insertValueSQL = array();
6da5bfce 695 // The activityTempTable contains the sorted rows
696 // so in order to maintain the sort order as-is we add an auto_increment
697 // field; we can sort by this later to ensure the sort order stays correct.
698 $sql .= " fixed_sort_order INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,";
6a488035
TO
699 foreach ($tableFields as $name => $desc) {
700 $sql .= "$name $desc,\n";
701 $insertValueSQL[] = $name;
702 }
703
6da5bfce 704 // add unique key on activity_id just to be sure
705 // this cannot be primary key because we need that for the auto_increment
706 // fixed_sort_order field
6a488035 707 $sql .= "
c1d26519 708 UNIQUE KEY ( activity_id )
6a488035
TO
709 ) ENGINE=HEAP DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
710 ";
711
712 CRM_Core_DAO::executeQuery($sql);
713
714 $insertSQL = "INSERT INTO {$activityTempTable} (" . implode(',', $insertValueSQL) . " ) ";
715
716 $order = $limit = $groupBy = '';
b8cab202 717 $groupBy = " GROUP BY tbl.activity_id ";
6a488035
TO
718
719 if (!empty($input['sort'])) {
720 if (is_a($input['sort'], 'CRM_Utils_Sort')) {
721 $orderBy = $input['sort']->orderBy();
722 if (!empty($orderBy)) {
723 $order = " ORDER BY $orderBy";
724 }
725 }
726 elseif (trim($input['sort'])) {
21d32567
DL
727 $sort = CRM_Utils_Type::escape($input['sort'], 'String');
728 $order = " ORDER BY $sort ";
6a488035
TO
729 }
730 }
731
732 if (empty($order)) {
6da5bfce 733 // context = 'activity' in Activities tab.
6a488035
TO
734 $order = (CRM_Utils_Array::value('context', $input) == 'activity') ? " ORDER BY tbl.activity_date_time desc " : " ORDER BY tbl.status_id asc, tbl.activity_date_time asc ";
735 }
736
737 if (!empty($input['rowCount']) &&
738 $input['rowCount'] > 0
739 ) {
740 $limit = " LIMIT {$input['offset']}, {$input['rowCount']} ";
741 }
742
743 $input['count'] = FALSE;
eacfbd68 744
745 // skip bulk activities in activity tab
746 $input['activity_type_exclude_id'][$bulkActivityTypeID] = $bulkActivityTypeID;
6a488035
TO
747 list($sqlClause, $params) = self::getActivitySQLClause($input);
748
749 $query = "{$insertSQL}
750 SELECT DISTINCT tbl.* from ( {$sqlClause} )
751as tbl ";
752
753 //filter case activities - CRM-5761
754 $components = self::activityComponents();
755 if (!in_array('CiviCase', $components)) {
756 $query .= "
757LEFT JOIN civicrm_case_activity ON ( civicrm_case_activity.activity_id = tbl.activity_id )
758 WHERE civicrm_case_activity.id IS NULL";
759 }
760
761 $query = $query . $groupBy . $order . $limit;
762
763 $dao = CRM_Core_DAO::executeQuery($query, $params);
764
6a488035
TO
765 // step 2: Get target and assignee contacts for above activities
766 // create temp table for target contacts
91da6cd5
DL
767 $activityContactTempTable = "civicrm_temp_activity_contact_{$randomNum}";
768 $query = "CREATE TEMPORARY TABLE {$activityContactTempTable} (
d10f9247 769 activity_id int unsigned, contact_id int unsigned, record_type_id varchar(16),
770 contact_name varchar(255), is_deleted int unsigned, INDEX index_activity_id( activity_id ) )
6a488035
TO
771 ENGINE=MYISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci";
772
773 CRM_Core_DAO::executeQuery($query);
774
775 // note that we ignore bulk email for targets, since we don't show it in selector
91da6cd5 776 $query = "
d8a22375 777INSERT INTO {$activityContactTempTable} ( activity_id, contact_id, record_type_id, contact_name, is_deleted )
91da6cd5
DL
778SELECT ac.activity_id,
779 ac.contact_id,
5b5da1ef 780 ac.record_type_id,
d8a22375
BS
781 c.sort_name,
782 c.is_deleted
d10f9247 783FROM {$activityTempTable}
eacfbd68 784INNER JOIN civicrm_activity a ON ( a.id = {$activityTempTable}.activity_id )
d10f9247 785INNER JOIN civicrm_activity_contact ac ON ( ac.activity_id = {$activityTempTable}.activity_id )
5b5da1ef 786INNER JOIN civicrm_contact c ON c.id = ac.contact_id
91da6cd5 787";
6a488035
TO
788 CRM_Core_DAO::executeQuery($query);
789
6a488035 790 // step 3: Combine all temp tables to get final query for activity selector
6da5bfce 791 // sort by the original sort order, stored in fixed_sort_order
6a488035 792 $query = "
91da6cd5
DL
793SELECT {$activityTempTable}.*,
794 {$activityContactTempTable}.contact_id,
a24b3694 795 {$activityContactTempTable}.record_type_id,
d8a22375
BS
796 {$activityContactTempTable}.contact_name,
797 {$activityContactTempTable}.is_deleted
91da6cd5
DL
798FROM {$activityTempTable}
799INNER JOIN {$activityContactTempTable} on {$activityTempTable}.activity_id = {$activityContactTempTable}.activity_id
6da5bfce 800ORDER BY fixed_sort_order
6a488035
TO
801 ";
802
803
804 $dao = CRM_Core_DAO::executeQuery($query);
805
806 //CRM-3553, need to check user has access to target groups.
807 $mailingIDs = CRM_Mailing_BAO_Mailing::mailingACLIDs();
808 $accessCiviMail = (
809 (CRM_Core_Permission::check('access CiviMail')) ||
810 (CRM_Mailing_Info::workflowEnabled() &&
811 CRM_Core_Permission::check('create mailings'))
812 );
813
814 //get all campaigns.
815 $allCampaigns = CRM_Campaign_BAO_Campaign::getCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
816
817 $values = array();
e7e657f0 818 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
a24b3694 819 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
820 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
821 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
b319d00a 822
a24b3694 823
6a488035
TO
824 while ($dao->fetch()) {
825 $activityID = $dao->activity_id;
826 $values[$activityID]['activity_id'] = $dao->activity_id;
827 $values[$activityID]['source_record_id'] = $dao->source_record_id;
828 $values[$activityID]['activity_type_id'] = $dao->activity_type_id;
829 $values[$activityID]['activity_type'] = $dao->activity_type;
830 $values[$activityID]['activity_date_time'] = $dao->activity_date_time;
831 $values[$activityID]['status_id'] = $dao->status_id;
832 $values[$activityID]['subject'] = $dao->subject;
6a488035
TO
833 $values[$activityID]['campaign_id'] = $dao->campaign_id;
834
835 if ($dao->campaign_id) {
836 $values[$activityID]['campaign'] = $allCampaigns[$dao->campaign_id];
837 }
838
a7488080 839 if (empty($values[$activityID]['assignee_contact_name'])) {
6a488035
TO
840 $values[$activityID]['assignee_contact_name'] = array();
841 }
842
a7488080 843 if (empty($values[$activityID]['target_contact_name'])) {
6a488035
TO
844 $values[$activityID]['target_contact_name'] = array();
845 }
846
d8a22375
BS
847 // if deleted, wrap in <del>
848 if ( $dao->is_deleted ) {
849 $dao->contact_name = "<del>{$dao->contact_name}</dao>";
850 }
851
a24b3694 852 if ($dao->record_type_id == $sourceID && $dao->contact_id) {
91da6cd5
DL
853 $values[$activityID]['source_contact_id'] = $dao->contact_id;
854 $values[$activityID]['source_contact_name'] = $dao->contact_name;
855 }
856
6a488035
TO
857 if (!$bulkActivityTypeID || ($bulkActivityTypeID != $dao->activity_type_id)) {
858 // build array of target / assignee names
a24b3694 859 if ($dao->record_type_id == $targetID && $dao->contact_id) {
91da6cd5 860 $values[$activityID]['target_contact_name'][$dao->contact_id] = $dao->contact_name;
6a488035 861 }
a24b3694 862 if ($dao->record_type_id == $assigneeID && $dao->contact_id) {
91da6cd5 863 $values[$activityID]['assignee_contact_name'][$dao->contact_id] = $dao->contact_name;
6a488035
TO
864 }
865
866 // case related fields
867 $values[$activityID]['case_id'] = $dao->case_id;
868 $values[$activityID]['case_subject'] = $dao->case_subject;
869 }
870 else {
871 $values[$activityID]['recipients'] = ts('(recipients)');
2678caac 872 $values[$activityID]['mailingId'] = false;
6a488035
TO
873 if (
874 $accessCiviMail &&
875 ($mailingIDs === TRUE || in_array($dao->source_record_id, $mailingIDs))
876 ) {
2678caac 877 $values[$activityID]['mailingId'] = true;
6a488035
TO
878 }
879 }
880 }
881
6a488035
TO
882 return $values;
883 }
884
885 /**
886 * Get the component id and name those are enabled and logged in
887 * user has permission. To decide whether we are going to include
888 * component related activities w/ core activity retrieve process.
889 *
890 * return an array of component id and name.
891 * @static
892 **/
893 static function activityComponents() {
894 $components = array();
895 $compInfo = CRM_Core_Component::getEnabledComponents();
896 foreach ($compInfo as $compObj) {
a7488080 897 if (!empty($compObj->info['showActivitiesInCore'])) {
6a488035
TO
898 if ($compObj->info['name'] == 'CiviCampaign') {
899 $componentPermission = "administer {$compObj->name}";
900 }
901 else {
902 $componentPermission = "access {$compObj->name}";
903 }
904 if ($compObj->info['name'] == 'CiviCase') {
905 if (CRM_Case_BAO_Case::accessCiviCase()) {
906 $components[$compObj->componentID] = $compObj->info['name'];
907 }
908 }
909 elseif (CRM_Core_Permission::check($componentPermission)) {
910 $components[$compObj->componentID] = $compObj->info['name'];
911 }
912 }
913 }
914
915 return $components;
916 }
917
918 /**
919 * function to get the activity Count
920 *
921 * @param array $input array of parameters
922 * Keys include
0a9f61c4 923 * - contact_id int contact_id whose activities we want to retrieve
6a488035
TO
924 * - admin boolean if contact is admin
925 * - caseId int case ID
926 * - context string page on which selector is build
0a9f61c4 927 * - activity_type_id int|string the activity types we want to restrict by
6a488035
TO
928 *
929 * @return int count of activities
930 *
931 * @access public
932 * @static
933 */
934 static function &getActivitiesCount($input) {
eacfbd68 935 // skip bulk activities in activity tab
936 $bulkActivityTypeID = CRM_Core_OptionGroup::getValue(
937 'activity_type',
938 'Bulk Email',
939 'name'
940 );
941 $input['activity_type_exclude_id'][$bulkActivityTypeID] = $bulkActivityTypeID;
942
6a488035
TO
943 $input['count'] = TRUE;
944 list($sqlClause, $params) = self::getActivitySQLClause($input);
945
946 //filter case activities - CRM-5761
947 $components = self::activityComponents();
948 if (!in_array('CiviCase', $components)) {
949 $query = "
950 SELECT COUNT(DISTINCT(tbl.activity_id)) as count
951 FROM ( {$sqlClause} ) as tbl
952LEFT JOIN civicrm_case_activity ON ( civicrm_case_activity.activity_id = tbl.activity_id )
953 WHERE civicrm_case_activity.id IS NULL";
954 }
955 else {
956 $query = "SELECT COUNT(DISTINCT(activity_id)) as count from ( {$sqlClause} ) as tbl";
957 }
958
959 return CRM_Core_DAO::singleValueQuery($query, $params);
960 }
961
962 /**
963 * function to get the activity sql clause to pick activities
964 *
965 * @param array $input array of parameters
966 * Keys include
0a9f61c4 967 * - contact_id int contact_id whose activities we want to retrieve
6a488035
TO
968 * - admin boolean if contact is admin
969 * - caseId int case ID
970 * - context string page on which selector is build
971 * - count boolean are we interested in the count clause only?
0a9f61c4 972 * - activity_type_id int|string the activity types we want to restrict by
6a488035
TO
973 *
974 * @return int count of activities
975 *
976 * @access public
977 * @static
978 */
979 static function getActivitySQLClause($input) {
980 $params = array();
981 $sourceWhere = $targetWhere = $assigneeWhere = $caseWhere = 1;
982
983 $config = CRM_Core_Config::singleton();
984 if (!CRM_Utils_Array::value('admin', $input, FALSE)) {
91da6cd5 985 $sourceWhere = ' ac.contact_id = %1 ';
6a488035
TO
986 $caseWhere = ' civicrm_case_contact.contact_id = %1 ';
987
988 $params = array(1 => array($input['contact_id'], 'Integer'));
989 }
990
991 $commonClauses = array(
992 "civicrm_option_group.name = 'activity_type'",
993 "civicrm_activity.is_deleted = 0",
994 "civicrm_activity.is_current_revision = 1",
2517d079 995 "civicrm_activity.is_test= 0",
6a488035
TO
996 );
997
998 if ($input['context'] != 'activity') {
999 $commonClauses[] = "civicrm_activity.status_id = 1";
1000 }
1001
1002 //Filter on component IDs.
1003 $components = self::activityComponents();
1004 if (!empty($components)) {
1005 $componentsIn = implode(',', array_keys($components));
1006 $commonClauses[] = "( civicrm_option_value.component_id IS NULL OR civicrm_option_value.component_id IN ( $componentsIn ) )";
1007 }
1008 else {
1009 $commonClauses[] = "civicrm_option_value.component_id IS NULL";
1010 }
1011
1012 // activity type ID clause
1013 if (!empty($input['activity_type_id'])) {
1014 if (is_array($input['activity_type_id'])) {
1015 foreach ($input['activity_type_id'] as $idx => $value) {
1016 $input['activity_type_id'][$idx] = CRM_Utils_Type::escape($value, 'Positive');
1017 }
1018 $commonClauses[] = "civicrm_activity.activity_type_id IN ( " . implode(",", $input['activity_type_id']) . " ) ";
1019 }
1020 else {
1021 $activityTypeID = CRM_Utils_Type::escape($input['activity_type_id'], 'Positive');
1022 $commonClauses[] = "civicrm_activity.activity_type_id = $activityTypeID";
1023 }
1024 }
1025
1026 // exclude by activity type clause
1027 if (!empty($input['activity_type_exclude_id'])) {
1028 if (is_array($input['activity_type_exclude_id'])) {
1029 foreach ($input['activity_type_exclude_id'] as $idx => $value) {
1030 $input['activity_type_exclude_id'][$idx] = CRM_Utils_Type::escape($value, 'Positive');
1031 }
1032 $commonClauses[] = "civicrm_activity.activity_type_id NOT IN ( " . implode(",", $input['activity_type_exclude_id']) . " ) ";
1033 }
1034 else {
1035 $activityTypeID = CRM_Utils_Type::escape($input['activity_type_exclude_id'], 'Positive');
1036 $commonClauses[] = "civicrm_activity.activity_type_id != $activityTypeID";
1037 }
1038 }
1039
1040 $commonClause = implode(' AND ', $commonClauses);
1041
1042 $includeCaseActivities = FALSE;
1043 if (in_array('CiviCase', $components)) {
1044 $includeCaseActivities = TRUE;
1045 }
1046
1047
1048 // build main activity table select clause
1049 $sourceSelect = '';
cec82bce 1050
1051 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
1052 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
a3696ce8 1053 $sourceJoin = "
b8cab202 1054INNER JOIN civicrm_activity_contact ac ON ac.activity_id = civicrm_activity.id
a3696ce8
DL
1055INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
1056";
6a488035
TO
1057
1058 if (!$input['count']) {
1059 $sourceSelect = ',
1060 civicrm_activity.activity_date_time,
b8cab202 1061 civicrm_activity.source_record_id,
6a488035
TO
1062 civicrm_activity.status_id,
1063 civicrm_activity.subject,
cec82bce 1064 contact.sort_name as source_contact_name,
6a488035
TO
1065 civicrm_option_value.value as activity_type_id,
1066 civicrm_option_value.label as activity_type,
1067 null as case_id, null as case_subject,
5b5da1ef 1068 civicrm_activity.campaign_id as campaign_id
6a488035
TO
1069 ';
1070
b8cab202
PJ
1071 $sourceJoin .= "
1072LEFT JOIN civicrm_activity_contact src ON (src.activity_id = ac.activity_id AND src.record_type_id = {$sourceID} AND src.contact_id = contact.id)
1073";
6a488035
TO
1074 }
1075
1076 $sourceClause = "
1077 SELECT civicrm_activity.id as activity_id
1078 {$sourceSelect}
1079 from civicrm_activity
1080 left join civicrm_option_value on
1081 civicrm_activity.activity_type_id = civicrm_option_value.value
1082 left join civicrm_option_group on
1083 civicrm_option_group.id = civicrm_option_value.option_group_id
1084 {$sourceJoin}
1085 where
1086 {$sourceWhere}
1087 AND $commonClause
1088 ";
1089
6a488035
TO
1090 // Build case clause
1091 // or else exclude Inbound Emails that have been filed on a case.
1092 $caseClause = '';
1093
1094 if ($includeCaseActivities) {
1095 $caseSelect = '';
1096 if (!$input['count']) {
1097 $caseSelect = ',
1098 civicrm_activity.activity_date_time,
b8cab202 1099 civicrm_activity.source_record_id,
6a488035
TO
1100 civicrm_activity.status_id,
1101 civicrm_activity.subject,
cec82bce 1102 contact.sort_name as source_contact_name,
6a488035
TO
1103 civicrm_option_value.value as activity_type_id,
1104 civicrm_option_value.label as activity_type,
1105 null as case_id, null as case_subject,
1106 civicrm_activity.campaign_id as campaign_id';
1107 }
1108
1109 $caseClause = "
1110 union all
1111
1112 SELECT civicrm_activity.id as activity_id
1113 {$caseSelect}
1114 from civicrm_activity
1115 inner join civicrm_case_activity on
1116 civicrm_case_activity.activity_id = civicrm_activity.id
1117 inner join civicrm_case on
1118 civicrm_case_activity.case_id = civicrm_case.id
1119 inner join civicrm_case_contact on
1120 civicrm_case_contact.case_id = civicrm_case.id and {$caseWhere}
1121 left join civicrm_option_value on
1122 civicrm_activity.activity_type_id = civicrm_option_value.value
1123 left join civicrm_option_group on
1124 civicrm_option_group.id = civicrm_option_value.option_group_id
1125 {$sourceJoin}
1126 where
1127 {$caseWhere}
1128 AND $commonClause
1129 and ( ( civicrm_case_activity.case_id IS NULL ) OR
1130 ( civicrm_option_value.name <> 'Inbound Email' AND
1131 civicrm_option_value.name <> 'Email' AND civicrm_case_activity.case_id
1132 IS NOT NULL )
1133 )
1134 ";
1135 }
1136
a3696ce8 1137 $returnClause = " {$sourceClause} {$caseClause} ";
6a488035
TO
1138
1139 return array($returnClause, $params);
1140 }
1141
1142 /**
1143 * send the message to all the contacts and also insert a
1144 * contact activity in each contacts record
1145 *
1146 * @param array $contactDetails the array of contact details to send the email
1147 * @param string $subject the subject of the message
1148 * @param string $message the message contents
1149 * @param string $emailAddress use this 'to' email address instead of the default Primary address
1150 * @param int $userID use this userID if set
1151 * @param string $from
1152 * @param array $attachments the array of attachments if any
0a9f61c4 1153 * @param string $cc cc recipient
1154 * @param string $bcc bcc recipient
6a488035 1155 * @param array $contactIds contact ids
c1d26519 1156 * @param string $additionalDetails the additional information of CC and BCC appended to the activity Details
6a488035
TO
1157 *
1158 * @return array ( sent, activityId) if any email is sent and activityId
1159 * @access public
1160 * @static
1161 */
1162 static function sendEmail(
1163 &$contactDetails,
1164 &$subject,
1165 &$text,
1166 &$html,
1167 $emailAddress,
1168 $userID = NULL,
1169 $from = NULL,
1170 $attachments = NULL,
1171 $cc = NULL,
1172 $bcc = NULL,
c1d26519 1173 $contactIds, // FIXME a param with no default shouldn't be last
1174 $additionalDetails = NULL
6a488035
TO
1175 ) {
1176 // get the contact details of logged in contact, which we set as from email
1177 if ($userID == NULL) {
1178 $session = CRM_Core_Session::singleton();
1179 $userID = $session->get('userID');
1180 }
1181
1182 list($fromDisplayName, $fromEmail, $fromDoNotEmail) = CRM_Contact_BAO_Contact::getContactDetails($userID);
1183 if (!$fromEmail) {
1184 return array(count($contactDetails), 0, count($contactDetails));
1185 }
1186 if (!trim($fromDisplayName)) {
1187 $fromDisplayName = $fromEmail;
1188 }
1189
1190 // CRM-4575
1191 // token replacement of addressee/email/postal greetings
1192 // get the tokens added in subject and message
1193 $subjectToken = CRM_Utils_Token::getTokens($subject);
1194 $messageToken = CRM_Utils_Token::getTokens($text);
1195 $messageToken = array_merge($messageToken, CRM_Utils_Token::getTokens($html));
c7436e9c 1196 $allTokens = array_merge($messageToken, $subjectToken);
6a488035
TO
1197
1198 if (!$from) {
1199 $from = "$fromDisplayName <$fromEmail>";
1200 }
1201
1202 //create the meta level record first ( email activity )
1203 $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type',
1204 'Email',
1205 'name'
1206 );
1207
1208 // CRM-6265: save both text and HTML parts in details (if present)
1209 if ($html and $text) {
c1d26519 1210 $details = "-ALTERNATIVE ITEM 0-\n$html$additionalDetails\n-ALTERNATIVE ITEM 1-\n$text$additionalDetails\n-ALTERNATIVE END-\n";
6a488035
TO
1211 }
1212 else {
1213 $details = $html ? $html : $text;
c1d26519 1214 $details .= $additionalDetails;
6a488035
TO
1215 }
1216
1217 $activityParams = array(
1218 'source_contact_id' => $userID,
1219 'activity_type_id' => $activityTypeID,
1220 'activity_date_time' => date('YmdHis'),
1221 'subject' => $subject,
1222 'details' => $details,
1223 // FIXME: check for name Completed and get ID from that lookup
1224 'status_id' => 2,
1225 );
1226
1227 // CRM-5916: strip [case #…] before saving the activity (if present in subject)
1228 $activityParams['subject'] = preg_replace('/\[case #([0-9a-h]{7})\] /', '', $activityParams['subject']);
1229
1230 // add the attachments to activity params here
1231 if ($attachments) {
1232 // first process them
1233 $activityParams = array_merge($activityParams,
1234 $attachments
1235 );
1236 }
1237
1238 $activity = self::create($activityParams);
1239
1240 // get the set of attachments from where they are stored
1241 $attachments = CRM_Core_BAO_File::getEntityFile('civicrm_activity',
1242 $activity->id
1243 );
1244 $returnProperties = array();
1245 if (isset($messageToken['contact'])) {
1246 foreach ($messageToken['contact'] as $key => $value) {
1247 $returnProperties[$value] = 1;
1248 }
1249 }
1250
1251 if (isset($subjectToken['contact'])) {
1252 foreach ($subjectToken['contact'] as $key => $value) {
1253 if (!isset($returnProperties[$value])) {
1254 $returnProperties[$value] = 1;
1255 }
1256 }
1257 }
1258
1259
1260 // get token details for contacts, call only if tokens are used
1261 $details = array();
db969160 1262 if (!empty($returnProperties) || !empty($tokens) || !empty($allTokens)) {
6a488035
TO
1263 list($details) = CRM_Utils_Token::getTokenDetails(
1264 $contactIds,
1265 $returnProperties,
1266 NULL, NULL, FALSE,
c7436e9c 1267 $allTokens,
6a488035
TO
1268 'CRM_Activity_BAO_Activity'
1269 );
1270 }
1271
1272 // call token hook
1273 $tokens = array();
1274 CRM_Utils_Hook::tokens($tokens);
1275 $categories = array_keys($tokens);
1276
1277 $escapeSmarty = FALSE;
1278 if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) {
1279 $smarty = CRM_Core_Smarty::singleton();
1280 $escapeSmarty = TRUE;
1281 }
1282
1283 $sent = $notSent = array();
1284 foreach ($contactDetails as $values) {
1285 $contactId = $values['contact_id'];
1286 $emailAddress = $values['email'];
1287
1288 if (!empty($details) && is_array($details["{$contactId}"])) {
1289 // unset email from details since it always returns primary email address
1290 unset($details["{$contactId}"]['email']);
1291 unset($details["{$contactId}"]['email_id']);
1292 $values = array_merge($values, $details["{$contactId}"]);
1293 }
1294
1295 $tokenSubject = CRM_Utils_Token::replaceContactTokens($subject, $values, FALSE, $subjectToken, FALSE, $escapeSmarty);
1296 $tokenSubject = CRM_Utils_Token::replaceHookTokens($tokenSubject, $values, $categories, FALSE, $escapeSmarty);
1297
1298 //CRM-4539
1299 if ($values['preferred_mail_format'] == 'Text' || $values['preferred_mail_format'] == 'Both') {
1300 $tokenText = CRM_Utils_Token::replaceContactTokens($text, $values, FALSE, $messageToken, FALSE, $escapeSmarty);
1301 $tokenText = CRM_Utils_Token::replaceHookTokens($tokenText, $values, $categories, FALSE, $escapeSmarty);
1302 }
1303 else {
1304 $tokenText = NULL;
1305 }
1306
1307 if ($values['preferred_mail_format'] == 'HTML' || $values['preferred_mail_format'] == 'Both') {
1308 $tokenHtml = CRM_Utils_Token::replaceContactTokens($html, $values, TRUE, $messageToken, FALSE, $escapeSmarty);
1309 $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $values, $categories, TRUE, $escapeSmarty);
1310 }
1311 else {
1312 $tokenHtml = NULL;
1313 }
1314
1315 if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) {
1316 // also add the contact tokens to the template
1317 $smarty->assign_by_ref('contact', $values);
1318
1319 $tokenSubject = $smarty->fetch("string:$tokenSubject");
1320 $tokenText = $smarty->fetch("string:$tokenText");
1321 $tokenHtml = $smarty->fetch("string:$tokenHtml");
1322 }
1323
1324 $sent = FALSE;
1325 if (self::sendMessage(
1326 $from,
1327 $userID,
1328 $contactId,
1329 $tokenSubject,
1330 $tokenText,
1331 $tokenHtml,
1332 $emailAddress,
1333 $activity->id,
1334 $attachments,
1335 $cc,
1336 $bcc
1337 )) {
1338 $sent = TRUE;
1339 }
1340 }
1341
1342 return array($sent, $activity->id);
1343 }
1344
1345 static function sendSMS(&$contactDetails,
1346 &$activityParams,
1347 &$smsParams = array(),
1348 &$contactIds,
1349 $userID = NULL
1350 ) {
1351 if ($userID == NULL) {
1352 $session = CRM_Core_Session::singleton();
1353 $userID = $session->get('userID');
1354 }
1355
1356 $text = &$activityParams['text_message'];
1357 $html = &$activityParams['html_message'];
1358
1359 // CRM-4575
1360 // token replacement of addressee/email/postal greetings
1361 // get the tokens added in subject and message
1362 $messageToken = CRM_Utils_Token::getTokens($text);
1363 $messageToken = array_merge($messageToken,
1364 CRM_Utils_Token::getTokens($html)
1365 );
1366
1367 //create the meta level record first ( sms activity )
1368 $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type',
1369 'SMS',
1370 'name'
1371 );
1372
1373 // CRM-6265: save both text and HTML parts in details (if present)
1374 if ($html and $text) {
1375 $details = "-ALTERNATIVE ITEM 0-\n$html\n-ALTERNATIVE ITEM 1-\n$text\n-ALTERNATIVE END-\n";
1376 }
1377 else {
1378 $details = $html ? $html : $text;
1379 }
1380
1381 $activitySubject = $activityParams['activity_subject'];
1382 $activityParams = array(
1383 'source_contact_id' => $userID,
1384 'activity_type_id' => $activityTypeID,
1385 'activity_date_time' => date('YmdHis'),
1386 'subject' => $activitySubject,
1387 'details' => $details,
1388 // FIXME: check for name Completed and get ID from that lookup
1389 'status_id' => 2,
1390 );
1391
1392 $activity = self::create($activityParams);
1393 $activityID = $activity->id;
1394
1395 $returnProperties = array();
1396
1397 if (isset($messageToken['contact'])) {
1398 foreach ($messageToken['contact'] as $key => $value) {
1399 $returnProperties[$value] = 1;
1400 }
1401 }
1402
1403 // call token hook
1404 $tokens = array();
1405 CRM_Utils_Hook::tokens($tokens);
1406 $categories = array_keys($tokens);
1407
1408 // get token details for contacts, call only if tokens are used
1409 $details = array();
1410 if (!empty($returnProperties) || !empty($tokens)) {
1411 list($details) = CRM_Utils_Token::getTokenDetails($contactIds,
1412 $returnProperties,
1413 NULL, NULL, FALSE,
1414 $messageToken,
1415 'CRM_Activity_BAO_Activity'
1416 );
1417 }
1418
f53ea1ce 1419 $success = 0;
c5a6413b
DS
1420 $escapeSmarty = FALSE;
1421 $errMsgs = array();
6a488035
TO
1422 foreach ($contactDetails as $values) {
1423 $contactId = $values['contact_id'];
1424
1425 if (!empty($details) && is_array($details["{$contactId}"])) {
1426 // unset email from details since it always returns primary email address
1427 unset($details["{$contactId}"]['email']);
1428 unset($details["{$contactId}"]['email_id']);
1429 $values = array_merge($values, $details["{$contactId}"]);
1430 }
1431
1432 $tokenText = CRM_Utils_Token::replaceContactTokens($text, $values, FALSE, $messageToken, FALSE, $escapeSmarty);
1433 $tokenText = CRM_Utils_Token::replaceHookTokens($tokenText, $values, $categories, FALSE, $escapeSmarty);
1434
1435 $tokenHtml = CRM_Utils_Token::replaceContactTokens($html, $values, TRUE, $messageToken, FALSE, $escapeSmarty);
1436 $tokenHtml = CRM_Utils_Token::replaceHookTokens($tokenHtml, $values, $categories, TRUE, $escapeSmarty);
1437
d65e1a68 1438 // Only send if the phone is of type mobile
9357a775
DS
1439 $phoneTypes = CRM_Core_OptionGroup::values('phone_type', TRUE, FALSE, FALSE, NULL, 'name');
1440 if ($values['phone_type_id'] == CRM_Utils_Array::value('Mobile', $phoneTypes)) {
d65e1a68 1441 $smsParams['To'] = $values['phone'];
01aca362
DL
1442 }
1443 else {
d65e1a68
TW
1444 $smsParams['To'] = '';
1445 }
6a488035 1446
c5a6413b
DS
1447 $sendResult = self::sendSMSMessage(
1448 $contactId,
1449 $tokenText,
1450 $tokenHtml,
1451 $smsParams,
e8cb3963
DS
1452 $activityID,
1453 $userID
c5a6413b
DS
1454 );
1455
1456 if (PEAR::isError($sendResult)) {
1457 // Collect all of the PEAR_Error objects
1458 $errMsgs[] = $sendResult;
1459 } else {
f53ea1ce 1460 $success++;
6a488035
TO
1461 }
1462 }
1463
c5a6413b
DS
1464 // If at least one message was sent and no errors
1465 // were generated then return a boolean value of TRUE.
1466 // Otherwise, return FALSE (no messages sent) or
1467 // and array of 1 or more PEAR_Error objects.
1468 $sent = FALSE;
1469 if ($success > 0 && count($errMsgs) == 0) {
1470 $sent = TRUE;
1471 } elseif (count($errMsgs) > 0) {
1472 $sent = $errMsgs;
1473 }
1474
f53ea1ce 1475 return array($sent, $activity->id, $success);
6a488035
TO
1476 }
1477
1478 /**
1479 * send the sms message to a specific contact
1480 *
1481 * @param int $toID the contact id of the recipient
1482 * @param int $activityID the activity ID that tracks the message
1483 * @param array $smsParams the params used for sending sms
1484 *
c5a6413b 1485 * @return mixed true on success or PEAR_Error object
6a488035
TO
1486 * @access public
1487 * @static
1488 */
1489 static function sendSMSMessage($toID,
1490 &$tokenText,
1491 &$tokenHtml,
1492 $smsParams = array(),
e8cb3963
DS
1493 $activityID,
1494 $userID = null
6a488035
TO
1495 ) {
1496 $toDoNotSms = "";
1497 $toPhoneNumber = "";
1498
1499 if ($smsParams['To']) {
1500 $toPhoneNumber = trim($smsParams['To']);
1501 }
1502 elseif ($toID) {
1503 $filters = array('is_deceased' => 0, 'is_deleted' => 0, 'do_not_sms' => 0);
1504 $toPhoneNumbers = CRM_Core_BAO_Phone::allPhones($toID, FALSE, 'Mobile', $filters);
1505 //to get primary mobile ph,if not get a first mobile ph
1506 if (!empty($toPhoneNumbers)) {
1507 $toPhoneNumerDetails = reset($toPhoneNumbers);
1508 $toPhoneNumber = CRM_Utils_Array::value('phone', $toPhoneNumerDetails);
1509 //contact allows to send sms
1510 $toDoNotSms = 0;
1511 }
1512 }
1513
1514 // make sure both phone are valid
1515 // and that the recipient wants to receive sms
1516 if (empty($toPhoneNumber) or $toDoNotSms) {
c5a6413b
DS
1517 return PEAR::raiseError(
1518 'Recipient phone number is invalid or recipient does not want to receive SMS',
1519 null,
1520 PEAR_ERROR_RETURN
1521 );
6a488035
TO
1522 }
1523
1524 $message = $tokenHtml ? $tokenHtml : $tokenText;
1525 $recipient = $smsParams['To'];
1526 $smsParams['contact_id'] = $toID;
1527 $smsParams['parent_activity_id'] = $activityID;
1528
1529 $providerObj = CRM_SMS_Provider::singleton(array('provider_id' => $smsParams['provider_id']));
e8cb3963 1530 $sendResult = $providerObj->send($recipient, $smsParams, $message, NULL, $userID);
c5a6413b
DS
1531 if (PEAR::isError($sendResult)) {
1532 return $sendResult;
6a488035
TO
1533 }
1534
e7e657f0 1535 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
a24b3694 1536 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
b319d00a 1537
a24b3694 1538
6a488035
TO
1539 // add activity target record for every sms that is send
1540 $activityTargetParams = array(
1541 'activity_id' => $activityID,
1d85d241 1542 'contact_id' => $toID,
a24b3694 1543 'record_type_id' => $targetID
6a488035 1544 );
1d85d241 1545 CRM_Activity_BAO_ActivityContact::create($activityTargetParams);
6a488035
TO
1546
1547 return TRUE;
1548 }
1549
1550 /**
1551 * send the message to a specific contact
1552 *
1553 * @param string $from the name and email of the sender
1554 * @param int $toID the contact id of the recipient
1555 * @param string $subject the subject of the message
1556 * @param string $message the message contents
1557 * @param string $emailAddress use this 'to' email address instead of the default Primary address
1558 * @param int $activityID the activity ID that tracks the message
1559 *
1560 * @return boolean true if successfull else false.
1561 * @access public
1562 * @static
1563 */
1564 static function sendMessage($from,
1565 $fromID,
1566 $toID,
1567 &$subject,
1568 &$text_message,
1569 &$html_message,
1570 $emailAddress,
1571 $activityID,
1572 $attachments = NULL,
1573 $cc = NULL,
1574 $bcc = NULL
1575 ) {
1576 list($toDisplayName, $toEmail, $toDoNotEmail) = CRM_Contact_BAO_Contact::getContactDetails($toID);
1577 if ($emailAddress) {
1578 $toEmail = trim($emailAddress);
1579 }
1580
1581 // make sure both email addresses are valid
1582 // and that the recipient wants to receive email
1583 if (empty($toEmail) or $toDoNotEmail) {
1584 return FALSE;
1585 }
1586 if (!trim($toDisplayName)) {
1587 $toDisplayName = $toEmail;
1588 }
1589
e7e657f0 1590 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
a24b3694 1591 //$sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
1592 //$assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
1593 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
1594
6a488035
TO
1595 // create the params array
1596 $mailParams = array(
1597 'groupName' => 'Activity Email Sender',
1598 'from' => $from,
1599 'toName' => $toDisplayName,
1600 'toEmail' => $toEmail,
1601 'subject' => $subject,
1602 'cc' => $cc,
1603 'bcc' => $bcc,
1604 'text' => $text_message,
1605 'html' => $html_message,
1606 'attachments' => $attachments,
1607 );
1608
1609 if (!CRM_Utils_Mail::send($mailParams)) {
1610 return FALSE;
1611 }
1612
1613 // add activity target record for every mail that is send
1614 $activityTargetParams = array(
1615 'activity_id' => $activityID,
1d85d241 1616 'contact_id' => $toID,
b319d00a 1617 'record_type_id' => $targetID
6a488035 1618 );
1d85d241 1619 CRM_Activity_BAO_ActivityContact::create($activityTargetParams);
6a488035
TO
1620 return TRUE;
1621 }
1622
1623 /**
1624 * combine all the importable fields from the lower levels object
1625 *
1626 * The ordering is important, since currently we do not have a weight
1627 * scheme. Adding weight is super important and should be done in the
1628 * next week or so, before this can be called complete.
1629 *
1630 * @param NULL
1631 *
1632 * @return array array of importable Fields
1633 * @access public
1634 * @static
1635 */
1636 static function &importableFields($status = FALSE) {
1637 if (!self::$_importableFields) {
1638 if (!self::$_importableFields) {
1639 self::$_importableFields = array();
1640 }
1641 if (!$status) {
1642 $fields = array('' => array('title' => ts('- do not import -')));
1643 }
1644 else {
1645 $fields = array('' => array('title' => ts('- Activity Fields -')));
1646 }
1647
1648 $tmpFields = CRM_Activity_DAO_Activity::import();
1649 $contactFields = CRM_Contact_BAO_Contact::importableFields('Individual', NULL);
1650
1651 // Using new Dedupe rule.
1652 $ruleParams = array(
1653 'contact_type' => 'Individual',
1654 'used' => 'Unsupervised',
1655 );
1656 $fieldsArray = CRM_Dedupe_BAO_Rule::dedupeRuleFields($ruleParams);
1657
1658 $tmpConatctField = array();
1659 if (is_array($fieldsArray)) {
1660 foreach ($fieldsArray as $value) {
1661 $customFieldId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
1662 $value,
1663 'id',
1664 'column_name'
1665 );
1666 $value = $customFieldId ? 'custom_' . $customFieldId : $value;
1667 $tmpConatctField[trim($value)] = $contactFields[trim($value)];
1668 $tmpConatctField[trim($value)]['title'] = $tmpConatctField[trim($value)]['title'] . " (match to contact)";
1669 }
1670 }
1671 $tmpConatctField['external_identifier'] = $contactFields['external_identifier'];
1672 $tmpConatctField['external_identifier']['title'] = $contactFields['external_identifier']['title'] . " (match to contact)";
1673 $fields = array_merge($fields, $tmpConatctField);
1674 $fields = array_merge($fields, $tmpFields);
1675 $fields = array_merge($fields, CRM_Core_BAO_CustomField::getFieldsForImport('Activity'));
1676 self::$_importableFields = $fields;
1677 }
1678 return self::$_importableFields;
1679 }
1680
1681 /**
1682 * To get the Activities of a target contact
1683 *
1684 * @param $contactId Integer ContactId of the contact whose activities
1685 * need to find
1686 *
1687 * @return array array of activity fields
1688 * @access public
1689 */
1690 static function getContactActivity($contactId) {
1691 $activities = array();
e7e657f0 1692 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
a24b3694 1693 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
1694 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
1695 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
b319d00a 1696
6a488035
TO
1697
1698 // First look for activities where contactId is one of the targets
91da6cd5 1699 $query = "
a24b3694 1700SELECT activity_id, record_type_id
91da6cd5
DL
1701FROM civicrm_activity_contact
1702WHERE contact_id = $contactId
1703";
1704 $dao = CRM_Core_DAO::executeQuery($query);
6a488035 1705 while ($dao->fetch()) {
a24b3694 1706 if ($dao->record_type_id == $targetID ) {
91da6cd5
DL
1707 $activities[$dao->activity_id]['targets'][$contactId] = $contactId;
1708 }
a24b3694 1709 else if ($dao->record_type_id == $assigneeID) {
91da6cd5
DL
1710 $activities[$dao->activity_id]['asignees'][$contactId] = $contactId;
1711 }
1712 else {
1713 // do source stuff here
42d30b83 1714 $activities[$dao->activity_id]['source_contact_id'] = $contactId;
91da6cd5 1715 }
6a488035
TO
1716 }
1717
91da6cd5 1718 $activityIds = array_keys($activities);
6a488035
TO
1719 if (count($activityIds) < 1) {
1720 return array();
1721 }
91da6cd5 1722
6a488035 1723 $activityIds = implode(',', $activityIds);
91da6cd5
DL
1724 $query = "
1725SELECT activity.id as activity_id,
1726 activity_type_id,
1727 subject, location, activity_date_time, details, status_id
1728FROM civicrm_activity activity
1729WHERE activity.id IN ($activityIds)";
6a488035 1730
91da6cd5 1731 $dao = CRM_Core_DAO::executeQuery($query);
6a488035
TO
1732
1733 $activityTypes = CRM_Core_OptionGroup::values('activity_type');
1734 $activityStatuses = CRM_Core_OptionGroup::values('activity_status');
1735
1736 while ($dao->fetch()) {
6a488035 1737 $activities[$dao->activity_id]['id'] = $dao->activity_id;
6a488035
TO
1738 $activities[$dao->activity_id]['activity_type_id'] = $dao->activity_type_id;
1739 $activities[$dao->activity_id]['subject'] = $dao->subject;
1740 $activities[$dao->activity_id]['location'] = $dao->location;
1741 $activities[$dao->activity_id]['activity_date_time'] = $dao->activity_date_time;
1742 $activities[$dao->activity_id]['details'] = $dao->details;
1743 $activities[$dao->activity_id]['status_id'] = $dao->status_id;
1744 $activities[$dao->activity_id]['activity_name'] = $activityTypes[$dao->activity_type_id];
1745 $activities[$dao->activity_id]['status'] = $activityStatuses[$dao->status_id];
42d30b83
DL
1746
1747 // set to null if not set
1748 if (!isset($activities[$dao->activity_id]['source_contact_id'])) {
1749 $activities[$dao->activity_id]['source_contact_id'] = NULL;
1750 }
6a488035
TO
1751 }
1752 return $activities;
1753 }
1754
1755 /**
1756 * Function to add activity for Membership/Event/Contribution
1757 *
1cfa04c4
EM
1758 * @param object $activity (reference) particular component object
1759 * @param string $activityType for Membership Signup or Renewal
1760 *
6a488035 1761 *
1cfa04c4 1762 * @param null $targetContactID
6a488035 1763 *
1cfa04c4 1764 * @return bool
6a488035
TO
1765 * @static
1766 * @access public
1767 */
1768 static function addActivity(&$activity,
1769 $activityType = 'Membership Signup',
1770 $targetContactID = NULL
1771 ) {
1772 if ($activity->__table == 'civicrm_membership') {
1773 $membershipType = CRM_Member_PseudoConstant::membershipType($activity->membership_type_id);
1774
1775 if (!$membershipType) {
1776 $membershipType = ts('Membership');
1777 }
1778
1779 $subject = "{$membershipType}";
1780
1781 if (!empty($activity->source) && $activity->source != 'null') {
1782 $subject .= " - {$activity->source}";
1783 }
1784
1785 if ($activity->owner_membership_id) {
1786 $query = "
1787SELECT display_name
1788 FROM civicrm_contact, civicrm_membership
1789 WHERE civicrm_contact.id = civicrm_membership.contact_id
1790 AND civicrm_membership.id = $activity->owner_membership_id
1791";
1792 $displayName = CRM_Core_DAO::singleValueQuery($query);
1793 $subject .= " (by {$displayName})";
1794 }
1795
1796 $subject .= " - Status: " . CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', $activity->status_id);
1797 // CRM-72097 changed from start date to today
1798 $date = date('YmdHis');
1799 $component = 'Membership';
1800 }
1801 elseif ($activity->__table == 'civicrm_participant') {
c2be40dc 1802 $event = CRM_Event_BAO_Event::getEvents(1, $activity->event_id, TRUE, FALSE);
6a488035
TO
1803
1804 $roles = CRM_Event_PseudoConstant::participantRole();
1805 $status = CRM_Event_PseudoConstant::participantStatus();
1806
1807 $subject = $event[$activity->event_id];
a7488080 1808 if (!empty($roles[$activity->role_id])) {
6a488035
TO
1809 $subject .= ' - ' . $roles[$activity->role_id];
1810 }
a7488080 1811 if (!empty($status[$activity->status_id])) {
6a488035
TO
1812 $subject .= ' - ' . $status[$activity->status_id];
1813 }
1814 $date = date('YmdHis');
1815 if ($activityType != 'Email') {
1816 $activityType = 'Event Registration';
1817 }
1818 $component = 'Event';
1819 }
1820 elseif ($activity->__table == 'civicrm_contribution') {
1821 //create activity record only for Completed Contributions
1822 if ($activity->contribution_status_id != 1) {
1823 return;
1824 }
1825
1826 $subject = NULL;
1827
1828 $subject .= CRM_Utils_Money::format($activity->total_amount, $activity->currency);
1829 if (!empty($activity->source) && $activity->source != 'null') {
1830 $subject .= " - {$activity->source}";
1831 }
1832 $date = CRM_Utils_Date::isoToMysql($activity->receive_date);
1833 $activityType = $component = 'Contribution';
1834 }
1835 $activityParams = array(
1836 'source_contact_id' => $activity->contact_id,
1837 'source_record_id' => $activity->id,
1838 'activity_type_id' => CRM_Core_OptionGroup::getValue('activity_type',
1839 $activityType,
1840 'name'
1841 ),
1842 'subject' => $subject,
1843 'activity_date_time' => $date,
1844 'is_test' => $activity->is_test,
1845 'status_id' => CRM_Core_OptionGroup::getValue('activity_status',
1846 'Completed',
1847 'name'
1848 ),
1849 'skipRecentView' => TRUE,
1850 'campaign_id' => $activity->campaign_id,
1851 );
1852
1853 // create activity with target contacts
1854 $session = CRM_Core_Session::singleton();
1855 $id = $session->get('userID');
1856 if ($id) {
1857 $activityParams['source_contact_id'] = $id;
1858 $activityParams['target_contact_id'][] = $activity->contact_id;
1859 }
1860
1861 //CRM-4027
1862 if ($targetContactID) {
1863 $activityParams['target_contact_id'][] = $targetContactID;
1864 }
1865 if (is_a(self::create($activityParams), 'CRM_Core_Error')) {
1866 CRM_Core_Error::fatal("Failed creating Activity for $component of id {$activity->id}");
1867 return FALSE;
1868 }
1869 }
1870
1871 /**
0a9f61c4 1872 * Function to get Parent activity for currently viewed activity
6a488035
TO
1873 *
1874 * @param int $activityId current activity id
1875 *
0a9f61c4 1876 * @return int $parentId Id of parent activity otherwise false.
6a488035
TO
1877 * @access public
1878 */
1879 static function getParentActivity($activityId) {
1880 static $parentActivities = array();
1881
1882 $activityId = CRM_Utils_Type::escape($activityId, 'Integer');
1883
1884 if (!array_key_exists($activityId, $parentActivities)) {
1885 $parentActivities[$activityId] = array();
1886
1887 $parentId = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity',
1888 $activityId,
1889 'parent_id'
1890 );
1891
1892 $parentActivities[$activityId] = $parentId ? $parentId : FALSE;
1893 }
1894
1895 return $parentActivities[$activityId];
1896 }
1897
1898 /**
1899 * Function to get total count of prior revision of currently viewd activity
1900 *
1901 * @param int $activityId current activity id
1902 *
0a9f61c4 1903 * @return int $params count of prior activities otherwise false.
6a488035
TO
1904 * @access public
1905 */
1906 static function getPriorCount($activityID) {
1907 static $priorCounts = array();
1908
1909 $activityID = CRM_Utils_Type::escape($activityID, 'Integer');
1910
1911 if (!array_key_exists($activityID, $priorCounts)) {
1912 $priorCounts[$activityID] = array();
1913 $originalID = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity',
1914 $activityID,
1915 'original_id'
1916 );
1917 $count = 0;
1918 if ($originalID) {
1919 $query = "
1920SELECT count( id ) AS cnt
1921FROM civicrm_activity
1922WHERE ( id = {$originalID} OR original_id = {$originalID} )
1923AND is_current_revision = 0
1924AND id < {$activityID}
1925";
1926 $params = array(1 => array($originalID, 'Integer'));
1927 $count = CRM_Core_DAO::singleValueQuery($query, $params);
1928 }
1929 $priorCounts[$activityID] = $count ? $count : 0;
1930 }
1931
1932 return $priorCounts[$activityID];
1933 }
1934
1935 /**
0a9f61c4 1936 * Function to get all prior activities of currently viewe
1937 * d activity
6a488035
TO
1938 *
1939 * @param int $activityId current activity id
1940 *
0a9f61c4 1941 * @return array $result prior activities info.
6a488035
TO
1942 * @access public
1943 */
1944 static function getPriorAcitivities($activityID, $onlyPriorRevisions = FALSE) {
1945 static $priorActivities = array();
1946
1947 $activityID = CRM_Utils_Type::escape($activityID, 'Integer');
1948 $index = $activityID . '_' . (int) $onlyPriorRevisions;
1949
1950 if (!array_key_exists($index, $priorActivities)) {
1951 $priorActivities[$index] = array();
1952
1953 $originalID = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity',
1954 $activityID,
1955 'original_id'
1956 );
1957 if ($originalID) {
1958 $query = "
1959SELECT c.display_name as name, cl.modified_date as date, ca.id as activityID
1960FROM civicrm_log cl, civicrm_contact c, civicrm_activity ca
1961WHERE (ca.id = %1 OR ca.original_id = %1)
1962AND cl.entity_table = 'civicrm_activity'
1963AND cl.entity_id = ca.id
1964AND cl.modified_id = c.id
1965";
1966 if ($onlyPriorRevisions) {
1967 $query .= " AND ca.id < {$activityID}";
1968 }
1969 $query .= " ORDER BY ca.id DESC";
1970
1971 $params = array(1 => array($originalID, 'Integer'));
1972 $dao = CRM_Core_DAO::executeQuery($query, $params);
1973
1974 while ($dao->fetch()) {
1975 $priorActivities[$index][$dao->activityID]['id'] = $dao->activityID;
1976 $priorActivities[$index][$dao->activityID]['name'] = $dao->name;
1977 $priorActivities[$index][$dao->activityID]['date'] = $dao->date;
6a488035
TO
1978 }
1979 $dao->free();
1980 }
1981 }
1982 return $priorActivities[$index];
1983 }
1984
1985 /**
1986 * Function to find the latest revision of a given activity
1987 *
1988 * @param int $activityId prior activity id
1989 *
1990 * @return int $params current activity id.
1991 * @access public
1992 */
1993 static function getLatestActivityId($activityID) {
1994 static $latestActivityIds = array();
1995
1996 $activityID = CRM_Utils_Type::escape($activityID, 'Integer');
1997
1998 if (!array_key_exists($activityID, $latestActivityIds)) {
1999 $latestActivityIds[$activityID] = array();
2000
2001 $originalID = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity',
2002 $activityID,
2003 'original_id'
2004 );
2005 if ($originalID) {
2006 $activityID = $originalID;
2007 }
2008 $params = array(1 => array($activityID, 'Integer'));
2009 $query = "SELECT id from civicrm_activity where original_id = %1 and is_current_revision = 1";
2010
2011 $latestActivityIds[$activityID] = CRM_Core_DAO::singleValueQuery($query, $params);
2012 }
2013
2014 return $latestActivityIds[$activityID];
2015 }
2016
2017 /**
2018 * Function to create a follow up a given activity
2019 *
2020 * @activityId int activity id of parent activity
2021 *
2022 * @param array $activity details
2023 *
2024 * @access public
2025 */
2026 static function createFollowupActivity($activityId, $params) {
2027 if (!$activityId) {
2028 return;
2029 }
2030
2031 $session = CRM_Core_Session::singleton();
2032
2033 $followupParams = array();
2034 $followupParams['parent_id'] = $activityId;
2035 $followupParams['source_contact_id'] = $session->get('userID');
2036 $followupParams['status_id'] = CRM_Core_OptionGroup::getValue('activity_status', 'Scheduled', 'name');
2037
2038 $followupParams['activity_type_id'] = $params['followup_activity_type_id'];
2039 // Get Subject of Follow-up Activiity, CRM-4491
2040 $followupParams['subject'] = CRM_Utils_Array::value('followup_activity_subject', $params);
90b05581 2041 $followupParams['assignee_contact_id'] = CRM_Utils_Array::value('followup_assignee_contact_id', $params);
6a488035
TO
2042
2043 //create target contact for followup
a7488080 2044 if (!empty($params['target_contact_id'])) {
6a488035
TO
2045 $followupParams['target_contact_id'] = $params['target_contact_id'];
2046 }
2047
2048 $followupParams['activity_date_time'] = CRM_Utils_Date::processDate($params['followup_date'],
2049 $params['followup_date_time']
2050 );
2051 $followupActivity = self::create($followupParams);
2052
2053 return $followupActivity;
2054 }
2055
2056 /**
2057 * Function to get Activity specific File according activity type Id.
2058 *
2059 * @param int $activityTypeId activity id
2060 *
2061 * @return if file exists returns $activityTypeFile activity filename otherwise false.
2062 *
2063 * @static
2064 */
2065 static function getFileForActivityTypeId($activityTypeId, $crmDir = 'Activity') {
2066 $activityTypes = CRM_Case_PseudoConstant::caseActivityType(FALSE, TRUE);
2067
2068 if ($activityTypes[$activityTypeId]['name']) {
2069 $activityTypeFile = CRM_Utils_String::munge(ucwords($activityTypes[$activityTypeId]['name']), '', 0);
2070 }
2071 else {
2072 return FALSE;
2073 }
2074
2075 global $civicrm_root;
2076 $config = CRM_Core_Config::singleton();
2077 if (!file_exists(rtrim($civicrm_root, '/') . "/CRM/{$crmDir}/Form/Activity/{$activityTypeFile}.php")) {
2078 if (empty($config->customPHPPathDir)) {
2079 return FALSE;
2080 }
2081 elseif (!file_exists(rtrim($config->customPHPPathDir, '/') . "/CRM/{$crmDir}/Form/Activity/{$activityTypeFile}.php")) {
2082 return FALSE;
2083 }
2084 }
2085
2086 return $activityTypeFile;
2087 }
2088
2089 /**
2090 * Function to restore the activity
2091 *
2092 * @param array $params associated array
2093 *
2094 * @return void
2095 * @access public
2096 *
2097 */
2098 public static function restoreActivity(&$params) {
2099 $activity = new CRM_Activity_DAO_Activity();
2100 $activity->copyValues($params);
2101
2102 $activity->is_deleted = 0;
2103 $result = $activity->save();
2104
2105 return $result;
2106 }
2107
2108 /**
2109 * Get the exportable fields for Activities
2110 *
2111 * @param string $name if it is called by case $name = Case else $name = Activity
2112 *
2113 * @return array array of exportable Fields
2114 * @access public
2115 * @static
2116 */
2117 static function &exportableFields($name = 'Activity') {
2118 if (!isset(self::$_exportableFields[$name])) {
2119 self::$_exportableFields[$name] = array();
2120
2121 // TO DO, ideally we should retrieve all fields from xml, in this case since activity processing is done
2122 // my case hence we have defined fields as case_*
2123 if ($name == 'Activity') {
2124 $exportableFields = CRM_Activity_DAO_Activity::export();
6a488035
TO
2125 $exportableFields['source_contact_id']['title'] = ts('Source Contact ID');
2126 $exportableFields['source_contact'] = array(
2127 'title' => ts('Source Contact'),
2128 'type' => CRM_Utils_Type::T_STRING,
2129 );
2130
2131
2132 $Activityfields = array(
2133 'activity_type' => array('title' => ts('Activity Type'), 'type' => CRM_Utils_Type::T_STRING),
2134 'activity_status' => array('title' => ts('Activity Status'), 'type' => CRM_Utils_Type::T_STRING),
2135 );
2136 $fields = array_merge($Activityfields, $exportableFields);
2137 }
2138 else {
2139 //set title to activity fields
2140 $fields = array(
2141 'case_activity_subject' => array('title' => ts('Activity Subject'), 'type' => CRM_Utils_Type::T_STRING),
2142 'case_source_contact_id' => array('title' => ts('Activity Reporter'), 'type' => CRM_Utils_Type::T_STRING),
2143 'case_recent_activity_date' => array('title' => ts('Activity Actual Date'), 'type' => CRM_Utils_Type::T_DATE),
2144 'case_scheduled_activity_date' => array('title' => ts('Activity Scheduled Date'), 'type' => CRM_Utils_Type::T_DATE),
2145 'case_recent_activity_type' => array('title' => ts('Activity Type'), 'type' => CRM_Utils_Type::T_STRING),
2146 'case_activity_status' => array('title' => ts('Activity Status'), 'type' => CRM_Utils_Type::T_STRING),
2147 'case_activity_duration' => array('title' => ts('Activity Duration'), 'type' => CRM_Utils_Type::T_INT),
2148 'case_activity_medium_id' => array('title' => ts('Activity Medium'), 'type' => CRM_Utils_Type::T_INT),
2149 'case_activity_details' => array('title' => ts('Activity Details'), 'type' => CRM_Utils_Type::T_TEXT),
2150 'case_activity_is_auto' => array('title' => ts('Activity Auto-generated?'), 'type' => CRM_Utils_Type::T_BOOLEAN),
2151 );
2152
2153 // add custom data for cases
2154 $fields = array_merge($fields, CRM_Core_BAO_CustomField::getFieldsForImport('Case'));
2155 }
2156
2157 // add custom data for case activities
2158 $fields = array_merge($fields, CRM_Core_BAO_CustomField::getFieldsForImport('Activity'));
2159
2160 self::$_exportableFields[$name] = $fields;
2161 }
2162 return self::$_exportableFields[$name];
2163 }
2164
2165 /**
2166 * Get the allowed profile fields for Activities
2167 *
2168 * @return array array of activity profile Fields
2169 * @access public
2170 */
2171 static function getProfileFields() {
2172 $exportableFields = self::exportableFields('Activity');
4f79a2f5 2173 $skipFields = array(
2174 'activity_id',
2175 'activity_type',
2176 'source_contact_id',
2177 'source_contact',
2178 'activity_campaign',
2179 'activity_is_test',
2180 'is_current_revision',
2181 'activity_is_deleted',
2182 );
6a488035
TO
2183 $config = CRM_Core_Config::singleton();
2184 if (!in_array('CiviCampaign', $config->enableComponents)) {
2185 $skipFields[] = 'activity_engagement_level';
2186 }
2187
2188 foreach ($skipFields as $field) {
2189 if (isset($exportableFields[$field])) {
2190 unset($exportableFields[$field]);
2191 }
2192 }
2193
2194 // hack to use 'activity_type_id' instead of 'activity_type'
2195 $exportableFields['activity_status_id'] = $exportableFields['activity_status'];
2196 unset($exportableFields['activity_status']);
2197
2198 return $exportableFields;
2199 }
2200
2201 /**
f1504541 2202 * This function deletes the activity record related to contact record,
6a488035
TO
2203 * when there are no target and assignee record w/ other contact.
2204 *
2205 * @param int $contactId contactId
2206 *
2207 * @return true/null
2208 * @access public
2209 */
2210 public static function cleanupActivity($contactId) {
2211 $result = NULL;
2212 if (!$contactId) {
2213 return $result;
2214 }
e7e657f0 2215 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
2bf96211 2216 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
6a488035
TO
2217
2218 $transaction = new CRM_Core_Transaction();
2219
f1504541
DL
2220 // delete activity if there is no record in civicrm_activity_contact
2221 // pointing to any other contact record
2bf96211 2222 $activityContact = new CRM_Activity_DAO_ActivityContact();
2223 $activityContact->contact_id = $contactId;
2224 $activityContact->record_type_id = $sourceID;
2225 $activityContact->find();
6a488035 2226
2bf96211 2227 while ($activityContact->fetch()) {
f1504541 2228 // delete activity_contact record for the deleted contact
32ecf7bb
BS
2229 $activityContact->delete();
2230
2231 $activityContactOther = new CRM_Activity_DAO_ActivityContact();
2232 $activityContactOther->activity_id = $activityContact->activity_id;
32ecf7bb 2233
83e0a89c 2234 // delete activity only if no other contacts connected
f1504541 2235 if ( ! $activityContactOther->find(TRUE) ) {
32ecf7bb
BS
2236 $activityParams = array('id' => $activityContact->activity_id);
2237 $result = self::deleteActivity($activityParams);
2238 }
2239
2240 $activityContactOther->free();
6a488035 2241 }
6a488035 2242
2bf96211 2243 $activityContact->free();
6a488035
TO
2244 $transaction->commit();
2245
2246 return $result;
2247 }
2248
2249 /**
2250 * Does user has sufficient permission for view/edit activity record.
2251 *
2252 * @param int $activityId activity record id.
2253 * @param int $action edit/view
2254 *
2255 * @return boolean $allow true/false
2256 * @access public
2257 */
2258 public static function checkPermission($activityId, $action) {
2259 $allow = FALSE;
2260 if (!$activityId ||
2261 !in_array($action, array(CRM_Core_Action::UPDATE, CRM_Core_Action::VIEW))
2262 ) {
2263 return $allow;
2264 }
2265
2266 $activity = new CRM_Activity_DAO_Activity();
2267 $activity->id = $activityId;
2268 if (!$activity->find(TRUE)) {
2269 return $allow;
2270 }
2271
2272 //component related permissions.
2273 $compPermissions = array(
2274 'CiviCase' => array('administer CiviCase',
2275 'access my cases and activities',
2276 'access all cases and activities',
2277 ),
2278 'CiviMail' => array('access CiviMail'),
2279 'CiviEvent' => array('access CiviEvent'),
2280 'CiviGrant' => array('access CiviGrant'),
2281 'CiviPledge' => array('access CiviPledge'),
2282 'CiviMember' => array('access CiviMember'),
2283 'CiviReport' => array('access CiviReport'),
2284 'CiviContribute' => array('access CiviContribute'),
2285 'CiviCampaign' => array('administer CiviCampaign'),
2286 );
2287
2288 //return early when it is case activity.
2289 $isCaseActivity = CRM_Case_BAO_Case::isCaseActivity($activityId);
2290 //check for civicase related permission.
2291 if ($isCaseActivity) {
2292 $allow = FALSE;
2293 foreach ($compPermissions['CiviCase'] as $per) {
2294 if (CRM_Core_Permission::check($per)) {
2295 $allow = TRUE;
2296 break;
2297 }
2298 }
2299
2300 //check for case specific permissions.
2301 if ($allow) {
2302 $oper = 'view';
2303 if ($action == CRM_Core_Action::UPDATE) {
2304 $oper = 'edit';
2305 }
2306 $allow = CRM_Case_BAO_Case::checkPermission($activityId,
2307 $oper,
2308 $activity->activity_type_id
2309 );
2310 }
2311
2312 return $allow;
2313 }
2314
6a488035
TO
2315 //first check the component permission.
2316 $sql = "
2317 SELECT component_id
2318 FROM civicrm_option_value val
2319INNER JOIN civicrm_option_group grp ON ( grp.id = val.option_group_id AND grp.name = %1 )
2320 WHERE val.value = %2";
2321 $params = array(1 => array('activity_type', 'String'),
2322 2 => array($activity->activity_type_id, 'Integer'),
2323 );
2324 $componentId = CRM_Core_DAO::singleValueQuery($sql, $params);
2325
2326 if ($componentId) {
2327 $componentName = CRM_Core_Component::getComponentName($componentId);
2328 $compPermission = CRM_Utils_Array::value($componentName, $compPermissions);
2329
2330 //here we are interesting in any single permission.
2331 if (is_array($compPermission)) {
2332 foreach ($compPermission as $per) {
2333 if (CRM_Core_Permission::check($per)) {
2334 $allow = TRUE;
2335 break;
2336 }
2337 }
2338 }
2339 }
2340
2341 //check for this permission related to contact.
2342 $permission = CRM_Core_Permission::VIEW;
2343 if ($action == CRM_Core_Action::UPDATE) {
2344 $permission = CRM_Core_Permission::EDIT;
2345 }
2346
e7e657f0 2347 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
034500d4 2348 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
2349 $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
2350 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
2351
6a488035
TO
2352 //check for source contact.
2353 if (!$componentId || $allow) {
65ebc887 2354 $sourceContactId = self::getActivityContact($activity->id, $sourceID);
32ecf7bb
BS
2355 //account for possibility of activity not having a source contact (as it may have been deleted)
2356 if ( $sourceContactId ) {
2357 $allow = CRM_Contact_BAO_Contact_Permission::allow($sourceContactId, $permission);
2358 }
6a488035
TO
2359 }
2360
2361 //check for target and assignee contacts.
2362 if ($allow) {
2363 //first check for supper permission.
2364 $supPermission = 'view all contacts';
2365 if ($action == CRM_Core_Action::UPDATE) {
2366 $supPermission = 'edit all contacts';
2367 }
2368 $allow = CRM_Core_Permission::check($supPermission);
2369
2370 //user might have sufficient permission, through acls.
2371 if (!$allow) {
2372 $allow = TRUE;
2373 //get the target contacts.
034500d4 2374 $targetContacts = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $targetID);
6a488035
TO
2375 foreach ($targetContacts as $cnt => $contactId) {
2376 if (!CRM_Contact_BAO_Contact_Permission::allow($contactId, $permission)) {
2377 $allow = FALSE;
2378 break;
2379 }
2380 }
2381
2382 //get the assignee contacts.
2383 if ($allow) {
d7f083ac 2384 $assigneeContacts = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $assigneeID);
6a488035
TO
2385 foreach ($assigneeContacts as $cnt => $contactId) {
2386 if (!CRM_Contact_BAO_Contact_Permission::allow($contactId, $permission)) {
2387 $allow = FALSE;
2388 break;
2389 }
2390 }
2391 }
2392 }
2393 }
2394
2395 return $allow;
2396 }
2397
2398 /**
2399 * This function is a wrapper for ajax activity selector
2400 *
2401 * @param array $params associated array for params record id.
2402 *
2403 * @return array $contactActivities associated array of contact activities
2404 * @access public
2405 */
2406 public static function getContactActivitySelector(&$params) {
2407 // format the params
2408 $params['offset'] = ($params['page'] - 1) * $params['rp'];
2409 $params['rowCount'] = $params['rp'];
2410 $params['sort'] = CRM_Utils_Array::value('sortBy', $params);
2411 $params['caseId'] = NULL;
2412 $context = CRM_Utils_Array::value('context', $params);
2413
2414 // get contact activities
2415 $activities = CRM_Activity_BAO_Activity::getActivities($params);
2416
2417 // add total
2418 $params['total'] = CRM_Activity_BAO_Activity::getActivitiesCount($params);
2419
2420 // format params and add links
2421 $contactActivities = array();
2422
2423 if (!empty($activities)) {
2424 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
2425
2426 // check logged in user for permission
2427 $page = new CRM_Core_Page();
2428 CRM_Contact_Page_View::checkUserPermission($page, $params['contact_id']);
2429 $permissions = array($page->_permission);
2430 if (CRM_Core_Permission::check('delete activities')) {
2431 $permissions[] = CRM_Core_Permission::DELETE;
2432 }
2433
2434 $mask = CRM_Core_Action::mask($permissions);
2435
2436 foreach ($activities as $activityId => $values) {
2437 $contactActivities[$activityId]['activity_type'] = $values['activity_type'];
2438 $contactActivities[$activityId]['subject'] = $values['subject'];
2439 if ($params['contact_id'] == $values['source_contact_id']) {
2440 $contactActivities[$activityId]['source_contact'] = $values['source_contact_name'];
2441 }
2442 elseif ($values['source_contact_id']) {
5a99d240
KJ
2443 $contactActivities[$activityId]['source_contact'] = CRM_Utils_System::href($values['source_contact_name'],
2444 'civicrm/contact/view', "reset=1&cid={$values['source_contact_id']}");
6a488035
TO
2445 }
2446 else {
2447 $contactActivities[$activityId]['source_contact'] = '<em>n/a</em>';
2448 }
2449
2450 if (isset($values['mailingId']) && !empty($values['mailingId'])) {
5a99d240
KJ
2451 $contactActivities[$activityId]['target_contact'] = CRM_Utils_System::href($values['recipients'],
2452 'civicrm/mailing/report/event',
2453 "mid={$values['source_record_id']}&reset=1&event=queue&cid={$params['contact_id']}&context=activitySelector");
6a488035 2454 }
a7488080 2455 elseif (!empty($values['recipients'])) {
6a488035
TO
2456 $contactActivities[$activityId]['target_contact'] = $values['recipients'];
2457 }
2458 elseif (!$values['target_contact_name']) {
2459 $contactActivities[$activityId]['target_contact'] = '<em>n/a</em>';
2460 }
2461 elseif (!empty($values['target_contact_name'])) {
2462 $count = 0;
2463 $contactActivities[$activityId]['target_contact'] = '';
2464 foreach ($values['target_contact_name'] as $tcID => $tcName) {
2465 if ($tcID && $count < 5) {
5a99d240
KJ
2466 $contactActivities[$activityId]['target_contact'] .= CRM_Utils_System::href($tcName,
2467 'civicrm/contact/view', "reset=1&cid={$tcID}");
6a488035
TO
2468 $count++;
2469 if ($count) {
2470 $contactActivities[$activityId]['target_contact'] .= ";&nbsp;";
2471 }
2472
2473 if ($count == 4) {
2474 $contactActivities[$activityId]['target_contact'] .= "(" . ts('more') . ")";
2475 break;
2476 }
2477 }
2478 }
2479 }
2480
2481 if (empty($values['assignee_contact_name'])) {
2482 $contactActivities[$activityId]['assignee_contact'] = '<em>n/a</em>';
2483 }
2484 elseif (!empty($values['assignee_contact_name'])) {
2485 $count = 0;
2486 $contactActivities[$activityId]['assignee_contact'] = '';
2487 foreach ($values['assignee_contact_name'] as $acID => $acName) {
2488 if ($acID && $count < 5) {
2489 $contactActivities[$activityId]['assignee_contact'] .= CRM_Utils_System::href($acName, 'civicrm/contact/view', "reset=1&cid={$acID}");
2490 $count++;
2491 if ($count) {
2492 $contactActivities[$activityId]['assignee_contact'] .= ";&nbsp;";
2493 }
2494
2495 if ($count == 4) {
2496 $contactActivities[$activityId]['assignee_contact'] .= "(" . ts('more') . ")";
2497 break;
2498 }
2499 }
2500 }
2501 }
6a488035
TO
2502
2503 $contactActivities[$activityId]['activity_date'] = CRM_Utils_Date::customFormat($values['activity_date_time']);
2504 $contactActivities[$activityId]['status'] = $activityStatus[$values['status_id']];
2505
2506 // add class to this row if overdue
2507 $contactActivities[$activityId]['class'] = '';
2508 if (CRM_Utils_Date::overdue(CRM_Utils_Array::value('activity_date_time', $values))
2509 && CRM_Utils_Array::value('status_id', $values) == 1
2510 ) {
2511 $contactActivities[$activityId]['class'] = 'status-overdue';
2512 }
2513 else {
2514 $contactActivities[$activityId]['class'] = 'status-ontime';
2515 }
2516
2517 // build links
2518 $contactActivities[$activityId]['links'] = '';
2519 $accessMailingReport = FALSE;
a7488080 2520 if (!empty($values['mailingId'])) {
6a488035
TO
2521 $accessMailingReport = TRUE;
2522 }
2523
2524 $actionLinks = CRM_Activity_Selector_Activity::actionLinks(
2525 CRM_Utils_Array::value('activity_type_id', $values),
2526 CRM_Utils_Array::value('source_record_id', $values),
2527 $accessMailingReport,
2528 CRM_Utils_Array::value('activity_id', $values)
2529 );
2530
2531 $actionMask = array_sum(array_keys($actionLinks)) & $mask;
2532
2533 $contactActivities[$activityId]['links'] = CRM_Core_Action::formLink($actionLinks,
2534 $actionMask,
2535 array(
2536 'id' => $values['activity_id'],
2537 'cid' => $params['contact_id'],
2538 'cxt' => $context,
2539 'caseid' => CRM_Utils_Array::value('case_id', $values),
87dab4a4
AH
2540 ),
2541 ts('more'),
2542 FALSE,
2543 'activity.tab.row',
2544 'Activity',
2545 $values['activity_id']
6a488035
TO
2546 );
2547 }
2548 }
2549
2550 return $contactActivities;
2551 }
2552
2553 /*
2554 * Used to copy custom fields and attachments from an existing activity to another.
2555 * see CRM_Case_Page_AJAX::_convertToCaseActivity() for example
2556 */
2557 static function copyExtendedActivityData($params) {
2558 // attach custom data to the new activity
2559 $customParams = $htmlType = array();
2560 $customValues = CRM_Core_BAO_CustomValueTable::getEntityValues($params['activityID'], 'Activity');
2561
2562 if (!empty($customValues)) {
2563 $fieldIds = implode(', ', array_keys($customValues));
2564 $sql = "SELECT id FROM civicrm_custom_field WHERE html_type = 'File' AND id IN ( {$fieldIds} )";
2565 $result = CRM_Core_DAO::executeQuery($sql);
2566
2567 while ($result->fetch()) {
2568 $htmlType[] = $result->id;
2569 }
2570
2571 foreach ($customValues as $key => $value) {
2572 if ($value !== NULL) { // CRM-10542
2573 if (in_array($key, $htmlType)) {
2574 $fileValues = CRM_Core_BAO_File::path($value, $params['activityID']);
2575 $customParams["custom_{$key}_-1"] = array(
2576 'name' => $fileValues[0],
2577 'path' => $fileValues[1],
2578 );
2579 }
2580 else {
2581 $customParams["custom_{$key}_-1"] = $value;
2582 }
2583 }
2584 }
2585 CRM_Core_BAO_CustomValueTable::postProcess($customParams, CRM_Core_DAO::$_nullArray, 'civicrm_activity',
2586 $params['mainActivityId'], 'Activity'
2587 );
2588 }
2589
2590 // copy activity attachments ( if any )
2591 CRM_Core_BAO_File::copyEntityFile('civicrm_activity', $params['activityID'], 'civicrm_activity', $params['mainActivityId']);
2592 }
65ebc887 2593
2594 public static function getActivityContact($activityId, $recordTypeID = NULL, $column = 'contact_id') {
2595 $activityContact = new CRM_Activity_BAO_ActivityContact();
2596 $activityContact->activity_id = $activityId;
2597 if ($recordTypeID) {
2598 $activityContact->record_type_id = $recordTypeID;
2599 }
2600 if ($activityContact->find(TRUE)) {
b319d00a 2601 return $activityContact->$column;
65ebc887 2602 }
42d30b83
DL
2603 return NULL;
2604 }
2605
2606 public static function getSourceContactID($activityId) {
2607 static $sourceID = NULL;
2608 if (!$sourceID) {
e7e657f0 2609 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
42d30b83
DL
2610 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
2611 }
2612
2613 return self::getActivityContact($activityId, $sourceID);
65ebc887 2614 }
42d30b83 2615
6e1bb60c
N
2616 function setApiFilter(&$params) {
2617 if (CRM_Utils_Array::value('target_contact_id', $params)) {
2618 $this->selectAdd();
2619 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
2620 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
2621 $obj = new CRM_Activity_BAO_ActivityContact();
2622 $params['return.target_contact_id'] = 1;
2623 $this->joinAdd($obj, 'LEFT');
2624 $this->selectAdd('civicrm_activity.*');
2625 $this->whereAdd(" civicrm_activity_contact.contact_id = {$params['target_contact_id']} AND civicrm_activity_contact.record_type_id = {$targetID}");
2626 }
2627 }
2628
6a488035
TO
2629}
2630