Merge pull request #22487 from mattwire/repeattransactiontemplatecontribution
[civicrm-core.git] / Civi / Api4 / Service / Spec / Provider / ContactGetSpecProvider.php
1 <?php
2
3 /*
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
6 | |
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 +--------------------------------------------------------------------+
11 */
12
13 namespace Civi\Api4\Service\Spec\Provider;
14
15 use Civi\Api4\Query\Api4SelectQuery;
16 use Civi\Api4\Service\Spec\FieldSpec;
17 use Civi\Api4\Service\Spec\RequestSpec;
18
19 class ContactGetSpecProvider implements Generic\SpecProviderInterface {
20
21 /**
22 * @param \Civi\Api4\Service\Spec\RequestSpec $spec
23 */
24 public function modifySpec(RequestSpec $spec) {
25 // Groups field
26 $field = new FieldSpec('groups', 'Contact', 'Array');
27 $field->setLabel(ts('In Groups'))
28 ->setTitle(ts('Groups'))
29 ->setColumnName('id')
30 ->setDescription(ts('Groups (or sub-groups of groups) to which this contact belongs'))
31 ->setType('Filter')
32 ->setOperators(['IN', 'NOT IN'])
33 ->addSqlFilter([__CLASS__, 'getContactGroupSql'])
34 ->setSuffixes(['name', 'label'])
35 ->setOptionsCallback([__CLASS__, 'getGroupList']);
36 $spec->addFieldSpec($field);
37
38 // Age 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)'))
45 ->setType('Extra')
46 ->setReadonly(TRUE)
47 ->setSqlRenderer([__CLASS__, 'calculateAge']);
48 $spec->addFieldSpec($field);
49 }
50 }
51
52 /**
53 * @param string $entity
54 * @param string $action
55 *
56 * @return bool
57 */
58 public function applies($entity, $action) {
59 return $entity === 'Contact' && $action === 'get';
60 }
61
62 /**
63 * @param array $field
64 * @param string $fieldAlias
65 * @param string $operator
66 * @param mixed $value
67 * @param \Civi\Api4\Query\Api4SelectQuery $query
68 * @param int $depth
69 * return string
70 */
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");
79 return '1';
80 }
81 // Else use IN or NOT IN (this filter only supports those 2 operators)
82 else {
83 return "$fieldAlias $operator (SELECT contact_id FROM `$tableName`)";
84 }
85 }
86
87 /**
88 * Callback function to build option lists groups pseudo-field.
89 *
90 * @param \Civi\Api4\Service\Spec\FieldSpec $spec
91 * @param array $values
92 * @param bool|array $returnFormat
93 * @param bool $checkPermissions
94 * @return array
95 */
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'],
103 ]);
104 while ($dao->fetch()) {
105 $options[$groupIndex[$dao->id]]['name'] = $dao->name;
106 }
107 }
108 return $options;
109 }
110
111 /**
112 * Generate SQL for age field
113 * @param array $field
114 * @return string
115 */
116 public static function calculateAge(array $field) {
117 return "TIMESTAMPDIFF(YEAR, {$field['sql_name']}, CURDATE())";
118 }
119
120 }