fixed activity count bug, CRM-14175
[civicrm-core.git] / CRM / Activity / BAO / Activity.php
index d46b1e3be7714a1e0f2e3dfd254d4d91f64c00de..42c2b993956160dd08d07ce2b98d2de8a6997a61 100644 (file)
@@ -676,6 +676,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
     $tableFields = array(
       'activity_id' => 'int unsigned',
       'activity_date_time' => 'datetime',
+      'source_record_id' => 'int unsigned',
       'status_id' => 'int unsigned',
       'subject' => 'varchar(255)',
       'source_contact_name' => 'varchar(255)',
@@ -710,6 +711,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
     $insertSQL = "INSERT INTO {$activityTempTable} (" . implode(',', $insertValueSQL) . " ) ";
 
     $order = $limit = $groupBy = '';
+    $groupBy = " GROUP BY tbl.activity_id ";
 
     if (!empty($input['sort'])) {
       if (is_a($input['sort'], 'CRM_Utils_Sort')) {
@@ -736,6 +738,9 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
     }
 
     $input['count'] = FALSE;
+
+    // skip bulk activities in activity tab
+    $input['activity_type_exclude_id'][$bulkActivityTypeID] = $bulkActivityTypeID;
     list($sqlClause, $params) = self::getActivitySQLClause($input);
 
     $query = "{$insertSQL}
@@ -758,23 +763,24 @@ LEFT JOIN  civicrm_case_activity ON ( civicrm_case_activity.activity_id = tbl.ac
     // create temp table for target contacts
     $activityContactTempTable = "civicrm_temp_activity_contact_{$randomNum}";
     $query = "CREATE TEMPORARY TABLE {$activityContactTempTable} (
-                activity_id int unsigned, contact_id int unsigned, record_type_id varchar(16), contact_name varchar(255) )
+                activity_id int unsigned, contact_id int unsigned, record_type_id varchar(16),
+                 contact_name varchar(255), is_deleted int unsigned, INDEX index_activity_id( activity_id ) )
                 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
     $query = "
-INSERT INTO {$activityContactTempTable} ( activity_id, contact_id, record_type_id, contact_name )
+INSERT INTO {$activityContactTempTable} ( activity_id, contact_id, record_type_id, contact_name, is_deleted )
 SELECT     ac.activity_id,
            ac.contact_id,
            ac.record_type_id,
-           c.sort_name
-FROM       civicrm_activity_contact ac
-INNER JOIN {$activityTempTable} ON ( ac.activity_id = {$activityTempTable}.activity_id )
+           c.sort_name,
+           c.is_deleted
+FROM       {$activityTempTable}
+INNER JOIN civicrm_activity a ON ( a.id = {$activityTempTable}.activity_id  )
+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      c.is_deleted = 0
-
 ";
     CRM_Core_DAO::executeQuery($query);
 
@@ -784,7 +790,8 @@ WHERE      c.is_deleted = 0
 SELECT     {$activityTempTable}.*,
            {$activityContactTempTable}.contact_id,
            {$activityContactTempTable}.record_type_id,
-           {$activityContactTempTable}.contact_name
+           {$activityContactTempTable}.contact_name,
+           {$activityContactTempTable}.is_deleted
 FROM       {$activityTempTable}
 INNER JOIN {$activityContactTempTable} on {$activityTempTable}.activity_id = {$activityContactTempTable}.activity_id
 ORDER BY    fixed_sort_order
@@ -834,6 +841,11 @@ ORDER BY    fixed_sort_order
         $values[$activityID]['target_contact_name'] = array();
       }
 
+      // if deleted, wrap in <del>
+      if ( $dao->is_deleted ) {
+        $dao->contact_name = "<del>{$dao->contact_name}</dao>";
+      }
+
       if ($dao->record_type_id == $sourceID  && $dao->contact_id) {
         $values[$activityID]['source_contact_id'] = $dao->contact_id;
         $values[$activityID]['source_contact_name'] = $dao->contact_name;
@@ -864,33 +876,6 @@ ORDER BY    fixed_sort_order
       }
     }
 
