Merge pull request #14891 from eileenmcnaughton/saved_search
[civicrm-core.git] / tests / phpunit / CRM / Activity / Form / ActivityTest.php
1 <?php
2
3 /**
4 * Include dataProvider for tests
5 * @group headless
6 */
7 class CRM_Activity_Form_ActivityTest extends CiviUnitTestCase {
8
9 public function setUp() {
10 parent::setUp();
11 $this->assignee1 = $this->individualCreate([
12 'first_name' => 'testassignee1',
13 'last_name' => 'testassignee1',
14 'email' => 'testassignee1@gmail.com',
15 ]);
16 $this->assignee2 = $this->individualCreate([
17 'first_name' => 'testassignee2',
18 'last_name' => 'testassignee2',
19 'email' => 'testassignee2@gmail.com',
20 ]);
21 $this->target = $this->individualCreate();
22 $this->source = $this->individualCreate();
23 }
24
25 public function testActivityCreate() {
26 Civi::settings()->set('activity_assignee_notification', TRUE);
27 //Reset filter to none.
28 Civi::settings()->set('do_not_notify_assignees_for', []);
29 $mut = new CiviMailUtils($this, TRUE);
30 $mut->clearMessages();
31
32 $form = new CRM_Activity_Form_Activity();
33 $activityTypeId = CRM_Core_PseudoConstant::getKey('CRM_Activity_DAO_Activity', 'activity_type_id', 'Meeting');
34 $params = [
35 'source_contact_id' => $this->source,
36 'assignee_contact_id' => [$this->assignee1],
37 'target_contact_id' => [$this->target],
38 'followup_assignee_contact_id' => [],
39 'activity_type_id' => $activityTypeId,
40 ];
41
42 $activityRef = new ReflectionClass('CRM_Activity_Form_Activity');
43 $method = $activityRef->getMethod('processActivity');
44 $method->setAccessible(TRUE);
45 $method->invokeArgs($form, [&$params]);
46
47 $msg = $mut->getMostRecentEmail();
48 $this->assertNotEmpty($msg);
49 $mut->clearMessages();
50
51 //Block Meeting notification.
52 Civi::settings()->set('do_not_notify_assignees_for', [$activityTypeId]);
53 $params['assignee_contact_id'] = [$this->assignee2];
54 $method->invokeArgs($form, [&$params]);
55 $msg = $mut->getMostRecentEmail();
56 $this->assertEmpty($msg);
57 }
58
59 public function testActivityDelete() {
60 // Set the parameters of the test.
61 $numberOfSingleActivitiesToCreate = 3;
62 $numberOfRepeatingActivitiesToCreate = 6;
63 $singleActivityToDeleteOffset = 1;
64 $mode1ActivityToDeleteOffset = 1;
65 $mode2ActivityToDeleteOffset = 3;
66 $mode3ActivityToDeleteOffset = 2;
67
68 // Track the target contact's activities.
69 $expectedActivityIds = array_keys(CRM_Activity_BAO_Activity::getActivities(['contact_id' => $this->target]));
70
71 // Create non-repeating activities.
72 $meetingActivityTypeId = CRM_Core_PseudoConstant::getKey('CRM_Activity_DAO_Activity', 'activity_type_id', 'Meeting');
73 $singleActivityIds = [];
74 for ($activityCount = 0; $activityCount < $numberOfSingleActivitiesToCreate; $activityCount++) {
75 $activityParams = [
76 'source_contact_id' => $this->source,
77 'target_contact_id' => $this->target,
78 'activity_type_id' => $meetingActivityTypeId,
79 'activity_date_time' => date_create('+' . $activityCount . ' weeks')->format('YmdHis'),
80 ];
81 $singleActivityBao = CRM_Activity_BAO_Activity::create($activityParams);
82 $singleActivityIds[] = $singleActivityBao->id;
83 }
84 $expectedActivityIds = array_merge($expectedActivityIds, $singleActivityIds);
85
86 // Create an activity to be repeated.
87 $activityParams = [
88 'source_contact_id' => $this->source,
89 'target_contact_id' => $this->target,
90 'activity_type_id' => $meetingActivityTypeId,
91 'activity_date_time' => date('YmdHis'),
92 ];
93 $repeatingActivityBao = CRM_Activity_BAO_Activity::create($activityParams);
94
95 // Create the repeating activity's schedule.
96 $actionScheduleParams = [
97 'used_for' => 'civicrm_activity',
98 'entity_value' => $repeatingActivityBao->id,
99 'start_action_date' => $repeatingActivityBao->activity_date_time,
100 'repetition_frequency_unit' => 'week',
101 'repetition_frequency_interval' => 1,
102 'start_action_offset' => $numberOfRepeatingActivitiesToCreate - 1,
103 ];
104 $actionScheduleBao = CRM_Core_BAO_ActionSchedule::add($actionScheduleParams);
105
106 // Create the activity's repeats.
107 $recurringEntityBao = new CRM_Core_BAO_RecurringEntity();
108 $recurringEntityBao->entity_table = 'civicrm_activity';
109 $recurringEntityBao->entity_id = $repeatingActivityBao->id;
110 $recurringEntityBao->dateColumns = ['activity_date_time'];
111 $recurringEntityBao->linkedEntities = [
112 [
113 'table' => 'civicrm_activity_contact',
114 'findCriteria' => ['activity_id' => $repeatingActivityBao->id],
115 'linkedColumns' => ['activity_id'],
116 'isRecurringEntityRecord' => FALSE,
117 ],
118 ];
119 $recurringEntityBao->scheduleId = $actionScheduleBao->id;
120 $newEntities = $recurringEntityBao->generate();
121 $repeatingActivityIds = array_merge([$repeatingActivityBao->id], $newEntities['civicrm_activity']);
122 $expectedActivityIds = array_merge($expectedActivityIds, $repeatingActivityIds);
123
124 // Assert that the expected activities exist.
125 $this->assertTargetActivityIds($expectedActivityIds);
126
127 // Delete a non-repeating activity.
128 $activityId = $singleActivityIds[$singleActivityToDeleteOffset];
129 $this->deleteActivity($activityId);
130 $expectedActivityIds = array_diff($expectedActivityIds, [$activityId]);
131 $this->assertTargetActivityIds($expectedActivityIds);
132
133 // Delete one activity from series (mode 1).
134 $activityId = $repeatingActivityIds[$mode1ActivityToDeleteOffset];
135 $this->deleteActivity($activityId, 1);
136 $expectedActivityIds = array_diff($expectedActivityIds, [$activityId]);
137 $this->assertTargetActivityIds($expectedActivityIds);
138
139 // Delete from one activity until end of series (mode 2).
140 $activityId = $repeatingActivityIds[$mode2ActivityToDeleteOffset];
141 $this->deleteActivity($activityId, 2);
142 $expectedActivityIds = array_diff($expectedActivityIds, array_slice($repeatingActivityIds, $mode2ActivityToDeleteOffset));
143 $this->assertTargetActivityIds($expectedActivityIds);
144
145 // Delete all activities in series (mode 3).
146 $activityId = $repeatingActivityIds[$mode3ActivityToDeleteOffset];
147 $this->deleteActivity($activityId, 3);
148 $expectedActivityIds = array_diff($expectedActivityIds, $repeatingActivityIds);
149 $this->assertTargetActivityIds($expectedActivityIds);
150 }
151
152 /**
153 * Asserts that the target contact has the expected activity IDs
154 *
155 * @param array $expectedActivityIds
156 * An array of the activity IDs that are expected to exist for the target contact
157 */
158 private function assertTargetActivityIds($expectedActivityIds) {
159 $actualActivityIds = array_keys(CRM_Activity_BAO_Activity::getActivities(['contact_id' => $this->target]));
160 $this->assertEquals(array_fill_keys($expectedActivityIds, NULL), array_fill_keys($actualActivityIds, NULL));
161 }
162
163 /**
164 * Tests the form's deletion of activities, with optional mode for repeating activities
165 *
166 * @param int $activityId
167 * The ID of the activity to delete
168 * @param int $mode
169 * 1 - delete the specified activity
170 * 2 - delete the specified activity and all following activities in the series
171 * 3 - delete all activities in the series
172 */
173 private function deleteActivity($activityId, $mode = NULL) {
174 // For repeating activities, set the recurring entity mode.
175 if (!is_null($mode)) {
176 $recurringEntityBao = new CRM_Core_BAO_RecurringEntity();
177 $recurringEntityBao->entity_table = 'civicrm_activity';
178 $recurringEntityBao->entity_id = $activityId;
179 $recurringEntityBao->mode($mode);
180 }
181
182 // Use a form to delete the activity.
183 $form = new CRM_Activity_Form_Activity();
184 $form->_action = CRM_Core_Action::DELETE;
185 $form->_activityId = $activityId;
186 $form->postProcess();
187 }
188
189 /**
190 * This is a bit messed up having a variable called name that means label but we don't want to fix it because it's a form member variable _activityTypeName that might be used in form hooks, so just make sure it doesn't flip between name and label. dev/core#1116
191 */
192 public function testActivityTypeNameIsReallyLabel() {
193 $form = new CRM_Activity_Form_Activity();
194
195 // the actual value is irrelevant we just need something for the tested function to act on
196 $form->_currentlyViewedContactId = $this->source;
197
198 // Let's make a new activity type that has a different name from its label just to be sure.
199 $actParams = [
200 'option_group_id' => 'activity_type',
201 'name' => 'wp1234',
202 'label' => 'Water Plants',
203 'is_active' => 1,
204 'is_default' => 0,
205 ];
206 $result = $this->callAPISuccess('option_value', 'create', $actParams);
207
208 $form->_activityTypeId = $result['values'][$result['id']]['value'];
209 $this->assertNotEmpty($form->_activityTypeId);
210
211 // Do the thing we want to test
212 $form->assignActivityType();
213
214 $this->assertEquals('Water Plants', $form->_activityTypeName);
215
216 // cleanup
217 $this->callAPISuccess('option_value', 'delete', ['id' => $result['id']]);
218 }
219
220 /**
221 * Test that the machineName and displayLabel are assigned correctly to the
222 * smarty template.
223 *
224 * See also testActivityTypeNameIsReallyLabel()
225 */
226 public function testActivityTypeAssignment() {
227 $form = new CRM_Activity_Form_Activity();
228
229 $form->_currentlyViewedContactId = $this->source;
230
231 // Let's make a new activity type that has a different name from its label just to be sure.
232 $actParams = [
233 'option_group_id' => 'activity_type',
234 'name' => '47395hc',
235 'label' => 'Hide Cookies',
236 'is_active' => 1,
237 'is_default' => 0,
238 ];
239 $result = $this->callAPISuccess('option_value', 'create', $actParams);
240
241 $form->_activityTypeId = $result['values'][$result['id']]['value'];
242
243 // Do the thing we want to test
244 $form->assignActivityType();
245
246 // Check the smarty template has the correct values assigned.
247 $keyValuePair = $form->getTemplate()->get_template_vars('activityTypeNameAndLabel');
248 $this->assertEquals('47395hc', $keyValuePair['machineName']);
249 $this->assertEquals('Hide Cookies', $keyValuePair['displayLabel']);
250
251 // cleanup
252 $this->callAPISuccess('option_value', 'delete', ['id' => $result['id']]);
253 }
254
255 }