CRM-14028 - Workaround the number 0 == empty() php bug
[civicrm-core.git] / api / v3 / utils.php
index 36e84b908049ef1351e0822e90be48a1188d283b..f810fcbf42505af0f47c9e5b031f98fe701b0ada 100644 (file)
@@ -116,7 +116,9 @@ function civicrm_api3_verify_mandatory($params, $daoName = NULL, $keys = array(
       }
     }
     else {
-      if (!array_key_exists($key, $params) || empty($params[$key])) {
+      // Disallow empty values except for the number zero.
+      // TODO: create a utility for this since it's needed in many places
+      if (!array_key_exists($key, $params) || (empty($params[$key]) && $params[$key] !== 0 && $params[$key] !== '0')) {
         $unmatched[] = $key;
       }
     }
@@ -307,8 +309,13 @@ function _civicrm_api3_get_DAO($name) {
  */
 function _civicrm_api3_get_BAO($name) {
   $dao = _civicrm_api3_get_DAO($name);
-  $dao = str_replace("DAO", "BAO", $dao);
-  return $dao;
+  if (!$dao) {
+    return NULL;
+  }
+  $bao = str_replace("DAO", "BAO", $dao);
+  $file = strtr($bao, '_', '/') . '.php';
+  // Check if this entity actually has a BAO. Fall back on the DAO if not.
+  return stream_resolve_include_path($file) ? $bao : $dao;
 }
 
 /**
@@ -910,7 +917,7 @@ function _civicrm_api3_check_required_fields($params, $daoName, $return = FALSE)
  * @param $entity string API entity being accessed
  * @param $action string API action being performed
  * @param $params array  params of the API call
- * @param $throw bool    whether to throw exception instead of returning false
+ * @param $throw deprecated bool    whether to throw exception instead of returning false
  *
  * @throws Exception
  * @return bool whether the current API user has the permission to make the call
@@ -929,16 +936,20 @@ function _civicrm_api3_api_check_permission($entity, $action, &$params, $throw =
     return TRUE;
   }
 
-  foreach ($permissions as $perm) {
-    if (!CRM_Core_Permission::check($perm)) {
-      if ($throw) {
-        throw new Exception("API permission check failed for $entity/$action call; missing permission: $perm.");
-      }
-      else {
-        return FALSE;
+  if (!CRM_Core_Permission::check($permissions)) {
+    if ($throw) {
+      if(is_array($permissions)) {
+        $permissions = implode(' and ', $permissions);
       }
+      throw new Exception("API permission check failed for $entity/$action call; insufficient permission: require $permissions");
+    }
+    else {
+      //@todo remove this - this is an internal api function called with $throw set to TRUE. It is only called with false
+      // in tests & that should be tidied up
+      return FALSE;
     }
   }
+
   return TRUE;
 }
 
@@ -996,6 +1007,16 @@ function _civicrm_api3_basic_create($bao_name, &$params, $entity = NULL) {
   if (is_null($bao)) {
     return civicrm_api3_create_error('Entity not created (' . $fct_name . ')');
   }
+  elseif (is_a($bao, 'CRM_Core_Error')) {
+    //some wierd circular thing means the error takes itself as an argument
+    $msg = $bao->getMessages($bao);
+    // the api deals with entities on a one-by-one basis. However, the contribution bao pushes entities
+    // onto the error object - presumably because the contribution import is not handling multiple errors correctly
+    // so we need to reset the error object here to avoid getting concatenated errors
+    //@todo - the mulitple error handling should be moved out of the contribution object to the import / multiple entity processes
+    CRM_Core_Error::singleton()->reset();
+    throw new API_Exception($msg);
+  }
   else {
     $values = array();
     _civicrm_api3_object_to_array($bao, $values[$bao->id]);