diff --git a/CRM/Case/Form/CaseView.php b/CRM/Case/Form/CaseView.php index 2123f2f7ee28..75b35d48c8e1 100644 --- a/CRM/Case/Form/CaseView.php +++ b/CRM/Case/Form/CaseView.php @@ -294,7 +294,8 @@ public function buildQuickForm() { $this->buildMergeCaseForm(); //call activity form - self::activityForm($this, $aTypes); + // @todo seems a little odd to call "self" but pass $this in a form function? The only other place this is called from is one place in civihr. + self::activityForm($this); //get case related relationships (Case Role) $caseRelationships = CRM_Case_BAO_Case::getCaseRoles($this->_contactID, $this->_caseID, NULL, FALSE); @@ -468,10 +469,8 @@ public function postProcess() { /** * Build the activity selector/datatable * @param CRM_Core_Form $form - * @param array $aTypes - * To include acivities related to current case id $form->_caseID. */ - public static function activityForm($form, $aTypes = []) { + public static function activityForm($form) { $caseRelationships = CRM_Case_BAO_Case::getCaseRoles($form->_contactID, $form->_caseID); //build reporter select $reporters = ["" => ts(' - any reporter - ')]; @@ -480,16 +479,22 @@ public static function activityForm($form, $aTypes = []) { } $form->add('select', 'reporter_id', ts('Reporter/Role'), $reporters, FALSE, ['id' => 'reporter_id_' . $form->_caseID]); - // take all case activity types for search filter, CRM-7187 + // List all the activity types that have been used on this case $aTypesFilter = []; - $allCaseActTypes = CRM_Case_PseudoConstant::caseActivityType(); - foreach ($allCaseActTypes as $typeDetails) { - if (!in_array($typeDetails['name'], ['Open Case'])) { - $aTypesFilter[$typeDetails['id']] = $typeDetails['label'] ?? NULL; - } + $activity_types_on_case = \Civi\Api4\CaseActivity::get() + ->addWhere('case_id', '=', $form->_caseID) + // we want to include deleted too since the filter can search for deleted + ->addWhere('activity_id.is_deleted', 'IN', [0, 1]) + // technically correct, but this might end up excluding some deleted ones depending on how they got deleted + // ->addWhere('activity_id.is_current_revision', '=', 1) + ->addSelect('activity_id.activity_type_id', 'activity_id.activity_type_id:label') + ->addGroupBy('activity_id.activity_type_id') + // this creates strange SQL - if it is too slow could sort in php instead + ->addOrderBy('activity_id.activity_type_id:label', 'ASC') + ->execute(); + foreach ($activity_types_on_case as $typeDetails) { + $aTypesFilter[$typeDetails['activity_id.activity_type_id']] = $typeDetails['activity_id.activity_type_id:label']; } - $aTypesFilter = $aTypesFilter + $aTypes; - asort($aTypesFilter); $form->add('select', 'activity_type_filter_id', ts('Activity Type'), ['' => ts('- select activity type -')] + $aTypesFilter, FALSE, ['id' => 'activity_type_filter_id_' . $form->_caseID]); $activityStatus = CRM_Core_PseudoConstant::activityStatus(); diff --git a/tests/phpunit/CRM/Case/Form/CaseViewTest.php b/tests/phpunit/CRM/Case/Form/CaseViewTest.php new file mode 100644 index 000000000000..dff194947056 --- /dev/null +++ b/tests/phpunit/CRM/Case/Form/CaseViewTest.php @@ -0,0 +1,85 @@ +individualCreate([], 0, TRUE); + $caseObj = $this->createCase($client_id, $this->_loggedInUser); + + $form = $this->getFormObject('CRM_Case_Form_CaseView'); + $form->set('cid', $client_id); + $form->set('id', $caseObj->id); + $form->buildForm(); + $options = $form->getElement('activity_type_filter_id')->_options; + // We don't care about the first one, just check it's what we expect + $this->assertEquals('- select activity type -', $options[0]['text']); + unset($options[0]); + $mappedOptions = array_map(function($v) { + return [$v['attr']['value'] => $v['text']]; + }, $options); + $this->assertEquals([ + [14 => 'Follow up'], + [60 => 'Income and benefits stabilization'], + [58 => 'Long-term housing plan'], + [55 => 'Medical evaluation'], + [56 => 'Mental health evaluation'], + [13 => 'Open Case'], + [57 => 'Secure temporary housing'], + ], array_values($mappedOptions)); + + // Now add some activities where the type might not even be in the config. + $this->callAPISuccess('Activity', 'create', [ + 'case_id' => $caseObj->id, + 'subject' => 'aaaa', + 'activity_type_id' => 'Inbound Email', + ]); + $this->callAPISuccess('Activity', 'create', [ + 'case_id' => $caseObj->id, + 'subject' => 'bbbb', + 'activity_type_id' => 'Email', + ]); + $this->callAPISuccess('Activity', 'create', [ + 'case_id' => $caseObj->id, + 'subject' => 'cccc', + 'activity_type_id' => 'Meeting', + ]); + + // And let's delete one since we still want it to be available as a filter + $this->callAPISuccess('Activity', 'create', [ + 'case_id' => $caseObj->id, + 'subject' => 'dddd', + 'activity_type_id' => 'Phone Call', + 'is_deleted' => 1, + ]); + + $form = $this->getFormObject('CRM_Case_Form_CaseView'); + $form->set('cid', $client_id); + $form->set('id', $caseObj->id); + $form->buildForm(); + $options = $form->getElement('activity_type_filter_id')->_options; + unset($options[0]); + $mappedOptions = array_map(function($v) { + return [$v['attr']['value'] => $v['text']]; + }, $options); + $this->assertEquals([ + [3 => 'Email'], + [14 => 'Follow up'], + [12 => 'Inbound Email'], + [60 => 'Income and benefits stabilization'], + [58 => 'Long-term housing plan'], + [55 => 'Medical evaluation'], + [1 => 'Meeting'], + [56 => 'Mental health evaluation'], + [13 => 'Open Case'], + [2 => 'Phone Call'], + [57 => 'Secure temporary housing'], + ], array_values($mappedOptions)); + } + +}