Activity.php 93.4 KB
Newer Older
totten's avatar
totten committed
1 2 3
<?php
/*
 +--------------------------------------------------------------------+
yashodha's avatar
yashodha committed
4
 | CiviCRM version 4.6                                                |
totten's avatar
totten committed
5
 +--------------------------------------------------------------------+
kurund's avatar
kurund committed
6
 | Copyright CiviCRM LLC (c) 2004-2014                                |
totten's avatar
totten committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 +--------------------------------------------------------------------+
 | This file is a part of CiviCRM.                                    |
 |                                                                    |
 | CiviCRM is free software; you can copy, modify, and distribute it  |
 | under the terms of the GNU Affero General Public License           |
 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
 |                                                                    |
 | CiviCRM is distributed in the hope that it will be useful, but     |
 | WITHOUT ANY WARRANTY; without even the implied warranty of         |
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
 | See the GNU Affero General Public License for more details.        |
 |                                                                    |
 | You should have received a copy of the GNU Affero General Public   |
 | License and the CiviCRM Licensing Exception along                  |
 | with this program; if not, contact CiviCRM LLC                     |
 | at info[AT]civicrm[DOT]org. If you have questions about the        |
 | GNU Affero General Public License or the licensing of CiviCRM,     |
 | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
 +--------------------------------------------------------------------+
26
 */
totten's avatar
totten committed
27 28 29 30

/**
 *
 * @package CRM
kurund's avatar
kurund committed
31
 * @copyright CiviCRM LLC (c) 2004-2014
totten's avatar
totten committed
32 33 34 35
 * $Id$
 */

/**
Eileen McNaughton's avatar
Eileen McNaughton committed
36
 * This class is for activity functions.s
totten's avatar
totten committed
37 38 39 40
 */
class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {

  /**
colemanw's avatar
colemanw committed
41
   * Static field for all the activity information that we can potentially export
totten's avatar
totten committed
42 43 44 45 46 47
   *
   * @var array
   */
  static $_exportableFields = NULL;

  /**
colemanw's avatar
colemanw committed
48
   * Static field for all the activity information that we can potentially import
totten's avatar
totten committed
49 50 51 52 53 54
   *
   * @var array
   */
  static $_importableFields = NULL;

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
55
   * Check if there is absolute minimum of data to add the object.
totten's avatar
totten committed
56
   *
57 58
   * @param array $params
   *   (reference ) an assoc array of name/value pairs.
totten's avatar
totten committed
59
   *
totten's avatar
totten committed
60
   * @return bool
totten's avatar
totten committed
61 62
   */
  public static function dataExists(&$params) {
63
    if (!empty($params['source_contact_id']) || !empty($params['id'])) {
totten's avatar
totten committed
64 65 66 67 68 69
      return TRUE;
    }
    return FALSE;
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
70
   * Fetch object based on array of properties.
totten's avatar
totten committed
71
   *
72 73 74 75
   * @param array $params
   *   (reference ) an assoc array of name/value pairs.
   * @param array $defaults
   *   (reference ) an assoc array to hold the flattened values.
Eileen McNaughton's avatar
Eileen McNaughton committed
76
   *
77
   * @return CRM_Activity_DAO_Activity
totten's avatar
totten committed
78 79 80 81 82 83
   */
  public static function retrieve(&$params, &$defaults) {
    $activity = new CRM_Activity_DAO_Activity();
    $activity->copyValues($params);

    if ($activity->find(TRUE)) {
84
      $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
yashodha's avatar
yashodha committed
85 86 87 88
      $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
      $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
      $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);

totten's avatar
totten committed
89 90 91
      // TODO: at some stage we'll have to deal
      // TODO: with multiple values for assignees and targets, but
      // TODO: for now, let's just fetch first row
yashodha's avatar
yashodha committed
92 93
      $defaults['assignee_contact'] = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $assigneeID);
      $assignee_contact_names = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $assigneeID);
totten's avatar
totten committed
94
      $defaults['assignee_contact_value'] = implode('; ', $assignee_contact_names);
yashodha's avatar
yashodha committed
95
      $sourceContactId = self::getActivityContact($activity->id, $sourceID);
totten's avatar
totten committed
96
      if ($activity->activity_type_id != CRM_Core_OptionGroup::getValue('activity_type', 'Bulk Email', 'name')) {
yashodha's avatar
yashodha committed
97 98
        $defaults['target_contact'] = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $targetID);
        $target_contact_names = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $targetID);
totten's avatar
totten committed
99 100 101 102 103 104 105 106
        $defaults['target_contact_value'] = implode('; ', $target_contact_names);
      }
      elseif (CRM_Core_Permission::check('access CiviMail') ||
        (CRM_Mailing_Info::workflowEnabled() &&
          CRM_Core_Permission::check('create mailings')
        )
      ) {
        $defaults['mailingId'] = CRM_Utils_System::url('civicrm/mailing/report',
yashodha's avatar
yashodha committed
107
          "mid={$activity->source_record_id}&reset=1&atype={$activity->activity_type_id}&aid={$activity->id}&cid={$sourceContactId}&context=activity"
totten's avatar
totten committed
108 109 110 111 112
        );
      }
      else {
        $defaults['target_contact_value'] = ts('(recipients)');
      }
lobo's avatar
lobo committed
113

yashodha's avatar
yashodha committed
114
      $sourceContactId = self::getActivityContact($activity->id, $sourceID);
yashodha's avatar
yashodha committed
115
      $defaults['source_contact_id'] = $sourceContactId;
totten's avatar
totten committed
116

yashodha's avatar
yashodha committed
117
      if ($sourceContactId &&
totten's avatar
totten committed
118
        !CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
yashodha's avatar
yashodha committed
119
          $sourceContactId,
totten's avatar
totten committed
120 121 122 123
          'is_deleted'
        )
      ) {
        $defaults['source_contact'] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
yashodha's avatar
yashodha committed
124
          $sourceContactId,
totten's avatar
totten committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
          'sort_name'
        );
      }

      //get case subject
      $defaults['case_subject'] = CRM_Case_BAO_Case::getCaseSubject($activity->id);

      CRM_Core_DAO::storeValues($activity, $defaults);

      return $activity;
    }
    return NULL;
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
140
   * Delete the activity.
totten's avatar
totten committed
141
   *
142
   * @param array $params
Eileen McNaughton's avatar
Eileen McNaughton committed
143
   * @param bool $moveToTrash
totten's avatar
totten committed
144
   *
Eileen McNaughton's avatar
Eileen McNaughton committed
145
   * @return mixed
