static function formRule($fields)
 {
     $errors = array();
     require_once 'api/api.php';
     $apiRequest = array();
     $apiRequest['entity'] = CRM_Utils_String::munge($fields['api_entity']);
     $apiRequest['action'] = CRM_Utils_String::munge($fields['api_action']);
     $apiRequest['version'] = substr($fields['api_prefix'], -1);
     // ie. civicrm_api3
     $apiRequest += _civicrm_api_resolve($apiRequest);
     // look up function, file, is_generic
     if (!$apiRequest['function']) {
         $errors['api_action'] = ts('Given API command is not defined.');
     }
     // CRM-9868- don't allow Enabled (is_active) for jobs that should never be run automatically via execute action or runjobs url
     if (($fields['api_action'] == 'process_membership_reminder_date' || $fields['api_action'] == 'update_greeting') && CRM_Utils_Array::value('is_active', $fields) == 1) {
         // pass "wiki" as 6th param to docURL2 if you are linking to a page in wiki.civicrm.org
         $docLink = CRM_Utils_System::docURL2("Managing Scheduled Jobs", NULL, NULL, NULL, NULL, "wiki");
         $errors['is_active'] = ts('You can not save this Scheduled Job as Active with the specified api action (%2). That action should not be run regularly - it should only be run manually for special conditions. %1', array(1 => $docLink, 2 => $fields['api_action']));
     }
     if (!empty($errors)) {
         return $errors;
     }
     return empty($errors) ? TRUE : $errors;
 }
Beispiel #2
0
 static function formRule($fields)
 {
     $errors = array();
     require_once 'api/api.php';
     $apiRequest = array();
     $apiRequest['entity'] = CRM_Utils_String::munge($fields['api_entity']);
     $apiRequest['action'] = CRM_Utils_String::munge($fields['api_action']);
     $apiRequest['version'] = 3;
     $apiRequest += _civicrm_api_resolve($apiRequest);
     // look up function, file, is_generic
     if (!$apiRequest['function']) {
         $errors['api_action'] = ts('Given API command is not defined.');
     }
     if (!empty($errors)) {
         return $errors;
     }
     return empty($errors) ? TRUE : $errors;
 }
Beispiel #3
0
/**
 * Get information about fields for a given api request. Getfields information
 * is used for documentation, validation, default setting
 * We first query the scheme using the $dao->fields function & then augment
 * that information by calling the _spec functions that apply to the relevant function
 * Note that we use 'unique' field names as described in the xml/schema files
 * for get requests & just field name for create. This is because some get functions
 * access multiple objects e.g. contact api accesses is_deleted from the activity
 * table & from the contact table
 *
 * @param array $apiRequest api request as an array. Keys are
 *  - entity: string
 *  - action: string
 *  - version: string
 *  - function: callback (mixed)
 *  - params: array, varies
 *  @return array API success object
 */
