Exemplo n.º 1
0
 /**
  * Attempts to retrieve the API entity name from any calling class.
  *
  * @param string|object $classNameOrObject
  *
  * @return string
  * @throws CRM_Core_Exception
  */
 static function getEntityName($classNameOrObject)
 {
     require_once 'api/api.php';
     $className = is_string($classNameOrObject) ? $classNameOrObject : get_class($classNameOrObject);
     // First try the obvious replacements
     $daoName = str_replace(array('_BAO_', '_Form_', '_Page_'), '_DAO_', $className);
     $shortName = CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
     // If that didn't work, try a different pattern
     if (!$shortName) {
         list(, $parent, , $child) = explode('_', $className);
         $daoName = "CRM_{$parent}_DAO_{$child}";
         $shortName = CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
     }
     // If that didn't work, try a different pattern
     if (!$shortName) {
         $daoName = "CRM_{$parent}_DAO_{$parent}";
         $shortName = CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
     }
     // If that didn't work, try a different pattern
     if (!$shortName) {
         $daoName = "CRM_Core_DAO_{$child}";
         $shortName = CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
     }
     if (!$shortName) {
         throw new CRM_Core_Exception('Could not find api name for supplied class');
     }
     return _civicrm_api_get_entity_name_from_camel($shortName);
 }
Exemplo n.º 2
0
/**
 * Generic api wrapper used for quicksearch and autocomplete.
 *
 * @param array $apiRequest
 *
 * @return mixed
 */
function civicrm_api3_generic_getList($apiRequest)
{
    $entity = _civicrm_api_get_entity_name_from_camel($apiRequest['entity']);
    $request = $apiRequest['params'];
    $meta = civicrm_api3_generic_getfields(array('action' => 'get') + $apiRequest, FALSE);
    // Hey api, would you like to provide default values?
    $fnName = "_civicrm_api3_{$entity}_getlist_defaults";
    $defaults = function_exists($fnName) ? $fnName($request) : array();
    _civicrm_api3_generic_getList_defaults($entity, $request, $defaults, $meta['values']);
    // Hey api, would you like to format the search params?
    $fnName = "_civicrm_api3_{$entity}_getlist_params";
    $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_params';
    $fnName($request);
    $request['params']['check_permissions'] = !empty($apiRequest['params']['check_permissions']);
    $result = civicrm_api3($entity, 'get', $request['params']);
    // Hey api, would you like to format the output?
    $fnName = "_civicrm_api3_{$entity}_getlist_output";
    $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_output';
    $values = $fnName($result, $request, $entity, $meta['values']);
    _civicrm_api3_generic_getlist_postprocess($result, $request, $values);
    $output = array('page_num' => $request['page_num']);
    // Limit is set for searching but not fetching by id
    if (!empty($request['params']['options']['limit'])) {
        // If we have an extra result then this is not the last page
        $last = $request['params']['options']['limit'] - 1;
        $output['more_results'] = isset($values[$last]);
        unset($values[$last]);
    }
    return civicrm_api3_create_success($values, $request['params'], $entity, 'getlist', CRM_Core_DAO::$_nullObject, $output);
}
Exemplo n.º 3
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // load Civi to get access to civicrm_api_get_function_name
     $civicrm_api3 = $this->getContainer()->get('civicrm_api3');
     if (!$civicrm_api3 || !$civicrm_api3->local) {
         $output->writeln("<error>Require access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>");
         return;
     }
     $ctx = array();
     $ctx['type'] = 'module';
     $ctx['basedir'] = rtrim(getcwd(), '/');
     $basedir = new Path($ctx['basedir']);
     $info = new Info($basedir->string('info.xml'));
     $info->load($ctx);
     $attrs = $info->get()->attributes();
     if ($attrs['type'] != 'module') {
         $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>');
         return;
     }
     if (!preg_match('/^[A-Za-z0-9]+$/', $input->getArgument('<EntityName>'))) {
         throw new Exception("Entity name must be alphanumeric camel-case");
     }
     $ctx['entityNameCamel'] = ucfirst($input->getArgument('<EntityName>'));
     $ctx['tableName'] = 'civicrm_' . strtolower($input->getArgument('<EntityName>'));
     if (function_exists('civicrm_api_get_function_name')) {
         $ctx['apiFunctionPrefix'] = strtolower(civicrm_api_get_function_name($ctx['entityNameCamel'], '', self::API_VERSION));
     } elseif (function_exists('_civicrm_api_get_entity_name_from_camel')) {
         $ctx['apiFunctionPrefix'] = 'civicrm_api' . self::API_VERSION . '_' . _civicrm_api_get_entity_name_from_camel($ctx['entityNameCamel']) . '_' . $ctx['actionNameCamel'];
     } else {
         throw new Exception("Failed to determine proper API function name. Perhaps the API internals have changed?");
     }
     $ctx['apiFile'] = $basedir->string('api', 'v3', $ctx['entityNameCamel'] . '.php');
     $ctx['daoClassName'] = strtr($ctx['namespace'], '/', '_') . '_DAO_' . $input->getArgument('<EntityName>');
     $ctx['daoClassFile'] = $basedir->string(strtr($ctx['daoClassName'], '_', '/') . '.php');
     $ctx['baoClassName'] = strtr($ctx['namespace'], '/', '_') . '_BAO_' . $input->getArgument('<EntityName>');
     $ctx['baoClassFile'] = $basedir->string(strtr($ctx['baoClassName'], '_', '/') . '.php');
     $ctx['schemaFile'] = $basedir->string('xml', 'schema', $ctx['namespace'], $input->getArgument('<EntityName>') . '.xml');
     $ctx['entityTypeFile'] = $basedir->string('xml', 'schema', $ctx['namespace'], $input->getArgument('<EntityName>') . '.entityType.php');
     $ext = new Collection();
     $ext->builders['dirs'] = new Dirs(array(dirname($ctx['apiFile']), dirname($ctx['daoClassFile']), dirname($ctx['baoClassFile']), dirname($ctx['schemaFile'])));
     $ext->builders['dirs']->save($ctx, $output);
     $ext->builders['api.php'] = new Template('CRMCivixBundle:Code:entity-api.php.php', $ctx['apiFile'], FALSE, $this->getContainer()->get('templating'));
     $ext->builders['bao.php'] = new Template('CRMCivixBundle:Code:entity-bao.php.php', $ctx['baoClassFile'], FALSE, $this->getContainer()->get('templating'));
     $ext->builders['entity.xml'] = new Template('CRMCivixBundle:Code:entity-schema.xml.php', $ctx['schemaFile'], FALSE, $this->getContainer()->get('templating'));
     if (!file_exists($ctx['entityTypeFile'])) {
         $mgdEntities = array(array('name' => $ctx['entityNameCamel'], 'class' => $ctx['daoClassName'], 'table' => $ctx['tableName']));
         $header = "// This file declares a new entity type. For more details, see \"hook_civicrm_entityTypes\" at:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC/Hook+Reference";
         $ext->builders['entityType.php'] = new PhpData($ctx['entityTypeFile'], $header);
         $ext->builders['entityType.php']->set($mgdEntities);
     }
     $ext->init($ctx);
     $ext->save($ctx, $output);
 }
Exemplo n.º 4
0
 /**
  * Flush constant.
  *
  * Wrapper for Pseudoconstant methods. We use this so the calling function
  * doesn't need to know which class the Pseudoconstant is on
  * (some are on the Contribute_Pseudoconsant Class etc
  *
  *
  * @param $constant
  *
  * @return array
  *   array reference of all relevant constant
  */
 public static function flushConstant($constant)
 {
     $class = self::findConstantClass($constant);
     if ($class) {
         $class::flush(lcfirst($constant));
         //@todo the rule is api functions should only be called from within the api - we
         // should move this function to a Core class
         $name = _civicrm_api_get_entity_name_from_camel($constant);
         CRM_Core_OptionGroup::flush($name);
         return TRUE;
     }
 }
Exemplo n.º 5
0
/**
 * Generic api wrapper used for quicksearch and autocomplete
 *
 * @param $apiRequest array
 * @return mixed
 */
