dev/core#2861 Saved search loading fix
[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 $field = new FieldSpec('groups', 'Contact', 'Array');
26 $field->setLabel(ts('In Groups'))
27 ->setTitle(ts('Groups'))
28 ->setColumnName('id')
29 ->setDescription(ts('Groups (or sub-groups of groups) to which this contact belongs'))
30 ->setType('Filter')
31 ->setOperators(['IN', 'NOT IN'])
32 ->addSqlFilter([__CLASS__, 'getContactGroupSql'])
33 ->setSuffixes(['id', 'name', 'label'])
34 ->setOptionsCallback([__CLASS__, 'getGroupList']);
35 $spec->addFieldSpec($field);
36 }
37
38 /**
39 * @param string $entity
40 * @param string $action
41 *
42 * @return bool
43 */
44 public function applies($entity, $action) {
45 return $entity === 'Contact' && $action === 'get';
46 }
47
48 /**
49 * @param array $field
50 * @param string $fieldAlias
51 * @param string $operator
52 * @param mixed $value
53 * @param \Civi\Api4\Query\Api4SelectQuery $query
54 * @param int $depth
55 * return string
56 */
57 public static function getContactGroupSql(array $field, string $fieldAlias, string $operator, $value, Api4SelectQuery $query, int $depth): string {
58 $tempTable = \CRM_Utils_SQL_TempTable::build();
59 $tempTable->createWithColumns('contact_id INT');
60 $tableName = $tempTable->getName();
61 \CRM_Contact_BAO_GroupContactCache::populateTemporaryTableWithContactsInGroups((array) $value, $tableName);
62 // SQL optimization - use INNER JOIN if the base table is Contact & this clause is not nested
63 if ($fieldAlias === '`a`.`id`' && $operator === "IN" && !$depth) {
64 $query->getQuery()->join($tableName, "INNER JOIN `$tableName` ON $fieldAlias = `$tableName`.contact_id");
65 return '1';
66 }
67 // Else use IN or NOT IN (this filter only supports those 2 operators)
68 else {
69 return "$fieldAlias $operator (SELECT contact_id FROM `$tableName`)";
70 }
71 }
72
73 /**
74 * Callback function to build option lists groups pseudo-field.
75 *
76 * @param \Civi\Api4\Service\Spec\FieldSpec $spec
77 * @param array $values
78 * @param bool|array $returnFormat
79 * @param bool $checkPermissions
80 * @return array
81 */
82 public static function getGroupList($spec, $values, $returnFormat, $checkPermissions) {
83 $groups = $checkPermissions ? \CRM_Core_PseudoConstant::group() : \CRM_Core_PseudoConstant::allGroup(NULL, FALSE);
84 $options = \CRM_Utils_Array::makeNonAssociative($groups, 'id', 'label');
85 if ($options && is_array($returnFormat) && in_array('name', $returnFormat)) {
86 $groupIndex = array_flip(array_keys($groups));
87 $dao = \CRM_Core_DAO::executeQuery('SELECT id, name FROM civicrm_group WHERE id IN (%1)', [
88 1 => [implode(',', array_keys($groups)), 'CommaSeparatedIntegers'],
89 ]);
90 while ($dao->fetch()) {
91 $options[$groupIndex[$dao->id]]['name'] = $dao->name;
92 }
93 }
94 return $options;
95 }
96
97 }