function civicrm_api3_generic_getfields($apiRequest)
{
    static $results = array();
    if (CRM_Utils_Array::value('cache_clear', $apiRequest['params'])) {
        $results = array();
        // we will also clear pseudoconstants here - should potentially be moved to relevant BAO classes
        CRM_Core_PseudoConstant::flush();
        if (!empty($apiRequest['params']['fieldname'])) {
            CRM_Utils_PseudoConstant::flushConstant($apiRequest['params']['fieldname']);
        }
        if (!empty($apiRequest['params']['option_group_id'])) {
            $optionGroupName = civicrm_api('option_group', 'getvalue', array('version' => 3, 'id' => $apiRequest['params']['option_group_id'], 'return' => 'name'));
            if (is_string($optionGroupName)) {
                CRM_Utils_PseudoConstant::flushConstant(_civicrm_api_get_camel_name($optionGroupName));
            }
        }
    }
    $entity = _civicrm_api_get_camel_name($apiRequest['entity']);
    $lcase_entity = _civicrm_api_get_entity_name_from_camel($entity);
    $subentity = CRM_Utils_Array::value('contact_type', $apiRequest['params']);
    $action = strtolower(CRM_Utils_Array::value('action', $apiRequest['params']));
    $sequential = empty($apiRequest['params']) ? 0 : 1;
    $apiOptions = CRM_Utils_Array::value('options', $apiRequest['params'], array());
    if ($action == 'getvalue' || $action == 'getvalue' || $action == 'getcount') {
        $action = 'get';
    }
    if (empty($action)) {
        $action = 'get';
    }
    // determines whether to use unique field names - seem comment block above
    $unique = TRUE;
    if (empty($apiOptions) && isset($results[$entity . $subentity]) && isset($action, $results[$entity . $subentity]) && isset($action, $results[$entity . $subentity][$sequential])) {
        return $results[$entity . $subentity][$action][$sequential];
    }
    // defaults based on data model and API policy
    switch ($action) {
        case 'getfields':
            $values = _civicrm_api_get_fields($entity, false, $apiRequest['params']);
            return civicrm_api3_create_success($values, $apiRequest['params'], $entity, 'getfields');
        case 'create':
        case 'update':
        case 'replace':
            $unique = FALSE;
        case 'get':
            $metadata = _civicrm_api_get_fields($apiRequest['entity'], $unique, $apiRequest['params']);
            if (empty($metadata['id'])) {
                // if id is not set we will set it eg. 'id' from 'case_id', case_id will be an alias
                if (!empty($metadata[strtolower($apiRequest['entity']) . '_id'])) {
                    $metadata['id'] = $metadata[$lcase_entity . '_id'];
                    unset($metadata[$lcase_entity . '_id']);
                    $metadata['id']['api.aliases'] = array($lcase_entity . '_id');
                }
            } else {
                // really the preference would be to set the unique name in the xml
                // question is which is a less risky fix this close to a release - setting in xml for the known failure
                // (note) or setting for all api where fields is returning 'id' & we want to accept 'note_id' @ the api layer
                // nb we don't officially accept note_id anyway - rationale here is more about centralising a now-tested
                // inconsistency
                $metadata['id']['api.aliases'] = array($lcase_entity . '_id');
            }
            break;
        case 'delete':
            $metadata = array('id' => array('title' => 'Unique Identifier', 'api.required' => 1, 'api.aliases' => array($lcase_entity . '_id'), 'type' => CRM_Utils_Type::T_INT));
            break;
        case 'getoptions':
            $metadata = array('field' => array('title' => 'Field to retrieve options for', 'api.required' => 1), 'context' => array('title' => 'Context string'));
            break;
        default:
            // oddballs are on their own
            $metadata = array();
    }
    // find any supplemental information
    $hypApiRequest = array('entity' => $apiRequest['entity'], 'action' => $action, 'version' => $apiRequest['version']);
    $hypApiRequest += _civicrm_api_resolve($hypApiRequest);
    $helper = '_' . $hypApiRequest['function'] . '_spec';
    if (function_exists($helper)) {
        // alter
        $helper($metadata, $apiRequest);
    }
    $fieldsToResolve = (array) CRM_Utils_Array::value('get_options', $apiOptions, array());
    foreach ($metadata as $fieldname => $fieldSpec) {
        _civicrm_api3_generic_get_metadata_options($metadata, $apiRequest['entity'], $fieldname, $fieldSpec, $fieldsToResolve);
    }
    $results[$entity][$action][$sequential] = civicrm_api3_create_success($metadata, $apiRequest['params'], NULL, 'getfields');
    return $results[$entity][$action][$sequential];
}
Beispiel #4
0
/**
 * @param string $entity
 *   type of entities to deal with
 * @param string $action
 *   create, get, delete or some special action name.
 * @param array $params
 *   array to be passed to function
 * @param null $extra
 *
 * @return array|int
 */
