Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM-18082 - Allow case API create to work with custom data #10728

Merged
merged 11 commits into from
Aug 14, 2017
5 changes: 4 additions & 1 deletion CRM/Case/BAO/Case.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ public static function enabled() {
public static function add(&$params) {
$caseDAO = new CRM_Case_DAO_Case();
$caseDAO->copyValues($params);
return $caseDAO->save();
$result = $caseDAO->save();
$caseDAO->find(TRUE); // Get other case values (required by XML processor), this adds to $result array
return $result;
}

/**
Expand Down Expand Up @@ -271,6 +273,7 @@ public static function retrieveContactIdsByCaseId($caseId, $contactID = NULL) {
$caseContact->case_id = $caseId;
$caseContact->find();
$contactArray = array();
// FIXME: Why does this return a 1-based array?
$count = 1;
while ($caseContact->fetch()) {
if ($contactID != $caseContact->contact_id) {
Expand Down
144 changes: 101 additions & 43 deletions api/v3/Case.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@
* @param array $params
*
* @code
* //REQUIRED:
* //REQUIRED for create:
* 'case_type_id' => int OR
* 'case_type' => str (provide one or the other)
* 'contact_id' => int // case client
* 'subject' => str
* //REQUIRED for update:
* 'id' => case Id
*
* //OPTIONAL
* 'medium_id' => int // see civicrm option values for possibilities
Expand All @@ -60,58 +62,110 @@
* api result array
*/
function civicrm_api3_case_create($params) {
_civicrm_api3_case_format_params($params);

if (!empty($params['id'])) {
return civicrm_api3_case_update($params);
if (empty($params['id'])) {
// Creating a new case, so make sure we have the necessary parameters
civicrm_api3_verify_mandatory($params, NULL, array(
'contact_id',
'subject',
array('case_type', 'case_type_id'),
)
);
}
else {
// Update an existing case
// FIXME: Some of this logic should move to the BAO object?
// FIXME: Should we check if case with ID actually exists?
if (!isset($params['case_id']) && isset($params['id'])) {
$params['case_id'] = $params['id'];
}

civicrm_api3_verify_mandatory($params, NULL, array(
'contact_id',
'subject',
array('case_type', 'case_type_id'))
);
_civicrm_api3_case_format_params($params);
if (array_key_exists('creator_id', $params)) {
throw new API_Exception('You cannot update creator id');
}

// If format_params didn't find what it was looking for, return error
if (empty($params['case_type_id'])) {
throw new API_Exception('Invalid case_type. No such case type exists.');
}
if (empty($params['case_type'])) {
throw new API_Exception('Invalid case_type_id. No such case type exists.');
}
$mergedCaseId = $origContactIds = array();

// Fixme: can we safely pass raw params to the BAO?
$newParams = array(
'case_type_id' => $params['case_type_id'],
'creator_id' => $params['creator_id'],
'status_id' => $params['status_id'],
'start_date' => $params['start_date'],
'end_date' => CRM_Utils_Array::value('end_date', $params),
'subject' => $params['subject'],
);
// get original contact id and creator id of case
if (!empty($params['contact_id'])) {
$origContactIds = CRM_Case_BAO_Case::retrieveContactIdsByCaseId($params['id']);
$origContactId = CRM_Utils_Array::first($origContactIds);
}

// FIXME: Refactor as separate method to get contactId
if (count($origContactIds) > 1) {
// check valid orig contact id
if (empty($params['orig_contact_id'])) {
throw new API_Exception('Case is linked with more than one contact id. Provide the required params orig_contact_id to be replaced');
}
if (!empty($params['orig_contact_id']) && !in_array($params['orig_contact_id'], $origContactIds)) {
throw new API_Exception('Invalid case contact id (orig_contact_id)');
}
$origContactId = $params['orig_contact_id'];
}

// check for same contact id for edit Client
if (!empty($params['contact_id']) && !in_array($params['contact_id'], $origContactIds)) {
$mergedCaseId = CRM_Case_BAO_Case::mergeCases($params['contact_id'], $params['case_id'], $origContactId, NULL, TRUE);
}

// If we merged cases then update the merged case
if (!empty($mergedCaseId[0])) {
$params['id'] = $mergedCaseId[0];
}
}

$caseBAO = CRM_Case_BAO_Case::create($newParams);
// Create/update the case
$caseBAO = CRM_Case_BAO_Case::create($params);

if (!$caseBAO) {
throw new API_Exception('Case not created. Please check input params.');
}

foreach ((array) $params['contact_id'] as $cid) {
$contactParams = array('case_id' => $caseBAO->id, 'contact_id' => $cid);
CRM_Case_BAO_CaseContact::create($contactParams);
if (isset($params['contact_id'])) {
foreach ((array) $params['contact_id'] as $cid) {
$contactParams = array('case_id' => $caseBAO->id, 'contact_id' => $cid);
CRM_Case_BAO_CaseContact::create($contactParams);
}
}

if (!isset($params['id'])) {
// As the API was not passed an id we have created a new case.
// Only run the xmlProcessor for new cases to get all configuration for the new case.
_civicrm_api3_case_create_xmlProcessor($params, $caseBAO);
}

// return case
$values = array();
_civicrm_api3_object_to_array($caseBAO, $values[$caseBAO->id]);

return civicrm_api3_create_success($values, $params, 'Case', 'create', $caseBAO);
}

/**
* When creating a new case, run the xmlProcessor to get all necessary params/configuration
* for the new case, as cases use an xml file to store their configuration.
* @param $params
* @param $caseBAO
*/
function _civicrm_api3_case_create_xmlProcessor($params, $caseBAO) {
// Format params for xmlProcessor
if (isset($caseBAO->id)) {
$params['id'] = $caseBAO->id;
}

// Initialize XML processor with $params
$xmlProcessor = new CRM_Case_XMLProcessor_Process();
$xmlProcessorParams = array(
'clientID' => $params['contact_id'],
'creatorID' => $params['creator_id'],
'clientID' => CRM_Utils_Array::value('contact_id', $params),
'creatorID' => CRM_Utils_Array::value('creator_id', $params),
'standardTimeline' => 1,
'activityTypeName' => 'Open Case',
'caseID' => $caseBAO->id,
'subject' => $params['subject'],
'caseID' => CRM_Utils_Array::value('id', $params),
'subject' => CRM_Utils_Array::value('subject', $params),
'location' => CRM_Utils_Array::value('location', $params),
'activity_date_time' => $params['start_date'],
'activity_date_time' => CRM_Utils_Array::value('start_date', $params),
'duration' => CRM_Utils_Array::value('duration', $params),
'medium_id' => CRM_Utils_Array::value('medium_id', $params),
'details' => CRM_Utils_Array::value('details', $params),
Expand All @@ -120,12 +174,6 @@ function civicrm_api3_case_create($params) {

// Do it! :-D
$xmlProcessor->run($params['case_type'], $xmlProcessorParams);

// return case
$values = array();
_civicrm_api3_object_to_array($caseBAO, $values[$caseBAO->id]);

return civicrm_api3_create_success($values, $params, 'Case', 'create', $caseBAO);
}

/**
Expand Down Expand Up @@ -446,7 +494,7 @@ function _civicrm_api3_case_deprecation() {
}

/**
* Update a specified case.
* @deprecated Update a specified case. Use civicrm_api3_case_create() instead.
*
* @param array $params
* //REQUIRED:
Expand Down Expand Up @@ -479,7 +527,7 @@ function civicrm_api3_case_update($params) {
// get original contact id and creator id of case
if (!empty($params['contact_id'])) {
$origContactIds = CRM_Case_BAO_Case::retrieveContactIdsByCaseId($params['id']);
$origContactId = $origContactIds[1];
$origContactId = CRM_Utils_Array::first($origContactIds);
}

if (count($origContactIds) > 1) {
Expand Down Expand Up @@ -645,7 +693,16 @@ function _civicrm_api3_case_read(&$cases, $options) {
* @param array $params
*/
function _civicrm_api3_case_format_params(&$params) {
// figure out case type id from case type and vice-versa
// Format/include custom params
$values = array();
_civicrm_api3_custom_format_params($params, $values, 'Case');
$params = array_merge($params, $values);

if (empty($params['case_type_id']) && empty($params['case_type'])) {
return;
}

// figure out case_type_id from case_type and vice-versa
$caseTypes = CRM_Case_PseudoConstant::caseType('name', FALSE);
if (empty($params['case_type_id'])) {
$params['case_type_id'] = array_search($params['case_type'], $caseTypes);
Expand All @@ -662,6 +719,7 @@ function _civicrm_api3_case_format_params(&$params) {
}
}


/**
* 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,
Expand Down
55 changes: 55 additions & 0 deletions tests/phpunit/api/v3/CaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,24 @@ public function testCaseCreate() {
$this->assertEquals($result['values'][$id]['subject'], $params['subject']);
}

/**
* Test case create with valid parameters and custom data.
*/
public function testCaseCreateCustom() {
$ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
$params = $this->_params;
$params['custom_' . $ids['custom_field_id']] = "custom string";
$result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__);
$result = $this->callAPISuccess($this->_entity, 'get', array(
'return.custom_' . $ids['custom_field_id'] => 1,
'id' => $result['id'],
));
$this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);

$this->customFieldDelete($ids['custom_field_id']);
$this->customGroupDelete($ids['custom_group_id']);
}

/**
* Test update (create with id) function with valid parameters.
*/
Expand All @@ -168,6 +186,43 @@ public function testCaseUpdate() {
$this->assertAPIArrayComparison($result, $case);
}

/**
* Test case update with custom data
*/
public function testCaseUpdateCustom() {
$ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
$params = $this->_params;

// Create a case with custom data
$params['custom_' . $ids['custom_field_id']] = 'custom string';
$result = $this->callAPISuccess($this->_entity, 'create', $params);

$caseId = $result['id'];
$result = $this->callAPISuccess($this->_entity, 'get', array(
'return.custom_' . $ids['custom_field_id'] => 1,
'version' => 3,
'id' => $result['id'],
));
$this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
$fields = $this->callAPISuccess($this->_entity, 'getfields', array('version' => $this->_apiversion));
$this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));

// Update the activity with custom data.
$params = array(
'id' => $caseId,
'custom_' . $ids['custom_field_id'] => 'Updated my test data',
'version' => $this->_apiversion,
);
$result = $this->callAPISuccess($this->_entity, 'create', $params);

$result = $this->callAPISuccess($this->_entity, 'get', array(
'return.custom_' . $ids['custom_field_id'] => 1,
'version' => 3,
'id' => $result['id'],
));
$this->assertEquals("Updated my test data", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
}

/**
* Test delete function with valid parameters.
*/
Expand Down