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