namespace Civi\Api4\Generic;
+use Civi\Api4\Utils\FormattingUtil;
use Civi\Api4\Utils\ReflectionUtils;
-use Civi\Api4\Utils\ActionUtil;
/**
* Base class for all api actions.
*
* Keys can be any string - this will be the name given to the output.
*
- * You can reference other values in the api results in this call by prefixing them with $
+ * You can reference other values in the api results in this call by prefixing them with `$`.
*
* For example, you could create a contact and place them in a group by chaining the
- * GroupContact api to the Contact api:
+ * `GroupContact` api to the `Contact` api:
*
+ * ```php
* Contact::create()
* ->setValue('first_name', 'Hello')
- * ->addChain('add_to_a_group', GroupContact::create()->setValue('contact_id', '$id')->setValue('group_id', 123))
+ * ->addChain('add_a_group', GroupContact::create()
+ * ->setValue('contact_id', '$id')
+ * ->setValue('group_id', 123)
+ * )
+ * ```
*
- * This will substitute the id of the newly created contact with $id.
+ * This will substitute the id of the newly created contact with `$id`.
*
* @var array
*/
/**
* Add debugging info to the api result.
*
- * When enabled, the $result->debug will be populated with information about the api call,
+ * When enabled, `$result->debug` will be populated with information about the api call,
* including sql queries executed.
*
- * Note: with checkPermissions enabled, debug info will only be returned if the user has "view debug output" permission.
+ * **Note:** with checkPermissions enabled, debug info will only be returned if the user has "view debug output" permission.
*
* @var bool
*/
* @param string $name
* Unique name for this chained request
* @param \Civi\Api4\Generic\AbstractAction $apiRequest
- * @param string|int $index
- * Either a string for how the results should be indexed e.g. 'name'
- * or the index of a single result to return e.g. 0 for the first result.
+ * @param string|int|array $index
+ * See `civicrm_api4()` for documentation of `$index` param
* @return $this
*/
public function addChain($name, AbstractAction $apiRequest, $index = NULL) {
public function getParamInfo($param = NULL) {
if (!isset($this->_paramInfo)) {
$defaults = $this->getParamDefaults();
+ $vars = [
+ 'entity' => $this->getEntityName(),
+ 'action' => $this->getActionName(),
+ ];
+ // For actions like "getFields" and "getActions" they are not getting the entity itself.
+ // So generic docs will make more sense like this:
+ if (substr($vars['action'], 0, 3) === 'get' && substr($vars['action'], -1) === 's') {
+ $vars['entity'] = lcfirst(substr($vars['action'], 3, -1));
+ }
foreach ($this->reflect()->getProperties(\ReflectionProperty::IS_PROTECTED) as $property) {
$name = $property->getName();
if ($name != 'version' && $name[0] != '_') {
- $this->_paramInfo[$name] = ReflectionUtils::getCodeDocs($property, 'Property');
+ $this->_paramInfo[$name] = ReflectionUtils::getCodeDocs($property, 'Property', $vars);
$this->_paramInfo[$name]['default'] = $defaults[$name];
}
}
*/
public function entityFields() {
if (!$this->_entityFields) {
- $getFields = ActionUtil::getAction($this->getEntityName(), 'getFields');
+ $getFields = \Civi\API\Request::create($this->getEntityName(), 'getFields', [
+ 'version' => 4,
+ 'checkPermissions' => $this->checkPermissions,
+ 'action' => $this->getActionName(),
+ 'includeCustom' => FALSE,
+ ]);
$result = new Result();
- if (method_exists($this, 'getBaoName')) {
- $getFields->setIncludeCustom(FALSE);
- }
- $getFields
- ->setCheckPermissions($this->checkPermissions)
- ->setAction($this->getActionName())
- ->_run($result);
+ $getFields->_run($result);
$this->_entityFields = (array) $result->indexBy('name');
}
return $this->_entityFields;
return $unmatched;
}
+ /**
+ * Replaces pseudoconstants in input values
+ *
+ * @param array $record
+ * @throws \API_Exception
+ */
+ protected function formatWriteValues(&$record) {
+ $optionFields = [];
+ // Collect fieldnames with a :pseudoconstant suffix & remove them from $record array
+ foreach (array_keys($record) as $expr) {
+ $suffix = strrpos($expr, ':');
+ if ($suffix) {
+ $fieldName = substr($expr, 0, $suffix);
+ $field = $this->entityFields()[$fieldName] ?? NULL;
+ if ($field) {
+ $optionFields[$fieldName] = [
+ 'val' => $record[$expr],
+ 'name' => empty($field['custom_field_id']) ? $field['name'] : 'custom_' . $field['custom_field_id'],
+ 'suffix' => substr($expr, $suffix + 1),
+ 'depends' => $field['input_attrs']['controlField'] ?? NULL,
+ ];
+ unset($record[$expr]);
+ }
+ }
+ }
+ // Sort option lookups by dependency, so e.g. country_id is processed first, then state_province_id, then county_id
+ uasort($optionFields, function ($a, $b) {
+ return $a['name'] === $b['depends'] ? -1 : 1;
+ });
+ // Replace pseudoconstants. Note this is a reverse lookup as we are evaluating input not output.
+ foreach ($optionFields as $fieldName => $info) {
+ $options = FormattingUtil::getPseudoconstantList($this->_entityName, $info['name'], $info['suffix'], $record, 'create');
+ $record[$fieldName] = FormattingUtil::replacePseudoconstant($options, $info['val'], TRUE);
+ }
+ }
+
/**
* This function is used internally for evaluating field annotations.
*