totten's avatar
totten committed
146 147 148
   */
  public static function deleteActivity(&$params, $moveToTrash = FALSE) {
    // CRM-9137
149
    if (!empty($params['id']) && !is_array($params['id'])) {
totten's avatar
totten committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
      CRM_Utils_Hook::pre('delete', 'Activity', $params['id'], $params);
    }
    else {
      CRM_Utils_Hook::pre('delete', 'Activity', NULL, $params);
    }

    $transaction = new CRM_Core_Transaction();
    if (is_array(CRM_Utils_Array::value('source_record_id', $params))) {
      $sourceRecordIds = implode(',', $params['source_record_id']);
    }
    else {
      $sourceRecordIds = CRM_Utils_Array::value('source_record_id', $params);
    }

    $result = NULL;
    if (!$moveToTrash) {
      if (!isset($params['id'])) {
        if (is_array($params['activity_type_id'])) {
          $activityTypes = implode(',', $params['activity_type_id']);
        }
        else {
          $activityTypes = $params['activity_type_id'];
        }

        $query = "DELETE FROM civicrm_activity WHERE source_record_id IN ({$sourceRecordIds}) AND activity_type_id IN ( {$activityTypes} )";
        $dao = CRM_Core_DAO::executeQuery($query);
      }
      else {
        $activity = new CRM_Activity_DAO_Activity();
        $activity->copyValues($params);
        $result = $activity->delete();

        // CRM-8708
        $activity->case_id = CRM_Case_BAO_Case::getCaseIdByActivityId($activity->id);
184 185 186 187

        // CRM-13994 delete activity entity_tag
        $query = "DELETE FROM civicrm_entity_tag WHERE entity_table = 'civicrm_activity' AND entity_id = {$activity->id}";
        $dao = CRM_Core_DAO::executeQuery($query);
totten's avatar
totten committed
188 189 190 191 192 193 194 195 196
      }
    }
    else {
      $activity = new CRM_Activity_DAO_Activity();
      $activity->copyValues($params);

      $activity->is_deleted = 1;
      $result = $activity->save();

197 198 199
      // CRM-4525 log activity delete
      $logMsg = 'Case Activity deleted for';
      $msgs = array();
yashodha's avatar
yashodha committed
200

201
      $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
yashodha's avatar
yashodha committed
202 203 204 205
      $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
      $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
      $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
      $sourceContactId = self::getActivityContact($activity->id, $sourceID);
totten's avatar
totten committed
206 207 208
      if ($sourceContactId) {
        $msgs[] = " source={$sourceContactId}";
      }
yashodha's avatar
yashodha committed
209

totten's avatar
totten committed
210
      //get target contacts.
yashodha's avatar
yashodha committed
211
      $targetContactIds = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $targetID);
totten's avatar
totten committed
212 213 214 215
      if (!empty($targetContactIds)) {
        $msgs[] = " target =" . implode(',', array_keys($targetContactIds));
      }
      //get assignee contacts.
yashodha's avatar
yashodha committed
216
      $assigneeContactIds = CRM_Activity_BAO_ActivityContact::getNames($activity->id, $assigneeID);
totten's avatar
totten committed
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
      if (!empty($assigneeContactIds)) {
        $msgs[] = " assignee =" . implode(',', array_keys($assigneeContactIds));
      }

      $logMsg .= implode(', ', $msgs);

      self::logActivityAction($activity, $logMsg);
    }

    // delete the recently created Activity
    if ($result) {
      $activityRecent = array(
        'id' => $activity->id,
        'type' => 'Activity',
      );
      CRM_Utils_Recent::del($activityRecent);
    }

    $transaction->commit();
    if (isset($activity)) {
      // CRM-8708
      $activity->case_id = CRM_Case_BAO_Case::getCaseIdByActivityId($activity->id);
      CRM_Utils_Hook::post('delete', 'Activity', $activity->id, $activity);
    }

    return $result;
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
246
   * Delete activity assignment record.
totten's avatar
totten committed
247
   *
248
   * @param int $activityId
colemanw's avatar
colemanw committed
249
   * @param int $recordTypeID
totten's avatar
totten committed
250
   */
