Merge pull request #17253 from mattwire/utf8convertblocksize
[civicrm-core.git] / tests / phpunit / CRM / Core / BAO / RecurringEntityTest.php
CommitLineData
25b72113 1<?php
2/*
3 +--------------------------------------------------------------------+
7d61e75f 4 | Copyright CiviCRM LLC. All rights reserved. |
25b72113 5 | |
7d61e75f
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
25b72113 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
25b72113 11
25b72113 12/**
060402a9 13 * Class CRM_Core_BAO_RecurringEntityTest
acb109b7 14 * @group headless
25b72113 15 */
060402a9 16class CRM_Core_BAO_RecurringEntityTest extends CiviUnitTestCase {
25b72113 17
6caeea75 18 /**
19 * Sets up the fixture, for example, opens a network connection.
20 * This method is called before a test is executed.
6caeea75 21 */
22 protected function setUp() {
25b72113 23 parent::setUp();
25b72113 24 }
59d63f8b 25
6caeea75 26 /**
27 * Tears down the fixture, for example, closes a network connection.
28 * This method is called after a test is executed.
6caeea75 29 */
6c6e6187
TO
30 protected function tearDown() {
31 }
25b72113 32
33 /**
eceb18cc 34 * Testing Activity Generation through Entity Recursion.
25b72113 35 */
00be9182 36 public function testActivityGeneration() {
206c0c43 37 //Activity set initial params
37b28176 38 $daoActivity = new CRM_Activity_DAO_Activity();
39 $daoActivity->activity_type_id = 1;
40 $daoActivity->subject = "Initial Activity";
f5f5a631 41 $daoActivity->activity_date_time = '20141002103000';
37b28176 42 $daoActivity->save();
25b72113 43
37b28176 44 $recursion = new CRM_Core_BAO_RecurringEntity();
92915c55 45 $recursion->entity_id = $daoActivity->id;
690bf076 46 $recursion->entity_table = 'civicrm_activity';
9099cab3
CW
47 $recursion->dateColumns = ['activity_date_time'];
48 $recursion->schedule = [
92915c55
TO
49 'entity_value' => $daoActivity->id,
50 'start_action_date' => $daoActivity->activity_date_time,
a1a821bc 51 'entity_status' => 'fourth saturday',
37b28176 52 'repetition_frequency_unit' => 'month',
53 'repetition_frequency_interval' => 3,
54 'start_action_offset' => 5,
92915c55 55 'used_for' => 'activity',
9099cab3 56 ];
206c0c43 57
59d63f8b 58 $generatedEntities = $recursion->generate();
f5f5a631 59 $this->assertEquals(5, count($generatedEntities['civicrm_activity']), "Cehck if number of iterations are 5");
9099cab3 60 $expectedDates = [
59d63f8b 61 '20141025103000',
4e12f3b2
PZ
62 '20150124103000',
63 '20150425103000',
64 '20150725103000',
65 '20151024103000',
9099cab3 66 ];
84f02991 67 foreach ($generatedEntities['civicrm_activity'] as $entityID) {
37b28176 68 $this->assertDBNotNull('CRM_Activity_DAO_Activity', $entityID, 'id',
69 'id', 'Check DB if repeating activities were created'
70 );
25b72113 71 }
25b72113 72
206c0c43 73 // set mode to ALL, i.e any change to changing activity affects all related recurring activities
74 $recursion->mode(3);
37b28176 75
e4f46be0 76 // lets change subject of initial activity that we created in beginning
25b72113 77 $daoActivity->find(TRUE);
690bf076 78 $daoActivity->subject = 'Changed Activity';
25b72113 79 $daoActivity->save();
25b72113 80
37b28176 81 // check if other activities were affected
9099cab3 82 $actualDates = [];
84f02991 83 foreach ($generatedEntities['civicrm_activity'] as $entityID) {
690bf076 84 $this->assertDBCompareValue('CRM_Activity_DAO_Activity', $entityID, 'subject', 'id', 'Changed Activity', 'Check if subject was updated');
f5f5a631 85 $actualDates[] = date('YmdHis', strtotime(CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $entityID, 'activity_date_time', 'id')));
6caeea75 86 }
f5f5a631 87 $resultDates = array_diff($actualDates, $expectedDates);
88 $this->assertEquals(0, count($resultDates), "Check if all the value in expected array matches actual array");
59d63f8b 89
6caeea75 90 }
59d63f8b 91
543aa76e
AP
92 /**
93 * Creating action schedule
94 */
95 private function createActionSchedule($entity_id, $entity_table) {
9099cab3 96 $params = [
543aa76e
AP
97 "used_for" => $entity_table,
98 "entity_value" => $entity_id,
99 "start_action_date" => date("YmdHis"),
100 "repetition_frequency_unit" => "week",
101 "repetition_frequency_interval" => "3",
102 "start_action_condition" => "monday,tuesday,wednesday,thursday,friday,saturday",
103 "start_action_offset" => "2",
9099cab3 104 ];
543aa76e
AP
105 $actionScheduleObj = CRM_Core_BAO_ActionSchedule::add($params);
106 return $actionScheduleObj;
107 }
108
109 /**
110 * Creating recurring entities
111 */
112 private function createRecurringEntities($actionScheduleObj, $entity_id, $entity_table) {
113 $recursion = new CRM_Core_BAO_RecurringEntity();
9099cab3 114 $recursion->dateColumns = [
543aa76e 115 "start_date",
9099cab3 116 ];
543aa76e
AP
117 $recursion->scheduleId = $actionScheduleObj->id;
118 $recursion->entity_id = $entity_id;
119 $recursion->entity_table = $entity_table;
9099cab3
CW
120 $recursion->linkedEntities = [
121 [
543aa76e 122 "table" => "civicrm_price_set_entity",
9099cab3 123 "findCriteria" => [
543aa76e
AP
124 "entity_id" => $entity_id,
125 "entity_table" => $entity_table,
9099cab3
CW
126 ],
127 "linkedColumns" => [
543aa76e 128 "entity_id",
9099cab3 129 ],
543aa76e 130 "isRecurringEntityRecord" => FALSE,
9099cab3
CW
131 ],
132 ];
543aa76e
AP
133 return $recursion->generate();
134 }
135
136 /**
137 * Testing Event Generation through Entity Recursion.
138 */
139 public function testRepeatEventCreation() {
140 $event = $this->eventCreate();
141 $entity_table = "civicrm_event";
142 $entity_id = $event["id"];
143 CRM_Price_BAO_PriceSet::addTo($entity_table, $entity_id, 1);
144 $actionScheduleObj = $this->createActionSchedule($entity_id, $entity_table);
145 $recurringEntities = $this->createRecurringEntities($actionScheduleObj, $entity_id, $entity_table);
9099cab3 146 $finalResult = CRM_Core_BAO_RecurringEntity::updateModeAndPriceSet($entity_id, $entity_table, CRM_Core_BAO_RecurringEntity::MODE_ALL_ENTITY_IN_SERIES, [], 2);
543aa76e
AP
147 $this->assertEquals(2, count($recurringEntities["civicrm_event"]), "Recurring events not created.");
148 $this->assertEquals(2, count($recurringEntities["civicrm_price_set_entity"]), "Recurring price sets not created.");
149 $priceSetOne = CRM_Price_BAO_PriceSet::getFor($entity_table, $recurringEntities["civicrm_price_set_entity"][0]);
150 $priceSetTwo = CRM_Price_BAO_PriceSet::getFor($entity_table, $recurringEntities["civicrm_price_set_entity"][1]);
151 $this->assertEquals(2, $priceSetOne, "Price set id of the recurring event is not updated.");
152 $this->assertEquals(2, $priceSetTwo, "Price set id of the recurring event is not updated.");
153 }
154
690bf076 155 /**
eceb18cc 156 * Testing Event Generation through Entity Recursion.
690bf076 157 */
00be9182 158 public function testEventGeneration() {
6c6e6187 159 //Event set initial params
690bf076 160 $daoEvent = new CRM_Event_DAO_Event();
161 $daoEvent->title = 'Test event for Recurring Entity';
162 $daoEvent->event_type_id = 3;
163 $daoEvent->is_public = 1;
f5f5a631 164 $daoEvent->start_date = date('YmdHis', strtotime('2014-10-26 10:30:00'));
92915c55 165 $daoEvent->end_date = date('YmdHis', strtotime('2014-10-28 10:30:00'));
690bf076 166 $daoEvent->created_date = date('YmdHis');
167 $daoEvent->is_active = 1;
168 $daoEvent->save();
cd3f28a7 169 $this->assertDBNotNull('CRM_Event_DAO_Event', $daoEvent->id, 'id', 'id', 'Check DB if event was created');
59d63f8b 170
cd3f28a7 171 //Create tell a friend for event
172 $daoTellAFriend = new CRM_Friend_DAO_Friend();
173 $daoTellAFriend->entity_table = 'civicrm_event';
39b959db
SL
174 // join with event
175 $daoTellAFriend->entity_id = $daoEvent->id;
cd3f28a7 176 $daoTellAFriend->title = 'Testing tell a friend';
177 $daoTellAFriend->is_active = 1;
178 $daoTellAFriend->save();
f5f5a631 179 $this->assertDBNotNull('CRM_Friend_DAO_Friend', $daoTellAFriend->id, 'id', 'id', 'Check DB if tell a friend was created');
690bf076 180
fb2120e7 181 // time to use recursion
690bf076 182 $recursion = new CRM_Core_BAO_RecurringEntity();
92915c55 183 $recursion->entity_id = $daoEvent->id;
690bf076 184 $recursion->entity_table = 'civicrm_event';
9099cab3
CW
185 $recursion->dateColumns = ['start_date'];
186 $recursion->schedule = [
92915c55
TO
187 'entity_value' => $daoEvent->id,
188 'start_action_date' => $daoEvent->start_date,
189 'start_action_condition' => 'monday',
190 'repetition_frequency_unit' => 'week',
690bf076 191 'repetition_frequency_interval' => 1,
92915c55
TO
192 'start_action_offset' => 4,
193 'used_for' => 'event',
9099cab3 194 ];
690bf076 195
9099cab3
CW
196 $recursion->linkedEntities = [
197 [
92915c55 198 'table' => 'civicrm_tell_friend',
9099cab3 199 'findCriteria' => [
92915c55 200 'entity_id' => $recursion->entity_id,
21dfd5f5 201 'entity_table' => 'civicrm_event',
9099cab3
CW
202 ],
203 'linkedColumns' => ['entity_id'],
342c3f9e 204 'isRecurringEntityRecord' => TRUE,
9099cab3
CW
205 ],
206 ];
59d63f8b 207
f5f5a631 208 $interval = $recursion->getInterval($daoEvent->start_date, $daoEvent->end_date);
9099cab3 209 $recursion->intervalDateColumns = ['end_date' => $interval];
59d63f8b 210 $generatedEntities = $recursion->generate();
cd3f28a7 211 $this->assertArrayHasKey('civicrm_event', $generatedEntities, 'Check if generatedEntities has civicrm_event as required key');
9099cab3 212 $expectedDates = [
f5f5a631 213 '20141027103000' => '20141029103000',
214 '20141103103000' => '20141105103000',
215 '20141110103000' => '20141112103000',
21dfd5f5 216 '20141117103000' => '20141119103000',
9099cab3 217 ];
59d63f8b 218
fb2120e7 219 $this->assertCount($recursion->schedule['start_action_offset'], $generatedEntities['civicrm_event'], 'Check if the number of events created are right');
9099cab3 220 $actualDates = [];
22e263ad 221 foreach ($generatedEntities['civicrm_event'] as $key => $val) {
fb2120e7 222 $this->assertDBNotNull('CRM_Event_DAO_Event', $val, 'id', 'id', 'Check if repeating events were created.');
f5f5a631 223 $startDate = date('YmdHis', strtotime(CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $val, 'start_date', 'id')));
224 $endDate = date('YmdHis', strtotime(CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $val, 'end_date', 'id')));
225 $actualDates[$startDate] = $endDate;
cd3f28a7 226 }
59d63f8b 227
f5f5a631 228 $resultDates = array_diff($actualDates, $expectedDates);
229 $this->assertEquals(0, count($resultDates), "Check if all the value in expected array matches actual array");
59d63f8b 230
22e263ad 231 foreach ($generatedEntities['civicrm_tell_friend'] as $key => $val) {
fb2120e7 232 $this->assertDBNotNull('CRM_Friend_DAO_Friend', $val, 'id', 'id', 'Check if friends were created in loop');
233 $this->assertDBCompareValue('CRM_Friend_DAO_Friend', $val, 'entity_id', 'id', $generatedEntities['civicrm_event'][$key], 'Check DB if correct FK was maintained with event for Friend');
cd3f28a7 234 }
fb2120e7 235 $this->assertCount($recursion->schedule['start_action_offset'], $generatedEntities['civicrm_tell_friend'], 'Check if the number of tell a friend records are right');
59d63f8b 236
206c0c43 237 // set mode to ALL, i.e any change to changing event affects all related recurring activities
238 $recursion->mode(3);
690bf076 239
240 $daoEvent->find(TRUE);
241 $daoEvent->title = 'Event Changed';
242 $daoEvent->save();
243
244 // check if other events were affected
84f02991 245 foreach ($generatedEntities['civicrm_event'] as $entityID) {
690bf076 246 $this->assertDBCompareValue('CRM_Event_DAO_Event', $entityID, 'title', 'id', 'Event Changed', 'Check if title was updated');
247 }
59d63f8b 248
249 end($generatedEntities['civicrm_event']);
2eac52b6 250 $key = key($generatedEntities['civicrm_event']);
59d63f8b 251
2eac52b6 252 end($generatedEntities['civicrm_tell_friend']);
253 $actKey = key($generatedEntities['civicrm_tell_friend']);
59d63f8b 254
2eac52b6 255 //Check if both(event/tell a friend) keys are same
256 $this->assertEquals($key, $actKey, "Check if both the keys are same");
59d63f8b 257
2eac52b6 258 //Cross check event exists before we test deletion
9099cab3 259 $searchParamsEventBeforeDelete = [
92915c55 260 'entity_id' => $generatedEntities['civicrm_event'][$key],
21dfd5f5 261 'entity_table' => 'civicrm_event',
9099cab3
CW
262 ];
263 $expectedValuesEventBeforeDelete = [
92915c55 264 'entity_id' => $generatedEntities['civicrm_event'][$key],
21dfd5f5 265 'entity_table' => 'civicrm_event',
9099cab3 266 ];
2eac52b6 267 $this->assertDBCompareValues('CRM_Core_DAO_RecurringEntity', $searchParamsEventBeforeDelete, $expectedValuesEventBeforeDelete);
59d63f8b 268
2eac52b6 269 //Cross check event exists before we test deletion
9099cab3 270 $searchParamsTellAFriendBeforeDelete = [
92915c55 271 'entity_id' => $generatedEntities['civicrm_tell_friend'][$actKey],
21dfd5f5 272 'entity_table' => 'civicrm_tell_friend',
9099cab3
CW
273 ];
274 $expectedValuesTellAFriendBeforeDelete = [
92915c55 275 'entity_id' => $generatedEntities['civicrm_tell_friend'][$actKey],
21dfd5f5 276 'entity_table' => 'civicrm_tell_friend',
9099cab3 277 ];
2eac52b6 278 $this->assertDBCompareValues('CRM_Core_DAO_RecurringEntity', $searchParamsTellAFriendBeforeDelete, $expectedValuesTellAFriendBeforeDelete);
59d63f8b 279
2eac52b6 280 //Delete an event from recurring set and respective linked entity should be deleted from civicrm_recurring_entity_table
281 $daoRecurEvent = new CRM_Event_DAO_Event();
282 $daoRecurEvent->id = $generatedEntities['civicrm_event'][$key];
283 if ($daoRecurEvent->find(TRUE)) {
284 $daoRecurEvent->delete();
2eac52b6 285 }
59d63f8b 286
2eac52b6 287 //Check if this event_id was deleted
288 $this->assertDBNull('CRM_Event_DAO_Event', $generatedEntities['civicrm_event'][$key], 'id', 'id', 'Check if event was deleted');
9099cab3 289 $searchParams = [
f9f8eda7 290 'entity_id' => $generatedEntities['civicrm_event'][$key],
21dfd5f5 291 'entity_table' => 'civicrm_event',
9099cab3
CW
292 ];
293 $compareParams = [];
2eac52b6 294 $this->assertDBCompareValues('CRM_Core_DAO_RecurringEntity', $searchParams, $compareParams);
f9f8eda7 295
2eac52b6 296 //Find tell_a_friend id if that was deleted from civicrm
9099cab3 297 $searchActParams = [
f9f8eda7 298 'entity_id' => $generatedEntities['civicrm_tell_friend'][$actKey],
21dfd5f5 299 'entity_table' => 'civicrm_tell_friend',
9099cab3
CW
300 ];
301 $compareActParams = [];
2eac52b6 302 $this->assertDBCompareValues('CRM_Friend_DAO_Friend', $searchActParams, $compareActParams);
690bf076 303 }
96025800 304
3fec1adc 305 /**
306 * Testing Activity Generation through Entity Recursion with Custom Data and Tags.
307 */
308 public function testRecurringEntityGenerationWithCustomDataAndTags() {
309
310 // Create custom group and field
311 $customGroup = $this->customGroupCreate([
312 'extends' => 'Activity',
313 ]);
314 $customField = $this->customFieldCreate([
9099cab3
CW
315 'custom_group_id' => $customGroup['id'],
316 'default_value' => '',
317 ]);
3fec1adc 318
319 // Create activity Tag
320 $tag = $this->tagCreate([
321 'used_for' => 'Activities',
322 ]);
323
324 // Create original activity
325 $customFieldValue = 'Custom Value';
326 $activityDateTime = date('YmdHis');
327 $activityId = $this->activityCreate([
328 'activity_date_time' => $activityDateTime,
329 'custom_' . $customField['id'] => $customFieldValue,
330 ]);
331
332 $activityId = $activityId['id'];
333
334 // Assign tag to a activity.
335 $this->callAPISuccess('EntityTag', 'create', [
336 'entity_table' => 'civicrm_activity',
337 'entity_id' => $activityId,
338 'tag_id' => $tag['id'],
339 ]);
340
341 // Create recurring activities.
342 $recursion = new CRM_Core_BAO_RecurringEntity();
343 $recursion->entity_id = $activityId;
344 $recursion->entity_table = 'civicrm_activity';
345 $recursion->dateColumns = ['activity_date_time'];
346 $recursion->schedule = [
347 'entity_value' => $activityId,
348 'start_action_date' => $activityDateTime,
349 'entity_status' => 'fourth saturday',
350 'repetition_frequency_unit' => 'month',
351 'repetition_frequency_interval' => 3,
352 'start_action_offset' => 3,
353 'used_for' => 'activity',
354 ];
355
356 $generatedEntities = $recursion->generate();
357 $generatedActivities = $generatedEntities['civicrm_activity'];
358
359 $this->assertEquals(3, count($generatedActivities), "Check if number of iterations are 3");
360
361 foreach ($generatedActivities as $generatedActivityId) {
362
363 /* Validate tag in recurring activity
364 // @todo - refer https://github.com/civicrm/civicrm-core/pull/13470
365 $this->callAPISuccess('EntityTag', 'getsingle', [
366 'entity_table' => 'civicrm_activity',
367 'entity_id' => $generatedActivityId,
368 ]);
369 */
370
371 // Validate custom data in recurring activity
372 $activity = $this->callAPISuccess('activity', 'getsingle', [
373 'return' => [
374 'custom_' . $customField['id'],
375 ],
376 'id' => $generatedActivityId,
377 ]);
378
379 $this->assertEquals($customFieldValue, $activity['custom_' . $customField['id']], 'Custom field value should be ' . $customFieldValue);
380
381 }
382 }
383
25b72113 384}