Merge pull request #23283 from eileenmcnaughton/import_saved_map
[civicrm-core.git] / tests / phpunit / api / v4 / Custom / CustomValueTest.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\Custom;
21
22 use Civi\Api4\CustomField;
23 use Civi\Api4\CustomGroup;
24 use Civi\Api4\CustomValue;
25 use Civi\Api4\Entity;
26
27 /**
28 * @group headless
29 */
30 class CustomValueTest extends CustomTestBase {
31
32 protected $contactID;
33
34 /**
35 * Test CustomValue::GetFields/Get/Create/Update/Replace/Delete
36 */
37 public function testCRUD() {
38 $optionValues = ['r' => 'Red', 'g' => 'Green', 'b' => 'Blue'];
39
40 $group = uniqid('groupc');
41 $colorFieldName = uniqid('colorc');
42 $multiFieldName = uniqid('chkbx');
43 $textFieldName = uniqid('txt');
44
45 $customGroup = CustomGroup::create(FALSE)
46 ->addValue('title', $group)
47 ->addValue('extends', 'Contact')
48 ->addValue('is_multiple', TRUE)
49 ->execute()
50 ->first();
51
52 $colorField = CustomField::create(FALSE)
53 ->addValue('label', $colorFieldName)
54 ->addValue('option_values', $optionValues)
55 ->addValue('custom_group_id', $customGroup['id'])
56 ->addValue('html_type', 'Select')
57 ->addValue('data_type', 'String')
58 ->execute()->first();
59
60 $multiField = CustomField::create(FALSE)
61 ->addValue('label', $multiFieldName)
62 ->addValue('option_values', $optionValues)
63 ->addValue('custom_group_id', $customGroup['id'])
64 ->addValue('html_type', 'CheckBox')
65 ->addValue('data_type', 'String')
66 ->execute()->first();
67
68 $textField = CustomField::create(FALSE)
69 ->addValue('label', $textFieldName)
70 ->addValue('custom_group_id', $customGroup['id'])
71 ->addValue('html_type', 'Text')
72 ->addValue('data_type', 'String')
73 ->execute()->first();
74
75 $this->contactID = $this->createTestRecord('Contact', [
76 'first_name' => 'Johann',
77 'last_name' => 'Tester',
78 'contact_type' => 'Individual',
79 ])['id'];
80
81 // Ensure virtual api entity has been created
82 $entity = Entity::get(FALSE)
83 ->addWhere('name', '=', "Custom_$group")
84 ->execute()->single();
85 $this->assertEquals(['CustomValue'], $entity['type']);
86 $this->assertEquals(['id'], $entity['primary_key']);
87 $this->assertEquals($customGroup['table_name'], $entity['table_name']);
88 $this->assertEquals('Civi\Api4\CustomValue', $entity['class']);
89 $this->assertEquals([$group], $entity['class_args']);
90 $this->assertEquals('secondary', $entity['searchable']);
91
92 // Retrieve and check the fields of CustomValue = Custom_$group
93 $fields = CustomValue::getFields($group, FALSE)->setLoadOptions(TRUE)->execute();
94 $expectedResult = [
95 [
96 'custom_group' => $group,
97 'type' => 'Field',
98 'name' => $colorFieldName,
99 'title' => $colorFieldName,
100 'entity' => "Custom_$group",
101 'table_name' => $customGroup['table_name'],
102 'column_name' => $colorField['column_name'],
103 'data_type' => 'String',
104 'fk_entity' => NULL,
105 'serialize' => 0,
106 'options' => $optionValues,
107 ],
108 [
109 'custom_group' => $group,
110 'type' => 'Field',
111 'name' => $multiFieldName,
112 'title' => $multiFieldName,
113 'entity' => "Custom_$group",
114 'table_name' => $customGroup['table_name'],
115 'column_name' => $multiField['column_name'],
116 'data_type' => 'String',
117 'fk_entity' => NULL,
118 'serialize' => 1,
119 'options' => $optionValues,
120 ],
121 [
122 'custom_group' => $group,
123 'type' => 'Field',
124 'name' => $textFieldName,
125 'title' => $textFieldName,
126 'entity' => "Custom_$group",
127 'table_name' => $customGroup['table_name'],
128 'column_name' => $textField['column_name'],
129 'data_type' => 'String',
130 'fk_entity' => NULL,
131 'serialize' => 0,
132 ],
133 [
134 'name' => 'id',
135 'type' => 'Field',
136 'title' => ts('Custom Value ID'),
137 'entity' => "Custom_$group",
138 'table_name' => $customGroup['table_name'],
139 'column_name' => 'id',
140 'data_type' => 'Integer',
141 'fk_entity' => NULL,
142 ],
143 [
144 'name' => 'entity_id',
145 'type' => 'Field',
146 'title' => ts('Entity ID'),
147 'table_name' => $customGroup['table_name'],
148 'column_name' => 'entity_id',
149 'entity' => "Custom_$group",
150 'data_type' => 'Integer',
151 'fk_entity' => 'Contact',
152 ],
153 ];
154
155 foreach ($expectedResult as $key => $field) {
156 foreach ($field as $attr => $value) {
157 $this->assertEquals($expectedResult[$key][$attr], $fields[$key][$attr], "$key $attr");
158 }
159 }
160
161 // CASE 1: Test CustomValue::create
162 // Create two records for a single contact and using CustomValue::get ensure that two records are created
163 $created = [
164 CustomValue::create($group)
165 ->addValue($colorFieldName, 'g')
166 ->addValue("entity_id", $this->contactID)
167 ->execute()->first(),
168 CustomValue::create($group)
169 ->addValue($colorFieldName . ':label', 'Red')
170 ->addValue("entity_id", $this->contactID)
171 ->execute()->first(),
172 ];
173 // fetch custom values using API4 CustomValue::get
174 $result = CustomValue::get($group)
175 ->addSelect('id', 'entity_id', $colorFieldName, $colorFieldName . ':label')
176 ->addOrderBy($colorFieldName, 'ASC')
177 ->execute();
178
179 // check if two custom values are created
180 $this->assertEquals(2, count($result));
181 $expectedResult = [
182 [
183 'id' => 1,
184 $colorFieldName => 'g',
185 $colorFieldName . ':label' => 'Green',
186 'entity_id' => $this->contactID,
187 ],
188 [
189 'id' => 2,
190 $colorFieldName => 'r',
191 $colorFieldName . ':label' => 'Red',
192 'entity_id' => $this->contactID,
193 ],
194 ];
195 // match the data
196 foreach ($expectedResult as $key => $field) {
197 foreach ($field as $attr => $value) {
198 $this->assertEquals($expectedResult[$key][$attr], $result[$key][$attr]);
199 if (!strpos($attr, ':')) {
200 $this->assertEquals($expectedResult[$key][$attr], $created[$key][$attr]);
201 }
202 }
203 }
204
205 // CASE 2: Test CustomValue::update
206 // Update a records whose id is 1 and change the custom field (name = Color) value to 'Blue' from 'Green'
207 CustomValue::update($group)
208 ->addWhere("id", "=", 1)
209 ->addValue($colorFieldName . ':label', 'Blue')
210 ->execute();
211
212 // ensure that the value is changed for id = 1
213 $color = CustomValue::get($group)
214 ->addWhere("id", "=", 1)
215 ->execute()
216 ->first()[$colorFieldName];
217 $this->assertEquals('b', $color);
218
219 // CASE 3: Test CustomValue::replace
220 // create a second contact which will be used to replace the custom values, created earlier
221 $secondContactID = $this->createTestRecord('Contact', [
222 'first_name' => 'Adam',
223 'last_name' => 'Tester',
224 'contact_type' => 'Individual',
225 ])['id'];
226 // Replace all the records which was created earlier with entity_id = first contact
227 // with custom record [$colorField => 'g', 'entity_id' => $secondContactID]
228 CustomValue::replace($group)
229 ->setRecords([[$colorFieldName => 'g', $multiFieldName . ':label' => ['Red', 'Green'], 'entity_id' => $secondContactID]])
230 ->addWhere('entity_id', '=', $this->contactID)
231 ->execute();
232
233 // Check the two records created earlier is replaced by new contact
234 $result = CustomValue::get($group)
235 ->addSelect('id', 'entity_id', $colorFieldName, $colorFieldName . ':label', $multiFieldName, $multiFieldName . ':label')
236 ->execute();
237 $this->assertEquals(1, count($result));
238
239 $expectedResult = [
240 [
241 'id' => 3,
242 $colorFieldName => 'g',
243 $colorFieldName . ':label' => 'Green',
244 $multiFieldName => ['r', 'g'],
245 $multiFieldName . ':label' => ['Red', 'Green'],
246 'entity_id' => $secondContactID,
247 ],
248 ];
249 foreach ($expectedResult as $key => $field) {
250 foreach ($field as $attr => $value) {
251 $this->assertEquals($expectedResult[$key][$attr], $result[$key][$attr]);
252 }
253 }
254
255 // Disable a field
256 CustomField::update(FALSE)
257 ->addValue('is_active', FALSE)
258 ->addWhere('id', '=', $multiField['id'])
259 ->execute();
260
261 $result = CustomValue::get($group)->execute()->single();
262 $this->assertArrayHasKey($colorFieldName, $result);
263 $this->assertArrayNotHasKey($multiFieldName, $result);
264
265 // CASE 4: Test CustomValue::delete
266 // There is only record left whose id = 3, delete that record on basis of criteria id = 3
267 CustomValue::delete($group)->addWhere("id", "=", 3)->execute();
268 $result = CustomValue::get($group)->execute();
269 // check that there are no custom values present
270 $this->assertEquals(0, count($result));
271 }
272
273 /**
274 * Whenever a CustomGroup toggles the `is_multiple` flag, the entity-list should be updated.
275 *
276 * @throws \API_Exception
277 * @throws \Civi\API\Exception\UnauthorizedException
278 */
279 public function testEntityRefresh() {
280 $groupName = uniqid('groupc');
281
282 $this->assertNotContains("Custom_$groupName", Entity::get()->execute()->column('name'));
283
284 CustomGroup::create(FALSE)
285 ->addValue('title', $groupName)
286 ->addValue('extends', 'Contact')
287 ->addValue('is_multiple', FALSE)
288 ->execute();
289
290 $this->assertNotContains("Custom_$groupName", Entity::get()->execute()->column('name'));
291
292 CustomGroup::update(FALSE)
293 ->addWhere('name', '=', $groupName)
294 ->addValue('is_multiple', TRUE)
295 ->execute();
296 $this->assertContains("Custom_$groupName", Entity::get()->execute()->column('name'));
297
298 CustomGroup::update(FALSE)
299 ->addWhere('name', '=', $groupName)
300 ->addValue('is_multiple', FALSE)
301 ->execute();
302 $this->assertNotContains("Custom_$groupName", Entity::get()->execute()->column('name'));
303 }
304
305 }