yashodha's avatar
yashodha committed
251
  public static function deleteActivityContact($activityId, $recordTypeID = NULL) {
lobo's avatar
lobo committed
252 253
    $activityContact = new CRM_Activity_BAO_ActivityContact();
    $activityContact->activity_id = $activityId;
yashodha's avatar
yashodha committed
254 255
    if ($recordTypeID) {
      $activityContact->record_type_id = $recordTypeID;
totten's avatar
totten committed
256
    }
lobo's avatar
lobo committed
257
    $activityContact->delete();
totten's avatar
totten committed
258 259 260
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
261
   * Process the activities.
totten's avatar
totten committed
262
   *
263 264
   * @param array $params
   *   Associated array of the submitted values.
Eileen McNaughton's avatar
Eileen McNaughton committed
265
   *
Eileen McNaughton's avatar
Eileen McNaughton committed
266
   * @throws CRM_Core_Exception
totten's avatar
totten committed
267
   *
totten's avatar
totten committed
268
   * @return CRM_Activity_BAO_Activity|null|object
totten's avatar
totten committed
269 270 271 272
   */
  public static function create(&$params) {
    // check required params
    if (!self::dataExists($params)) {
273
      throw new CRM_Core_Exception('Not enough data to create activity object');
totten's avatar
totten committed
274 275 276 277 278 279 280 281
    }

    $activity = new CRM_Activity_DAO_Activity();

    if (isset($params['id']) && empty($params['id'])) {
      unset($params['id']);
    }

282
    if (empty($params['status_id']) && empty($params['activity_status_id']) && empty($params['id'])) {
totten's avatar
totten committed
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
      if (isset($params['activity_date_time']) &&
        strcmp($params['activity_date_time'], CRM_Utils_Date::processDate(date('Ymd')) == -1)
      ) {
        $params['status_id'] = 2;
      }
      else {
        $params['status_id'] = 1;
      }
    }

    //set priority to Normal for Auto-populated activities (for Cases)
    if (CRM_Utils_Array::value('priority_id', $params) === NULL &&
      // if not set and not 0
      !CRM_Utils_Array::value('id', $params)
    ) {
298
      $priority = CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id');
totten's avatar
totten committed
299 300 301 302 303 304 305 306 307 308 309
      $params['priority_id'] = array_search('Normal', $priority);
    }

    if (!empty($params['target_contact_id']) && is_array($params['target_contact_id'])) {
      $params['target_contact_id'] = array_unique($params['target_contact_id']);
    }
    if (!empty($params['assignee_contact_id']) && is_array($params['assignee_contact_id'])) {
      $params['assignee_contact_id'] = array_unique($params['assignee_contact_id']);
    }

    // CRM-9137
310
    if (!empty($params['id'])) {
totten's avatar
totten committed
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
      CRM_Utils_Hook::pre('edit', 'Activity', $activity->id, $params);
    }
    else {
      CRM_Utils_Hook::pre('create', 'Activity', NULL, $params);
    }

    $activity->copyValues($params);
    if (isset($params['case_id'])) {
      // CRM-8708, preserve case ID even though it's not part of the SQL model
      $activity->case_id = $params['case_id'];
    }
    elseif (is_numeric($activity->id)) {
      // CRM-8708, preserve case ID even though it's not part of the SQL model
      $activity->case_id = CRM_Case_BAO_Case::getCaseIdByActivityId($activity->id);
    }

    // start transaction
    $transaction = new CRM_Core_Transaction();

    $result = $activity->save();

    if (is_a($result, 'CRM_Core_Error')) {
      $transaction->rollback();
      return $result;
    }

    $activityId = $activity->id;
338
    $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
yashodha's avatar
yashodha committed
339 340 341
    $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
    $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
    $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
totten's avatar
totten committed
342

lobo's avatar
lobo committed
343 344 345
    if (isset($params['source_contact_id'])) {
      $acParams = array(
        'activity_id' => $activityId,
totten's avatar
totten committed
346
        'contact_id' => $params['source_contact_id'],
347
        'record_type_id' => $sourceID,
lobo's avatar
lobo committed
348
      );
yashodha's avatar
yashodha committed
349
      self::deleteActivityContact($activityId, $sourceID);
lobo's avatar
lobo committed
350 351 352
      CRM_Activity_BAO_ActivityContact::create($acParams);
    }

totten's avatar
totten committed
353 354 355 356 357
    // check and attach and files as needed
    CRM_Core_BAO_File::processAttachment($params, 'civicrm_activity', $activityId);

    // attempt to save activity assignment
    $resultAssignment = NULL;
358
    if (!empty($params['assignee_contact_id'])) {
totten's avatar
totten committed
359 360 361 362 363 364

      $assignmentParams = array('activity_id' => $activityId);

      if (is_array($params['assignee_contact_id'])) {
        if (CRM_Utils_Array::value('deleteActivityAssignment', $params, TRUE)) {
          // first delete existing assignments if any
yashodha's avatar
yashodha committed
365
          self::deleteActivityContact($activityId, $assigneeID);
totten's avatar
totten committed
366 367 368 369 370
        }

        $values = array();
        foreach ($params['assignee_contact_id'] as $acID) {
          if ($acID) {
yashodha's avatar
yashodha committed
371
            $values[] = "( $activityId, $acID, $assigneeID )";
totten's avatar
totten committed
372 373 374 375
          }
        }
        while (!empty($values)) {
          $input = array_splice($values, 0, CRM_Core_DAO::BULK_INSERT_COUNT);
totten's avatar
totten committed
376 377
          $str = implode(',', $input);
          $sql = "INSERT IGNORE INTO civicrm_activity_contact ( activity_id, contact_id, record_type_id ) VALUES $str;";
totten's avatar
totten committed
378 379 380 381
          CRM_Core_DAO::executeQuery($sql);
        }
      }
      else {
lobo's avatar
lobo committed
382
        $assignmentParams['contact_id'] = $params['assignee_contact_id'];
yashodha's avatar
yashodha committed
383
        $assignmentParams['record_type_id'] = $assigneeID;
384
        if (!empty($params['id'])) {
yashodha's avatar
yashodha committed
385
          $assignment = new CRM_Activity_BAO_ActivityContact();
totten's avatar
totten committed
386
          $assignment->activity_id = $activityId;
yashodha's avatar
yashodha committed
387
          $assignment->record_type_id = $assigneeID;
totten's avatar
totten committed
388 389
          $assignment->find(TRUE);

lobo's avatar
lobo committed
390
          if ($assignment->contact_id != $params['assignee_contact_id']) {
totten's avatar
totten committed
391
            $assignmentParams['id'] = $assignment->id;
yashodha's avatar
yashodha committed
392
            $resultAssignment = CRM_Activity_BAO_ActivityContact::create($assignmentParams);
totten's avatar
totten committed
393 394 395
          }
        }
        else {
yashodha's avatar
yashodha committed
396
          $resultAssignment = CRM_Activity_BAO_ActivityContact::create($assignmentParams);
totten's avatar
totten committed
397 398 399 400 401
        }
      }
    }
    else {
      if (CRM_Utils_Array::value('deleteActivityAssignment', $params, TRUE)) {
yashodha's avatar
yashodha committed
402
        self::deleteActivityContact($activityId, $assigneeID);
totten's avatar
totten committed
403 404 405 406 407 408 409 410 411 412
      }
    }

    if (is_a($resultAssignment, 'CRM_Core_Error')) {
      $transaction->rollback();
      return $resultAssignment;
    }

    // attempt to save activity targets
    $resultTarget = NULL;
413
    if (!empty($params['target_contact_id'])) {
totten's avatar
totten committed
414 415 416 417 418 419

      $targetParams = array('activity_id' => $activityId);
      $resultTarget = array();
      if (is_array($params['target_contact_id'])) {
        if (CRM_Utils_Array::value('deleteActivityTarget', $params, TRUE)) {
          // first delete existing targets if any
totten's avatar
totten committed
420
          self::deleteActivityContact($activityId, $targetID);
totten's avatar
totten committed
421 422 423 424 425
        }

        $values = array();
        foreach ($params['target_contact_id'] as $tid) {
          if ($tid) {
yashodha's avatar
yashodha committed
426
            $values[] = "( $activityId, $tid,  $targetID )";
totten's avatar
totten committed
427 428 429 430 431
          }
        }

        while (!empty($values)) {
          $input = array_splice($values, 0, CRM_Core_DAO::BULK_INSERT_COUNT);
totten's avatar
totten committed
432 433
          $str = implode(',', $input);
          $sql = "INSERT IGNORE INTO civicrm_activity_contact ( activity_id, contact_id, record_type_id ) VALUES $str;";
totten's avatar
totten committed
434 435 436 437
          CRM_Core_DAO::executeQuery($sql);
        }
      }
      else {
lobo's avatar
lobo committed
438
        $targetParams['contact_id'] = $params['target_contact_id'];
yashodha's avatar
yashodha committed
439
        $targetParams['record_type_id'] = $targetID;
440
        if (!empty($params['id'])) {
yashodha's avatar
yashodha committed
441
          $target = new CRM_Activity_BAO_ActivityContact();
totten's avatar
totten committed
442
          $target->activity_id = $activityId;
yashodha's avatar
yashodha committed
443
          $target->record_type_id = $targetID;
totten's avatar
totten committed
444 445
          $target->find(TRUE);

lobo's avatar
lobo committed
446
          if ($target->contact_id != $params['target_contact_id']) {
totten's avatar
totten committed
447
            $targetParams['id'] = $target->id;
yashodha's avatar
yashodha committed
448
            $resultTarget = CRM_Activity_BAO_ActivityContact::create($targetParams);
totten's avatar
totten committed
449 450 451
          }
        }
        else {
yashodha's avatar
yashodha committed
452
          $resultTarget = CRM_Activity_BAO_ActivityContact::create($targetParams);
totten's avatar
totten committed
453 454 455 456 457
        }
      }
    }
    else {
      if (CRM_Utils_Array::value('deleteActivityTarget', $params, TRUE)) {
totten's avatar
totten committed
458
        self::deleteActivityContact($activityId, $targetID);
totten's avatar
totten committed
459 460 461
      }
    }

yashodha's avatar
yashodha committed
462
    // write to changelog before transaction is committed/rolled
totten's avatar
totten committed
463
    // back (and prepare status to display)
464
    if (!empty($params['id'])) {
totten's avatar
totten committed
465 466 467 468 469 470 471 472 473 474 475
      $logMsg = "Activity (id: {$result->id} ) updated with ";
    }
    else {
      $logMsg = "Activity created for ";
    }

    $msgs = array();
    if (isset($params['source_contact_id'])) {
      $msgs[] = "source={$params['source_contact_id']}";
    }

476
    if (!empty($params['target_contact_id'])) {
totten's avatar
totten committed
477 478 479 480 481 482 483
      if (is_array($params['target_contact_id']) && !CRM_Utils_array::crmIsEmptyArray($params['target_contact_id'])) {
        $msgs[] = "target=" . implode(',', $params['target_contact_id']);
        // take only first target
        // will be used for recently viewed display
        $t = array_slice($params['target_contact_id'], 0, 1);
        $recentContactId = $t[0];
      }
484 485 486
      //is array check fixes warning without degrading functionality but it seems this bit of code may no longer work
      // as it may always be an array
      elseif (isset($params['target_contact_id']) && !is_array($params['target_contact_id'])) {
totten's avatar
totten committed
487 488 489 490 491 492 493
        $msgs[] = "target={$params['target_contact_id']}";
        // will be used for recently viewed display
        $recentContactId = $params['target_contact_id'];
      }
    }
    else {
      // at worst, take source for recently viewed display
totten's avatar
totten committed
494
      $recentContactId = CRM_Utils_Array::value('source_contact_id', $params);
totten's avatar
totten committed
495 496 497 498 499 500 501 502 503 504 505 506 507 508
    }

    if (isset($params['assignee_contact_id'])) {
      if (is_array($params['assignee_contact_id'])) {
        $msgs[] = "assignee=" . implode(',', $params['assignee_contact_id']);
      }
      else {
        $msgs[] = "assignee={$params['assignee_contact_id']}";
      }
    }
    $logMsg .= implode(', ', $msgs);

    self::logActivityAction($result, $logMsg);

509
    if (!empty($params['custom']) &&
totten's avatar
totten committed
510 511 512 513 514 515
      is_array($params['custom'])
    ) {
      CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_activity', $result->id);
    }

    $transaction->commit();
516
    if (empty($params['skipRecentView'])) {
totten's avatar
totten committed
517
      $recentOther = array();
518
      if (!empty($params['case_id'])) {
totten's avatar
totten committed
519 520 521 522 523 524
        $caseContactID = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseContact', $params['case_id'], 'contact_id', 'case_id');
        $url = CRM_Utils_System::url('civicrm/case/activity/view',
          "reset=1&aid={$activity->id}&cid={$caseContactID}&caseID={$params['case_id']}&context=home"
        );
      }
      else {
525
        $q = "action=view&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid=" . CRM_Utils_Array::value('source_contact_id', $params) . "&context=home";
totten's avatar
totten committed
526 527 528 529
        if ($activity->activity_type_id != CRM_Core_OptionGroup::getValue('activity_type', 'Email', 'name')) {
          $url = CRM_Utils_System::url('civicrm/activity', $q);
          if ($activity->activity_type_id == CRM_Core_OptionGroup::getValue('activity_type', 'Print PDF Letter', 'name')) {
            $recentOther['editUrl'] = CRM_Utils_System::url('civicrm/activity/pdf/add',
yashodha's avatar
yashodha committed
530
              "action=update&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid={$params['source_contact_id']}&context=home"
totten's avatar
totten committed
531 532 533 534
            );
          }
          else {
            $recentOther['editUrl'] = CRM_Utils_System::url('civicrm/activity/add',
Eileen McNaughton's avatar
Eileen McNaughton committed
535
              "action=update&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid=" . CRM_Utils_Array::value('source_contact_id', $params) . "&context=home"
totten's avatar
totten committed
536 537 538 539 540
            );
          }

          if (CRM_Core_Permission::check("delete activities")) {
            $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/activity',
Eileen McNaughton's avatar
Eileen McNaughton committed
541
              "action=delete&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid=" . CRM_Utils_Array::value('source_contact_id', $params) . "&context=home"
totten's avatar
totten committed
542 543 544 545 546 547 548
            );
          }
        }
        else {
          $url = CRM_Utils_System::url('civicrm/activity/view', $q);
          if (CRM_Core_Permission::check('delete activities')) {
            $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/activity',
549
              "action=delete&reset=1&id={$activity->id}&atype={$activity->activity_type_id}&cid=" . CRM_Utils_Array::value('source_contact_id', $params) . "&context=home"
totten's avatar
totten committed
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
            );
          }
        }
      }

      if (!isset($activity->parent_id)) {
        $recentContactDisplay = CRM_Contact_BAO_Contact::displayName($recentContactId);
        // add the recently created Activity
        $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE);
        $activitySubject = CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $activity->id, 'subject');

        $title = "";
        if (isset($activitySubject)) {
          $title = $activitySubject . ' - ';
        }

        $title = $title . $recentContactDisplay;