function civicrm_api($entity, $action, $params, $extra = NULL)
{
    $apiRequest = array();
    $apiRequest['entity'] = CRM_Utils_String::munge($entity);
    $apiRequest['action'] = CRM_Utils_String::munge($action);
    $apiRequest['version'] = civicrm_get_api_version($params);
    $apiRequest['params'] = $params;
    $apiRequest['extra'] = $extra;
    $apiWrappers = array(CRM_Utils_API_HTMLInputCoder::singleton(), CRM_Utils_API_NullOutputCoder::singleton(), CRM_Utils_API_ReloadOption::singleton(), CRM_Utils_API_MatchOption::singleton());
    CRM_Utils_Hook::apiWrappers($apiWrappers, $apiRequest);
    try {
        require_once 'api/v3/utils.php';
        require_once 'api/Exception.php';
        if (!is_array($params)) {
            throw new API_Exception('Input variable `params` is not an array', 2000);
        }
        _civicrm_api3_initialize();
        $errorScope = CRM_Core_TemporaryErrorScope::useException();
        // look up function, file, is_generic
        $apiRequest += _civicrm_api_resolve($apiRequest);
        if (strtolower($action) == 'create' || strtolower($action) == 'delete' || strtolower($action) == 'submit') {
            $apiRequest['is_transactional'] = 1;
            $transaction = new CRM_Core_Transaction();
        }
        // support multi-lingual requests
        if ($language = CRM_Utils_Array::value('option.language', $params)) {
            _civicrm_api_set_locale($language);
        }
        _civicrm_api3_api_check_permission($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']);
        $fields = _civicrm_api3_api_getfields($apiRequest);
        // we do this before we
        _civicrm_api3_swap_out_aliases($apiRequest, $fields);
        if (strtolower($action) != 'getfields') {
            if (empty($apiRequest['params']['id'])) {
                $apiRequest['params'] = array_merge(_civicrm_api3_getdefaults($apiRequest, $fields), $apiRequest['params']);
            }
            //if 'id' is set then only 'version' will be checked but should still be checked for consistency
            civicrm_api3_verify_mandatory($apiRequest['params'], NULL, _civicrm_api3_getrequired($apiRequest, $fields));
        }
        // For input filtering, process $apiWrappers in forward order
        foreach ($apiWrappers as $apiWrapper) {
            $apiRequest = $apiWrapper->fromApiInput($apiRequest);
        }
        $function = $apiRequest['function'];
        if ($apiRequest['function'] && $apiRequest['is_generic']) {
            // Unlike normal API implementations, generic implementations require explicit
            // knowledge of the entity and action (as well as $params). Bundle up these bits
            // into a convenient data structure.
            $result = $function($apiRequest);
        } elseif ($apiRequest['function'] && !$apiRequest['is_generic']) {
            _civicrm_api3_validate_fields($apiRequest['entity'], $apiRequest['action'], $apiRequest['params'], $fields);
            $result = isset($extra) ? $function($apiRequest['params'], $extra) : $function($apiRequest['params']);
        } else {
            return civicrm_api3_create_error("API (" . $apiRequest['entity'] . ", " . $apiRequest['action'] . ") does not exist (join the API team and implement it!)");
        }
        // For output filtering, process $apiWrappers in reverse order
        foreach (array_reverse($apiWrappers) as $apiWrapper) {
            $result = $apiWrapper->toApiOutput($apiRequest, $result);
        }
        if (CRM_Utils_Array::value('format.is_success', $apiRequest['params']) == 1) {
            if ($result['is_error'] === 0) {
                return 1;
            } else {
                return 0;
            }
        }
        if (!empty($apiRequest['params']['format.only_id']) && isset($result['id'])) {
            return $result['id'];
        }
        if (CRM_Utils_Array::value('is_error', $result, 0) == 0) {
            _civicrm_api_call_nested_api($apiRequest['params'], $result, $apiRequest['action'], $apiRequest['entity'], $apiRequest['version']);
        }
        if (function_exists('xdebug_time_index') && CRM_Utils_Array::value('debug', $apiRequest['params']) && is_array($result)) {
            $result['xdebug']['peakMemory'] = xdebug_peak_memory_usage();
            $result['xdebug']['memory'] = xdebug_memory_usage();
            $result['xdebug']['timeIndex'] = xdebug_time_index();
        }
        return $result;
    } catch (PEAR_Exception $e) {
        if (CRM_Utils_Array::value('format.is_success', $apiRequest['params']) == 1) {
            return 0;
        }
        $error = $e->getCause();
        if ($error instanceof DB_Error) {
            $data["error_code"] = DB::errorMessage($error->getCode());
            $data["sql"] = $error->getDebugInfo();
        }
        if (!empty($apiRequest['params']['debug'])) {
            if (method_exists($e, 'getUserInfo')) {
                $data['debug_info'] = $error->getUserInfo();
            }
            if (method_exists($e, 'getExtraData')) {
                $data['debug_info'] = $data + $error->getExtraData();
            }
            $data['trace'] = $e->getTraceAsString();
        } else {
            $data['tip'] = "add debug=1 to your API call to have more info about the error";
        }
        $err = civicrm_api3_create_error($e->getMessage(), $data, $apiRequest);
        if (!empty($apiRequest['is_transactional'])) {
            $transaction->rollback();
        }
        return $err;
    } catch (API_Exception $e) {
        if (!isset($apiRequest)) {
            $apiRequest = array();
        }
        if (CRM_Utils_Array::value('format.is_success', CRM_Utils_Array::value('params', $apiRequest)) == 1) {
            return 0;
        }
        $data = $e->getExtraParams();
        $data['entity'] = CRM_Utils_Array::value('entity', $apiRequest);
        $data['action'] = CRM_Utils_Array::value('action', $apiRequest);
        $err = civicrm_api3_create_error($e->getMessage(), $data, $apiRequest, $e->getCode());
        if (CRM_Utils_Array::value('debug', CRM_Utils_Array::value('params', $apiRequest)) && empty($data['trace'])) {
            $err['trace'] = $e->getTraceAsString();
        }
        if (!empty($apiRequest['is_transactional'])) {
            $transaction->rollback();
        }
        return $err;
    } catch (Exception $e) {
        if (CRM_Utils_Array::value('format.is_success', $apiRequest['params']) == 1) {
            return 0;
        }
        $data = array();
        $err = civicrm_api3_create_error($e->getMessage(), $data, $apiRequest, $e->getCode());
        if (!empty($apiRequest['params']['debug'])) {
            $err['trace'] = $e->getTraceAsString();
        }
        if (!empty($apiRequest['is_transactional'])) {
            $transaction->rollback();
        }
        return $err;
    }
}
/**
 * Get information about fields for a given api request. Getfields information
 * is used for documentation, validation, default setting
 * We first query the scheme using the $dao->fields function & then augment
 * that information by calling the _spec functions that apply to the relevant function
 * Note that we use 'unique' field names as described in the xml/schema files
 * for get requests & just field name for create. This is because some get functions
 * access multiple objects e.g. contact api accesses is_deleted from the activity
 * table & from the contact table
 *
 * @param array $apiRequest api request as an array. Keys are
 *  - entity: string
 *  - action: string
 *  - version: string
 *  - function: callback (mixed)
 *  - params: array, varies
 *  @return array API success object
 */
function civicrm_api3_generic_getfields($apiRequest)
{
    static $results = array();
    if (CRM_Utils_Array::value('cache_clear', $apiRequest['params'])) {
        $results = array();
    }
    $entity = _civicrm_api_get_camel_name($apiRequest['entity']);
    $lcase_entity = _civicrm_api_get_entity_name_from_camel($entity);
    $subentity = CRM_Utils_Array::value('contact_type', $apiRequest['params']);
    $action = strtolower(CRM_Utils_Array::value('action', $apiRequest['params']));
    if ($action == 'getvalue' || $action == 'getvalue' || $action == 'getcount') {
        $action = 'get';
    }
    if (empty($action)) {
        if (CRM_Utils_Array::value($entity . $subentity, $results) && CRM_Utils_Array::value('values', $results[$entity . $subentity])) {
            return $results[$entity . $subentity];
        } else {
            $values = _civicrm_api_get_fields($entity);
            $results[$entity] = civicrm_api3_create_success($values, $apiRequest['params'], $entity, 'getfields');
            return $results[$entity];
        }
    }
    // determines whether to use unique field names - seem comment block above
    $unique = TRUE;
    if (isset($results[$entity . $subentity]) && CRM_Utils_Array::value($action, $results[$entity])) {
        return $results[$entity . $subentity][$action];
    }
    // defaults based on data model and API policy
    switch ($action) {
        case 'getfields':
            $values = _civicrm_api_get_fields($entity, $apiRequest['params']);
            $results[$entity][$action] = civicrm_api3_create_success($values, $apiRequest['params'], $entity, 'getfields');
            return $results[$entity][$action];
        case 'create':
        case 'update':
        case 'replace':
            $unique = FALSE;
        case 'get':
            $metadata = _civicrm_api_get_fields($apiRequest['entity'], $unique, $apiRequest['params']);
            if (empty($metadata['id']) && !empty($metadata[$apiRequest['entity'] . '_id'])) {
                $metadata['id'] = $metadata[$lcase_entity . '_id'];
                $metadata['id']['api.aliases'] = array($lcase_entity . '_id');
                unset($metadata[$lcase_entity . '_id']);
            }
            break;
        case 'delete':
            $metadata = array('id' => array('title' => 'Unique Identifier', 'api.required' => 1, 'api.aliases' => array($lcase_entity . '_id')));
            break;
        default:
            // oddballs are on their own
            $metadata = array();
    }
    // find any supplemental information
    $hypApiRequest = array('entity' => $apiRequest['entity'], 'action' => $action, 'version' => $apiRequest['version']);
    $hypApiRequest += _civicrm_api_resolve($hypApiRequest);
    $helper = '_' . $hypApiRequest['function'] . '_spec';
    if (function_exists($helper)) {
        // alter
        $helper($metadata);
    }
    foreach ($metadata as $fieldname => $field) {
        if (array_key_exists('pseudoconstant', $field) && !CRM_Utils_Array::value('FKClassName', $field)) {
            $options = civicrm_api('constant', 'get', array('version' => 3, 'name' => $field['pseudoconstant']));
            if (is_array(CRM_Utils_Array::value('values', $options))) {
                $metadata[$fieldname]['options'] = $options['values'];
            }
        }
        if (array_key_exists('enumValues', $field)) {
            $metadata[$fieldname]['options'] = explode(',', $field['enumValues']);
        }
    }
    $results[$entity][$action] = civicrm_api3_create_success($metadata, $apiRequest['params'], NULL, 'getfields');
    return $results[$entity][$action];
}
function civicrm_api($entity, $action, $params, $extra = NULL)
{
    $apiWrappers = array(CRM_Core_HTMLInputCoder::singleton());
    try {
        require_once 'api/v3/utils.php';
        require_once 'api/Exception.php';
        if (!is_array($params)) {
            throw new API_Exception('Input variable `params` is not an array', 2000);
        }
        _civicrm_api3_initialize();
        $errorScope = CRM_Core_TemporaryErrorScope::useException();
        require_once 'CRM/Utils/String.php';
        require_once 'CRM/Utils/Array.php';
        $apiRequest = array();
        $apiRequest['entity'] = CRM_Utils_String::munge($entity);
        $apiRequest['action'] = CRM_Utils_String::munge($action);
        $apiRequest['version'] = civicrm_get_api_version($params);
        $apiRequest['params'] = $params;
        $apiRequest['extra'] = $extra;
        // look up function, file, is_generic
        $apiRequest += _civicrm_api_resolve($apiRequest);
        if (strtolower($action) == 'create' || strtolower($action) == 'delete') {
            $apiRequest['is_transactional'] = 1;
            $tx = new CRM_Core_Transaction();
        }
        $errorFnName = $apiRequest['version'] == 2 ? 'civicrm_create_error' : 'civicrm_api3_create_error';
        if ($apiRequest['version'] > 2) {
            _civicrm_api3_api_check_permission($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']);
        }
        // we do this before we
        _civicrm_api3_swap_out_aliases($apiRequest);
        if (strtolower($action) != 'getfields') {
            if (!CRM_Utils_Array::value('id', $params)) {
                $apiRequest['params'] = array_merge(_civicrm_api3_getdefaults($apiRequest), $apiRequest['params']);
            }
            //if 'id' is set then only 'version' will be checked but should still be checked for consistency
            civicrm_api3_verify_mandatory($apiRequest['params'], NULL, _civicrm_api3_getrequired($apiRequest));
        }
        foreach ($apiWrappers as $apiWrapper) {
            $apiRequest = $apiWrapper->fromApiInput($apiRequest);
        }
        $function = $apiRequest['function'];
        if ($apiRequest['function'] && $apiRequest['is_generic']) {
            // Unlike normal API implementations, generic implementations require explicit
            // knowledge of the entity and action (as well as $params). Bundle up these bits
            // into a convenient data structure.
            $result = $function($apiRequest);
        } elseif ($apiRequest['function'] && !$apiRequest['is_generic']) {
            _civicrm_api3_validate_fields($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']);
            $result = isset($extra) ? $function($apiRequest['params'], $extra) : $function($apiRequest['params']);
        } else {
            return $errorFnName("API (" . $apiRequest['entity'] . "," . $apiRequest['action'] . ") does not exist (join the API team and implement it!)");
        }
        foreach ($apiWrappers as $apiWrapper) {
            $result = $apiWrapper->toApiOutput($apiRequest, $result);
        }
        if (CRM_Utils_Array::value('format.is_success', $apiRequest['params']) == 1) {
            if ($result['is_error'] === 0) {
                return 1;
            } else {
                return 0;
            }
        }
        if (CRM_Utils_Array::value('format.only_id', $apiRequest['params']) && isset($result['id'])) {
            return $result['id'];
        }
        if (CRM_Utils_Array::value('is_error', $result, 0) == 0) {
            _civicrm_api_call_nested_api($apiRequest['params'], $result, $apiRequest['action'], $apiRequest['entity'], $apiRequest['version']);
        }
        if (CRM_Utils_Array::value('format.smarty', $apiRequest['params']) || CRM_Utils_Array::value('format_smarty', $apiRequest['params'])) {
            // return _civicrm_api_parse_result_through_smarty($result,$apiRequest['params']);
        }
        if (function_exists('xdebug_time_index') && CRM_Utils_Array::value('debug', $apiRequest['params']) && is_array($result)) {
            $result['xdebug']['peakMemory'] = xdebug_peak_memory_usage();
            $result['xdebug']['memory'] = xdebug_memory_usage();
            $result['xdebug']['timeIndex'] = xdebug_time_index();
        }
        return $result;
    } catch (PEAR_Exception $e) {
        if (CRM_Utils_Array::value('format.is_success', $apiRequest['params']) == 1) {
            return 0;
        }
        $data = array();
        $err = civicrm_api3_create_error($e->getMessage(), $data, $apiRequest);
        if (CRM_Utils_Array::value('debug', $apiRequest['params'])) {
            $err['trace'] = $e->getTraceSafe();
        } else {
            $err['tip'] = "add debug=1 to your API call to have more info about the error";
        }
        if (CRM_Utils_Array::value('is_transactional', $apiRequest)) {
            $tx->rollback();
        }
        return $err;
    } catch (API_Exception $e) {
        if (!isset($apiRequest)) {
            $apiRequest = array();
        }
        if (CRM_Utils_Array::value('format.is_success', CRM_Utils_Array::value('params', $apiRequest)) == 1) {
            return 0;
        }
        $data = $e->getExtraParams();
        $err = civicrm_api3_create_error($e->getMessage(), $data, $apiRequest, $e->getCode());
        if (CRM_Utils_Array::value('debug', CRM_Utils_Array::value('params', $apiRequest))) {
            $err['trace'] = $e->getTraceAsString();
        }
        if (CRM_Utils_Array::value('is_transactional', CRM_Utils_Array::value('params', $apiRequest))) {
            $tx->rollback();
        }
        return $err;
    } catch (Exception $e) {
        if (CRM_Utils_Array::value('format.is_success', $apiRequest['params']) == 1) {
            return 0;
        }
        $data = array();
        $err = civicrm_api3_create_error($e->getMessage(), $data, $apiRequest, $e->getCode());
        if (CRM_Utils_Array::value('debug', $apiRequest['params'])) {
            $err['trace'] = $e->getTraceAsString();
        }
        if (CRM_Utils_Array::value('is_transactional', $apiRequest)) {
            $tx->rollback();
        }
        return $err;
    }
}