-    // add info on whether the related contacts are deleted (CRM-5673)
-    // FIXME: ideally this should be tied to ACLs
-
-    // grab all the related contact ids
-    $cids = array();
-    foreach ($values as $value) {
-      $cids[] = $value['source_contact_id'];
-    }
-    $cids = array_filter(array_unique($cids));
-
-    // see which of the cids are of deleted contacts
-    if ($cids) {
-      $sql  = 'SELECT id FROM civicrm_contact WHERE id IN (' . implode(', ', $cids) . ') AND is_deleted = 1';
-      $dao  = CRM_Core_DAO::executeQuery($sql);
-      $dels = array();
-      while ($dao->fetch()) {
-        $dels[] = $dao->id;
-      }
-
-      // hide the deleted contacts
-      foreach ($values as & $value) {
-        if (in_array($value['source_contact_id'], $dels)) {
-          unset($value['source_contact_id'], $value['source_contact_name']);
-        }
-      }
-    }
-
     return $values;
   }
 
@@ -944,6 +929,14 @@ ORDER BY    fixed_sort_order
    * @static
    */
   static function &getActivitiesCount($input) {
+    // skip bulk activities in activity tab
+    $bulkActivityTypeID = CRM_Core_OptionGroup::getValue(
+      'activity_type',
+      'Bulk Email',
+      'name'
+    );
+    $input['activity_type_exclude_id'][$bulkActivityTypeID] = $bulkActivityTypeID;
+
     $input['count'] = TRUE;
     list($sqlClause, $params) = self::getActivitySQLClause($input);
 
@@ -1055,13 +1048,14 @@ LEFT JOIN   civicrm_case_activity ON ( civicrm_case_activity.activity_id = tbl.a
     $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
     $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
     $sourceJoin = "
-INNER JOIN civicrm_activity_contact ac ON ac.activity_id = civicrm_activity.id AND record_type_id = {$sourceID}
+INNER JOIN civicrm_activity_contact ac ON ac.activity_id = civicrm_activity.id
 INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
 ";
 
     if (!$input['count']) {
       $sourceSelect = ',
                 civicrm_activity.activity_date_time,
+                civicrm_activity.source_record_id,
                 civicrm_activity.status_id,
                 civicrm_activity.subject,
                 contact.sort_name as source_contact_name,
@@ -1071,6 +1065,9 @@ INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
                 civicrm_activity.campaign_id as campaign_id
             ';
 
+      $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)
+";
     }
 
     $sourceClause = "
@@ -1096,9 +1093,9 @@ INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
       if (!$input['count']) {
         $caseSelect = ',
                 civicrm_activity.activity_date_time,
+                civicrm_activity.source_record_id,
                 civicrm_activity.status_id,
                 civicrm_activity.subject,
-                ac.contact_id,
                 contact.sort_name as source_contact_name,
                 civicrm_option_value.value as activity_type_id,
                 civicrm_option_value.label as activity_type,
@@ -1193,6 +1190,7 @@ INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
     $subjectToken = CRM_Utils_Token::getTokens($subject);
     $messageToken = CRM_Utils_Token::getTokens($text);
     $messageToken = array_merge($messageToken, CRM_Utils_Token::getTokens($html));
+    $allTokens = array_merge($messageToken, $subjectToken);
 
     if (!$from) {
       $from = "$fromDisplayName <$fromEmail>";
@@ -1258,12 +1256,12 @@ INNER JOIN civicrm_contact contact ON ac.contact_id = contact.id
 
     // get token details for contacts, call only if tokens are used
     $details = array();
-    if (!empty($returnProperties)) {
+    if (!empty($returnProperties) || !empty($tokens) || !empty($allTokens)) {
       list($details) = CRM_Utils_Token::getTokenDetails(
         $contactIds,
         $returnProperties,
         NULL, NULL, FALSE,
-        $messageToken,
+        $allTokens,
         'CRM_Activity_BAO_Activity'
       );
     }
@@ -2118,9 +2116,6 @@ AND cl.modified_id  = c.id
       // my case hence we have defined fields as case_*
       if ($name == 'Activity') {
         $exportableFields = CRM_Activity_DAO_Activity::export();
-        if (isset($exportableFields['activity_campaign_id'])) {
-          $exportableFields['activity_campaign'] = array('title' => ts('Campaign Title'));
-        }
         $exportableFields['source_contact_id']['title'] = ts('Source Contact ID');
         $exportableFields['source_contact'] = array(
           'title' => ts('Source Contact'),
@@ -2198,7 +2193,7 @@ AND cl.modified_id  = c.id
   }
 
   /**
-   * This function delete activity record related to contact record,
+   * This function deletes the activity record related to contact record,
    * when there are no target and assignee record w/ other contact.
    *
    * @param  int $contactId contactId
@@ -2216,18 +2211,27 @@ AND cl.modified_id  = c.id
 
     $transaction = new CRM_Core_Transaction();
 
-    // delete activity if there is no record in
-    // civicrm_activity_contact
-    // pointing to any other contact record.
+    // delete activity if there is no record in civicrm_activity_contact
+    // pointing to any other contact record
     $activityContact = new CRM_Activity_DAO_ActivityContact();
     $activityContact->contact_id = $contactId;
     $activityContact->record_type_id = $sourceID;
     $activityContact->find();
 
     while ($activityContact->fetch()) {
-      // finally delete activity.
-      $activityParams = array('id' => $activityContact->activity_id);
-      $result = self::deleteActivity($activityParams);
+      // delete activity_contact record for the deleted contact
+      $activityContact->delete();
+
+      $activityContactOther = new CRM_Activity_DAO_ActivityContact();
+      $activityContactOther->activity_id = $activityContact->activity_id;
+
+      // delete activity only if no other contacts connected
+      if ( ! $activityContactOther->find(TRUE) ) {
+        $activityParams = array('id' => $activityContact->activity_id);
+        $result = self::deleteActivity($activityParams);
+      }
+
+      $activityContactOther->free();
     }
 
     $activityContact->free();
@@ -2342,7 +2346,10 @@ INNER JOIN  civicrm_option_group grp ON ( grp.id = val.option_group_id AND grp.n
     //check for source contact.
     if (!$componentId || $allow) {
       $sourceContactId = self::getActivityContact($activity->id, $sourceID);
-      $allow = CRM_Contact_BAO_Contact_Permission::allow($sourceContactId, $permission);
+      //account for possibility of activity not having a source contact (as it may have been deleted)
+      if ( $sourceContactId ) {
+        $allow = CRM_Contact_BAO_Contact_Permission::allow($sourceContactId, $permission);
+      }
     }
 
     //check for target and assignee contacts.
@@ -2368,7 +2375,7 @@ INNER JOIN  civicrm_option_group grp ON ( grp.id = val.option_group_id AND grp.n
 
         //get the assignee contacts.
         if ($allow) {
-          $assigneeContacts = CRM_Activity_BAO_Contact::retrieveContactIdsByActivityId($activity->id, $assigneeID);
+          $assigneeContacts = CRM_Activity_BAO_ActivityContact::retrieveContactIdsByActivityId($activity->id, $assigneeID);
           foreach ($assigneeContacts as $cnt => $contactId) {
             if (!CRM_Contact_BAO_Contact_Permission::allow($contactId, $permission)) {
               $allow = FALSE;
@@ -2595,5 +2602,18 @@ INNER JOIN  civicrm_option_group grp ON ( grp.id = val.option_group_id AND grp.n
     return self::getActivityContact($activityId, $sourceID);
   }
 
+  function setApiFilter(&$params) {
+    if (CRM_Utils_Array::value('target_contact_id', $params)) {
+      $this->selectAdd();
+      $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
+      $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
+      $obj = new CRM_Activity_BAO_ActivityContact();
+      $params['return.target_contact_id'] = 1;
+      $this->joinAdd($obj, 'LEFT');
+      $this->selectAdd('civicrm_activity.*');
+      $this->whereAdd(" civicrm_activity_contact.contact_id = {$params['target_contact_id']} AND civicrm_activity_contact.record_type_id = {$targetID}");
+    }
+  }
+
 }