567
        if (!empty($activityTypes[$activity->activity_type_id])) {
totten's avatar
totten committed
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
          $title .= ' (' . $activityTypes[$activity->activity_type_id] . ')';
        }

        CRM_Utils_Recent::add($title,
          $url,
          $activity->id,
          'Activity',
          $recentContactId,
          $recentContactDisplay,
          $recentOther
        );
      }
    }

    // reset the group contact cache since smart groups might be affected due to this
    CRM_Contact_BAO_GroupContactCache::remove();

585
    if (!empty($params['id'])) {
totten's avatar
totten committed
586 587 588 589 590 591 592 593 594
      CRM_Utils_Hook::post('edit', 'Activity', $activity->id, $activity);
    }
    else {
      CRM_Utils_Hook::post('create', 'Activity', $activity->id, $activity);
    }

    // if the subject contains a ‘[case #…]’ string, file that activity on the related case (CRM-5916)
    $matches = array();
    if (preg_match('/\[case #([0-9a-h]{7})\]/', CRM_Utils_Array::value('subject', $params), $matches)) {
totten's avatar
totten committed
595 596 597
      $key = CRM_Core_DAO::escapeString(CIVICRM_SITE_KEY);
      $hash = $matches[1];
      $query = "SELECT id FROM civicrm_case WHERE SUBSTR(SHA1(CONCAT('$key', id)), 1, 7) = '$hash'";
totten's avatar
totten committed
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
      $caseParams = array(
        'activity_id' => $activity->id,
        'case_id' => CRM_Core_DAO::singleValueQuery($query),
      );
      if ($caseParams['case_id']) {
        CRM_Case_BAO_Case::processCaseActivity($caseParams);
      }
      else {
        self::logActivityAction($activity, "unknown case hash encountered: $hash");
      }
    }

    return $result;
  }

