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); }
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); }
/** * Look up the implementation for a given API request * * @param $apiRequest array with keys: * - entity: string, required * - action: string, required * - params: array * - version: scalar, required * * @return array with keys * - function: callback (mixed) * - is_generic: boolean */ function _civicrm_api_resolve($apiRequest) { static $cache; $cachekey = strtolower($apiRequest['entity']) . ':' . strtolower($apiRequest['action']) . ':' . $apiRequest['version']; if (isset($cache[$cachekey])) { return $cache[$cachekey]; } $camelName = _civicrm_api_get_camel_name($apiRequest['entity'], $apiRequest['version']); $actionCamelName = _civicrm_api_get_camel_name($apiRequest['action']); // Determine if there is an entity-specific implementation of the action $stdFunction = civicrm_api_get_function_name($apiRequest['entity'], $apiRequest['action'], $apiRequest['version']); if (function_exists($stdFunction)) { // someone already loaded the appropriate file // FIXME: This has the affect of masking bugs in load order; this is included to provide bug-compatibility $cache[$cachekey] = array('function' => $stdFunction, 'is_generic' => FALSE); return $cache[$cachekey]; } $stdFiles = array('api/v' . $apiRequest['version'] . '/' . $camelName . '.php', 'api/v' . $apiRequest['version'] . '/' . $camelName . '/' . $actionCamelName . '.php'); foreach ($stdFiles as $stdFile) { if (CRM_Utils_File::isIncludable($stdFile)) { require_once $stdFile; if (function_exists($stdFunction)) { $cache[$cachekey] = array('function' => $stdFunction, 'is_generic' => FALSE); return $cache[$cachekey]; } } } // Determine if there is a generic implementation of the action require_once 'api/v3/Generic.php'; # $genericFunction = 'civicrm_api3_generic_' . $apiRequest['action']; $genericFunction = civicrm_api_get_function_name('generic', $apiRequest['action'], $apiRequest['version']); $genericFiles = array('api/v' . $apiRequest['version'] . '/Generic.php', 'api/v' . $apiRequest['version'] . '/Generic/' . $actionCamelName . '.php'); foreach ($genericFiles as $genericFile) { if (CRM_Utils_File::isIncludable($genericFile)) { require_once $genericFile; if (function_exists($genericFunction)) { $cache[$cachekey] = array('function' => $genericFunction, 'is_generic' => TRUE); return $cache[$cachekey]; } } } $cache[$cachekey] = array('function' => FALSE, 'is_generic' => FALSE); return $cache[$cachekey]; }