Add is empty filter to search / api
[civicrm-core.git] / tests / phpunit / api / v4 / Action / ContactGetTest.php
CommitLineData
19b53e5b
C
1<?php
2
380f3545
TO
3/*
4 +--------------------------------------------------------------------+
7d61e75f 5 | Copyright CiviCRM LLC. All rights reserved. |
380f3545 6 | |
7d61e75f
TO
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 |
380f3545
TO
10 +--------------------------------------------------------------------+
11 */
12
13/**
14 *
15 * @package CRM
ca5cec67 16 * @copyright CiviCRM LLC https://civicrm.org/licensing
380f3545
TO
17 */
18
19
19b53e5b
C
20namespace api\v4\Action;
21
22use Civi\Api4\Contact;
23
24/**
25 * @group headless
26 */
27class ContactGetTest extends \api\v4\UnitTestCase {
28
29 public function testGetDeletedContacts() {
30 $last_name = uniqid('deleteContactTest');
31
32 $bob = Contact::create()
33 ->setValues(['first_name' => 'Bob', 'last_name' => $last_name])
34 ->execute()->first();
35
36 $jan = Contact::create()
37 ->setValues(['first_name' => 'Jan', 'last_name' => $last_name])
38 ->execute()->first();
39
40 $del = Contact::create()
41 ->setValues(['first_name' => 'Del', 'last_name' => $last_name, 'is_deleted' => 1])
42 ->execute()->first();
43
44 // Deleted contacts are not fetched by default
45 $this->assertCount(2, Contact::get()->addWhere('last_name', '=', $last_name)->selectRowCount()->execute());
46
47 // You can search for them specifically
48 $contacts = Contact::get()->addWhere('last_name', '=', $last_name)->addWhere('is_deleted', '=', 1)->addSelect('id')->execute();
49 $this->assertEquals($del['id'], $contacts->first()['id']);
50
51 // Or by id
52 $this->assertCount(3, Contact::get()->addWhere('id', 'IN', [$bob['id'], $jan['id'], $del['id']])->selectRowCount()->execute());
53
54 // Putting is_deleted anywhere in the where clause will disable the default
55 $contacts = Contact::get()->addClause('OR', ['last_name', '=', $last_name], ['is_deleted', '=', 0])->addSelect('id')->execute();
56 $this->assertContains($del['id'], $contacts->column('id'));
57 }
58
f8bf8e26
CW
59 public function testGetWithLimit() {
60 $last_name = uniqid('getWithLimitTest');
61
62 $bob = Contact::create()
63 ->setValues(['first_name' => 'Bob', 'last_name' => $last_name])
64 ->execute()->first();
65
66 $jan = Contact::create()
67 ->setValues(['first_name' => 'Jan', 'last_name' => $last_name])
68 ->execute()->first();
69
70 $dan = Contact::create()
71 ->setValues(['first_name' => 'Dan', 'last_name' => $last_name])
72 ->execute()->first();
73
fe806431 74 $num = Contact::get(FALSE)->selectRowCount()->execute()->count();
651c4c95
CW
75
76 // The object's count() method will account for all results, ignoring limit & offset, while the array results are limited
fe806431 77 $offset1 = Contact::get(FALSE)->setOffset(1)->execute();
651c4c95
CW
78 $this->assertCount($num, $offset1);
79 $this->assertCount($num - 1, (array) $offset1);
fe806431 80 $offset2 = Contact::get(FALSE)->setOffset(2)->execute();
651c4c95
CW
81 $this->assertCount($num - 2, (array) $offset2);
82 $this->assertCount($num, $offset2);
83 // With limit, it doesn't fetch total count by default
fe806431 84 $limit2 = Contact::get(FALSE)->setLimit(2)->execute();
651c4c95
CW
85 $this->assertCount(2, (array) $limit2);
86 $this->assertCount(2, $limit2);
87 // With limit, you have to trigger the full row count manually
fe806431 88 $limit2 = Contact::get(FALSE)->setLimit(2)->addSelect('sort_name', 'row_count')->execute();
651c4c95
CW
89 $this->assertCount(2, (array) $limit2);
90 $this->assertCount($num, $limit2);
d34aa010 91 $msg = '';
4c6ad36a
TO
92 try {
93 $limit2->single();
94 }
95 catch (\API_Exception $e) {
d34aa010 96 $msg = $e->getMessage();
4c6ad36a 97 }
d34aa010 98 $this->assertRegExp(';Expected to find one Contact record;', $msg);
4c6ad36a
TO
99 $limit1 = Contact::get(FALSE)->setLimit(1)->execute();
100 $this->assertCount(1, (array) $limit1);
101 $this->assertCount(1, $limit1);
102 $this->assertTrue(!empty($limit1->single()['sort_name']));
f8bf8e26
CW
103 }
104
91f1ab62 105 /**
106 * Test a lack of fatal errors when the where contains an emoji.
107 *
108 * By default our DBs are not 🦉 compliant. This test will age
109 * out when we are.
110 *
111 * @throws \API_Exception
112 */
113 public function testEmoji(): void {
114 $schemaNeedsAlter = \CRM_Core_BAO_SchemaHandler::databaseSupportsUTF8MB4();
115 if ($schemaNeedsAlter) {
116 \CRM_Core_DAO::executeQuery("
117 ALTER TABLE civicrm_contact MODIFY COLUMN
118 `first_name` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'First Name.',
119 CHARSET utf8
120 ");
121 }
122 Contact::get()
123 ->setDebug(TRUE)
124 ->addWhere('first_name', '=', '🦉Claire')
125 ->execute();
126 if ($schemaNeedsAlter) {
127 \CRM_Core_DAO::executeQuery("
128 ALTER TABLE civicrm_contact MODIFY COLUMN
129 `first_name` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'First Name.',
130 CHARSET utf8mb4
131 ");
132 }
133 }
134
c0e68893 135 public function testEmptyAndNullOperators() {
136 $last_name = uniqid(__FUNCTION__);
137
138 $bob = Contact::create()
139 ->setValues(['first_name' => 'Bob', 'last_name' => $last_name, 'prefix_id' => 0])
140 ->execute()->first();
141 // Initial value is NULL, but to test the empty operator, change it to an empty string
142 \CRM_Core_DAO::executeQuery("UPDATE civicrm_contact SET middle_name = '' WHERE id = " . $bob['id']);
143
144 $jan = Contact::create()
145 ->setValues(['first_name' => 'Jan', 'middle_name' => 'J', 'last_name' => $last_name, 'prefix_id' => 1])
146 ->execute()->first();
147
148 $dan = Contact::create()
149 ->setValues(['first_name' => 'Dan', 'last_name' => $last_name, 'prefix_id' => NULL])
150 ->execute()->first();
151
152 // Test EMPTY and NULL operators on string fields
153 $result = Contact::get(FALSE)
154 ->addWhere('last_name', '=', $last_name)
155 ->addWhere('middle_name', 'IS EMPTY')
156 ->execute()->indexBy('id');
157 $this->assertCount(2, $result);
158 $this->assertArrayNotHasKey($jan['id'], (array) $result);
159
160 $result = Contact::get(FALSE)
161 ->addWhere('last_name', '=', $last_name)
162 ->addWhere('middle_name', 'IS NOT NULL')
163 ->execute()->indexBy('id');
164 $this->assertCount(2, $result);
165 $this->assertArrayNotHasKey($dan['id'], (array) $result);
166
167 $result = Contact::get(FALSE)
168 ->addWhere('last_name', '=', $last_name)
169 ->addWhere('middle_name', 'IS NOT EMPTY')
170 ->execute()->indexBy('id');
171 $this->assertCount(1, $result);
172 $this->assertArrayHasKey($jan['id'], (array) $result);
173
174 // Test EMPTY and NULL operators on Integer fields
175 $result = Contact::get(FALSE)
176 ->addWhere('last_name', '=', $last_name)
177 ->addWhere('prefix_id', 'IS EMPTY')
178 ->execute()->indexBy('id');
179 $this->assertCount(2, $result);
180 $this->assertArrayNotHasKey($jan['id'], (array) $result);
181
182 $result = Contact::get(FALSE)
183 ->addWhere('last_name', '=', $last_name)
184 ->addWhere('prefix_id', 'IS NOT NULL')
185 ->execute()->indexBy('id');
186 $this->assertCount(2, $result);
187 $this->assertArrayNotHasKey($dan['id'], (array) $result);
188
189 $result = Contact::get(FALSE)
190 ->addWhere('last_name', '=', $last_name)
191 ->addWhere('prefix_id', 'IS NOT EMPTY')
192 ->execute()->indexBy('id');
193 $this->assertCount(1, $result);
194 $this->assertArrayHasKey($jan['id'], (array) $result);
195 }
196
19b53e5b 197}