613
  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
614 615 616 617 618 619
   * Create an activity.
   *
   * @todo elaborate on what this does.
   *
   * @param CRM_Core_DAO_Activity $activity
   * @param string $logMessage
620 621 622
   *
   * @return bool
   */
totten's avatar
totten committed
623 624 625 626
  public static function logActivityAction($activity, $logMessage = NULL) {
    $session = CRM_Core_Session::singleton();
    $id = $session->get('userID');
    if (!$id) {
627
      $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
lobo's avatar
lobo committed
628
      $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
totten's avatar
totten committed
629
      $id = self::getActivityContact($activity->id . $sourceID);
totten's avatar
totten committed
630 631 632 633 634 635 636 637 638 639 640 641 642
    }
    $logParams = array(
      'entity_table' => 'civicrm_activity',
      'entity_id' => $activity->id,
      'modified_id' => $id,
      'modified_date' => date('YmdHis'),
      'data' => $logMessage,
    );
    CRM_Core_BAO_Log::add($logParams);
    return TRUE;
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
643
   * Get the list Activities.
totten's avatar
totten committed
644
   *
645 646
   * @param array $input
   *   Array of parameters.
totten's avatar
totten committed
647
   *    Keys include
yashodha's avatar
yashodha committed
648
   *    - contact_id  int            contact_id whose activities we want to retrieve
totten's avatar
totten committed
649 650 651 652 653 654 655 656
   *    - offset      int            which row to start from ?
   *    - rowCount    int            how many rows to fetch
   *    - sort        object|array   object or array describing sort order for sql query.
   *    - admin       boolean        if contact is admin
   *    - caseId      int            case ID
   *    - context     string         page on which selector is build
   *    - activity_type_id int|string the activitiy types we want to restrict by
   *
657
   * @return array
Eileen McNaughton's avatar
Eileen McNaughton committed
658
   *   Relevant data object values of open activities
totten's avatar
totten committed
659
   */
660
  public static function &getActivities($input) {
totten's avatar
totten committed
661
    //step 1: Get the basic activity data
lobo's avatar
lobo committed
662 663
    $bulkActivityTypeID = CRM_Core_OptionGroup::getValue(
      'activity_type',
totten's avatar
totten committed
664 665 666 667
      'Bulk Email',
      'name'
    );

668 669 670 671 672
    $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
    $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
    $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
    $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);

totten's avatar
totten committed
673 674 675 676 677 678 679 680
    $config = CRM_Core_Config::singleton();

    $randomNum = md5(uniqid());
    $activityTempTable = "civicrm_temp_activity_details_{$randomNum}";

    $tableFields = array(
      'activity_id' => 'int unsigned',
      'activity_date_time' => 'datetime',
pratik.joshi's avatar
pratik.joshi committed
681
      'source_record_id' => 'int unsigned',
totten's avatar
totten committed
682 683
      'status_id' => 'int unsigned',
      'subject' => 'varchar(255)',
684
      'source_contact_name' => 'varchar(255)',
totten's avatar
totten committed
685 686 687 688 689 690 691 692 693
      'activity_type_id' => 'int unsigned',
      'activity_type' => 'varchar(128)',
      'case_id' => 'int unsigned',
      'case_subject' => 'varchar(255)',
      'campaign_id' => 'int unsigned',
    );

    $sql = "CREATE TEMPORARY TABLE {$activityTempTable} ( ";
    $insertValueSQL = array();
yashodha's avatar
yashodha committed
694 695 696 697
    // The activityTempTable contains the sorted rows
    // so in order to maintain the sort order as-is we add an auto_increment
    // field; we can sort by this later to ensure the sort order stays correct.
    $sql .= " fixed_sort_order INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,";
totten's avatar
totten committed
698 699 700 701 702
    foreach ($tableFields as $name => $desc) {
      $sql .= "$name $desc,\n";
      $insertValueSQL[] = $name;
    }

yashodha's avatar
yashodha committed
703 704 705
    // add unique key on activity_id just to be sure
    // this cannot be primary key because we need that for the auto_increment
    // fixed_sort_order field
totten's avatar
totten committed
706
    $sql .= "
monishdeb's avatar
monishdeb committed
707
          UNIQUE KEY ( activity_id )
totten's avatar
totten committed
708 709 710 711 712 713 714 715
        ) ENGINE=HEAP DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
        ";

    CRM_Core_DAO::executeQuery($sql);

    $insertSQL = "INSERT INTO {$activityTempTable} (" . implode(',', $insertValueSQL) . " ) ";

    $order = $limit = $groupBy = '';
pratik.joshi's avatar
pratik.joshi committed
716
    $groupBy = " GROUP BY tbl.activity_id ";
totten's avatar
totten committed
717 718 719 720 721 722 723 724 725

    if (!empty($input['sort'])) {
      if (is_a($input['sort'], 'CRM_Utils_Sort')) {
        $orderBy = $input['sort']->orderBy();
        if (!empty($orderBy)) {
          $order = " ORDER BY $orderBy";
        }
      }
      elseif (trim($input['sort'])) {
lobo's avatar
lobo committed
726 727
        $sort = CRM_Utils_Type::escape($input['sort'], 'String');
        $order = " ORDER BY $sort ";
totten's avatar
totten committed
728 729 730 731
      }
    }

    if (empty($order)) {
yashodha's avatar
yashodha committed
732
      // context = 'activity' in Activities tab.
totten's avatar
totten committed
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
      $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 ";
    }

    if (!empty($input['rowCount']) &&
      $input['rowCount'] > 0
    ) {
      $limit = " LIMIT {$input['offset']}, {$input['rowCount']} ";
    }

    $input['count'] = FALSE;
    list($sqlClause, $params) = self::getActivitySQLClause($input);

    $query = "{$insertSQL}
       SELECT DISTINCT tbl.*  from ( {$sqlClause} )
