Skip to content

Commit

Permalink
CRM-20327 - API chaining - replace $value when using operators.
Browse files Browse the repository at this point in the history
  • Loading branch information
colemanw committed Mar 23, 2017
1 parent de42de6 commit 3775586
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 34 deletions.
7 changes: 1 addition & 6 deletions CRM/Case/XMLProcessor/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -437,12 +437,7 @@ public function createActivity($activityTypeXML, &$params) {
$statusName = 'Scheduled';
}

if ($this->_isMultiClient) {
$client = $params['clientID'];
}
else {
$client = array(1 => $params['clientID']);
}
$client = (array) $params['clientID'];

//set order
$orderVal = '';
Expand Down
69 changes: 42 additions & 27 deletions api/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,42 +128,57 @@ function _civicrm_api_get_camel_name($entity) {
* @param string $separator
*/
function _civicrm_api_replace_variables(&$params, &$parentResult, $separator = '.') {

foreach ($params as $field => $value) {

foreach ($params as $field => &$value) {
if (is_string($value) && substr($value, 0, 6) == '$value') {
$valueSubstitute = substr($value, 7);
$value = _civicrm_api_replace_variable($value, $parentResult, $separator);
}
// Handle the operator syntax: array('OP' => $val)
elseif (is_array($value) && is_string(reset($value)) && substr(reset($value), 0, 6) == '$value') {
$key = key($value);
$value[$key] = _civicrm_api_replace_variable($value[$key], $parentResult, $separator);
}
}
}

if (!empty($parentResult[$valueSubstitute])) {
$params[$field] = $parentResult[$valueSubstitute];
}
else {
/**
* Swap out a $value.foo variable with the value from parent api results.
*
* Called by _civicrm_api_replace_variables to do the substitution.
*
* @param string $value
* @param array $parentResult
* @param string $separator
* @return mixed|null
*/
function _civicrm_api_replace_variable($value, $parentResult, $separator) {
$valueSubstitute = substr($value, 7);

$stringParts = explode($separator, $value);
unset($stringParts[0]);
if (!empty($parentResult[$valueSubstitute])) {
return $parentResult[$valueSubstitute];
}
else {
$stringParts = explode($separator, $value);
unset($stringParts[0]);
// CRM-16168 If we have failed to swap it out we should unset it rather than leave the placeholder.
$value = NULL;

$fieldname = array_shift($stringParts);
$fieldname = array_shift($stringParts);

//when our string is an array we will treat it as an array from that . onwards
$count = count($stringParts);
while ($count > 0) {
$fieldname .= "." . array_shift($stringParts);
if (array_key_exists($fieldname, $parentResult) && is_array($parentResult[$fieldname])) {
$arrayLocation = $parentResult[$fieldname];
foreach ($stringParts as $key => $innerValue) {
$arrayLocation = CRM_Utils_Array::value($innerValue, $arrayLocation);
}
$params[$field] = $arrayLocation;
}
$count = count($stringParts);
//when our string is an array we will treat it as an array from that . onwards
$count = count($stringParts);
while ($count > 0) {
$fieldname .= "." . array_shift($stringParts);
if (array_key_exists($fieldname, $parentResult) && is_array($parentResult[$fieldname])) {
$arrayLocation = $parentResult[$fieldname];
foreach ($stringParts as $key => $innerValue) {
$arrayLocation = CRM_Utils_Array::value($innerValue, $arrayLocation);
}
$value = $arrayLocation;
}
// CRM-16168 If we have failed to swap it out we should unset it rather than leave the placeholder.
if (substr($params[$field], 0, 6) == '$value') {
$params[$field] = NULL;
}
$count = count($stringParts);
}
}
return $value;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion api/v3/Case.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ function civicrm_api3_case_get($params) {

if (empty($options['is_count']) && !empty($cases['values'])) {
// For historic reasons we return these by default only when fetching a case by id
if (!empty($params['id']) && empty($options['return'])) {
if (!empty($params['id']) && is_numeric($params['id']) && empty($options['return'])) {
$options['return'] = array(
'contacts' => 1,
'activities' => 1,
Expand Down
50 changes: 50 additions & 0 deletions tests/phpunit/api/v3/CaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -513,4 +513,54 @@ public function testCaseGetTags() {
$this->assertEquals('CaseTag1', $result['tag_id'][$tag1['id']]['tag_id.name']);
}

/**
* Test that a chained api call can use the operator syntax.
*
* E.g. array('IN' => $value.contact_id)
*
* @throws \Exception
*/
public function testCaseGetChainedOp() {
$contact1 = $this->individualCreate(array(), 1);
$contact2 = $this->individualCreate(array(), 2);
$case1 = $this->callAPISuccess('Case', 'create', array(
'contact_id' => $contact1,
'subject' => "Test case 1",
'case_type_id' => $this->caseTypeId,
));
$case2 = $this->callAPISuccess('Case', 'create', array(
'contact_id' => $contact2,
'subject' => "Test case 2",
'case_type_id' => $this->caseTypeId,
));
$case3 = $this->callAPISuccess('Case', 'create', array(
'contact_id' => array($contact1, $contact2),
'subject' => "Test case 3",
'case_type_id' => $this->caseTypeId,
));

// Fetch case 1 and all cases with the same client. Chained get should return case 3.
$result = $this->callAPISuccessGetSingle('Case', array(
'id' => $case1['id'],
'return' => 'contact_id',
'api.Case.get' => array(
'contact_id' => array('IN' => "\$value.contact_id"),
'id' => array('!=' => "\$value.id"),
),
));
$this->assertEquals($case3['id'], $result['api.Case.get']['id']);

// Fetch case 3 and all cases with the same clients. Chained get should return case 1&2.
$result = $this->callAPISuccessGetSingle('Case', array(
'id' => $case3['id'],
'return' => array('contact_id'),
'api.Case.get' => array(
'return' => 'id',
'contact_id' => array('IN' => "\$value.contact_id"),
'id' => array('!=' => "\$value.id"),
),
));
$this->assertEquals(array($case1['id'], $case2['id']), array_keys(CRM_Utils_Array::rekey($result['api.Case.get']['values'], 'id')));
}

}

0 comments on commit 3775586

Please sign in to comment.