'case_id',
'campaign_id',
];
+ // Q. What does the code below achieve? case_id and campaign_id are already
+ // in the array, defined above, and this code adds them in again if their
+ // component is enabled? @fixme remove case_id and campaign_id from the array above?
foreach (['case_id' => 'CiviCase', 'campaign_id' => 'CiviCampaign'] as $attr => $component) {
if (in_array($component, self::activityComponents())) {
$activityParams['return'][] = $attr;
// Eventually this second iteration should just handle the target contacts. It's a bit muddled at
// the moment as the bulk activity stuff needs unravelling & test coverage.
+ $caseIds = [];
foreach ($result as $id => $activity) {
$isBulkActivity = (!$bulkActivityTypeID || ($bulkActivityTypeID === $activity['activity_type_id']));
foreach ($mappingParams as $apiKey => $expectedName) {
// fetch case subject for case ID found
if (!empty($activity['case_id'])) {
- $activities[$id]['case_subject'] = civicrm_api3('Case', 'getvalue', [
- 'return' => 'subject',
- 'id' => reset($activity['case_id']),
- ]);
+ // Store cases; we'll look them up in one query below. We convert
+ // to int here so we can trust it for SQL.
+ $caseIds[$id] = (int) current($activity['case_id']);
}
}
else {
$activities[$id]['is_recurring_activity'] = CRM_Core_BAO_RecurringEntity::getParentFor($id, 'civicrm_activity');
}
+ // Look up any case subjects we need in a single query and add them in the relevant activities under 'case_subject'
+ if ($caseIds) {
+ $subjects = CRM_Core_DAO::executeQuery('SELECT id, subject FROM civicrm_case WHERE id IN (' . implode(',', array_unique($caseIds)) . ')')
+ ->fetchMap('id', 'subject');
+ foreach ($caseIds as $activityId => $caseId) {
+ $result[$activityId]['case_subject'] = $subjects[$caseId];
+ }
+ }
+
return $activities;
}
// Format params and add links.
$contactActivities = [];
+ // View-only activity types
+ $viewOnlyCaseActivityTypeIDs = array_flip(CRM_Activity_BAO_Activity::getViewOnlyActivityTypeIDs());
+
if (!empty($activities)) {
$activityStatus = CRM_Core_PseudoConstant::activityStatus();
}
$mask = CRM_Core_Action::mask($permissions);
+ $userID = CRM_Core_Session::getLoggedInContactID();
foreach ($activities as $activityId => $values) {
$activity = ['source_contact_name' => '', 'target_contact_name' => ''];
$accessMailingReport = TRUE;
}
- $actionLinks = CRM_Activity_Selector_Activity::actionLinks(
- CRM_Utils_Array::value('activity_type_id', $values),
- CRM_Utils_Array::value('source_record_id', $values),
- $accessMailingReport,
- CRM_Utils_Array::value('activity_id', $values)
- );
+ // Get action links.
+
+ // If this is a case activity, then we hand off to Case's actionLinks instead.
+ if (!empty($values['case_id']) && Civi::settings()->get('civicaseShowCaseActivities')) {
+ // This activity belongs to a case.
+ $caseId = current($values['case_id']);
+
+ $activity['subject'] = $values['subject'];
+
+ // Get the view and edit (update) links:
+ $caseActionLinks =
+ $actionLinks = array_intersect_key(
+ CRM_Case_Selector_Search::actionLinks(),
+ array_fill_keys([CRM_Core_Action::VIEW, CRM_Core_Action::UPDATE], NULL));
+
+ // Create a Manage Case link (using ADVANCED as can't use two VIEW ones)
+ $actionLinks[CRM_Core_Action::ADVANCED] = [
+ "name" => 'Manage Case',
+ "url" => 'civicrm/contact/view/case',
+ 'qs' => 'reset=1&id=%%caseid%%&cid=%%cid%%&action=view&context=&selectedChild=case',
+ "title" => ts('Manage Case %1', [1 => $caseId]),
+ 'class' => 'no-popup',
+ ];
+
+ $caseLinkValues = [
+ 'aid' => $activityId,
+ 'caseid' => $caseId,
+ 'cid' => current(CRM_Case_BAO_Case::getCaseClients($caseId) ?? []),
+ // Unlike other 'context' params, this 'ctx' param is appended raw to the URL.
+ 'cxt' => '',
+ ];
+
+ $caseActivityPermissions = CRM_Core_Action::VIEW | CRM_Core_Action::ADVANCED;
+ // Allow Edit link if:
+ // 1. Activity type is NOT view-only type. CRM-5871
+ // 2. User has edit permission.
+ if (!isset($viewOnlyCaseActivityTypeIDs[$values['activity_type_id']])
+ && CRM_Case_BAO_Case::checkPermission($activityId, 'edit', $values['activity_type_id'], $userID)) {
+ // We're allowed to edit.
+ $caseActivityPermissions |= CRM_Core_Action::UPDATE;
+ }
- $actionMask = array_sum(array_keys($actionLinks)) & $mask;
-
- $activity['links'] = CRM_Core_Action::formLink($actionLinks,
- $actionMask,
- [
- 'id' => $values['activity_id'],
- 'cid' => $params['contact_id'],
- 'cxt' => $context,
- 'caseid' => CRM_Utils_Array::value('case_id', $values),
- ],
- ts('more'),
- FALSE,
- 'activity.tab.row',
- 'Activity',
- $values['activity_id']
- );
+ $activity['links'] = CRM_Core_Action::formLink($actionLinks,
+ $caseActivityPermissions,
+ $caseLinkValues,
+ ts('more'),
+ FALSE,
+ 'activity.tab.row',
+ 'Activity',
+ $values['activity_id']
+ );
+ }
+ else {
+ // Non-case activity
+ $actionLinks = CRM_Activity_Selector_Activity::actionLinks(
+ CRM_Utils_Array::value('activity_type_id', $values),
+ CRM_Utils_Array::value('source_record_id', $values),
+ $accessMailingReport,
+ CRM_Utils_Array::value('activity_id', $values)
+ );
+ $actionMask = array_sum(array_keys($actionLinks)) & $mask;
+
+ $activity['links'] = CRM_Core_Action::formLink($actionLinks,
+ $actionMask,
+ [
+ 'id' => $values['activity_id'],
+ 'cid' => $params['contact_id'],
+ 'cxt' => $context,
+ 'caseid' => NULL,
+ ],
+ ts('more'),
+ FALSE,
+ 'activity.tab.row',
+ 'Activity',
+ $values['activity_id']
+ );
+ }
if ($values['is_recurring_activity']) {
$activity['is_recurring_activity'] = CRM_Core_BAO_RecurringEntity::getPositionAndCount($values['activity_id'], 'civicrm_activity');
/**
* Test getActivities BAO method for getting count.
+ *
*/
public function testGetActivitiesCountForAdminDashboard() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->setUpForActivityDashboardTests();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
+
$activityCount = CRM_Activity_BAO_Activity::getActivitiesCount($this->_params);
$this->assertEquals(8, $activityCount);
+
+ // If we're showing case activities, we exepct to see one more (the scheduled meeting)...
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activityCount = CRM_Activity_BAO_Activity::getActivitiesCount($this->_params);
+ $this->assertEquals(9, $activityCount);
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method for getting count
+ *
*/
public function testGetActivitiesCountforNonAdminDashboard() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$params = [
'contact_id' => 9,
];
//since we are loading activities from dataset, we know total number of activities for this contact
- // 5 activities ( 2 scheduled, 3 Completed ), note that dashboard shows only scheduled activities
+ // 5 activities ( 2 scheduled, 3 Completed, 1 Scheduled Case activity ),
+ // note that dashboard shows only scheduled activities
$this->assertEquals(2, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+
+ // If we're showing case activities, we exepct to see one more (the scheduled meeting)...
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $this->assertEquals(3, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method for getting count
+ *
*/
public function testGetActivitiesCountforContactSummary() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$params = [
'contact_id' => 9,
];
//since we are loading activities from dataset, we know total number of activities for this contact
- // 5 activities, Contact Summary should show all activities
+ // 5 activities
$this->assertEquals(5, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+
+ // If we're showing case activities, we exepct to see one more (the scheduled meeting)...
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $this->assertEquals(6, CRM_Activity_BAO_Activity::getActivitiesCount($params));
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesForAdminDashboard() {
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->setUpForActivityDashboardTests();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
+
$activitiesNew = CRM_Activity_BAO_Activity::getActivities($this->_params);
// $this->assertEquals($activities, $activitiesDeprecatedFn);
$this->assertEquals($value['status_id'], 1, 'Verify all activities are scheduled.');
}
}
+
+ // Now check that we get the scheduled meeting, if civicaseShowCaseActivities is set.
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activitiesNew = CRM_Activity_BAO_Activity::getActivities($this->_params);
+ $this->assertEquals(9, count($activitiesNew));
+ // Scan through to find the meeting.
+ $this->assertTrue(in_array('test meeting activity', array_column($activitiesNew, 'subject')),
+ "failed to find scheduled case Meeting activity");
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesforNonAdminDashboard() {
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$contactID = 9;
$params = [
}
}
}
+
+ // Now check that we get the scheduled meeting, if civicaseShowCaseActivities is set.
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activities = CRM_Activity_BAO_Activity::getActivities($params);
+ $this->assertEquals(3, count($activities));
+ // Scan through to find the meeting.
+ $this->assertTrue(in_array('test meeting activity', array_column($activities, 'subject')),
+ "failed to find scheduled case Meeting activity");
+
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesForContactSummary() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
+ $this->addCaseWithActivity();
+ CRM_Core_Config::singleton()->userPermissionClass->permissions[] = 'access all cases and activities';
$contactID = 9;
$params = [
$this->assertArrayHasKey($contactID, $value['assignee_contact_name']);
}
}
+
+ // Now check that we get the scheduled meeting, if civicaseShowCaseActivities is set.
+ $this->setShowCaseActivitiesInCore(TRUE);
+ $activities = CRM_Activity_BAO_Activity::getActivities($params);
+ $this->assertEquals(6, count($activities));
+ // Scan through to find the meeting.
+ $this->assertTrue(in_array('test meeting activity', array_column($activities, 'subject')),
+ "failed to find scheduled case Meeting activity");
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
}
/**
* Test getActivities BAO method.
*/
public function testGetActivitiesforContactSummaryWithActivities() {
+ // Reset to default
+ $this->setShowCaseActivitiesInCore(FALSE);
$this->createTestActivities();
// parameters for different test cases, check each array key for the specific test-case
$mut->stop();
}
+ /**
+ * Adds a case with one activity.
+ *
+ */
+ protected function addCaseWithActivity() {
+ // case is not enabled by default do that now.
+ $enableResult = CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
+ $this->assertTrue($enableResult, 'Cannot enable CiviCase in line ' . __LINE__);
+
+ // We need a minimal case setup.
+ $case_type_id = civicrm_api3('CaseType', 'get', ['return' => 'id', 'name' => 'test_case_type'])['id'] ?? NULL;
+ if (!$case_type_id) {
+ $params = [
+ 'name' => 'test_case_type',
+ 'title' => 'test_case_type',
+ "is_active" => "1",
+ "definition" => [
+ "activityTypes" => [
+ ["name" => "Open Case", "max_instances" => "1"],
+ ["name" => "Meeting"],
+ ],
+ "activitySets" => [
+ [
+ "name" => "standard_timeline",
+ "label" => "Standard Timeline",
+ "timeline" => "1",
+ "activityTypes" => [
+ [
+ "name" => "Open Case",
+ "status" => "Completed",
+ "label" => "Open Case",
+ "default_assignee_type" => "1",
+ ],
+ ],
+ ],
+ ],
+ "timelineActivityTypes" => [
+ [
+ "name" => "Open Case",
+ "status" => "Completed",
+ "label" => "Open Case",
+ "default_assignee_type" => "1",
+ ],
+ ],
+ "caseRoles" => [
+ [
+ "name" => "Case Coordinator",
+ "creator" => "1",
+ "manager" => "1",
+ ],
+ ],
+ ],
+ ];
+ $case_type_id = $this->callAPISuccess('CaseType', 'create', $params)['id'];
+ }
+
+ // Create a case with Contact #3 as the client.
+ $case_id = civicrm_api3('case', 'get', ['subject' => 'test case 1'])['id'] ?? NULL;
+ if (!$case_id) {
+ // Create case
+ $params = [
+ 'subject' => 'test case 1',
+ 'contact_id' => 3,
+ 'status_id' => 'Open',
+ 'case_type_id' => $case_type_id,
+ 'creator_id' => 3,
+ ];
+ $case_id = $this->callAPISuccess('case', 'create', $params)['id'];
+ }
+
+ // Create a scheduled 'Meeting' activity that belongs to this case, but is
+ // assigned to contact #9
+ $activity_id = $this->callAPISuccess('Activity', 'create', [
+ 'activity_type_id' => 'Meeting',
+ 'status_id' => 'Scheduled',
+ 'case_id' => $case_id,
+ 'source_contact_id' => 3,
+ 'assignee_id' => [9],
+ 'subject' => 'test meeting activity',
+ ])['id'] ?? NULL;
+ }
+
+ /**
+ * Change setting, and the cache of it.
+ */
+ protected function setShowCaseActivitiesInCore(bool $val) {
+ Civi::settings()->set('civicaseShowCaseActivities', $val ? 1 : 0);
+ CRM_Core_Component::getEnabledComponents();
+ Civi::$statics['CRM_Core_Component']['info']['CiviCase']->info['showActivitiesInCore'] = $val;
+ }
+
}