as tbl ";

    //filter case activities - CRM-5761
    $components = self::activityComponents();
    if (!in_array('CiviCase', $components)) {
      $query .= "
LEFT JOIN  civicrm_case_activity ON ( civicrm_case_activity.activity_id = tbl.activity_id )
    WHERE  civicrm_case_activity.id IS NULL";
    }

    $query = $query . $groupBy . $order . $limit;

    $dao = CRM_Core_DAO::executeQuery($query, $params);

    // step 2: Get target and assignee contacts for above activities
    // create temp table for target contacts
763 764
    $activityContactTempTable = "civicrm_temp_activity_contact_{$randomNum}";
    $query = "CREATE TEMPORARY TABLE {$activityContactTempTable} (
765
                activity_id int unsigned, contact_id int unsigned, record_type_id varchar(16),
766
                 contact_name varchar(255), is_deleted int unsigned, counter int unsigned, INDEX index_activity_id( activity_id ) )
totten's avatar
totten committed
767 768 769 770 771
                ENGINE=MYISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci";

    CRM_Core_DAO::executeQuery($query);

    // note that we ignore bulk email for targets, since we don't show it in selector
772
    $query = "
773
INSERT INTO {$activityContactTempTable} ( activity_id, contact_id, record_type_id, contact_name, is_deleted )
774 775
SELECT     ac.activity_id,
           ac.contact_id,
yashodha's avatar
yashodha committed
776
           ac.record_type_id,
777 778
           c.sort_name,
           c.is_deleted
779
FROM       {$activityTempTable}
780
INNER JOIN civicrm_activity a ON ( a.id = {$activityTempTable}.activity_id )
781
INNER JOIN civicrm_activity_contact ac ON ( ac.activity_id = {$activityTempTable}.activity_id )
yashodha's avatar
yashodha committed
782
INNER JOIN civicrm_contact c ON c.id = ac.contact_id
783
WHERE ac.record_type_id != %1
784
";
785 786
    $params = array(1 => array($targetID, 'Integer'));
    CRM_Core_DAO::executeQuery($query, $params);
totten's avatar
totten committed
787

788 789 790 791 792 793 794 795 796 797 798
    // for each activity insert one target contact
    // if we load all target contacts the performance will suffer a lot for mass-activities;
    $query = "
INSERT INTO {$activityContactTempTable} ( activity_id, contact_id, record_type_id, contact_name, is_deleted, counter )
SELECT     ac.activity_id,
           ac.contact_id,
           ac.record_type_id,
           c.sort_name,
           c.is_deleted,
           count(ac.contact_id)
FROM       {$activityTempTable}
799
INNER JOIN civicrm_activity a ON ( a.id = {$activityTempTable}.activity_id )
800 801 802 803 804
INNER JOIN civicrm_activity_contact ac ON ( ac.activity_id = {$activityTempTable}.activity_id )
INNER JOIN civicrm_contact c ON c.id = ac.contact_id
WHERE ac.record_type_id = %1
GROUP BY ac.activity_id
";
805

806 807
    CRM_Core_DAO::executeQuery($query, $params);

totten's avatar
totten committed
808
    // step 3: Combine all temp tables to get final query for activity selector
yashodha's avatar
yashodha committed
809
    // sort by the original sort order, stored in fixed_sort_order
totten's avatar
totten committed
810
    $query = "
811 812
SELECT     {$activityTempTable}.*,
           {$activityContactTempTable}.contact_id,
yashodha's avatar
yashodha committed
813
           {$activityContactTempTable}.record_type_id,
814
           {$activityContactTempTable}.contact_name,
815
           {$activityContactTempTable}.is_deleted,
816 817
           {$activityContactTempTable}.counter,
           re.parent_id as is_recurring_activity
818 819
FROM       {$activityTempTable}
INNER JOIN {$activityContactTempTable} on {$activityTempTable}.activity_id = {$activityContactTempTable}.activity_id
820
LEFT JOIN civicrm_recurring_entity re on {$activityContactTempTable}.activity_id = re.entity_id
yashodha's avatar
yashodha committed
821
ORDER BY    fixed_sort_order
totten's avatar
totten committed
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
        ";

    $dao = CRM_Core_DAO::executeQuery($query);

    //CRM-3553, need to check user has access to target groups.
    $mailingIDs = CRM_Mailing_BAO_Mailing::mailingACLIDs();
    $accessCiviMail = (
      (CRM_Core_Permission::check('access CiviMail')) ||
      (CRM_Mailing_Info::workflowEnabled() &&
        CRM_Core_Permission::check('create mailings'))
    );

    //get all campaigns.
    $allCampaigns = CRM_Campaign_BAO_Campaign::getCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
    $values = array();
    while ($dao->fetch()) {
      $activityID = $dao->activity_id;
      $values[$activityID]['activity_id'] = $dao->activity_id;
      $values[$activityID]['source_record_id'] = $dao->source_record_id;
      $values[$activityID]['activity_type_id'] = $dao->activity_type_id;
      $values[$activityID]['activity_type'] = $dao->activity_type;
      $values[$activityID]['activity_date_time'] = $dao->activity_date_time;
      $values[$activityID]['status_id'] = $dao->status_id;
      $values[$activityID]['subject'] = $dao->subject;
      $values[$activityID]['campaign_id'] = $dao->campaign_id;
847
      $values[$activityID]['is_recurring_activity'] = $dao->is_recurring_activity;
totten's avatar
totten committed
848 849 850 851 852

      if ($dao->campaign_id) {
        $values[$activityID]['campaign'] = $allCampaigns[$dao->campaign_id];
      }

853
      if (empty($values[$activityID]['assignee_contact_name'])) {
totten's avatar
totten committed
854 855 856
        $values[$activityID]['assignee_contact_name'] = array();
      }

857
      if (empty($values[$activityID]['target_contact_name'])) {
totten's avatar
totten committed
858
        $values[$activityID]['target_contact_name'] = array();
859
        $values[$activityID]['target_contact_counter'] = $dao->counter;
totten's avatar
totten committed
860 861
      }

862
      // if deleted, wrap in <del>
totten's avatar
totten committed
863
      if ($dao->is_deleted) {
864 865 866
        $dao->contact_name = "<del>{$dao->contact_name}</dao>";
      }

totten's avatar
totten committed
867
      if ($dao->record_type_id == $sourceID && $dao->contact_id) {
868 869 870 871
        $values[$activityID]['source_contact_id'] = $dao->contact_id;
        $values[$activityID]['source_contact_name'] = $dao->contact_name;
      }

totten's avatar
totten committed
872 873
      if (!$bulkActivityTypeID || ($bulkActivityTypeID != $dao->activity_type_id)) {
        // build array of target / assignee names
yashodha's avatar
yashodha committed
874
        if ($dao->record_type_id == $targetID && $dao->contact_id) {
875
          $values[$activityID]['target_contact_name'][$dao->contact_id] = $dao->contact_name;
totten's avatar
totten committed
876
        }
yashodha's avatar
yashodha committed
877
        if ($dao->record_type_id == $assigneeID && $dao->contact_id) {
878
          $values[$activityID]['assignee_contact_name'][$dao->contact_id] = $dao->contact_name;
totten's avatar
totten committed
879 880 881 882 883 884 885
        }

        // case related fields
        $values[$activityID]['case_id'] = $dao->case_id;
        $values[$activityID]['case_subject'] = $dao->case_subject;
      }
      else {
totten's avatar
totten committed
886 887
        $values[$activityID]['recipients'] = ts('(%1 recipients)', array(1 => $dao->counter));
        $values[$activityID]['mailingId'] = FALSE;
totten's avatar
totten committed
888 889 890 891
        if (
          $accessCiviMail &&
          ($mailingIDs === TRUE || in_array($dao->source_record_id, $mailingIDs))
        ) {
totten's avatar
totten committed
892
          $values[$activityID]['mailingId'] = TRUE;
totten's avatar
totten committed
893 894 895 896 897 898 899 900
        }
      }
    }

    return $values;
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
901 902 903 904 905 906
   * Get the component id and name if those are enabled and allowed.
   *
   * Checks whether logged in user has permission.
   * To decide whether we are going to include
   * component related activities with core activity retrieve process.
   * (what did that just mean?)