function civicrm_api3_generic_getList($apiRequest)
{
    $entity = _civicrm_api_get_entity_name_from_camel($apiRequest['entity']);
    $request = $apiRequest['params'];
    _civicrm_api3_generic_getList_defaults($entity, $request);
    // Hey api, would you like to format the search params?
    $fnName = "_civicrm_api3_{$entity}_getlist_params";
    $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_params';
    $fnName($request);
    $result = civicrm_api3($entity, 'get', $request['params']);
    // Hey api, would you like to format the output?
    $fnName = "_civicrm_api3_{$entity}_getlist_output";
    $fnName = function_exists($fnName) ? $fnName : '_civicrm_api3_generic_getlist_output';
    $values = $fnName($result, $request);
    $output = array('more_results' => isset($values[10]), 'page_num' => $request['page_num']);
    unset($values[10]);
    return civicrm_api3_create_success($values, $request['params'], $entity, 'getlist', CRM_Core_DAO::$_nullObject, $output);
}
Exemplo n.º 6
0
 /**
  * @param int $id
  * @param $values
  * @param int $wildcard
  * @param bool $useEquals
  *
  * @param string $apiEntity
  *
  * @return array|null
  */
 public static function &fixWhereValues($id, &$values, $wildcard = 0, $useEquals = FALSE, $apiEntity = NULL)
 {
     // skip a few search variables
     static $skipWhere = NULL;
     static $likeNames = NULL;
     $result = NULL;
     // Change camelCase EntityName to lowercase with underscores
     $apiEntity = _civicrm_api_get_entity_name_from_camel($apiEntity);
     if (CRM_Utils_System::isNull($values)) {
         return $result;
     }
     if (!$skipWhere) {
         $skipWhere = array('task', 'radio_ts', 'uf_group_id', 'component_mode', 'qfKey', 'operator', 'display_relationship_type');
     }
     if (in_array($id, $skipWhere) || substr($id, 0, 4) == '_qf_' || substr($id, 0, 7) == 'hidden_') {
         return $result;
     }
     if ($apiEntity && substr($id, 0, strlen($apiEntity)) != $apiEntity && (substr($id, 0, 10) != 'financial_' && substr($id, 0, 8) != 'payment_')) {
         $id = $apiEntity . '_' . $id;
     }
     if (!$likeNames) {
         $likeNames = array('sort_name', 'email', 'note', 'display_name');
     }
     // email comes in via advanced search
     // so use wildcard always
     if ($id == 'email') {
         $wildcard = 1;
     }
     if (!$useEquals && in_array($id, $likeNames)) {
         $result = array($id, 'LIKE', $values, 0, 1);
     } elseif (is_string($values) && strpos($values, '%') !== FALSE) {
         $result = array($id, 'LIKE', $values, 0, 0);
     } elseif ($id == 'group') {
         if (is_array($values)) {
             foreach ($values as $groupIds => $val) {
                 $matches = array();
                 if (preg_match('/-(\\d+)$/', $groupIds, $matches)) {
                     if (strlen($matches[1]) > 0) {
                         $values[$matches[1]] = 1;
                         unset($values[$groupIds]);
                     }
                 }
             }
         } else {
             $groupIds = explode(',', $values);
             unset($values);
             foreach ($groupIds as $groupId) {
                 $values[$groupId] = 1;
             }
         }
         $result = array($id, 'IN', $values, 0, 0);
     } elseif ($id == 'contact_tags' || $id == 'tag') {
         if (!is_array($values)) {
             $tagIds = explode(',', $values);
             unset($values);
             foreach ($tagIds as $tagId) {
                 $values[$tagId] = 1;
             }
         }
         $result = array($id, 'IN', $values, 0, 0);
     } elseif ($id == 'contact_type') {
         $result = array($id, 'IN', $values, 0, $wildcard);
     } else {
         $result = array($id, '=', $values, 0, $wildcard);
     }
     return $result;
 }
Exemplo n.º 7
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
 *
 * @param bool $unique
 *   Determines whether to key by unique field names (only affects get-type) actions
 *
 * @return array
 *   API success object
 */
function civicrm_api3_generic_getfields($apiRequest, $unique = TRUE)
{
    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 = $apiRequest['entity'];
    $lowercase_entity = _civicrm_api_get_entity_name_from_camel($entity);
    $subentity = CRM_Utils_Array::value('contact_type', $apiRequest['params']);
    $action = CRM_Utils_Array::value('action', $apiRequest['params']);
    $sequential = empty($apiRequest['params']['sequential']) ? 0 : 1;
    $apiRequest['params']['options'] = CRM_Utils_Array::value('options', $apiRequest['params'], array());
    $optionsToResolve = (array) CRM_Utils_Array::value('get_options', $apiRequest['params']['options'], array());
    if (!$action || $action == 'getvalue' || $action == 'getcount') {
        $action = 'get';
    }
    // If no options, return results from cache
    if (!$apiRequest['params']['options'] && 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':
        case 'getsingle':
        case 'getcount':
        case 'getstat':
            $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[$lowercase_entity . '_id'];
                    unset($metadata[$lowercase_entity . '_id']);
                    $metadata['id']['api.aliases'] = array($lowercase_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($lowercase_entity . '_id');
            }
            break;
        case 'delete':
            $metadata = array('id' => array('title' => $entity . ' ID', 'api.required' => 1, 'api.aliases' => array($lowercase_entity . '_id'), 'type' => CRM_Utils_Type::T_INT));
            break;
            // Note: adding setvalue case here instead of in a generic spec function because
            // some APIs override the generic setvalue fn which causes the generic spec to be overlooked.
        // Note: adding setvalue case here instead of in a generic spec function because
        // some APIs override the generic setvalue fn which causes the generic spec to be overlooked.
        case 'setvalue':
            $metadata = array('field' => array('title' => 'Field name', 'api.required' => 1, 'type' => CRM_Utils_Type::T_STRING), 'id' => array('title' => $entity . ' ID', 'api.required' => 1, 'type' => CRM_Utils_Type::T_INT), 'value' => array('title' => 'Value', 'description' => "Field value to set", 'api.required' => 1));
            if (array_intersect(array('all', 'field'), $optionsToResolve)) {
                $options = civicrm_api3_generic_getfields(array('entity' => $entity, array('params' => array('action' => 'create'))));
                $metadata['field']['options'] = CRM_Utils_Array::collect('title', $options['values']);
            }
            break;
        default:
            // oddballs are on their own
            $metadata = array();
    }
    // Normalize this for the sake of spec funcions
    $apiRequest['params']['options']['get_options'] = $optionsToResolve;
    // find any supplemental information
    $hypApiRequest = array('entity' => $apiRequest['entity'], 'action' => $action, 'version' => $apiRequest['version']);
    try {
        list($apiProvider, $hypApiRequest) = \Civi::service('civi_api_kernel')->resolve($hypApiRequest);
        if (isset($hypApiRequest['function'])) {
            $helper = '_' . $hypApiRequest['function'] . '_spec';
        } else {
            // not implemented MagicFunctionProvider
            $helper = NULL;
        }
    } catch (\Civi\API\Exception\NotImplementedException $e) {
        $helper = NULL;
    }
    if (function_exists($helper)) {
        // alter
        $helper($metadata, $apiRequest);
    }
    foreach ($metadata as $fieldname => $fieldSpec) {
        // Ensure 'name' is set
        if (!isset($fieldSpec['name'])) {
            $metadata[$fieldname]['name'] = $fieldname;
        }
        _civicrm_api3_generic_get_metadata_options($metadata, $apiRequest, $fieldname, $fieldSpec);
        // Convert options to "sequential" format
        if ($sequential && !empty($metadata[$fieldname]['options'])) {
            $metadata[$fieldname]['options'] = CRM_Utils_Array::makeNonAssociative($metadata[$fieldname]['options']);
        }
    }
    $results[$entity][$action][$sequential] = civicrm_api3_create_success($metadata, $apiRequest['params'], $entity, 'getfields');
    return $results[$entity][$action][$sequential];
}
 /**
  * Create two entities and make sure we can fetch them individually by ID (e.g. using "contact_id=>2"
  * or "group_id=>4")
  *
  * @dataProvider entities_get
  *
  * limitations include the problem with avoiding loops when creating test objects -
  * hence FKs only set by createTestObject when required. e.g parent_id on campaign is not being followed through
  * Currency - only seems to support US
  */
 public function testByIDAlias_get($entityName)
 {
     if (in_array($entityName, self::toBeSkipped_automock(TRUE))) {
         // $this->markTestIncomplete("civicrm_api3_{$Entity}_create to be implemented");
         return;
     }
     $baoString = _civicrm_api3_get_DAO($entityName);
     if (empty($baoString)) {
         $this->markTestIncomplete("Entity [{$entityName}] cannot be mocked - no known DAO");
         return;
     }
     $idFieldName = _civicrm_api_get_entity_name_from_camel($entityName) . '_id';
     // create entities
     $baoObj1 = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
     $this->assertTrue(is_integer($baoObj1->id), 'check first id');
     $this->deletableTestObjects[$baoString][] = $baoObj1->id;
     $baoObj2 = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
     $this->assertTrue(is_integer($baoObj2->id), 'check second id');
     $this->deletableTestObjects[$baoString][] = $baoObj2->id;
     // fetch first by ID
     $result = civicrm_api($entityName, 'get', array('version' => 3, $idFieldName => $baoObj1->id));
     $this->assertAPISuccess($result);
     $this->assertTrue(!empty($result['values'][$baoObj1->id]), 'Should find first object by id');
     $this->assertEquals($baoObj1->id, $result['values'][$baoObj1->id]['id'], 'Should find id on first object');
     $this->assertEquals(1, count($result['values']));
     // fetch second by ID
     $result = civicrm_api($entityName, 'get', array('version' => 3, $idFieldName => $baoObj2->id));
     $this->assertAPISuccess($result);
     $this->assertTrue(!empty($result['values'][$baoObj2->id]), 'Should find second object by id');
     $this->assertEquals($baoObj2->id, $result['values'][$baoObj2->id]['id'], 'Should find id on second object');
     $this->assertEquals(1, count($result['values']));
 }
