4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
7 | This work is published under the GNU AGPLv3 license with some |
8 | permitted exceptions and without any warranty. For full license |
9 | and copyright information, see https://civicrm.org/licensing |
10 +--------------------------------------------------------------------+
13 namespace Civi\Api4\Service\Spec\Provider
;
15 use Civi\Api4\Query\Api4SelectQuery
;
16 use Civi\Api4\Service\Spec\FieldSpec
;
17 use Civi\Api4\Service\Spec\RequestSpec
;
19 class ContactGetSpecProvider
implements Generic\SpecProviderInterface
{
22 * @param \Civi\Api4\Service\Spec\RequestSpec $spec
24 public function modifySpec(RequestSpec
$spec) {
26 $field = new FieldSpec('groups', 'Contact', 'Array');
27 $field->setLabel(ts('In Groups'))
28 ->setTitle(ts('Groups'))
30 ->setDescription(ts('Groups (or sub-groups of groups) to which this contact belongs'))
32 ->setOperators(['IN', 'NOT IN'])
33 ->addSqlFilter([__CLASS__
, 'getContactGroupSql'])
34 ->setSuffixes(['name', 'label'])
35 ->setOptionsCallback([__CLASS__
, 'getGroupList']);
36 $spec->addFieldSpec($field);
39 if (!$spec->getValue('contact_type') ||
$spec->getValue('contact_type') === 'Individual') {
40 $field = new FieldSpec('age_years', 'Contact', 'Integer');
41 $field->setLabel(ts('Age (years)'))
42 ->setTitle(ts('Age (years)'))
43 ->setColumnName('birth_date')
44 ->setDescription(ts('Age of individual (in years)'))
47 ->setSqlRenderer([__CLASS__
, 'calculateAge']);
48 $spec->addFieldSpec($field);
53 * @param string $entity
54 * @param string $action
58 public function applies($entity, $action) {
59 return $entity === 'Contact' && $action === 'get';
64 * @param string $fieldAlias
65 * @param string $operator
67 * @param \Civi\Api4\Query\Api4SelectQuery $query
71 public static function getContactGroupSql(array $field, string $fieldAlias, string $operator, $value, Api4SelectQuery
$query, int $depth): string {
72 $tempTable = \CRM_Utils_SQL_TempTable
::build();
73 $tempTable->createWithColumns('contact_id INT');
74 $tableName = $tempTable->getName();
75 \CRM_Contact_BAO_GroupContactCache
::populateTemporaryTableWithContactsInGroups((array) $value, $tableName);
76 // SQL optimization - use INNER JOIN if the base table is Contact & this clause is not nested
77 if ($fieldAlias === '`a`.`id`' && $operator === "IN" && !$depth) {
78 $query->getQuery()->join($tableName, "INNER JOIN `$tableName` ON $fieldAlias = `$tableName`.contact_id");
81 // Else use IN or NOT IN (this filter only supports those 2 operators)
83 return "$fieldAlias $operator (SELECT contact_id FROM `$tableName`)";
88 * Callback function to build option lists groups pseudo-field.
90 * @param \Civi\Api4\Service\Spec\FieldSpec $spec
91 * @param array $values
92 * @param bool|array $returnFormat
93 * @param bool $checkPermissions
96 public static function getGroupList($spec, $values, $returnFormat, $checkPermissions) {
97 $groups = $checkPermissions ? \CRM_Core_PseudoConstant
::group() : \CRM_Core_PseudoConstant
::allGroup(NULL, FALSE);
98 $options = \CRM_Utils_Array
::makeNonAssociative($groups, 'id', 'label');
99 if ($options && is_array($returnFormat) && in_array('name', $returnFormat)) {
100 $groupIndex = array_flip(array_keys($groups));
101 $dao = \CRM_Core_DAO
::executeQuery('SELECT id, name FROM civicrm_group WHERE id IN (%1)', [
102 1 => [implode(',', array_keys($groups)), 'CommaSeparatedIntegers'],
104 while ($dao->fetch()) {
105 $options[$groupIndex[$dao->id
]]['name'] = $dao->name
;
112 * Generate SQL for age field
113 * @param array $field
116 public static function calculateAge(array $field) {
117 return "TIMESTAMPDIFF(YEAR, {$field['sql_name']}, CURDATE())";