Merge pull request #20929 from eileenmcnaughton/5.40
[civicrm-core.git] / tests / phpunit / api / v4 / Action / BasicCustomFieldTest.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 /**
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 */
18
19
20 namespace api\v4\Action;
21
22 use Civi\Api4\Contact;
23 use Civi\Api4\CustomField;
24 use Civi\Api4\CustomGroup;
25 use Civi\Api4\OptionGroup;
26 use Civi\Api4\Relationship;
27 use Civi\Api4\RelationshipCache;
28
29 /**
30 * @group headless
31 */
32 class BasicCustomFieldTest extends BaseCustomValueTest {
33
34 public function testWithSingleField() {
35
36 $customGroup = CustomGroup::create(FALSE)
37 ->addValue('name', 'MyIndividualFields')
38 ->addValue('extends', 'Individual')
39 ->execute()
40 ->first();
41
42 CustomField::create(FALSE)
43 ->addValue('label', 'FavColor')
44 ->addValue('custom_group_id', $customGroup['id'])
45 ->addValue('html_type', 'Text')
46 ->addValue('data_type', 'String')
47 ->execute();
48
49 // Individual fields should show up when contact_type = null|Individual but not other contact types
50 $getFields = Contact::getFields(FALSE);
51 $this->assertEquals('Custom', $getFields->execute()->indexBy('name')['MyIndividualFields.FavColor']['type']);
52 $this->assertContains('MyIndividualFields.FavColor', $getFields->setValues(['contact_type' => 'Individual'])->execute()->column('name'));
53 $this->assertNotContains('MyIndividualFields.FavColor', $getFields->setValues(['contact_type' => 'Household'])->execute()->column('name'));
54
55 $contactId = Contact::create(FALSE)
56 ->addValue('first_name', 'Johann')
57 ->addValue('last_name', 'Tester')
58 ->addValue('contact_type', 'Individual')
59 ->addValue('MyIndividualFields.FavColor', 'Red')
60 ->execute()
61 ->first()['id'];
62
63 $contact = Contact::get(FALSE)
64 ->addSelect('first_name')
65 ->addSelect('MyIndividualFields.FavColor')
66 ->addWhere('id', '=', $contactId)
67 ->addWhere('MyIndividualFields.FavColor', '=', 'Red')
68 ->execute()
69 ->first();
70
71 $this->assertEquals('Red', $contact['MyIndividualFields.FavColor']);
72
73 Contact::update()
74 ->addWhere('id', '=', $contactId)
75 ->addValue('MyIndividualFields.FavColor', 'Blue')
76 ->execute();
77
78 $contact = Contact::get(FALSE)
79 ->addSelect('MyIndividualFields.FavColor')
80 ->addWhere('id', '=', $contactId)
81 ->execute()
82 ->first();
83
84 $this->assertEquals('Blue', $contact['MyIndividualFields.FavColor']);
85 }
86
87 public function testWithTwoFields() {
88
89 // First custom set
90 CustomGroup::create(FALSE)
91 ->addValue('name', 'MyContactFields')
92 ->addValue('extends', 'Contact')
93 ->addChain('field1', CustomField::create()
94 ->addValue('label', 'FavColor')
95 ->addValue('custom_group_id', '$id')
96 ->addValue('html_type', 'Text')
97 ->addValue('data_type', 'String'))
98 ->addChain('field2', CustomField::create()
99 ->addValue('label', 'FavFood')
100 ->addValue('custom_group_id', '$id')
101 ->addValue('html_type', 'Text')
102 ->addValue('data_type', 'String'))
103 ->execute();
104
105 // Second custom set
106 CustomGroup::create(FALSE)
107 ->addValue('name', 'MyContactFields2')
108 ->addValue('extends', 'Contact')
109 ->addChain('field1', CustomField::create()
110 ->addValue('label', 'FavColor')
111 ->addValue('custom_group_id', '$id')
112 ->addValue('html_type', 'Text')
113 ->addValue('data_type', 'String'))
114 ->addChain('field2', CustomField::create()
115 ->addValue('label', 'FavFood')
116 ->addValue('custom_group_id', '$id')
117 ->addValue('html_type', 'Text')
118 ->addValue('data_type', 'String'))
119 ->execute();
120
121 $contactId1 = Contact::create(FALSE)
122 ->addValue('first_name', 'Johann')
123 ->addValue('last_name', 'Tester')
124 ->addValue('MyContactFields.FavColor', 'Red')
125 ->addValue('MyContactFields.FavFood', 'Cherry')
126 ->execute()
127 ->first()['id'];
128
129 $contactId2 = Contact::create(FALSE)
130 ->addValue('first_name', 'MaryLou')
131 ->addValue('last_name', 'Tester')
132 ->addValue('MyContactFields.FavColor', 'Purple')
133 ->addValue('MyContactFields.FavFood', 'Grapes')
134 ->execute()
135 ->first()['id'];
136
137 $contact = Contact::get(FALSE)
138 ->addSelect('first_name')
139 ->addSelect('MyContactFields.FavColor')
140 ->addSelect('MyContactFields.FavFood')
141 ->addWhere('id', '=', $contactId1)
142 ->addWhere('MyContactFields.FavColor', '=', 'Red')
143 ->addWhere('MyContactFields.FavFood', '=', 'Cherry')
144 ->execute()
145 ->first();
146 $this->assertArrayHasKey('MyContactFields.FavColor', $contact);
147 $this->assertEquals('Red', $contact['MyContactFields.FavColor']);
148
149 // By default custom fields are not returned
150 $contact = Contact::get(FALSE)
151 ->addWhere('id', '=', $contactId1)
152 ->addWhere('MyContactFields.FavColor', '=', 'Red')
153 ->addWhere('MyContactFields.FavFood', '=', 'Cherry')
154 ->execute()
155 ->first();
156 $this->assertArrayNotHasKey('MyContactFields.FavColor', $contact);
157
158 // Update 2nd set and ensure 1st hasn't changed
159 Contact::update()
160 ->addWhere('id', '=', $contactId1)
161 ->addValue('MyContactFields2.FavColor', 'Orange')
162 ->addValue('MyContactFields2.FavFood', 'Tangerine')
163 ->execute();
164 $contact = Contact::get(FALSE)
165 ->addSelect('MyContactFields.FavColor', 'MyContactFields2.FavColor', 'MyContactFields.FavFood', 'MyContactFields2.FavFood')
166 ->addWhere('id', '=', $contactId1)
167 ->execute()
168 ->first();
169 $this->assertEquals('Red', $contact['MyContactFields.FavColor']);
170 $this->assertEquals('Orange', $contact['MyContactFields2.FavColor']);
171 $this->assertEquals('Cherry', $contact['MyContactFields.FavFood']);
172 $this->assertEquals('Tangerine', $contact['MyContactFields2.FavFood']);
173
174 // Update 1st set and ensure 2st hasn't changed
175 Contact::update()
176 ->addWhere('id', '=', $contactId1)
177 ->addValue('MyContactFields.FavColor', 'Blue')
178 ->execute();
179 $contact = Contact::get(FALSE)
180 ->addSelect('custom.*')
181 ->addWhere('id', '=', $contactId1)
182 ->execute()
183 ->first();
184 $this->assertEquals('Blue', $contact['MyContactFields.FavColor']);
185 $this->assertEquals('Orange', $contact['MyContactFields2.FavColor']);
186 $this->assertEquals('Cherry', $contact['MyContactFields.FavFood']);
187 $this->assertEquals('Tangerine', $contact['MyContactFields2.FavFood']);
188
189 $search = Contact::get(FALSE)
190 ->addClause('OR', ['MyContactFields.FavColor', '=', 'Blue'], ['MyContactFields.FavFood', '=', 'Grapes'])
191 ->addSelect('id')
192 ->addOrderBy('id')
193 ->execute()
194 ->indexBy('id');
195
196 $this->assertEquals([$contactId1, $contactId2], array_keys((array) $search));
197
198 $search = Contact::get(FALSE)
199 ->addClause('NOT', ['MyContactFields.FavColor', '=', 'Purple'], ['MyContactFields.FavFood', '=', 'Grapes'])
200 ->addSelect('id')
201 ->addOrderBy('id')
202 ->execute()
203 ->indexBy('id');
204
205 $this->assertNotContains($contactId2, array_keys((array) $search));
206
207 $search = Contact::get(FALSE)
208 ->addClause('NOT', ['MyContactFields.FavColor', '=', 'Purple'], ['MyContactFields.FavFood', '=', 'Grapes'])
209 ->addSelect('id')
210 ->addOrderBy('id')
211 ->execute()
212 ->indexBy('id');
213
214 $this->assertContains($contactId1, array_keys((array) $search));
215 $this->assertNotContains($contactId2, array_keys((array) $search));
216
217 $search = Contact::get(FALSE)
218 ->setWhere([['NOT', ['OR', [['MyContactFields.FavColor', '=', 'Blue'], ['MyContactFields.FavFood', '=', 'Grapes']]]]])
219 ->addSelect('id')
220 ->addOrderBy('id')
221 ->execute()
222 ->indexBy('id');
223
224 $this->assertNotContains($contactId1, array_keys((array) $search));
225 $this->assertNotContains($contactId2, array_keys((array) $search));
226 }
227
228 public function testRelationshipCacheCustomFields() {
229 $cgName = uniqid('RelFields');
230
231 $customGroup = CustomGroup::create(FALSE)
232 ->addValue('name', $cgName)
233 ->addValue('extends', 'Relationship')
234 ->execute()
235 ->first();
236
237 CustomField::create(FALSE)
238 ->addValue('label', 'PetName')
239 ->addValue('custom_group_id', $customGroup['id'])
240 ->addValue('html_type', 'Text')
241 ->addValue('data_type', 'String')
242 ->execute();
243
244 $parent = Contact::create(FALSE)
245 ->addValue('first_name', 'Parent')
246 ->addValue('last_name', 'Tester')
247 ->addValue('contact_type', 'Individual')
248 ->execute()
249 ->first()['id'];
250
251 $child = Contact::create(FALSE)
252 ->addValue('first_name', 'Child')
253 ->addValue('last_name', 'Tester')
254 ->addValue('contact_type', 'Individual')
255 ->execute()
256 ->first()['id'];
257
258 $relationship = Relationship::create(FALSE)
259 ->addValue('contact_id_a', $parent)
260 ->addValue('contact_id_b', $child)
261 ->addValue('relationship_type_id', 1)
262 ->addValue("$cgName.PetName", 'Buddy')
263 ->execute();
264
265 $results = RelationshipCache::get(FALSE)
266 ->addSelect("$cgName.PetName")
267 ->addWhere("$cgName.PetName", '=', 'Buddy')
268 ->execute();
269
270 $this->assertCount(2, $results);
271 $this->assertEquals('Buddy', $results[0]["$cgName.PetName"]);
272 }
273
274 /**
275 * Some types are creating a dummy option group even if we don't have
276 * any option values.
277 * @throws \API_Exception
278 */
279 public function testUndesiredOptionGroupCreation(): void {
280 $optionGroupCount = OptionGroup::get(FALSE)->selectRowCount()->execute()->count();
281
282 $customGroup = CustomGroup::create(FALSE)
283 ->addValue('name', 'MyIndividualFields')
284 ->addValue('extends', 'Individual')
285 ->execute()
286 ->first();
287
288 // This one doesn't make sense to have an option group.
289 CustomField::create(FALSE)
290 ->addValue('label', 'FavColor')
291 ->addValue('custom_group_id', $customGroup['id'])
292 ->addValue('html_type', 'Number')
293 ->addValue('data_type', 'Money')
294 ->execute();
295
296 // This one might be ok if we planned to then use the autocreated option
297 // group, but if we go on to create our own after then we have an extra
298 // unused group.
299 CustomField::create(FALSE)
300 ->addValue('label', 'FavMovie')
301 ->addValue('custom_group_id', $customGroup['id'])
302 ->addValue('html_type', 'Select')
303 ->addValue('data_type', 'String')
304 ->execute();
305
306 $this->assertEquals($optionGroupCount, OptionGroup::get(FALSE)->selectRowCount()->execute()->count());
307 }
308
309 }