Exemplo n.º 9
0
/**
 * Having a DAO object find the entity name
 * @param object $bao DAO being passed in
 * @return string
 */
function _civicrm_api_get_entity_name_from_dao($bao)
{
    $daoName = str_replace("BAO", "DAO", get_class($bao));
    return _civicrm_api_get_entity_name_from_camel(CRM_Core_DAO_AllCoreTables::getBriefName($daoName));
}
 /**
  * @param int $id
  * @param $values
  * @param int $wildcard
  * @param bool $useEquals
  *
  * @param string $apiEntity
  *
  * @return array|null
  */
 public static function &fixWhereValues($id, &$values, $wildcard = 0, $useEquals = FALSE, $apiEntity = NULL)
 {
     // skip a few search variables
     static $skipWhere = NULL;
     static $likeNames = NULL;
     $result = NULL;
     // Change camelCase EntityName to lowercase with underscores
     $apiEntity = _civicrm_api_get_entity_name_from_camel($apiEntity);
     if (CRM_Utils_System::isNull($values)) {
         return $result;
     }
     if (!$skipWhere) {
         $skipWhere = array('task', 'radio_ts', 'uf_group_id', 'component_mode', 'qfKey', 'operator');
     }
     if (in_array($id, $skipWhere) || substr($id, 0, 4) == '_qf_' || substr($id, 0, 7) == 'hidden_') {
         return $result;
     }
     if ($apiEntity && substr($id, 0, strlen($apiEntity)) != $apiEntity) {
         $id = $apiEntity . '_' . $id;
     }
     if (!$likeNames) {
         $likeNames = array('relationship_target_name');
     }
     if (!$useEquals && in_array($id, $likeNames)) {
         $result = array($id, 'LIKE', $values, 0, 1);
     } elseif (is_string($values) && strpos($values, '%') !== FALSE) {
         $result = array($id, 'LIKE', $values, 0, 0);
     } elseif ($id == 'relationship_type_id') {
         $result = array($id, 'IN', $values, 0, $wildcard);
     } else {
         $result = array($id, '=', $values, 0, $wildcard);
     }
     return $result;
 }
Exemplo n.º 11
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // load Civi to get access to civicrm_api_get_function_name
     $civicrm_api3 = $this->getContainer()->get('civicrm_api3');
     if (!$civicrm_api3 || !$civicrm_api3->local) {
         $output->writeln("<error>--copy requires access to local CiviCRM source tree. Configure civicrm_api3_conf_path.</error>");
         return;
     }
     $ctx = array();
     $ctx['type'] = 'module';
     $ctx['basedir'] = rtrim(getcwd(), '/');
     $basedir = new Path($ctx['basedir']);
     $info = new Info($basedir->string('info.xml'));
     $info->load($ctx);
     $attrs = $info->get()->attributes();
     if ($attrs['type'] != 'module') {
         $output->writeln('<error>Wrong extension type: ' . $attrs['type'] . '</error>');
         return;
     }
     if (!preg_match('/^[A-Za-z0-9]+$/', $input->getArgument('<EntityName>'))) {
         throw new Exception("Entity name must be alphanumeric camel-case");
     }
     if (!preg_match('/^[A-Za-z0-9]+$/', $input->getArgument('<ActionName>'))) {
         throw new Exception("Action name must be alphanumeric camel-case");
     }
     if ($input->getOption('schedule') && !in_array($input->getOption('schedule'), self::getSchedules())) {
         throw new Exception("Schedule must be one of: " . implode(', ', self::getSchedules()));
     }
     $ctx['entityNameCamel'] = ucfirst($input->getArgument('<EntityName>'));
     $ctx['actionNameCamel'] = ucfirst($input->getArgument('<ActionName>'));
     if (function_exists('civicrm_api_get_function_name')) {
         $ctx['apiFunction'] = strtolower(civicrm_api_get_function_name($ctx['entityNameCamel'], $ctx['actionNameCamel'], self::API_VERSION));
     } elseif (function_exists('_civicrm_api_get_entity_name_from_camel')) {
         $ctx['apiFunction'] = 'civicrm_api' . self::API_VERSION . '_' . _civicrm_api_get_entity_name_from_camel($ctx['entityNameCamel']) . '_' . $ctx['actionNameCamel'];
     } else {
         throw new Exception("Failed to determine proper API function name. Perhaps the API internals have changed?");
     }
     $ctx['apiFile'] = $basedir->string('api', 'v3', $ctx['entityNameCamel'], $ctx['actionNameCamel'] . '.php');
     $ctx['apiCronFile'] = $basedir->string('api', 'v3', $ctx['entityNameCamel'], $ctx['actionNameCamel'] . '.mgd.php');
     $dirs = new Dirs(array(dirname($ctx['apiFile'])));
     $dirs->save($ctx, $output);
     if (!file_exists($ctx['apiFile'])) {
         $output->writeln(sprintf('<info>Write %s</info>', $ctx['apiFile']));
         file_put_contents($ctx['apiFile'], $this->getContainer()->get('templating')->render('CRMCivixBundle:Code:api.php.php', $ctx));
     } else {
         $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $ctx['apiFile']));
     }
     if ($input->getOption('schedule')) {
         if (!file_exists($ctx['apiCronFile'])) {
             $mgdEntities = array(array('name' => 'Cron:' . $ctx['entityNameCamel'] . '.' . $ctx['actionNameCamel'], 'entity' => 'Job', 'params' => array('version' => 3, 'name' => sprintf('Call %s.%s API', $ctx['entityNameCamel'], $ctx['actionNameCamel']), 'description' => sprintf('Call %s.%s API', $ctx['entityNameCamel'], $ctx['actionNameCamel']), 'run_frequency' => $input->getOption('schedule'), 'api_entity' => $ctx['entityNameCamel'], 'api_action' => $ctx['actionNameCamel'], 'parameters' => '')));
             $header = "// This file declares a managed database record of type \"Job\".\n" . "// The record will be automatically inserted, updated, or deleted from the\n" . "// database as appropriate. For more details, see \"hook_civicrm_managed\" at:\n" . "// http://wiki.civicrm.org/confluence/display/CRMDOC42/Hook+Reference";
             $mgdBuilder = new PhpData($ctx['apiCronFile'], $header);
             $mgdBuilder->set($mgdEntities);
             $mgdBuilder->save($ctx, $output);
         } else {
             $output->writeln(sprintf('<error>Skip %s: file already exists</error>', $ctx['apiCronFile']));
         }
     }
     $module = new Module($this->getContainer()->get('templating'));
     $module->loadInit($ctx);
     $module->save($ctx, $output);
 }
Exemplo n.º 12
0
/**
 * Function to return the DAO of the function or Entity
 * @param String $name  either a function of the api (civicrm_{entity}_create or the entity name
 * return the DAO name to manipulate this function
 * eg. "civicrm_api3_contact_create" or "Contact" will return "CRM_Contact_BAO_Contact"
 * @return mixed|string
 */
