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-20327 - API chaining - replace $value when using operators. #10033

Merged
merged 1 commit into from
Mar 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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')));
}

}