totten's avatar
totten committed
907
   *
908
   * @return array
909
   *   Array of component id and name.
totten's avatar
totten committed
910
   */
911
  public static function activityComponents() {
totten's avatar
totten committed
912 913 914
    $components = array();
    $compInfo = CRM_Core_Component::getEnabledComponents();
    foreach ($compInfo as $compObj) {
915
      if (!empty($compObj->info['showActivitiesInCore'])) {
totten's avatar
totten committed
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
        if ($compObj->info['name'] == 'CiviCampaign') {
          $componentPermission = "administer {$compObj->name}";
        }
        else {
          $componentPermission = "access {$compObj->name}";
        }
        if ($compObj->info['name'] == 'CiviCase') {
          if (CRM_Case_BAO_Case::accessCiviCase()) {
            $components[$compObj->componentID] = $compObj->info['name'];
          }
        }
        elseif (CRM_Core_Permission::check($componentPermission)) {
          $components[$compObj->componentID] = $compObj->info['name'];
        }
      }
    }

    return $components;
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
937
   * Get the activity Count.
totten's avatar
totten committed
938
   *
939 940
   * @param array $input
   *   Array of parameters.
totten's avatar
totten committed
941
   *    Keys include
yashodha's avatar
yashodha committed
942
   *    - contact_id  int            contact_id whose activities we want to retrieve
totten's avatar
totten committed
943 944 945
   *    - admin       boolean        if contact is admin
   *    - caseId      int            case ID
   *    - context     string         page on which selector is build
yashodha's avatar
yashodha committed
946
   *    - activity_type_id int|string the activity types we want to restrict by
totten's avatar
totten committed
947
   *
948 949
   * @return int
   *   count of activities
totten's avatar
totten committed
950
   */
951
  public static function &getActivitiesCount($input) {
totten's avatar
totten committed
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
    $input['count'] = TRUE;
    list($sqlClause, $params) = self::getActivitySQLClause($input);

    //filter case activities - CRM-5761
    $components = self::activityComponents();
    if (!in_array('CiviCase', $components)) {
      $query = "
   SELECT   COUNT(DISTINCT(tbl.activity_id)) as count
     FROM   ( {$sqlClause} ) as tbl
LEFT JOIN   civicrm_case_activity ON ( civicrm_case_activity.activity_id = tbl.activity_id )
    WHERE   civicrm_case_activity.id IS NULL";
    }
    else {
      $query = "SELECT COUNT(DISTINCT(activity_id)) as count  from ( {$sqlClause} ) as tbl";
    }

    return CRM_Core_DAO::singleValueQuery($query, $params);
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
972
   * Get the activity sql clause to pick activities.
totten's avatar
totten committed
973
   *
974 975
   * @param array $input
   *   Array of parameters.
totten's avatar
totten committed
976
   *    Keys include
yashodha's avatar
yashodha committed
977
   *    - contact_id  int            contact_id whose activities we want to retrieve
totten's avatar
totten committed
978 979 980 981
   *    - admin       boolean        if contact is admin
   *    - caseId      int            case ID
   *    - context     string         page on which selector is build
   *    - count       boolean        are we interested in the count clause only?
yashodha's avatar
yashodha committed
982
   *    - activity_type_id int|string the activity types we want to restrict by
totten's avatar
totten committed
983
   *
984 985
   * @return int
   *   count of activities
totten's avatar
totten committed
986
   */
987
  public static function getActivitySQLClause($input) {
totten's avatar
totten committed
988 989 990 991 992
    $params = array();
    $sourceWhere = $targetWhere = $assigneeWhere = $caseWhere = 1;

    $config = CRM_Core_Config::singleton();
    if (!CRM_Utils_Array::value('admin', $input, FALSE)) {
totten's avatar
totten committed
993 994
      $sourceWhere = ' ac.contact_id = %1 ';
      $caseWhere = ' civicrm_case_contact.contact_id = %1 ';
totten's avatar
totten committed
995 996 997 998 999 1000 1001 1002

      $params = array(1 => array($input['contact_id'], 'Integer'));
    }

    $commonClauses = array(
      "civicrm_option_group.name = 'activity_type'",
      "civicrm_activity.is_deleted = 0",
      "civicrm_activity.is_current_revision =  1",
lobo's avatar
lobo committed
1003
      "civicrm_activity.is_test= 0",
totten's avatar
totten committed
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
    );

    if ($input['context'] != 'activity') {
      $commonClauses[] = "civicrm_activity.status_id = 1";
    }

    //Filter on component IDs.
    $components = self::activityComponents();
    if (!empty($components)) {
      $componentsIn = implode(',', array_keys($components));
      $commonClauses[] = "( civicrm_option_value.component_id IS NULL OR civicrm_option_value.component_id IN ( $componentsIn ) )";
    }
    else {
      $commonClauses[] = "civicrm_option_value.component_id IS NULL";
    }

    // activity type ID clause
    if (!empty($input['activity_type_id'])) {
      if (is_array($input['activity_type_id'])) {
        foreach ($input['activity_type_id'] as $idx => $value) {
          $input['activity_type_id'][$idx] = CRM_Utils_Type::escape($value, 'Positive');
        }
        $commonClauses[] = "civicrm_activity.activity_type_id IN ( " . implode(",", $input['activity_type_id']) . " ) ";
      }
      else {
        $activityTypeID = CRM_Utils_Type::escape($input['activity_type_id'], 'Positive');
        $commonClauses[] = "civicrm_activity.activity_type_id = $activityTypeID";
      }
    }

    // exclude by activity type clause
    if (!empty($input['activity_type_exclude_id'])) {
      if (is_array($input['activity_type_exclude_id'])) {
        foreach ($input['activity_type_exclude_id'] as $idx => $value) {
          $input['activity_type_exclude_id'][$idx] = CRM_Utils_Type::escape($value, 'Positive');
        }
        $commonClauses[] = "civicrm_activity.activity_type_id NOT IN ( " . implode(",", $input['activity_type_exclude_id']) . " ) ";
      }
      else {
        $activityTypeID = CRM_Utils_Type::escape($input['activity_type_exclude_id'], 'Positive');
        $commonClauses[] = "civicrm_activity.activity_type_id != $activityTypeID";
      }
    }

    $commonClause = implode(' AND ', $commonClauses);

    $includeCaseActivities = FALSE;
    if (in_array('CiviCase', $components)) {
      $includeCaseActivities = TRUE;
    }

    // build main activity table select clause
    $sourceSelect = '';
1057 1058 1059

    $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
    $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
lobo's avatar
lobo committed
1060
    $sourceJoin = "
pratik.joshi's avatar
pratik.joshi committed
1061
INNER JOIN civicrm_activity_contact ac ON ac.activity_id = civicrm_activity.id
lobo's avatar
lobo committed
1062 1063
INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
";
totten's avatar
totten committed
1064 1065 1066 1067

    if (!$input['count']) {
      $sourceSelect = ',
                civicrm_activity.activity_date_time,
pratik.joshi's avatar
pratik.joshi committed
1068
                civicrm_activity.source_record_id,
totten's avatar
totten committed
1069 1070
                civicrm_activity.status_id,
                civicrm_activity.subject,
1071
                contact.sort_name as source_contact_name,
totten's avatar
totten committed
1072 1073 1074
                civicrm_option_value.value as activity_type_id,
                civicrm_option_value.label as activity_type,
                null as case_id, null as case_subject,
yashodha's avatar
yashodha committed
1075
                civicrm_activity.campaign_id as campaign_id
totten's avatar
totten committed
1076 1077
            ';

pratik.joshi's avatar
pratik.joshi committed
1078 1079 1080
      $sourceJoin .= "
LEFT JOIN civicrm_activity_contact src ON (src.activity_id = ac.activity_id AND src.record_type_id = {$sourceID} AND src.contact_id = contact.id)
";
totten's avatar
totten committed
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
    }

    $sourceClause = "
            SELECT civicrm_activity.id as activity_id
            {$sourceSelect}
            from civicrm_activity
            left join civicrm_option_value on
                civicrm_activity.activity_type_id = civicrm_option_value.value
            left join civicrm_option_group on
                civicrm_option_group.id = civicrm_option_value.option_group_id
            {$sourceJoin}
            where
                    {$sourceWhere}
                AND $commonClause
        ";

    // Build case clause
    // or else exclude Inbound Emails that have been filed on a case.
    $caseClause = '';

    if ($includeCaseActivities) {
      $caseSelect = '';
      if (!$input['count']) {
        $caseSelect = ',
                civicrm_activity.activity_date_time,
pratik.joshi's avatar
pratik.joshi committed
1106
                civicrm_activity.source_record_id,
totten's avatar
totten committed
1107 1108
                civicrm_activity.status_id,
                civicrm_activity.subject,
1109
                contact.sort_name as source_contact_name,
totten's avatar
totten committed
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
                civicrm_option_value.value as activity_type_id,
                civicrm_option_value.label as activity_type,
                null as case_id, null as case_subject,
                civicrm_activity.campaign_id as campaign_id';
      }

      $caseClause = "
                union all

                SELECT civicrm_activity.id as activity_id
                {$caseSelect}
                from civicrm_activity
                inner join civicrm_case_activity on
                    civicrm_case_activity.activity_id = civicrm_activity.id
                inner join civicrm_case on
                    civicrm_case_activity.case_id = civicrm_case.id
                inner join civicrm_case_contact on
                    civicrm_case_contact.case_id = civicrm_case.id and {$caseWhere}
                left join civicrm_option_value on
                    civicrm_activity.activity_type_id = civicrm_option_value.value
                left join civicrm_option_group on
                    civicrm_option_group.id = civicrm_option_value.option_group_id
                {$sourceJoin}
                where
                        {$caseWhere}
                    AND $commonClause
                        and  ( ( civicrm_case_activity.case_id IS NULL ) OR
                           ( civicrm_option_value.name <> 'Inbound Email' AND
                             civicrm_option_value.name <> 'Email' AND civicrm_case_activity.case_id
                             IS NOT NULL )
                         )
            ";
    }

lobo's avatar
lobo committed
1144
    $returnClause = " {$sourceClause} {$caseClause} ";
totten's avatar
totten committed
1145 1146 1147 1148 1149

    return array($returnClause, $params);
  }

  /**
Eileen McNaughton's avatar
Eileen McNaughton committed
1150 1151 1152
   * Send the message to all the contacts.
   *
   * Also insert a contact activity in each contacts record.
totten's avatar
totten committed
1153
   *
1154 1155 1156 1157
   * @param array $contactDetails
   *   The array of contact details to send the email.
   * @param string $subject
   *   The subject of the message.
Eileen McNaughton's avatar
Eileen McNaughton committed
1158 1159
   * @param $text
   * @param $html
1160 1161 1162 1163
   * @param string $emailAddress
   *   Use this 'to' email address instead of the default Primary address.
   * @param int $userID
   *   Use this userID if set.
totten's avatar
totten committed
1164
   * @param string $from
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
   * @param array $attachments
   *   The array of attachments if any.
   * @param string $cc
   *   Cc recipient.
   * @param string $bcc
   *   Bcc recipient.
   * @param array $contactIds
   *   Contact ids.
   * @param string $additionalDetails
   *   The additional information of CC and BCC appended to the activity Details.
totten's avatar
totten committed
1175
   *
1176 1177
   * @return array
   *   ( sent, activityId) if any email is sent and activityId
totten's avatar
totten committed
1178
   */
totten's avatar
totten committed
1179
  public static function sendEmail(
totten's avatar
totten committed
1180 1181 1182 1183 1184
    &$contactDetails,
    &$subject,
    &$text,
    &$html,
    $emailAddress,
totten's avatar
totten committed
1185 1186
    $userID = NULL,
    $from = NULL,
totten's avatar
totten committed
1187
    $attachments = NULL,
totten's avatar
totten committed
1188 1189
    $cc = NULL,
    $bcc = NULL,
Eileen McNaughton's avatar
Eileen McNaughton committed
1190 1191
    // FIXME a param with no default shouldn't be last
    $contactIds,
monishdeb's avatar
monishdeb committed
1192
    $additionalDetails = NULL
totten's avatar
totten committed
1193 1194 1195