function _civicrm_api3_get_DAO($name)
{
    if (strpos($name, 'civicrm_api3') !== FALSE) {
        $last = strrpos($name, '_');
        // len ('civicrm_api3_') == 13
        $name = substr($name, 13, $last - 13);
    }
    $name = _civicrm_api_get_camel_name($name, 3);
    if ($name == 'Individual' || $name == 'Household' || $name == 'Organization') {
        $name = 'Contact';
    }
    // hack to deal with incorrectly named BAO/DAO - see CRM-10859
    // FIXME: DAO should be renamed CRM_Mailing_DAO_MailingRecipients
    // but am not confident mailing_recipients is tested so have not tackled.
    if ($name == 'MailingRecipients') {
        return 'CRM_Mailing_DAO_Recipients';
    }
    // FIXME: DAO should be renamed CRM_Mailing_DAO_MailingComponent
    if ($name == 'MailingComponent') {
        return 'CRM_Mailing_DAO_Component';
    }
    // FIXME: DAO should be renamed CRM_ACL_DAO_AclRole
    if ($name == 'AclRole') {
        return 'CRM_ACL_DAO_EntityRole';
    }
    // FIXME: DAO should be renamed CRM_SMS_DAO_SmsProvider
    // But this would impact SMS extensions so need to coordinate
    // Probably best approach is to migrate them to use the api and decouple them from core BAOs
    if ($name == 'SmsProvider') {
        return 'CRM_SMS_DAO_Provider';
    }
    // FIXME: DAO names should follow CamelCase convention
    if ($name == 'Im' || $name == 'Acl') {
        $name = strtoupper($name);
    }
    $dao = CRM_Core_DAO_AllCoreTables::getFullName($name);
    if ($dao || !$name) {
        return $dao;
    }
    // Really weird apis can declare their own DAO name. Not sure if this is a good idea...
    if (file_exists("api/v3/{$name}.php")) {
        include_once "api/v3/{$name}.php";
    }
    $daoFn = "_civicrm_api3_" . _civicrm_api_get_entity_name_from_camel($name) . "_DAO";
    if (function_exists($daoFn)) {
        return $daoFn();
    }
    return NULL;
}
Exemplo n.º 13
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();
    }
    $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];
}
Exemplo n.º 14
0
 /**
  * Call any nested api calls
  *
  * TODO: We don't really need this to be a separate function.
  */
 protected function _civicrm_api_call_nested_api(&$params, &$result, $action, $entity, $version)
 {
     $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'))) {
         return;
     }
     if (strtolower($action) == 'getsingle') {
         // I don't understand the protocol here, but we don't want
         // $result to be a recursive array
         // $result['values'][0] = $result;
         $oldResult = $result;
         $result = array('values' => array(0 => $oldResult));
     }
     foreach ($params as $field => $newparams) {
         if ((is_array($newparams) || $newparams === 1) && $field != 'api.has_parent' && substr($field, 0, 3) == 'api') {
             // 'api.participant.delete' => 1 is a valid options - handle 1 instead of an array
             if ($newparams === 1) {
                 $newparams = array('version' => $version);
             }
             // can be api_ or api.
             $separator = $field[3];
             if (!($separator == '.' || $separator == '_')) {
                 continue;
             }
             $subAPI = explode($separator, $field);
             $subaction = empty($subAPI[2]) ? $action : $subAPI[2];
             $subParams = array('debug' => \CRM_Utils_Array::value('debug', $params));
             $subEntity = $subAPI[1];
             foreach ($result['values'] as $idIndex => $parentAPIValues) {
                 if (strtolower($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 'entity_table' will be set to 'contact' & 'id' to the contact id 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'];
                 }
                 if (strtolower($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 &
                     //thus limiting the ability to chain email
                     //TODO - this might need the camel treatment
                     $subParams['id'] = $parentAPIValues[$subEntity . "_id"];
                 }
                 if (\CRM_Utils_Array::value('entity_table', $result['values'][$idIndex]) == $subEntity) {
                     $subParams['id'] = $result['values'][$idIndex]['entity_id'];
                 }
                 // if we are dealing with the same entity pass 'id' through (useful for get + delete for example)
                 if (strtolower($entity) == strtolower($subEntity)) {
                     $subParams['id'] = $result['values'][$idIndex]['id'];
                 }
                 $subParams['version'] = $version;
                 if (!empty($params['check_permissions'])) {
                     $subParams['check_permissions'] = $params['check_permissions'];
                 }
                 $subParams['sequential'] = 1;
                 $subParams['api.has_parent'] = 1;
                 if (array_key_exists(0, $newparams)) {
                     $genericParams = $subParams;
                     // 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);
                         if ($result['is_error'] === 1) {
                             throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
                         }
                     }
                 } 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);
                     if (!empty($result['is_error'])) {
                         throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
                     }
                 }
             }
         }
     }
     if (strtolower($action) == 'getsingle') {
         $result = $result['values'][0];
     }
 }
Exemplo n.º 15
0
/**
 * Function to return the DAO of the function or Entity
 * @param String $name  either a function of the api (civicrm_{entity}_create or the entity name
 * return the DAO name to manipulate this function
 * eg. "civicrm_api3_contact_create" or "Contact" will return "CRM_Contact_BAO_Contact"
 * @return mixed|string
 */
function _civicrm_api3_get_DAO($name)
{
    if (strpos($name, 'civicrm_api3') !== FALSE) {
        $last = strrpos($name, '_');
        // len ('civicrm_api3_') == 13
        $name = substr($name, 13, $last - 13);
    }
    $name = _civicrm_api_get_camel_name($name, 3);
    if ($name == 'Individual' || $name == 'Household' || $name == 'Organization') {
        $name = 'Contact';
    }
    //hack to deal with incorrectly named BAO/DAO - see CRM-10859 -
    // several of these have been removed but am not confident mailing_recipients is
    // tests so have not tackled.
    // correct approach for im is unclear
    if ($name == 'mailing_recipients' || $name == 'MailingRecipients') {
        return 'CRM_Mailing_BAO_Recipients';
    }
    if (strtolower($name) == 'im') {
        return 'CRM_Core_BAO_IM';
    }
    $dao = CRM_Core_DAO_AllCoreTables::getFullName($name);
    if ($dao || !$name) {
        return $dao;
    }
    // Really weird apis can declare their own DAO name. Not sure if this is a good idea...
    if (file_exists("api/v3/{$name}.php")) {
        include_once "api/v3/{$name}.php";
    }
    $daoFn = "_civicrm_api3_" . _civicrm_api_get_entity_name_from_camel($name) . "_DAO";
    if (function_exists($daoFn)) {
        return $daoFn();
    }
    return NULL;
}
Exemplo n.º 16
0
 function testFromCamel()
 {
     $cases = array('Contribution' => 'contribution', 'contribution' => 'contribution', 'OptionValue' => 'option_value', 'optionValue' => 'option_value', 'option_value' => 'option_value', 'UFJoin' => 'uf_join', 'ufJoin' => 'uf_join', 'uf_join' => 'uf_join');
     foreach ($cases as $input => $expected) {
         $actual = _civicrm_api_get_entity_name_from_camel($input);
         $this->assertEquals($expected, $actual, sprintf('input=%s expected=%s actual=%s', $input, $expected, $actual));
     }
 }
Exemplo n.º 17
0
 /**
  * Get documentation block.
  *
  * @param string $entity
  * @param string|null $action
  * @return array|bool
  *   [docblock, code]
  */
 private static function getDocBlock($entity, $action)
 {
     if (!$entity) {
         return FALSE;
     }
     $file = "api/v3/{$entity}.php";
     $contents = file_get_contents($file, FILE_USE_INCLUDE_PATH);
     if (!$contents) {
         // Api does not exist
         return FALSE;
     }
     $docblock = $code = array();
     // Fetch docblock for the api file
     if (!$action) {
         if (preg_match('#/\\*\\*\\n.*?\\n \\*/\\n#s', $contents, $docblock)) {
             return array($docblock[0], NULL, $file);
         }
     } else {
         $action = strtolower($action);
         $fnName = 'civicrm_api3_' . _civicrm_api_get_entity_name_from_camel($entity) . '_' . $action;
         // Support the alternate "1 file per action" structure
         $actionFile = "api/v3/{$entity}/" . ucfirst($action) . '.php';
         $actionFileContents = file_get_contents("api/v3/{$entity}/" . ucfirst($action) . '.php', FILE_USE_INCLUDE_PATH);
         if ($actionFileContents) {
             $file = $actionFile;
             $contents = $actionFileContents;
         }
         // If action isn't in this file, try generic
         if (strpos($contents, "function {$fnName}") === FALSE) {
             $fnName = "civicrm_api3_generic_{$action}";
             $file = "api/v3/Generic/" . ucfirst($action) . '.php';
             $contents = file_get_contents($file, FILE_USE_INCLUDE_PATH);
             if (!$contents) {
                 $file = "api/v3/Generic.php";
                 $contents = file_get_contents($file, FILE_USE_INCLUDE_PATH);
             }
         }
         if (preg_match('#(/\\*\\*(\\n \\*.*)*\\n \\*/\\n)function[ ]+' . $fnName . '#i', $contents, $docblock)) {
             // Fetch the code in a separate regex to preserve sanity
             preg_match("#^function[ ]+{$fnName}.*?^}#ism", $contents, $code);
             return array($docblock[1], $code[0], $file);
         }
     }
 }
