Merge pull request #14891 from eileenmcnaughton/saved_search
[civicrm-core.git] / tests / phpunit / CRM / Case / XMLProcessor / ProcessTest.php
1 <?php
2 require_once 'CiviTest/CiviCaseTestCase.php';
3
4 /**
5 * Class CRM_Case_PseudoConstantTest
6 * @group headless
7 */
8 class CRM_Case_XMLProcessor_ProcessTest extends CiviCaseTestCase {
9
10 public function setUp() {
11 parent::setUp();
12
13 $this->defaultAssigneeOptionsValues = [];
14
15 $this->setupContacts();
16 $this->setupDefaultAssigneeOptions();
17 $this->setupRelationships();
18 $this->setupActivityDefinitions();
19
20 $this->process = new CRM_Case_XMLProcessor_Process();
21 }
22
23 /**
24 * Creates sample contacts.
25 */
26 protected function setUpContacts() {
27 $this->contacts = [
28 'ana' => $this->individualCreate(),
29 'beto' => $this->individualCreate(),
30 'carlos' => $this->individualCreate(),
31 ];
32 }
33
34 /**
35 * Adds the default assignee group and options to the test database.
36 * It also stores the IDs of the options in an index.
37 */
38 protected function setupDefaultAssigneeOptions() {
39 $options = [
40 'NONE', 'BY_RELATIONSHIP', 'SPECIFIC_CONTACT', 'USER_CREATING_THE_CASE',
41 ];
42
43 CRM_Core_BAO_OptionGroup::ensureOptionGroupExists([
44 'name' => 'activity_default_assignee',
45 ]);
46
47 foreach ($options as $option) {
48 $optionValue = CRM_Core_BAO_OptionValue::ensureOptionValueExists([
49 'option_group_id' => 'activity_default_assignee',
50 'name' => $option,
51 'label' => $option,
52 ]);
53
54 $this->defaultAssigneeOptionsValues[$option] = $optionValue['value'];
55 }
56 }
57
58 /**
59 * Adds a relationship between the activity's target contact and default assignee.
60 */
61 protected function setupRelationships() {
62 $this->relationships = [
63 'ana_is_pupil_of_beto' => [
64 'type_id' => NULL,
65 'name_a_b' => 'Pupil of',
66 'name_b_a' => 'Instructor',
67 'contact_id_a' => $this->contacts['ana'],
68 'contact_id_b' => $this->contacts['beto'],
69 ],
70 'ana_is_spouse_of_carlos' => [
71 'type_id' => NULL,
72 'name_a_b' => 'Spouse of',
73 'name_b_a' => 'Spouse of',
74 'contact_id_a' => $this->contacts['ana'],
75 'contact_id_b' => $this->contacts['carlos'],
76 ],
77 'unassigned_employee' => [
78 'type_id' => NULL,
79 'name_a_b' => 'Employee of',
80 'name_b_a' => 'Employer',
81 ],
82 ];
83
84 foreach ($this->relationships as $name => &$relationship) {
85 $relationship['type_id'] = $this->relationshipTypeCreate([
86 'contact_type_a' => 'Individual',
87 'contact_type_b' => 'Individual',
88 'name_a_b' => $relationship['name_a_b'],
89 'label_a_b' => $relationship['name_a_b'],
90 'name_b_a' => $relationship['name_b_a'],
91 'label_b_a' => $relationship['name_b_a'],
92 ]);
93
94 if (isset($relationship['contact_id_a'])) {
95 $this->callAPISuccess('Relationship', 'create', [
96 'contact_id_a' => $relationship['contact_id_a'],
97 'contact_id_b' => $relationship['contact_id_b'],
98 'relationship_type_id' => $relationship['type_id'],
99 ]);
100 }
101 }
102 }
103
104 /**
105 * Defines the the activity parameters and XML definitions. These can be used
106 * to create the activity.
107 */
108 protected function setupActivityDefinitions() {
109 $activityTypeXml = '<activity-type><name>Open Case</name></activity-type>';
110 $this->activityTypeXml = new SimpleXMLElement($activityTypeXml);
111 $this->activityParams = [
112 'activity_date_time' => date('Ymd'),
113 'caseID' => $this->caseTypeId,
114 'clientID' => $this->contacts['ana'],
115 'creatorID' => $this->_loggedInUser,
116 ];
117 }
118
119 /**
120 * Tests the creation of activities where the default assignee should be the
121 * target contact's instructor. Beto is the instructor for Ana.
122 */
123 public function testCreateActivityWithDefaultContactByRelationship() {
124 $relationship = $this->relationships['ana_is_pupil_of_beto'];
125 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['BY_RELATIONSHIP'];
126 $this->activityTypeXml->default_assignee_relationship = "{$relationship['type_id']}_b_a";
127
128 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
129 $this->assertActivityAssignedToContactExists($this->contacts['beto']);
130 }
131
132 /**
133 * Tests when the default assignee relationship exists, but in the other direction only.
134 * Ana is a pupil, but has no pupils related to her.
135 */
136 public function testCreateActivityWithDefaultContactByRelationshipMissing() {
137 $relationship = $this->relationships['ana_is_pupil_of_beto'];
138 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['BY_RELATIONSHIP'];
139 $this->activityTypeXml->default_assignee_relationship = "{$relationship['type_id']}_a_b";
140
141 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
142 $this->assertActivityAssignedToContactExists(NULL);
143 }
144
145 /**
146 * Tests when the the default assignee relationship exists and is a bidirectional
147 * relationship. Ana and Carlos are spouses.
148 */
149 public function testCreateActivityWithDefaultContactByRelationshipBidirectional() {
150 $relationship = $this->relationships['ana_is_spouse_of_carlos'];
151 $this->activityParams['clientID'] = $this->contacts['carlos'];
152 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['BY_RELATIONSHIP'];
153 $this->activityTypeXml->default_assignee_relationship = "{$relationship['type_id']}_a_b";
154
155 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
156 $this->assertActivityAssignedToContactExists($this->contacts['ana']);
157 }
158
159 /**
160 * Tests when the default assignee relationship does not exist. Ana is not an
161 * employee for anyone.
162 */
163 public function testCreateActivityWithDefaultContactByRelationButTheresNoRelationship() {
164 $relationship = $this->relationships['unassigned_employee'];
165 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['BY_RELATIONSHIP'];
166 $this->activityTypeXml->default_assignee_relationship = "{$relationship['type_id']}_b_a";
167
168 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
169 $this->assertActivityAssignedToContactExists(NULL);
170 }
171
172 /**
173 * Tests the creation of activities with default assignee set to a specific contact.
174 */
175 public function testCreateActivityAssignedToSpecificContact() {
176 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['SPECIFIC_CONTACT'];
177 $this->activityTypeXml->default_assignee_contact = $this->contacts['carlos'];
178
179 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
180 $this->assertActivityAssignedToContactExists($this->contacts['carlos']);
181 }
182
183 /**
184 * Tests the creation of activities with default assignee set to a specific contact,
185 * but the contact does not exist.
186 */
187 public function testCreateActivityAssignedToNonExistantSpecificContact() {
188 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['SPECIFIC_CONTACT'];
189 $this->activityTypeXml->default_assignee_contact = 987456321;
190
191 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
192 $this->assertActivityAssignedToContactExists(NULL);
193 }
194
195 /**
196 * Tests the creation of activities with the default assignee being the one
197 * creating the case's activity.
198 */
199 public function testCreateActivityAssignedToUserCreatingTheCase() {
200 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['USER_CREATING_THE_CASE'];
201
202 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
203 $this->assertActivityAssignedToContactExists($this->_loggedInUser);
204 }
205
206 /**
207 * Tests the creation of activities when the default assignee is set to NONE.
208 */
209 public function testCreateActivityAssignedNoUser() {
210 $this->activityTypeXml->default_assignee_type = $this->defaultAssigneeOptionsValues['NONE'];
211
212 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
213 $this->assertActivityAssignedToContactExists(NULL);
214 }
215
216 /**
217 * Tests the creation of activities when the default assignee is set to NONE.
218 */
219 public function testCreateActivityWithNoDefaultAssigneeOption() {
220 $this->process->createActivity($this->activityTypeXml, $this->activityParams);
221 $this->assertActivityAssignedToContactExists(NULL);
222 }
223
224 /**
225 * Asserts that an activity was created where the assignee was the one related
226 * to the target contact.
227 *
228 * @param int|null $assigneeContactId the ID of the expected assigned contact or NULL if expected to be empty.
229 */
230 protected function assertActivityAssignedToContactExists($assigneeContactId) {
231 $expectedContact = $assigneeContactId === NULL ? [] : [$assigneeContactId];
232 $result = $this->callAPISuccess('Activity', 'get', [
233 'target_contact_id' => $this->activityParams['clientID'],
234 'return' => ['assignee_contact_id'],
235 ]);
236 $activity = CRM_Utils_Array::first($result['values']);
237
238 $this->assertNotNull($activity, 'Target contact has no activities assigned to them');
239 $this->assertEquals($expectedContact, $activity['assignee_contact_id'], 'Activity is not assigned to expected contact');
240 }
241
242 /**
243 * Test that locateNameOrLabel does the right things.
244 *
245 * @dataProvider xmlDataProvider
246 */
247 public function testLocateNameOrLabel($xmlString, $expected) {
248 $xmlObj = new SimpleXMLElement($xmlString);
249 $this->assertEquals($expected, $this->process->locateNameOrLabel($xmlObj));
250 }
251
252 /**
253 * Data provider for testLocateNameOrLabel
254 * @return array
255 */
256 public function xmlDataProvider() {
257 return [
258 ['<RelationshipType><name>Senior Services Coordinator</name><creator>1</creator><manager>1</manager></RelationshipType>', 'Senior Services Coordinator'],
259 ['<RelationshipType><name>Senior Services Coordinator</name></RelationshipType>', 'Senior Services Coordinator'],
260 ['<RelationshipType><name>Lion Tamer&#39;s Obituary Writer</name></RelationshipType>', "Lion Tamer's Obituary Writer"],
261 ['<RelationshipType><machineName>BP1234</machineName><name>Banana Peeler</name></RelationshipType>', 'BP1234'],
262 ['<RelationshipType><machineName>BP1234</machineName><name>Banana Peeler</name><creator>1</creator><manager>1</manager></RelationshipType>', 'BP1234'],
263 ['<RelationshipType><machineName>0</machineName><name>Assistant Level 0</name></RelationshipType>', '0'],
264 ['<RelationshipType><machineName></machineName><name>Banana Peeler</name></RelationshipType>', 'Banana Peeler'],
265 // hopefully nobody would do this
266 ['<RelationshipType><machineName>null</machineName><name>Annulled Relationship</name></RelationshipType>', 'null'],
267 ];
268 }
269
270 }