Merge pull request #5520 from totten/4.6-cxn
[civicrm-core.git] / Civi / API / Subscriber / ChainSubscriber.php
index 93a2d3454098f9d2af82fc408776a6c2f7b5c402..944dc71fa01cd1f181a080a0c6fcc789f041aa61 100644 (file)
@@ -3,7 +3,7 @@
  +--------------------------------------------------------------------+
  | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2014                                |
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
  +--------------------------------------------------------------------+
  | This file is a part of CiviCRM.                                    |
  |                                                                    |
  | GNU Affero General Public License or the licensing of CiviCRM,     |
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
-*/
+ */
 
 namespace Civi\API\Subscriber;
+
 use Civi\API\Events;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
@@ -68,26 +69,33 @@ class ChainSubscriber implements EventSubscriberInterface {
     $apiRequest = $event->getApiRequest();
     $result = $event->getResponse();
     if (\CRM_Utils_Array::value('is_error', $result, 0) == 0) {
-      $this->callNestedApi($apiRequest['params'], $result, $apiRequest['action'], $apiRequest['entity'], $apiRequest['version']);
+      $this->callNestedApi($event->getApiKernel(), $apiRequest['params'], $result, $apiRequest['action'], $apiRequest['entity'], $apiRequest['version']);
       $event->setResponse($result);
     }
   }
 
   /**
-   * Call any nested api calls
+   * Call any nested api calls.
    *
    * TODO: We don't really need this to be a separate function.
+   * @param \Civi\API\Kernel $apiKernel
+   * @param $params
+   * @param $result
+   * @param $action
+   * @param $entity
+   * @param $version
+   * @throws \Exception
    */
-  protected function callNestedApi(&$params, &$result, $action, $entity, $version) {
-    $entity = _civicrm_api_get_entity_name_from_camel($entity);
+  protected function callNestedApi($apiKernel, &$params, &$result, $action, $entity, $version) {
+    $lowercase_entity = _civicrm_api_get_entity_name_from_camel($entity);
 
     // We don't need to worry about nested api in the getfields/getoptions
     // actions, so just return immediately.
-    if (in_array(strtolower($action), array('getfields', 'getoptions'))) {
+    if (in_array($action, array('getfields', 'getoptions'))) {
       return;
     }
 
-    if (strtolower($action) == 'getsingle') {
+    if ($action == 'getsingle') {
       // I don't understand the protocol here, but we don't want
       // $result to be a recursive array
       // $result['values'][0] = $result;
@@ -113,11 +121,11 @@ class ChainSubscriber implements EventSubscriberInterface {
         $subParams = array(
           'debug' => \CRM_Utils_Array::value('debug', $params),
         );
-        $subEntity = $subAPI[1];
+        $subEntity = _civicrm_api_get_entity_name_from_camel($subAPI[1]);
 
         foreach ($result['values'] as $idIndex => $parentAPIValues) {
 
-          if (strtolower($subEntity) != 'contact') {
+          if ($subEntity != 'contact') {
             //contact spits the dummy at activity_id so what else won't it like?
             //set entity_id & entity table based on the parent's id & entity.
             //e.g for something like note if the parent call is contact
@@ -125,10 +133,27 @@ class ChainSubscriber implements EventSubscriberInterface {
             //from the parent call. in this case 'contact_id' will also be
             //set to the parent's id
             $subParams["entity_id"] = $parentAPIValues['id'];
-            $subParams['entity_table'] = 'civicrm_' . _civicrm_api_get_entity_name_from_camel($entity);
-            $subParams[strtolower($entity) . "_id"] = $parentAPIValues['id'];
+            $subParams['entity_table'] = 'civicrm_' . $lowercase_entity;
+
+            $crm16084 = FALSE;
+            if ($subEntity == 'relationship' && $lowercase_entity == 'contact') {
+              // if a relationship call is chained to a contact call, we need
+              // to check whether contact_id_a or contact_id_b for the
+              // relationship is given. If so, don't add an extra subParam
+              // "contact_id" => parent_id.
+              // See CRM-16084.
+              foreach (array_keys($newparams) as $key) {
+                if (substr($key, 0, 11) == 'contact_id_') {
+                  $crm16084 = TRUE;
+                  break;
+                }
+              }
+            }
+            if (!$crm16084) {
+              $subParams[$lowercase_entity . "_id"] = $parentAPIValues['id'];
+            }
           }
-          if (strtolower($entity) != 'contact' && \CRM_Utils_Array::value(strtolower($subEntity . "_id"), $parentAPIValues)) {
+          if ($entity != 'Contact' && \CRM_Utils_Array::value(strtolower($subEntity . "_id"), $parentAPIValues)) {
             //e.g. if event_id is in the values returned & subentity is event
             //then pass in event_id as 'id' don't do this for contact as it
             //does some wierd things like returning primary email &
@@ -142,7 +167,7 @@ class ChainSubscriber implements EventSubscriberInterface {
           }
           // if we are dealing with the same entity pass 'id' through
           // (useful for get + delete for example)
-          if (strtolower($entity) == strtolower($subEntity)) {
+          if ($lowercase_entity == $subEntity) {
             $subParams['id'] = $result['values'][$idIndex]['id'];
           }
 
@@ -157,8 +182,8 @@ class ChainSubscriber implements EventSubscriberInterface {
             // it is a numerically indexed array - ie. multiple creates
             foreach ($newparams as $entityparams) {
               $subParams = array_merge($genericParams, $entityparams);
-              _civicrm_api_replace_variables($subAPI[1], $subaction, $subParams, $result['values'][$idIndex], $separator);
-              $result['values'][$result['id']][$field][] = civicrm_api($subEntity, $subaction, $subParams);
+              _civicrm_api_replace_variables($subParams, $result['values'][$idIndex], $separator);
+              $result['values'][$result['id']][$field][] = $apiKernel->run($subEntity, $subaction, $subParams);
               if ($result['is_error'] === 1) {
                 throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
               }
@@ -167,8 +192,8 @@ class ChainSubscriber implements EventSubscriberInterface {
           else {
 
             $subParams = array_merge($subParams, $newparams);
-            _civicrm_api_replace_variables($subAPI[1], $subaction, $subParams, $result['values'][$idIndex], $separator);
-            $result['values'][$idIndex][$field] = civicrm_api($subEntity, $subaction, $subParams);
+            _civicrm_api_replace_variables($subParams, $result['values'][$idIndex], $separator);
+            $result['values'][$idIndex][$field] = $apiKernel->run($subEntity, $subaction, $subParams);
             if (!empty($result['is_error'])) {
               throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
             }
@@ -176,7 +201,7 @@ class ChainSubscriber implements EventSubscriberInterface {
         }
       }
     }
-    if (strtolower($action) == 'getsingle') {
+    if ($action == 'getsingle') {
       $result = $result['values'][0];
     }
   }