Exemplo n.º 18
0
/**
 * Decide what permissions to check for an api call
 *
 * @param $entity : (str) api entity
 * @param $action : (str) api action
 * @param $params : (array) api params
 *
 * @return array
 *   Array of permissions to check for this entity-action combo
 */
function _civicrm_api3_permissions($entity, $action, &$params)
{
    // FIXME: Lowercase entity_names are nonstandard but difficult to fix here
    // because this function invokes hook_civicrm_alterAPIPermissions
    $entity = _civicrm_api_get_entity_name_from_camel($entity);
    /**
     * @var array of permissions
     *
     * For each entity, we declare an array of permissions required for each action
     * The action is the array key, possible values:
     *  * create: applies to create (with no id in params)
     *  * update: applies to update, setvalue, create (with id in params)
     *  * get: applies to getcount, getsingle, getvalue and other gets
     *  * delete: applies to delete, replace
     *  * meta: applies to getfields, getoptions, getspec
     *  * default: catch-all for anything not declared
     *
     *  Note: some APIs declare other actions as well
     *
     * Permissions should use arrays for AND and arrays of arrays for OR
     * @see CRM_Core_Permission::check for more documentation
     */
    $permissions = array();
    // These are the default permissions - if any entity does not declare permissions for a given action,
    // (or the entity does not declare permissions at all) - then the action will be used from here
    $permissions['default'] = array('meta' => array('access CiviCRM'), 'default' => array('administer CiviCRM'));
    // Note: Additional permissions in DynamicFKAuthorization
    $permissions['attachment'] = array('default' => array(array('access CiviCRM', 'access AJAX API')));
    // Contact permissions
    $permissions['contact'] = array('create' => array('access CiviCRM', 'add contacts'), 'delete' => array('access CiviCRM', 'delete contacts'), 'get' => array(), 'update' => array(), 'getquick' => array(array('access CiviCRM', 'access AJAX API')));
    // CRM-16963 - Permissions for country.
    $permissions['country'] = array('get' => array('access CiviCRM'), 'default' => array('administer CiviCRM'));
    // Contact-related data permissions.
    $permissions['address'] = array('default' => array());
    $permissions['email'] = $permissions['address'];
    $permissions['phone'] = $permissions['address'];
    $permissions['website'] = $permissions['address'];
    $permissions['im'] = $permissions['address'];
    // @todo - implement CRM_Core_BAO_EntityTag::addSelectWhereClause and remove this heavy-handed restriction
    $permissions['entity_tag'] = array('get' => array('access CiviCRM', 'view all contacts'), 'default' => array('access CiviCRM', 'edit all contacts'));
    // @todo - ditto
    $permissions['note'] = $permissions['entity_tag'];
    // Allow non-admins to get and create tags to support tagset widget
    // Delete is still reserved for admins
    $permissions['tag'] = array('get' => array('access CiviCRM'), 'create' => array('access CiviCRM'), 'update' => array('access CiviCRM'));
    //relationship permissions
    $permissions['relationship'] = array('get' => array(), 'delete' => array('access CiviCRM', 'edit all contacts'), 'default' => array('access CiviCRM', 'edit all contacts'));
    // CRM-17741 - Permissions for RelationshipType.
    $permissions['relationship_type'] = array('get' => array('access CiviCRM'), 'default' => array('administer CiviCRM'));
    // Activity permissions
    $permissions['activity'] = array('delete' => array('access CiviCRM', 'delete activities'), 'default' => array('access CiviCRM', 'view all activities'));
    // Case permissions
    $permissions['case'] = array('create' => array('access CiviCRM', 'add cases'), 'delete' => array('access CiviCRM', 'delete in CiviCase'), 'default' => array(array('access my cases and activities', 'access all cases and activities')));
    $permissions['case_contact'] = $permissions['case'];
    $permissions['case_type'] = array('default' => array('administer CiviCase'), 'get' => array(array('access my cases and activities', 'access all cases and activities')));
    // Campaign permissions
    $permissions['campaign'] = array('get' => array('access CiviCRM'), 'default' => array(array('administer CiviCampaign', 'manage campaign')));
    $permissions['survey'] = $permissions['campaign'];
    // Financial permissions
    $permissions['contribution'] = array('get' => array('access CiviCRM', 'access CiviContribute'), 'delete' => array('access CiviCRM', 'access CiviContribute', 'delete in CiviContribute'), 'completetransaction' => array('edit contributions'), 'default' => array('access CiviCRM', 'access CiviContribute', 'edit contributions'));
    $permissions['line_item'] = $permissions['contribution'];
    // Custom field permissions
    $permissions['custom_field'] = array('default' => array('administer CiviCRM', 'access all custom data'));
    $permissions['custom_group'] = $permissions['custom_field'];
    // Event permissions
    $permissions['event'] = array('create' => array('access CiviCRM', 'access CiviEvent', 'edit all events'), 'delete' => array('access CiviCRM', 'access CiviEvent', 'delete in CiviEvent'), 'get' => array('access CiviCRM', 'access CiviEvent', 'view event info'), 'update' => array('access CiviCRM', 'access CiviEvent', 'edit all events'));
    // Loc block is only used for events
    $permissions['loc_block'] = $permissions['event'];
    // File permissions
    $permissions['file'] = array('default' => array('access CiviCRM', 'access uploaded files'));
    $permissions['files_by_entity'] = $permissions['file'];
    // Group permissions
    $permissions['group'] = array('get' => array('access CiviCRM'), 'default' => array('access CiviCRM', 'edit groups'));
    $permissions['group_nesting'] = $permissions['group'];
    $permissions['group_organization'] = $permissions['group'];
    //Group Contact permission
    $permissions['group_contact'] = array('get' => array('access CiviCRM'), 'default' => array('access CiviCRM', 'edit all contacts'));
    // CiviMail Permissions
    $civiMailBasePerms = array('access CiviMail', 'create mailings', 'schedule mailings', 'approve mailings');
    $permissions['mailing'] = array('get' => array('access CiviCRM', $civiMailBasePerms), 'delete' => array('access CiviCRM', $civiMailBasePerms, 'delete in CiviMail'), 'submit' => array('access CiviCRM', array('access CiviMail', 'schedule mailings')), 'default' => array('access CiviCRM', $civiMailBasePerms));
    $permissions['mailing_group'] = $permissions['mailing'];
    $permissions['mailing_job'] = $permissions['mailing'];
    $permissions['mailing_recipients'] = $permissions['mailing'];
    $permissions['mailing_a_b'] = array('get' => array('access CiviCRM', 'access CiviMail'), 'delete' => array('access CiviCRM', 'access CiviMail', 'delete in CiviMail'), 'submit' => array('access CiviCRM', array('access CiviMail', 'schedule mailings')), 'default' => array('access CiviCRM', 'access CiviMail'));
    // Membership permissions
    $permissions['membership'] = array('get' => array('access CiviCRM', 'access CiviMember'), 'delete' => array('access CiviCRM', 'access CiviMember', 'delete in CiviMember'), 'default' => array('access CiviCRM', 'access CiviMember', 'edit memberships'));
    $permissions['membership_status'] = $permissions['membership'];
    $permissions['membership_type'] = $permissions['membership'];
    $permissions['membership_payment'] = array('create' => array('access CiviCRM', 'access CiviMember', 'edit memberships', 'access CiviContribute', 'edit contributions'), 'delete' => array('access CiviCRM', 'access CiviMember', 'delete in CiviMember', 'access CiviContribute', 'delete in CiviContribute'), 'get' => array('access CiviCRM', 'access CiviMember', 'access CiviContribute'), 'update' => array('access CiviCRM', 'access CiviMember', 'edit memberships', 'access CiviContribute', 'edit contributions'));
    // Participant permissions
    $permissions['participant'] = array('create' => array('access CiviCRM', 'access CiviEvent', 'register for events'), 'delete' => array('access CiviCRM', 'access CiviEvent', 'edit event participants'), 'get' => array('access CiviCRM', 'access CiviEvent', 'view event participants'), 'update' => array('access CiviCRM', 'access CiviEvent', 'edit event participants'));
    $permissions['participant_payment'] = array('create' => array('access CiviCRM', 'access CiviEvent', 'register for events', 'access CiviContribute', 'edit contributions'), 'delete' => array('access CiviCRM', 'access CiviEvent', 'edit event participants', 'access CiviContribute', 'delete in CiviContribute'), 'get' => array('access CiviCRM', 'access CiviEvent', 'view event participants', 'access CiviContribute'), 'update' => array('access CiviCRM', 'access CiviEvent', 'edit event participants', 'access CiviContribute', 'edit contributions'));
    // Pledge permissions
    $permissions['pledge'] = array('create' => array('access CiviCRM', 'access CiviPledge', 'edit pledges'), 'delete' => array('access CiviCRM', 'access CiviPledge', 'delete in CiviPledge'), 'get' => array('access CiviCRM', 'access CiviPledge'), 'update' => array('access CiviCRM', 'access CiviPledge', 'edit pledges'));
    //CRM-16777: Disable schedule reminder for user that have 'edit all events' and 'administer CiviCRM' permission.
    $permissions['action_schedule'] = array('update' => array(array('access CiviCRM', 'edit all events')));
    $permissions['pledge_payment'] = array('create' => array('access CiviCRM', 'access CiviPledge', 'edit pledges', 'access CiviContribute', 'edit contributions'), 'delete' => array('access CiviCRM', 'access CiviPledge', 'delete in CiviPledge', 'access CiviContribute', 'delete in CiviContribute'), 'get' => array('access CiviCRM', 'access CiviPledge', 'access CiviContribute'), 'update' => array('access CiviCRM', 'access CiviPledge', 'edit pledges', 'access CiviContribute', 'edit contributions'));
    // Profile permissions
    $permissions['profile'] = array('get' => array());
    $permissions['uf_group'] = array('create' => array('access CiviCRM', array('administer CiviCRM', 'manage event profiles')), 'get' => array('access CiviCRM'), 'update' => array('access CiviCRM', array('administer CiviCRM', 'manage event profiles')));
    $permissions['uf_field'] = $permissions['uf_join'] = $permissions['uf_group'];
    $permissions['uf_field']['delete'] = array('access CiviCRM', array('administer CiviCRM', 'manage event profiles'));
    $permissions['option_value'] = $permissions['uf_group'];
    $permissions['option_group'] = $permissions['option_value'];
    $permissions['message_template'] = array('get' => array('access CiviCRM'), 'create' => array('edit message templates'), 'update' => array('edit message templates'));
    // Translate 'create' action to 'update' if id is set
    if ($action == 'create' && (!empty($params['id']) || !empty($params[$entity . '_id']))) {
        $action = 'update';
    }
    // let third parties modify the permissions
    CRM_Utils_Hook::alterAPIPermissions($entity, $action, $params, $permissions);
    // Merge permissions for this entity with the defaults
    $perm = CRM_Utils_Array::value($entity, $permissions, array()) + $permissions['default'];
    // Return exact match if permission for this action has been declared
    if (isset($perm[$action])) {
        return $perm[$action];
    }
    // Translate specific actions into their generic equivalents
    $snippet = substr($action, 0, 3);
    if ($action == 'replace' || $snippet == 'del') {
        // 'Replace' is a combination of get+create+update+delete; however, the permissions
        // on each of those will be tested separately at runtime. This is just a sniff-test
        // based on the heuristic that 'delete' tends to be the most closely guarded
        // of the necessary permissions.
        $action = 'delete';
    } elseif ($action == 'setvalue' || $snippet == 'upd') {
        $action = 'update';
    } elseif ($action == 'getfields' || $action == 'getfield' || $action == 'getspec' || $action == 'getoptions') {
        $action = 'meta';
    } elseif ($snippet == 'get') {
        $action = 'get';
    }
    return isset($perm[$action]) ? $perm[$action] : $perm['default'];
}
Exemplo n.º 19
0
/**
 * Here we map the profile fields as stored in the uf_field table to their 'real entity'
 * we also return the profile fieldname
 *
 * @param $field
 *
 * @return array
 */
