Skip to content

Commit

Permalink
Merge pull request #21718 from colemanw/age_years
Browse files Browse the repository at this point in the history
APIv4 - Add Contact.age_years extra field to make age calculations easy
  • Loading branch information
eileenmcnaughton authored Oct 4, 2021
2 parents 558b41a + 04ef69d commit 34258da
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 15 deletions.
23 changes: 23 additions & 0 deletions Civi/Api4/Service/Spec/Provider/ContactGetSpecProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ContactGetSpecProvider implements Generic\SpecProviderInterface {
* @param \Civi\Api4\Service\Spec\RequestSpec $spec
*/
public function modifySpec(RequestSpec $spec) {
// Groups field
$field = new FieldSpec('groups', 'Contact', 'Array');
$field->setLabel(ts('In Groups'))
->setTitle(ts('Groups'))
Expand All @@ -33,6 +34,19 @@ public function modifySpec(RequestSpec $spec) {
->setSuffixes(['id', 'name', 'label'])
->setOptionsCallback([__CLASS__, 'getGroupList']);
$spec->addFieldSpec($field);

// Age field
if (!$spec->getValue('contact_type') || $spec->getValue('contact_type') === 'Individual') {
$field = new FieldSpec('age_years', 'Contact', 'Integer');
$field->setLabel(ts('Age (years)'))
->setTitle(ts('Age (years)'))
->setColumnName('birth_date')
->setDescription(ts('Age of individual (in years)'))
->setType('Extra')
->setReadonly(TRUE)
->setSqlRenderer([__CLASS__, 'calculateAge']);
$spec->addFieldSpec($field);
}
}

/**
Expand Down Expand Up @@ -94,4 +108,13 @@ public static function getGroupList($spec, $values, $returnFormat, $checkPermiss
return $options;
}

/**
* Generate SQL for age field
* @param array $field
* @return string
*/
public static function calculateAge(array $field) {
return "TIMESTAMPDIFF(YEAR, {$field['sql_name']}, CURDATE())";
}

}
31 changes: 30 additions & 1 deletion Civi/Api4/Service/Spec/RequestSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,30 @@ class RequestSpec implements \Iterator {
*/
protected $fields = [];

/**
* @var array
*/
protected $values = [];

/**
* @param string $entity
* @param string $action
* @param array $values
*/
public function __construct($entity, $action) {
public function __construct($entity, $action, $values = []) {
$this->entity = $entity;
$this->action = $action;
$this->entityTableName = CoreUtil::getTableName($entity);
// Set contact_type from id if possible
if ($entity === 'Contact' && empty($values['contact_type']) && !empty($values['id'])) {
$values['contact_type'] = \CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $values['id'], 'contact_id');
}
$this->values = $values;
}

/**
* @param FieldSpec $field
*/
public function addFieldSpec(FieldSpec $field) {
if (!$field->getEntity()) {
$field->setEntity($this->entity);
Expand Down Expand Up @@ -126,6 +140,21 @@ public function getEntity() {
return $this->entity;
}

/**
* @return array
*/
public function getValues() {
return $this->values;
}

/**
* @param string $key
* @return mixed
*/
public function getValue(string $key) {
return $this->values[$key] ?? NULL;
}

/**
* @return string
*/
Expand Down
25 changes: 11 additions & 14 deletions Civi/Api4/Service/Spec/SpecGatherer.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SpecGatherer {
* @return \Civi\Api4\Service\Spec\RequestSpec
*/
public function getSpec($entity, $action, $includeCustom, $values = []) {
$specification = new RequestSpec($entity, $action);
$specification = new RequestSpec($entity, $action, $values);

// Real entities
if (strpos($entity, 'Custom_') !== 0) {
Expand Down Expand Up @@ -80,17 +80,16 @@ public function addSpecProvider(SpecProviderInterface $provider) {
/**
* @param string $entity
* @param string $action
* @param \Civi\Api4\Service\Spec\RequestSpec $specification
* @param array $values
* @param \Civi\Api4\Service\Spec\RequestSpec $spec
*/
private function addDAOFields($entity, $action, RequestSpec $specification, $values = []) {
private function addDAOFields($entity, $action, RequestSpec $spec) {
$DAOFields = $this->getDAOFields($entity);

foreach ($DAOFields as $DAOField) {
if ($DAOField['name'] == 'id' && $action == 'create') {
continue;
}
if (array_key_exists('contactType', $DAOField) && !empty($values['contact_type']) && $DAOField['contactType'] != $values['contact_type']) {
if (array_key_exists('contactType', $DAOField) && $spec->getValue('contact_type') && $DAOField['contactType'] != $spec->getValue('contact_type')) {
continue;
}
if (!empty($DAOField['component']) &&
Expand All @@ -105,28 +104,26 @@ private function addDAOFields($entity, $action, RequestSpec $specification, $val
$DAOField['default'] = '1';
}
$field = SpecFormatter::arrayToField($DAOField, $entity);
$specification->addFieldSpec($field);
$spec->addFieldSpec($field);
}
}

/**
* Get custom fields that extend this entity
*
* @see \CRM_Core_SelectValues::customGroupExtends
*
* @param string $entity
* @param \Civi\Api4\Service\Spec\RequestSpec $specification
* @param array $values
* @param \Civi\Api4\Service\Spec\RequestSpec $spec
* @throws \API_Exception
* @see \CRM_Core_SelectValues::customGroupExtends
*/
private function addCustomFields($entity, RequestSpec $specification, $values = []) {
private function addCustomFields($entity, RequestSpec $spec) {
$customInfo = \Civi\Api4\Utils\CoreUtil::getCustomGroupExtends($entity);
if (!$customInfo) {
return;
}
// If a contact_type was passed in, exclude custom groups for other contact types
if ($entity === 'Contact' && !empty($values['contact_type'])) {
$extends = ['Contact', $values['contact_type']];
if ($entity === 'Contact' && $spec->getValue('contact_type')) {
$extends = ['Contact', $spec->getValue('contact_type')];
}
else {
$extends = $customInfo['extends'];
Expand All @@ -139,7 +136,7 @@ private function addCustomFields($entity, RequestSpec $specification, $values =

foreach ($customFields as $fieldArray) {
$field = SpecFormatter::arrayToField($fieldArray, $entity);
$specification->addFieldSpec($field);
$spec->addFieldSpec($field);
}
}

Expand Down
23 changes: 23 additions & 0 deletions tests/phpunit/api/v4/Action/ContactGetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,27 @@ public function testOrClause(): void {
->execute();
}

public function testAge(): void {
$lastName = uniqid(__FUNCTION__);
$sampleData = [
['first_name' => 'abc', 'last_name' => $lastName, 'birth_date' => 'now - 1 year - 1 month'],
['first_name' => 'def', 'last_name' => $lastName, 'birth_date' => 'now - 21 year - 6 month'],
];
Contact::save(FALSE)
->setRecords($sampleData)
->execute();

$result = Contact::get(FALSE)
->addWhere('last_name', '=', $lastName)
->addSelect('first_name', 'age_years')
->execute()->indexBy('first_name');
$this->assertEquals(1, $result['abc']['age_years']);
$this->assertEquals(21, $result['def']['age_years']);

Contact::get(FALSE)
->addWhere('age_years', '=', 21)
->addWhere('last_name', '=', $lastName)
->execute()->single();
}

}

0 comments on commit 34258da

Please sign in to comment.