From ff9340a442cce1a060bf4739edfec0ea2d67db91 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Tue, 12 Jan 2016 23:04:32 -0500 Subject: [PATCH] CRM-17645 - Add entityRef support for autocompleting Cases --- CRM/Case/BAO/Case.php | 86 ++++--------------- CRM/Case/BAO/CaseContact.php | 107 ++++++++++++++++++++++++ CRM/Case/Form/Activity/OpenCase.php | 4 +- CRM/Case/Page/AJAX.php | 2 +- CRM/Core/DAO/permissions.php | 1 + api/v3/Case.php | 38 +++++++++ api/v3/CaseContact.php | 100 ++++++++++++++++++++++ tests/phpunit/CRM/Case/BAO/CaseTest.php | 2 +- 8 files changed, 264 insertions(+), 76 deletions(-) create mode 100644 CRM/Case/BAO/CaseContact.php create mode 100644 api/v3/CaseContact.php diff --git a/CRM/Case/BAO/Case.php b/CRM/Case/BAO/Case.php index 9e29f77a6b..97fd1764ee 100644 --- a/CRM/Case/BAO/Case.php +++ b/CRM/Case/BAO/Case.php @@ -149,66 +149,6 @@ class CRM_Case_BAO_Case extends CRM_Case_DAO_Case { return $case; } - /** - * Create case contact record. - * - * @param array $params - * case_id, contact_id - * - * @return object - */ - public static function addCaseToContact($params) { - $caseContact = new CRM_Case_DAO_CaseContact(); - $caseContact->case_id = $params['case_id']; - $caseContact->contact_id = $params['contact_id']; - $caseContact->find(TRUE); - $caseContact->save(); - - // add to recently viewed - $caseType = CRM_Case_BAO_Case::getCaseType($caseContact->case_id); - $url = CRM_Utils_System::url('civicrm/contact/view/case', - "action=view&reset=1&id={$caseContact->case_id}&cid={$caseContact->contact_id}&context=home" - ); - - $title = CRM_Contact_BAO_Contact::displayName($caseContact->contact_id) . ' - ' . $caseType; - - $recentOther = array(); - if (CRM_Core_Permission::checkActionPermission('CiviCase', CRM_Core_Action::DELETE)) { - $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/contact/view/case', - "action=delete&reset=1&id={$caseContact->case_id}&cid={$caseContact->contact_id}&context=home" - ); - } - - // add the recently created case - CRM_Utils_Recent::add($title, - $url, - $caseContact->case_id, - 'Case', - $params['contact_id'], - NULL, - $recentOther - ); - - return $caseContact; - } - - /** - * Delete case contact record. - * - * @param int $caseID - */ - public static function deleteCaseContact($caseID) { - $caseContact = new CRM_Case_DAO_CaseContact(); - $caseContact->case_id = $caseID; - $caseContact->delete(); - - // delete the recently created Case - $caseRecent = array( - 'id' => $caseID, - 'type' => 'Case', - ); - CRM_Utils_Recent::del($caseRecent); - } /** * Convert associative array names to values and vice-versa. @@ -3426,28 +3366,30 @@ WHERE id IN (' . implode(',', $copiedActivityIds) . ')'; /** * @inheritDoc */ - public function apiWhereClause($tableAlias) { - $clauses = array(); - // Only case admins can view deleted cases - if (!CRM_Core_Permission::check('administer CiviCase')) { - $clauses[] = "`$tableAlias`.is_deleted = 0"; - } + public function apiWhereClause() { + $clauses = array( + 'id' => array(), + // Only case admins can view deleted cases + 'is_deleted' => CRM_Core_Permission::check('administer CiviCase') ? NULL : "= 0", + ); // Ensure the user has permission to view the case client - $contactClause = CRM_Contact_BAO_Contact_Permission::cacheSubquery('contact_id'); - if ($contactClause !== NULL) { - $clauses[] = "`$tableAlias`.id IN (SELECT case_id FROM civicrm_case_contact WHERE $contactClause)"; + $contactClause = CRM_Contact_BAO_Contact_Permission::cacheSubquery(); + if ($contactClause) { + $contactClause = implode(' AND contact_id ', $contactClause); + $clauses['id'][] = "IN (SELECT case_id FROM civicrm_case_contact WHERE contact_id $contactClause)"; } // The api gatekeeper ensures the user has at least "access all cases and activities" // so if they do not have permission to see all cases we'll assume they can only access their own if (!CRM_Core_Permission::check('access all cases and activities')) { $user = (int) CRM_Core_Session::getLoggedInContactID(); - $clauses[] = "`$tableAlias`.id IN ( + $clauses['id'][] = "IN ( SELECT r.case_id FROM civicrm_relationship r, civicrm_case_contact cc WHERE r.is_active = 1 AND cc.case_id = r.case_id AND ( - (contact_id_a = cc.contact_id AND contact_id_b = $user) OR (contact_id_b = cc.contact_id AND contact_id_a = $user) + (r.contact_id_a = cc.contact_id AND r.contact_id_b = $user) OR (r.contact_id_b = cc.contact_id AND r.contact_id_a = $user) ) )"; } - return $clauses ? implode(' AND ', $clauses) : NULL; + + return $clauses; } } diff --git a/CRM/Case/BAO/CaseContact.php b/CRM/Case/BAO/CaseContact.php new file mode 100644 index 0000000000..4b4bd06c58 --- /dev/null +++ b/CRM/Case/BAO/CaseContact.php @@ -0,0 +1,107 @@ +copyValues($params); + $caseContact->save(); + + // add to recently viewed + $caseType = CRM_Case_BAO_Case::getCaseType($caseContact->case_id); + $url = CRM_Utils_System::url('civicrm/contact/view/case', + "action=view&reset=1&id={$caseContact->case_id}&cid={$caseContact->contact_id}&context=home" + ); + + $title = CRM_Contact_BAO_Contact::displayName($caseContact->contact_id) . ' - ' . $caseType; + + $recentOther = array(); + if (CRM_Core_Permission::checkActionPermission('CiviCase', CRM_Core_Action::DELETE)) { + $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/contact/view/case', + "action=delete&reset=1&id={$caseContact->case_id}&cid={$caseContact->contact_id}&context=home" + ); + } + + // add the recently created case + CRM_Utils_Recent::add($title, + $url, + $caseContact->case_id, + 'Case', + $caseContact->contact_id, + NULL, + $recentOther + ); + + return $caseContact; + } + + /** + * @inheritDoc + */ + public function apiWhereClause() { + // In order to make things easier for downstream developers, we reuse and adapt case acls here. + // This doesn't yield the most straightforward query, but hopefully the sql engine will sort it out. + $clauses = array( + // Case acls already check for contact access so we can just mark contact_id as handled + 'contact_id' => NULL, + 'case_id' => array(), + ); + $caseSubclauses = array(); + $caseBao = new CRM_Case_BAO_Case(); + foreach ($caseBao->apiWhereClause() as $field => $fieldClauses) { + if ($field == 'id') { + $clauses['case_id'] = array_merge($clauses['case_id'], (array) $fieldClauses); + } + else { + $caseSubclauses[] = "$field " . implode(" AND $field ", (array) $fieldClauses); + } + } + if ($caseSubclauses) { + $clauses['case_id'][] = 'IN (SELECT id FROM civicrm_case WHERE ' . implode(' AND ', $caseSubclauses) . ')'; + } + return $clauses; + } + +} diff --git a/CRM/Case/Form/Activity/OpenCase.php b/CRM/Case/Form/Activity/OpenCase.php index 2bb75669ed..b6e32b03ca 100644 --- a/CRM/Case/Form/Activity/OpenCase.php +++ b/CRM/Case/Form/Activity/OpenCase.php @@ -303,7 +303,7 @@ class CRM_Case_Form_Activity_OpenCase { 'case_id' => $params['case_id'], 'contact_id' => $cliId, ); - CRM_Case_BAO_Case::addCaseToContact($contactParams); + CRM_Case_BAO_CaseContact::create($contactParams); } } else { @@ -311,7 +311,7 @@ class CRM_Case_Form_Activity_OpenCase { 'case_id' => $params['case_id'], 'contact_id' => $form->_currentlyViewedContactId, ); - CRM_Case_BAO_Case::addCaseToContact($contactParams); + CRM_Case_BAO_CaseContact::create($contactParams); } // 2. initiate xml processor diff --git a/CRM/Case/Page/AJAX.php b/CRM/Case/Page/AJAX.php index 9dbc11a69e..874c2aa135 100644 --- a/CRM/Case/Page/AJAX.php +++ b/CRM/Case/Page/AJAX.php @@ -167,7 +167,7 @@ class CRM_Case_Page_AJAX { 'contact_id' => $contactId, ); - CRM_Case_BAO_Case::addCaseToContact($params); + CRM_Case_BAO_CaseContact::create($params); // add case relationships CRM_Case_BAO_Case::addCaseRelationships($caseId, $contactId); diff --git a/CRM/Core/DAO/permissions.php b/CRM/Core/DAO/permissions.php index bc2634d0ab..a09cbadbce 100644 --- a/CRM/Core/DAO/permissions.php +++ b/CRM/Core/DAO/permissions.php @@ -183,6 +183,7 @@ function _civicrm_api3_permissions($entity, $action, &$params) { 'access my cases and activities', ), ); + $permissions['case_contact'] = $permissions['case']; // Campaign permissions $permissions['campaign'] = array( diff --git a/api/v3/Case.php b/api/v3/Case.php index cb57f1537a..acc17ee042 100644 --- a/api/v3/Case.php +++ b/api/v3/Case.php @@ -434,3 +434,41 @@ function _civicrm_api3_case_format_params(&$params) { $params['case_type'] = $caseTypes[$params['case_type_id']]; } } + +/** + * It actually works a lot better to use the CaseContact api instead of the Case api + * for entityRef fields so we can perform the necessary joins, + * so we pass off getlist requests to the CaseContact api. + * + * @param array $params + * @return mixed + */ +function civicrm_api3_case_getList($params) { + require_once 'api/v3/Generic/Getlist.php'; + require_once 'api/v3/CaseContact.php'; + $params['id_field'] = 'case_id'; + $params['label_field'] = $params['search_field'] = 'contact_id.sort_name'; + $params['description_field'] = array( + 'case_id', + 'case_id.case_type_id.title', + 'case_id.subject', + 'case_id.status_id', + 'case_id.start_date', + ); + $apiRequest = array( + 'entity' => 'CaseContact', + 'action' => 'getlist', + 'params' => $params, + ); + return civicrm_api3_generic_getList($apiRequest); +} + +/** + * Needed due to the above override + * @param $params + * @param $apiRequest + */ +function _civicrm_api3_case_getlist_spec(&$params, $apiRequest) { + require_once 'api/v3/Generic/Getlist.php'; + _civicrm_api3_generic_getlist_spec($params, $apiRequest); +} diff --git a/api/v3/CaseContact.php b/api/v3/CaseContact.php new file mode 100644 index 0000000000..e24cabb59a --- /dev/null +++ b/api/v3/CaseContact.php @@ -0,0 +1,100 @@ + $row[$request['id_field']], + 'label' => $row[$request['label_field']] . ' - ' . $row['case_id.case_type_id.title'], + ); + $status = CRM_Core_PseudoConstant::getLabel('CRM_Case_BAO_Case', 'status_id', $row['case_id.status_id']); + $date = CRM_Utils_Date::customFormat($row['case_id.start_date']); + $data['description'] = array( + "#{$row['case_id']}: $status " . ts('(opened %1)', array(1 => $date)), + $row['case_id.subject'], + ); + if (!empty($request['image_field'])) { + $data['image'] = isset($row[$request['image_field']]) ? $row[$request['image_field']] : ''; + } + $output[] = $data; + } + } + return $output; +} diff --git a/tests/phpunit/CRM/Case/BAO/CaseTest.php b/tests/phpunit/CRM/Case/BAO/CaseTest.php index a45f2fc5aa..3a2addb01f 100644 --- a/tests/phpunit/CRM/Case/BAO/CaseTest.php +++ b/tests/phpunit/CRM/Case/BAO/CaseTest.php @@ -41,7 +41,7 @@ class CRM_Case_BAO_CaseTest extends CiviUnitTestCase { 'case_id' => 1, 'contact_id' => 17, ); - CRM_Case_BAO_Case::addCaseToContact($params); + CRM_Case_BAO_CaseContact::create($params); $recent = CRM_Utils_Recent::get(); $this->assertEquals('Test Contact - Housing Support', $recent[0]['title']); -- 2.25.1