function _civicrm_api3_map_profile_fields_to_entity(&$field)
{
    $entity = $field['field_type'];
    $contactTypes = civicrm_api3('contact', 'getoptions', array('field' => 'contact_type'));
    if (in_array($entity, $contactTypes['values'])) {
        $entity = 'contact';
    }
    $entity = _civicrm_api_get_entity_name_from_camel($entity);
    $locationFields = array('email' => 'email');
    $fieldName = $field['field_name'];
    if (!empty($field['location_type_id'])) {
        if ($fieldName == 'email') {
            $entity = 'email';
        } else {
            $entity = 'address';
        }
        $fieldName .= '-' . $field['location_type_id'];
    } elseif (array_key_exists($fieldName, $locationFields)) {
        $fieldName .= '-Primary';
        $entity = 'email';
    }
    if (!empty($field['phone_type_id'])) {
        $fieldName .= '-' . $field['location_type_id'];
        $entity = 'phone';
    }
    // @todo - sort this out!
    //here we do a hard-code list of known fields that don't map to where they are mapped to
    // not a great solution but probably if we looked in the BAO we'd find a scary switch statement
    // in a perfect world the uf_field table would hold the correct entity for each item
    // & only the relationships between entities would need to be coded
    $hardCodedEntityMappings = array('street_address' => 'address', 'street_number' => 'address', 'supplemental_address_1' => 'address', 'supplemental_address_2' => 'address', 'supplemental_address_3' => 'address', 'postal_code' => 'address', 'city' => 'address', 'email' => 'email', 'state_province' => 'address', 'country' => 'address', 'county' => 'address', 'financial_type' => 'contribution', 'total_amount' => 'contribution', 'receive_date' => 'contribution', 'payment_instrument' => 'contribution', 'check_number' => 'contribution', 'contribution_status_id' => 'contribution', 'soft_credit' => 'contribution', 'soft_credit_type' => 'contribution_soft', 'group' => 'group_contact', 'tag' => 'entity_tag');
    if (array_key_exists($fieldName, $hardCodedEntityMappings)) {
        $entity = $hardCodedEntityMappings[$fieldName];
    }
    return array($entity, $fieldName);
}
Exemplo n.º 20
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];
}
Exemplo n.º 21
0
 /**
  * Fix values from query from/to something no-one cared enough to document.
  *
  * @param int $id
  * @param array $values
  * @param int $wildcard
  * @param bool $useEquals
  *
  * @param string $apiEntity
  *
  * @return array|null
  */
 public static function fixWhereValues($id, &$values, $wildcard = 0, $useEquals = FALSE, $apiEntity = NULL)
 {
     // skip a few search variables
     static $skipWhere = NULL;
     static $likeNames = NULL;
     $result = NULL;
     // Change camelCase EntityName to lowercase with underscores
     $apiEntity = _civicrm_api_get_entity_name_from_camel($apiEntity);
     if (CRM_Utils_System::isNull($values)) {
         return $result;
     }
     if (!$skipWhere) {
         $skipWhere = array('task', 'radio_ts', 'uf_group_id', 'component_mode', 'qfKey', 'operator', 'display_relationship_type');
     }
     if (in_array($id, $skipWhere) || substr($id, 0, 4) == '_qf_' || substr($id, 0, 7) == 'hidden_') {
         return $result;
     }
     if ($apiEntity && substr($id, 0, strlen($apiEntity)) != $apiEntity && (substr($id, 0, 10) != 'financial_' && substr($id, 0, 8) != 'payment_')) {
         $id = $apiEntity . '_' . $id;
     }
     if (!$likeNames) {
         $likeNames = array('sort_name', 'email', 'note', 'display_name');
     }
     // email comes in via advanced search
     // so use wildcard always
     if ($id == 'email') {
         $wildcard = 1;
     }
     if (!$useEquals && in_array($id, $likeNames)) {
         $result = array($id, 'LIKE', $values, 0, 1);
     } elseif (is_string($values) && strpos($values, '%') !== FALSE) {
         $result = array($id, 'LIKE', $values, 0, 0);
     } elseif ($id == 'contact_type' || !empty($values) && is_array($values) && !in_array(key($values), CRM_Core_DAO::acceptedSQLOperators(), TRUE)) {
         $result = array($id, 'IN', $values, 0, $wildcard);
     } else {
         $result = array($id, '=', $values, 0, $wildcard);
     }
     return $result;
 }
Exemplo n.º 22
0
/**
 * Check if the function is deprecated.
 *
 * @param string $entity
 * @param array $result
 *
 * @return string|array|null
 */
function _civicrm_api3_deprecation_check($entity, $result = array())
{
    if ($entity) {
        $apiFile = "api/v3/{$entity}.php";
        if (CRM_Utils_File::isIncludable($apiFile)) {
            require_once $apiFile;
        }
        $lowercase_entity = _civicrm_api_get_entity_name_from_camel($entity);
        $fnName = "_civicrm_api3_{$lowercase_entity}_deprecation";
        if (function_exists($fnName)) {
            return $fnName($result);
        }
    }
}
Exemplo n.º 23
0
/**
 * Decide what permissions to check for an api call
 * The contact must have all of the returned permissions for the api call to be allowed
 *
 * @param $entity: (str) api entity
 * @param $action: (str) api action
 * @param $params: (array) api params
 *
 * @return array of permissions to check for this entity-action combo
 */
function _civicrm_api3_permissions($entity, $action, &$params)
{
    $entity = _civicrm_api_get_entity_name_from_camel($entity);
    $action = strtolower($action);
    /**
     * @var array of permissions
     *
     * For each entity, we declare an array of permissions required for each action
     * The action is the array key, possible values:
     *  * create: applies to create (with no id in params)
     *  * update: applies to update, setvalue, create (with id in params)
     *  * get: applies to getcount, getsingle, getvalue and other gets
     *  * delete: applies to delete, replace
     *  * meta: applies to getfields, getoptions, getspec
     *  * default: catch-all for anything not declared
     *
     *  Note: some APIs declare other actions as well
     */
    $permissions = array();
    // These are the default permissions - if any entity does not declare permissions for a given action,
    // (or the entity does not declare permissions at all) - then the action will be used from here
    $permissions['default'] = array('meta' => array('access CiviCRM'), 'default' => array('administer CiviCRM'));
    // Contact permissions
    $permissions['contact'] = array('create' => array('access CiviCRM', 'add contacts'), 'delete' => array('access CiviCRM', 'delete contacts'), 'get' => array(), 'update' => array('access CiviCRM', 'edit all contacts'), 'getquick' => array(array('access CiviCRM', 'access AJAX API')));
    // Contact-related data permissions
    $permissions['address'] = array('get' => array('access CiviCRM', 'view all contacts'), 'delete' => array('access CiviCRM', 'delete contacts'), 'default' => array('access CiviCRM', 'edit all contacts'));
    $permissions['email'] = $permissions['address'];
    $permissions['phone'] = $permissions['address'];
    $permissions['website'] = $permissions['address'];
    $permissions['im'] = $permissions['address'];
    $permissions['loc_block'] = $permissions['address'];
    $permissions['entity_tag'] = $permissions['address'];
    $permissions['note'] = $permissions['address'];
    // Activity permissions
    $permissions['activity'] = array('delete' => array('access CiviCRM', 'delete activities'), 'default' => array('access CiviCRM', 'view all activities'));
    // Case permissions
    $permissions['case'] = array('create' => array('access CiviCRM', 'add cases'), 'delete' => array('access CiviCRM', 'delete in CiviCase'), 'default' => array('access CiviCRM', 'access all cases and activities'));
    // Financial permissions
    $permissions['contribution'] = array('get' => array('access CiviCRM', 'access CiviContribute'), 'delete' => array('access CiviCRM', 'access CiviContribute', 'delete in CiviContribute'), 'completetransaction' => array('edit contributions'), 'default' => array('access CiviCRM', 'access CiviContribute', 'edit contributions'));
    $permissions['line_item'] = $permissions['contribution'];
    // Custom field permissions
    $permissions['custom_field'] = array('default' => array('administer CiviCRM', 'access all custom data'));
    $permissions['custom_group'] = $permissions['custom_field'];
    // Event permissions
    $permissions['event'] = array('create' => array('access CiviCRM', 'access CiviEvent', 'edit all events'), 'delete' => array('access CiviCRM', 'access CiviEvent', 'delete in CiviEvent'), 'get' => array('access CiviCRM', 'access CiviEvent', 'view event info'), 'update' => array('access CiviCRM', 'access CiviEvent', 'edit all events'));
    // File permissions
    $permissions['file'] = array('default' => array('access CiviCRM', 'access uploaded files'));
    $permissions['files_by_entity'] = $permissions['file'];
    // Group permissions
    $permissions['group'] = array('get' => array('access CiviCRM'), 'default' => array('access CiviCRM', 'edit groups'));
    $permissions['group_contact'] = $permissions['group'];
    $permissions['group_nesting'] = $permissions['group'];
    $permissions['group_organization'] = $permissions['group'];
    // Membership permissions
    $permissions['membership'] = array('get' => array('access CiviCRM', 'access CiviMember'), 'delete' => array('access CiviCRM', 'access CiviMember', 'delete in CiviMember'), 'default' => array('access CiviCRM', 'access CiviMember', 'edit memberships'));
    $permissions['membership_status'] = $permissions['membership'];
    $permissions['membership_type'] = $permissions['membership'];
    $permissions['membership_payment'] = array('create' => array('access CiviCRM', 'access CiviMember', 'edit memberships', 'access CiviContribute', 'edit contributions'), 'delete' => array('access CiviCRM', 'access CiviMember', 'delete in CiviMember', 'access CiviContribute', 'delete in CiviContribute'), 'get' => array('access CiviCRM', 'access CiviMember', 'access CiviContribute'), 'update' => array('access CiviCRM', 'access CiviMember', 'edit memberships', 'access CiviContribute', 'edit contributions'));
    // Participant permissions
    $permissions['participant'] = array('create' => array('access CiviCRM', 'access CiviEvent', 'register for events'), 'delete' => array('access CiviCRM', 'access CiviEvent', 'edit event participants'), 'get' => array('access CiviCRM', 'access CiviEvent', 'view event participants'), 'update' => array('access CiviCRM', 'access CiviEvent', 'edit event participants'));
    $permissions['participant_payment'] = array('create' => array('access CiviCRM', 'access CiviEvent', 'register for events', 'access CiviContribute', 'edit contributions'), 'delete' => array('access CiviCRM', 'access CiviEvent', 'edit event participants', 'access CiviContribute', 'delete in CiviContribute'), 'get' => array('access CiviCRM', 'access CiviEvent', 'view event participants', 'access CiviContribute'), 'update' => array('access CiviCRM', 'access CiviEvent', 'edit event participants', 'access CiviContribute', 'edit contributions'));
    // Pledge permissions
    $permissions['pledge'] = array('create' => array('access CiviCRM', 'access CiviPledge', 'edit pledges'), 'delete' => array('access CiviCRM', 'access CiviPledge', 'delete in CiviPledge'), 'get' => array('access CiviCRM', 'access CiviPledge'), 'update' => array('access CiviCRM', 'access CiviPledge', 'edit pledges'));
    $permissions['pledge_payment'] = array('create' => array('access CiviCRM', 'access CiviPledge', 'edit pledges', 'access CiviContribute', 'edit contributions'), 'delete' => array('access CiviCRM', 'access CiviPledge', 'delete in CiviPledge', 'access CiviContribute', 'delete in CiviContribute'), 'get' => array('access CiviCRM', 'access CiviPledge', 'access CiviContribute'), 'update' => array('access CiviCRM', 'access CiviPledge', 'edit pledges', 'access CiviContribute', 'edit contributions'));
    // Profile permissions
    $permissions['profile'] = array('get' => array());
    $permissions['uf_group'] = array('get' => array('access CiviCRM'));
    $permissions['uf_field'] = $permissions['uf_group'];
    // Translate 'create' action to 'update' if id is set
    if ($action == 'create' && (!empty($params['id']) || !empty($params[$entity . '_id']))) {
        $action = 'update';
    }
    // let third parties modify the permissions
    CRM_Utils_Hook::alterAPIPermissions($entity, $action, $params, $permissions);
    // Merge permissions for this entity with the defaults
    $perm = CRM_Utils_Array::value($entity, $permissions, array()) + $permissions['default'];
    // Return exact match if permission for this action has been declared
    if (isset($perm[$action])) {
        return $perm[$action];
    }
    // Translate specific actions into their generic equivalents
    $snippet = substr($action, 0, 3);
    if ($action == 'replace' || $snippet == 'del') {
        // 'Replace' is a combination of get+create+update+delete; however, the permissions
        // on each of those will be tested separately at runtime. This is just a sniff-test
        // based on the heuristic that 'delete' tends to be the most closesly guarded
        // of the necessary permissions.
        $action = 'delete';
    } elseif ($action == 'setvalue' || $snippet == 'upd') {
        $action = 'update';
    } elseif ($action == 'getfields' || $action == 'getspec' || $action == 'getoptions') {
        $action = 'meta';
    } elseif ($snippet == 'get') {
        $action = 'get';
    }
    return isset($perm[$action]) ? $perm[$action] : $perm['default'];
}
Exemplo n.º 24
0
 /**
  * Create test generated example in api/v3/examples.
  *
  * To turn this off (e.g. on the server) set
  * define(DONT_DOCUMENT_TEST_CONFIG ,1);
  * in your settings file
  *
  * @param string $entity
  * @param string $action
  * @param array $params
  *   Array as passed to civicrm_api function.
  * @param array $result
  *   Array as received from the civicrm_api function.
  * @param string $testFunction
  *   Calling function - generally __FUNCTION__.
  * @param string $testFile
  *   Called from file - generally __FILE__.
  * @param string $description
  *   Descriptive text for the example file.
  * @param string $exampleName
  *   Name for this example file (CamelCase) - if omitted the action name will be substituted.
  */
 private function documentMe($entity, $action, $params, $result, $testFunction, $testFile, $description = "", $exampleName = NULL)
 {
     if (defined('DONT_DOCUMENT_TEST_CONFIG') && DONT_DOCUMENT_TEST_CONFIG) {
         return;
     }
     $entity = _civicrm_api_get_camel_name($entity);
     $action = strtolower($action);
     if (empty($exampleName)) {
         // Attempt to convert lowercase action name to CamelCase.
         // This is clunky/imperfect due to the convention of all lowercase actions.
         $exampleName = CRM_Utils_String::convertStringToCamel($action);
         $knownPrefixes = array('Get', 'Set', 'Create', 'Update', 'Send');
         foreach ($knownPrefixes as $prefix) {
             if (strpos($exampleName, $prefix) === 0 && $prefix != $exampleName) {
                 $exampleName[strlen($prefix)] = strtoupper($exampleName[strlen($prefix)]);
             }
         }
     }
     $this->tidyExampleResult($result);
     if (isset($params['version'])) {
         unset($params['version']);
     }
     // Format multiline description as array
     $desc = array();
     if (is_string($description) && strlen($description)) {
         foreach (explode("\n", $description) as $line) {
             $desc[] = trim($line);
         }
     }
     $smarty = CRM_Core_Smarty::singleton();
     $smarty->assign('testFunction', $testFunction);
     $smarty->assign('function', _civicrm_api_get_entity_name_from_camel($entity) . "_{$action}");
     $smarty->assign('params', $params);
     $smarty->assign('entity', $entity);
     $smarty->assign('testFile', basename($testFile));
     $smarty->assign('description', $desc);
     $smarty->assign('result', $result);
     $smarty->assign('action', $action);
     global $civicrm_root;
     if (file_exists($civicrm_root . '/tests/templates/documentFunction.tpl')) {
         if (!is_dir($civicrm_root . "/api/v3/examples/{$entity}")) {
             mkdir($civicrm_root . "/api/v3/examples/{$entity}");
         }
         $f = fopen($civicrm_root . "/api/v3/examples/{$entity}/{$exampleName}.php", "w+b");
         fwrite($f, $smarty->fetch($civicrm_root . '/tests/templates/documentFunction.tpl'));
         fclose($f);
     }
 }
Exemplo n.º 25
0
 /**
  * Create a single or multiple entity ref field.
  * @param string $name
  * @param string $label
  * @param array $props
  *   Mix of html and widget properties, including:.
  *   - select - params to give to select2 widget
  *   - entity - defaults to contact
  *   - create - can the user create a new entity on-the-fly?
  *             Set to TRUE if entity is contact and you want the default profiles,
  *             or pass in your own set of links. @see CRM_Core_BAO_UFGroup::getCreateLinks for format
  *             note that permissions are checked automatically
  *   - api - array of settings for the getlist api wrapper
  *          note that it accepts a 'params' setting which will be passed to the underlying api
  *   - placeholder - string
  *   - multiple - bool
  *   - class, etc. - other html properties
  * @param bool $required
  *
  * @return HTML_QuickForm_Element
  */
 public function addEntityRef($name, $label = '', $props = array(), $required = FALSE)
 {
     require_once "api/api.php";
     $config = CRM_Core_Config::singleton();
     // Default properties
     $props['api'] = CRM_Utils_Array::value('api', $props, array());
     $props['entity'] = _civicrm_api_get_entity_name_from_camel(CRM_Utils_Array::value('entity', $props, 'contact'));
     $props['class'] = ltrim(CRM_Utils_Array::value('class', $props, '') . ' crm-form-entityref');
     if ($props['entity'] == 'contact' && isset($props['create']) && !(CRM_Core_Permission::check('edit all contacts') || CRM_Core_Permission::check('add contacts'))) {
         unset($props['create']);
     }
     $props['placeholder'] = CRM_Utils_Array::value('placeholder', $props, $required ? ts('- select %1 -', array(1 => ts(str_replace('_', ' ', $props['entity'])))) : ts('- none -'));
     $defaults = array();
     if (!empty($props['multiple'])) {
         $defaults['multiple'] = TRUE;
     }
     $props['select'] = CRM_Utils_Array::value('select', $props, array()) + $defaults;
     $this->formatReferenceFieldAttributes($props);
     return $this->add('text', $name, $label, $props, $required);
 }
Exemplo n.º 26
0
 /**
  * Determine the function name for a given API request.
  *
  * @param string $entity
  *   API entity name.
  * @param string $action
  *   API action name.
  * @param int $version
  *   API version.
  *
  * @return string
  */
 protected function getFunctionName($entity, $action, $version)
 {
     $entity = _civicrm_api_get_entity_name_from_camel($entity);
     return 'civicrm_api' . $version . '_' . $entity . '_' . $action;
 }
Exemplo n.º 27
0
 /**
  * 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($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($action, array('getfields', 'getfield', 'getoptions'))) {
         return;
     }
     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;
         $oldResult = $result;
         $result = array('values' => array(0 => $oldResult));
     }
     foreach ($params as $field => $newparams) {
         if ((is_array($newparams) || $newparams === 1) && $field != 'api.has_parent' && substr($field, 0, 3) == 'api') {
             // 'api.participant.delete' => 1 is a valid options - handle 1
             // instead of an array
             if ($newparams === 1) {
                 $newparams = array('version' => $version);
             }
             // can be api_ or api.
             $separator = $field[3];
             if (!($separator == '.' || $separator == '_')) {
                 continue;
             }
             $subAPI = explode($separator, $field);
             $subaction = empty($subAPI[2]) ? $action : $subAPI[2];
             $subParams = array('debug' => \CRM_Utils_Array::value('debug', $params));
             $subEntity = _civicrm_api_get_entity_name_from_camel($subAPI[1]);
             foreach ($result['values'] as $idIndex => $parentAPIValues) {
                 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
                     //'entity_table' will be set to 'contact' & 'id' to the contact id
                     //from the parent call. in this case 'contact_id' will also be
                     //set to the parent's id
                     if (!($subEntity == 'line_item' && $lowercase_entity == 'contribution' && $action != 'create')) {
                         $subParams["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 ($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 weird things like returning primary email &
                     //thus limiting the ability to chain email
                     //TODO - this might need the camel treatment
                     $subParams['id'] = $parentAPIValues[$subEntity . "_id"];
                 }
                 if (\CRM_Utils_Array::value('entity_table', $result['values'][$idIndex]) == $subEntity) {
                     $subParams['id'] = $result['values'][$idIndex]['entity_id'];
                 }
                 // if we are dealing with the same entity pass 'id' through
                 // (useful for get + delete for example)
                 if ($lowercase_entity == $subEntity) {
                     $subParams['id'] = $result['values'][$idIndex]['id'];
                 }
                 $subParams['version'] = $version;
                 if (!empty($params['check_permissions'])) {
                     $subParams['check_permissions'] = $params['check_permissions'];
                 }
                 $subParams['sequential'] = 1;
                 $subParams['api.has_parent'] = 1;
                 if (array_key_exists(0, $newparams)) {
                     $genericParams = $subParams;
                     // it is a numerically indexed array - ie. multiple creates
                     foreach ($newparams as $entityparams) {
                         $subParams = array_merge($genericParams, $entityparams);
                         _civicrm_api_replace_variables($subParams, $result['values'][$idIndex], $separator);
                         $result['values'][$idIndex][$field][] = $apiKernel->run($subEntity, $subaction, $subParams);
                         if ($result['is_error'] === 1) {
                             throw new \Exception($subEntity . ' ' . $subaction . 'call failed with' . $result['error_message']);
                         }
                     }
                 } else {
                     $subParams = array_merge($subParams, $newparams);
                     _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']);
                     }
                 }
             }
         }
     }
     if ($action == 'getsingle') {
         $result = $result['values'][0];
     }
 }
Exemplo n.º 28
0
function _civicrm_api_get_entity_name_from_dao($bao)
{
    $daoName = str_replace("BAO", "DAO", get_class($bao));
    $dao = array();
    require 'CRM/Core/DAO/.listAll.php';
    $daos = array_flip($dao);
    return _civicrm_api_get_entity_name_from_camel($daos[$daoName]);
}