62933949 |
1 | <?php |
2 | /* |
3 | +--------------------------------------------------------------------+ |
4 | | CiviCRM version 4.4 | |
5 | +--------------------------------------------------------------------+ |
6 | | Copyright CiviCRM LLC (c) 2004-2013 | |
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 | +--------------------------------------------------------------------+ |
26 | */ |
27 | |
28 | /** |
29 | * |
30 | * @package CRM |
31 | * @copyright CiviCRM LLC (c) 2004-2013 |
32 | * $Id$ |
33 | * |
34 | */ |
35 | |
36 | require_once 'packages/When/When.php'; |
37 | |
38 | class CRM_Core_BAO_RecurringEntity extends CRM_Core_DAO_RecurringEntity { |
39 | |
40 | static $_tableDAOMapper = |
41 | array( |
42 | 'civicrm_event' => 'CRM_Event_DAO_Event', |
43 | 'civicrm_price_set_entity' => 'CRM_Price_DAO_PriceSetEntity', |
44 | 'civicrm_uf_join' => 'CRM_Core_DAO_UFJoin', |
45 | 'civicrm_tell_friend' => 'CRM_Friend_DAO_Friend', |
46 | 'civicrm_pcp_block' => 'CRM_PCP_DAO_PCPBlock', |
47 | ); |
48 | |
49 | static function add(&$params) { |
50 | if (CRM_Utils_Array::value('id', $params)) { |
51 | CRM_Utils_Hook::pre('edit', 'RecurringEntity', $params['id'], $params); |
52 | } |
53 | else { |
54 | CRM_Utils_Hook::pre('create', 'RecurringEntity', NULL, $params); |
55 | } |
56 | |
57 | $daoRecurringEntity = new CRM_Core_DAO_RecurringEntity(); |
58 | $daoRecurringEntity->copyValues($params); |
59 | $result = $daoRecurringEntity->save(); |
60 | |
61 | if (CRM_Utils_Array::value('id', $params)) { |
62 | CRM_Utils_Hook::post('edit', 'RecurringEntity', $daoRecurringEntity->id, $daoRecurringEntity); |
63 | } |
64 | else { |
65 | CRM_Utils_Hook::post('create', 'RecurringEntity', $daoRecurringEntity->id, $daoRecurringEntity); |
66 | } |
67 | return $result; |
68 | } |
69 | |
70 | static function quickAdd($parentId, $entityId, $entityTable) { |
71 | $params = |
72 | array( |
73 | 'parent_id' => $parentId, |
74 | 'entity_id' => $entityId, |
75 | 'entity_table' => $entityTable |
76 | ); |
77 | return self::add($params); |
78 | } |
79 | |
36b8b5f3 |
80 | // MODE = 3 (ALL) |
81 | static public function getEntitiesForParent($parentId, $entityTable, $includeParent = TRUE, $mode = 3, $initiatorId = NULL) { |
62933949 |
82 | $entities = array(); |
83 | |
36b8b5f3 |
84 | if (!$initiatorId) { |
85 | $initiatorId = $parentId; |
86 | } |
87 | |
88 | $queryParams = array( |
89 | 1 => array($parentId, 'Integer'), |
90 | 2 => array($entityTable, 'String'), |
91 | 3 => array($initiatorId, 'Integer'), |
92 | ); |
93 | |
94 | if (!$mode) { |
60b36f60 |
95 | $mode = CRM_Core_DAO::singleValueQuery("SELECT mode FROM civicrm_recurring_entity WHERE entity_id = %3 AND entity_table = %2", $queryParams); |
36b8b5f3 |
96 | } |
97 | |
62933949 |
98 | $query = "SELECT * |
99 | FROM civicrm_recurring_entity |
100 | WHERE parent_id = %1 AND entity_table = %2"; |
101 | if (!$includeParent) { |
36b8b5f3 |
102 | $query .= " AND entity_id != " . ($initiatorId ? "%3" : "%1"); |
103 | } |
104 | |
105 | if ($mode == '1') { // MODE = SINGLE |
106 | $query .= " AND entity_id = %3"; |
107 | } else if ($mode == '2') { // MODE = FUTURE |
108 | $recurringEntityID = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_recurring_entity WHERE entity_id = %3 AND entity_table = %2", $queryParams); |
109 | if ($recurringEntityID) { |
110 | $query .= $includeParent ? " AND id >= %4" : " AND id > %4"; |
111 | $query .= " ORDER BY id ASC"; // FIXME: change to order by dates |
112 | $queryParams[4] = array($recurringEntityID, 'Integer'); |
113 | } else { |
114 | // something wrong, return empty |
115 | return array(); |
116 | } |
62933949 |
117 | } |
62933949 |
118 | |
36b8b5f3 |
119 | $dao = CRM_Core_DAO::executeQuery($query, $queryParams); |
62933949 |
120 | while ($dao->fetch()) { |
121 | $entities["{$dao->entity_table}_{$dao->entity_id}"]['table'] = $dao->entity_table; |
122 | $entities["{$dao->entity_table}_{$dao->entity_id}"]['id'] = $dao->entity_id; |
123 | } |
124 | return $entities; |
125 | } |
126 | |
36b8b5f3 |
127 | static public function getEntitiesFor($entityId, $entityTable, $includeParent = TRUE, $mode = 3) { |
62933949 |
128 | $parentId = self::getParentFor($entityId, $entityTable); |
129 | if ($parentId) { |
36b8b5f3 |
130 | return self::getEntitiesForParent($parentId, $entityTable, $includeParent, $mode, $entityId); |
62933949 |
131 | } |
132 | return array(); |
133 | } |
134 | |
135 | static public function getParentFor($entityId, $entityTable, $includeParent = TRUE) { |
136 | $query = " |
137 | SELECT parent_id |
138 | FROM civicrm_recurring_entity |
139 | WHERE entity_id = %1 AND entity_table = %2"; |
140 | if (!$includeParent) { |
141 | $query .= " AND parent_id != %1"; |
142 | } |
143 | $parentId = |
144 | CRM_Core_DAO::singleValueQuery($query, |
145 | array( |
146 | 1 => array($entityId, 'Integer'), |
147 | 2 => array($entityTable, 'String'), |
148 | ) |
149 | ); |
150 | return $parentId; |
151 | } |
152 | |
62933949 |
153 | static public function copyCreateEntity($entityTable, $fromCriteria, $newParams, $createRecurringEntity = TRUE) { |
154 | $daoName = self::$_tableDAOMapper[$entityTable]; |
155 | $newObject = CRM_Core_DAO::copyGeneric($daoName, $fromCriteria, $newParams); |
156 | |
157 | if ($newObject->id && $createRecurringEntity) { |
158 | $object = new $daoName( ); |
159 | foreach ($fromCriteria as $key => $value) { |
160 | $object->$key = $value; |
161 | } |
162 | $object->find(TRUE); |
163 | |
164 | CRM_Core_BAO_RecurringEntity::quickAdd($object->id, $newObject->id, $entityTable); |
165 | } |
166 | return $newObject; |
167 | } |
168 | |
169 | static public function triggerUpdate($obj) { |
60b36f60 |
170 | // if DB version is earlier than 4.6 skip any processing |
171 | static $currentVer = NULL; |
172 | if (!$currentVer) { |
173 | $currentVer = CRM_Core_BAO_Domain::version(); |
174 | } |
175 | if (version_compare($currentVer, '4.6.alpha1') < 0) { |
176 | return; |
177 | } |
178 | |
62933949 |
179 | static $processedEntities = array(); |
180 | if (empty($obj->id) || empty($obj->__table)) { |
181 | return FALSE; |
182 | } |
183 | $key = "{$obj->__table}_{$obj->id}"; |
184 | |
185 | if (array_key_exists($key, $processedEntities)) { |
186 | // already processed |
187 | return NULL; |
188 | } |
189 | |
190 | // get related entities |
36b8b5f3 |
191 | $repeatingEntities = self::getEntitiesFor($obj->id, $obj->__table, FALSE, NULL); |
62933949 |
192 | if (empty($repeatingEntities)) { |
193 | // return if its not a recurring entity parent |
194 | return NULL; |
195 | } |
36b8b5f3 |
196 | // mark being processed |
62933949 |
197 | $processedEntities[$key] = 1; |
198 | |
36b8b5f3 |
199 | // to make sure we not copying to source itself |
200 | unset($repeatingEntities[$key]); |
201 | |
202 | foreach($repeatingEntities as $key => $val) { |
62933949 |
203 | $entityID = $val['id']; |
204 | $entityTable = $val['table']; |
205 | |
206 | $processedEntities[$key] = 1; |
207 | |
208 | if (array_key_exists($entityTable, self::$_tableDAOMapper)) { |
209 | $daoName = self::$_tableDAOMapper[$entityTable]; |
210 | |
62933949 |
211 | // FIXME: generalize me |
212 | $skipData = array('start_date' => NULL, |
213 | 'end_date' => NULL, |
214 | ); |
215 | |
36b8b5f3 |
216 | $updateDAO = CRM_Core_DAO::cascadeUpdate($daoName, $obj->id, $entityID, $skipData); |
217 | CRM_Core_DAO::freeResult(); |
62933949 |
218 | } |
219 | } |
220 | // done with processing. lets unset static var. |
221 | unset($processedEntities); |
222 | } |
223 | |
224 | static function mapFormValuesToDB($formParams = array()){ |
225 | $dbParams = array(); |
226 | if(CRM_Utils_Array::value('used_for', $formParams)){ |
227 | $dbParams['used_for'] = $formParams['used_for']; |
228 | } |
229 | |
230 | if(CRM_Utils_Array::value('parent_event_id', $formParams)){ |
231 | $dbParams['entity_value'] = $formParams['parent_event_id']; |
b1d1479a |
232 | } |
233 | |
66f66040 |
234 | if(CRM_Utils_Array::value('repetition_start_date', $formParams) && |
235 | CRM_Utils_Array::value('repetition_start_date_time', $formParams)){ |
236 | $repetition_start_date = new DateTime($formParams['repetition_start_date']." ".$formParams['repetition_start_date_time']); |
b1d1479a |
237 | $repetition_start_date->modify('+1 day'); |
238 | $dbParams['entity_status'] = CRM_Utils_Date::processDate($repetition_start_date->format('Y-m-d H:i:s')); |
239 | } |
62933949 |
240 | |
241 | if(CRM_Utils_Array::value('repetition_frequency_unit', $formParams)){ |
b1d1479a |
242 | $dbParams['repetition_frequency_unit'] = $formParams['repetition_frequency_unit']; |
243 | } |
62933949 |
244 | |
245 | if(CRM_Utils_Array::value('repetition_frequency_interval', $formParams)){ |
b1d1479a |
246 | $dbParams['repetition_frequency_interval'] = $formParams['repetition_frequency_interval']; |
247 | } |
62933949 |
248 | |
249 | //For Repeats on:(weekly case) |
b1d1479a |
250 | if($formParams['repetition_frequency_unit'] == 'week'){ |
251 | if(CRM_Utils_Array::value('start_action_condition', $formParams)){ |
252 | $repeats_on = CRM_Utils_Array::value('start_action_condition', $formParams); |
253 | $dbParams['start_action_condition'] = implode(",", array_keys($repeats_on)); |
62933949 |
254 | } |
b1d1479a |
255 | } |
62933949 |
256 | |
257 | //For Repeats By:(monthly case) |
b1d1479a |
258 | if($formParams['repetition_frequency_unit'] == 'month'){ |
259 | if($formParams['repeats_by'] == 1){ |
260 | if(CRM_Utils_Array::value('limit_to', $formParams)){ |
261 | $dbParams['limit_to'] = $formParams['limit_to']; |
62933949 |
262 | } |
b1d1479a |
263 | } |
264 | if($formParams['repeats_by'] == 2){ |
265 | if(CRM_Utils_Array::value('start_action_date_1', $formParams) && CRM_Utils_Array::value('start_action_date_2', $formParams)){ |
266 | $dbParams['start_action_date'] = $formParams['start_action_date_1']." ".$formParams['start_action_date_2']; |
62933949 |
267 | } |
268 | } |
b1d1479a |
269 | } |
62933949 |
270 | |
271 | //For "Ends" - After: |
b1d1479a |
272 | if($formParams['ends'] == 1){ |
273 | if(CRM_Utils_Array::value('start_action_offset', $formParams)){ |
274 | $dbParams['start_action_offset'] = $formParams['start_action_offset']; |
62933949 |
275 | } |
b1d1479a |
276 | } |
62933949 |
277 | |
b1d1479a |
278 | //For "Ends" - On: |
279 | if($formParams['ends'] == 2){ |
280 | if(CRM_Utils_Array::value('repeat_absolute_date', $formParams)){ |
281 | $dbParams['absolute_date'] = CRM_Utils_Date::processDate($formParams['repeat_absolute_date']); |
62933949 |
282 | } |
62933949 |
283 | } |
b1d1479a |
284 | return $dbParams; |
285 | } |
62933949 |
286 | |
b1d1479a |
287 | static public function getScheduleReminderDetailsById($scheduleReminderId){ |
288 | $query = "SELECT * |
289 | FROM civicrm_action_schedule WHERE 1"; |
290 | if($scheduleReminderId){ |
291 | $query .= " |
292 | AND id = %1"; |
62933949 |
293 | } |
b1d1479a |
294 | $dao = CRM_Core_DAO::executeQuery($query, |
295 | array( |
296 | 1 => array($scheduleReminderId, 'Integer') |
297 | ) |
298 | ); |
299 | $dao->fetch(); |
300 | return $dao; |
301 | } |
62933949 |
302 | |
b1d1479a |
303 | static function getRecursionFromReminder($scheduleReminderId){ |
304 | if($scheduleReminderId){ |
305 | //Get all the details from schedule reminder table |
306 | $scheduleReminderDetails = self::getScheduleReminderDetailsById($scheduleReminderId); |
307 | $scheduleReminderDetails = (array) $scheduleReminderDetails; |
308 | $recursionDetails = self::getRecursionFromReminderByDBParams($scheduleReminderDetails); |
62933949 |
309 | } |
b1d1479a |
310 | return $recursionDetails; |
311 | } |
62933949 |
312 | |
b1d1479a |
313 | static function getRecursionFromReminderByDBParams($scheduleReminderDetails = array()){ |
314 | $r = new When(); |
315 | //If there is some data for this id |
316 | if($scheduleReminderDetails['repetition_frequency_unit']){ |
317 | if($scheduleReminderDetails['entity_status']){ |
318 | $currDate = date('Y-m-d H:i:s', strtotime($scheduleReminderDetails['entity_status'])); |
319 | }else{ |
62933949 |
320 | $currDate = date("Y-m-d H:i:s"); |
b1d1479a |
321 | } |
322 | $start = new DateTime($currDate); |
323 | if($scheduleReminderDetails['repetition_frequency_unit']){ |
324 | $repetition_frequency_unit = $scheduleReminderDetails['repetition_frequency_unit']; |
325 | if($repetition_frequency_unit == "day"){ |
326 | $repetition_frequency_unit = "dai"; |
62933949 |
327 | } |
b1d1479a |
328 | $repetition_frequency_unit = $repetition_frequency_unit.'ly'; |
329 | $r->recur($start, $repetition_frequency_unit); |
330 | } |
62933949 |
331 | |
b1d1479a |
332 | if($scheduleReminderDetails['repetition_frequency_interval']){ |
333 | $r->interval($scheduleReminderDetails['repetition_frequency_interval']); |
334 | }else{ |
335 | $r->errors[] = 'Repeats every: is a required field'; |
336 | } |
62933949 |
337 | |
b1d1479a |
338 | //week |
339 | if($scheduleReminderDetails['repetition_frequency_unit'] == 'week'){ |
340 | if($scheduleReminderDetails['start_action_condition']){ |
341 | $startActionCondition = $scheduleReminderDetails['start_action_condition']; |
342 | $explodeStartActionCondition = explode(',', $startActionCondition); |
343 | $buildRuleArray = array(); |
344 | foreach($explodeStartActionCondition as $key => $val){ |
345 | $buildRuleArray[] = strtoupper(substr($val, 0, 2)); |
62933949 |
346 | } |
b1d1479a |
347 | $r->wkst('MO')->byday($buildRuleArray); |
62933949 |
348 | } |
b1d1479a |
349 | } |
62933949 |
350 | |
b1d1479a |
351 | //month |
352 | if($scheduleReminderDetails['repetition_frequency_unit'] == 'month'){ |
353 | if($scheduleReminderDetails['limit_to']){ |
354 | $r->bymonthday(array($scheduleReminderDetails['limit_to'])); |
62933949 |
355 | } |
b1d1479a |
356 | if($scheduleReminderDetails['start_action_date']){ |
357 | $startActionDate = explode(" ", $scheduleReminderDetails['start_action_date']); |
358 | switch ($startActionDate[0]) { |
359 | case 'first': |
360 | $startActionDate1 = 1; |
361 | break; |
362 | case 'second': |
363 | $startActionDate1 = 2; |
364 | break; |
365 | case 'third': |
366 | $startActionDate1 = 3; |
367 | break; |
368 | case 'fourth': |
369 | $startActionDate1 = 4; |
370 | break; |
371 | case 'last': |
372 | $startActionDate1 = -1; |
373 | break; |
c828f12a |
374 | } |
b1d1479a |
375 | $concatStartActionDateBits = $startActionDate1.strtoupper(substr($startActionDate[1], 0, 2)); |
376 | $r->byday(array($concatStartActionDateBits)); |
62933949 |
377 | } |
b1d1479a |
378 | } |
62933949 |
379 | |
b1d1479a |
380 | //Ends |
381 | if($scheduleReminderDetails['start_action_offset']){ |
382 | if($scheduleReminderDetails['start_action_offset'] > 30){ |
383 | $r->errors[] = 'Occurrences should be less than or equal to 30'; |
62933949 |
384 | } |
b1d1479a |
385 | $r->count($scheduleReminderDetails['start_action_offset']); |
386 | } |
62933949 |
387 | |
b1d1479a |
388 | if($scheduleReminderDetails['absolute_date']){ |
389 | $absoluteDate = CRM_Utils_Date::setDateDefaults($scheduleReminderDetails['absolute_date']); |
390 | $endDate = new DateTime($absoluteDate[0].' '.$absoluteDate[1]); |
391 | $r->until($endDate); |
392 | } |
393 | |
394 | if(!$scheduleReminderDetails['start_action_offset'] && !$scheduleReminderDetails['absolute_date']){ |
395 | $r->errors[] = 'Ends: is a required field'; |
396 | } |
397 | }else{ |
398 | $r->errors[] = 'Repeats: is a required field'; |
399 | } |
400 | return $r; |
401 | } |
62933949 |
402 | |
d10273dc |
403 | /* |
404 | * Get Reminder id based on event id |
405 | */ |
406 | static public function getReminderDetailsByEventId($eventId, $used_for){ |
407 | if($eventId){ |
408 | $query = " |
409 | SELECT * |
410 | FROM civicrm_action_schedule |
411 | WHERE entity_value = %1"; |
412 | if($used_for){ |
413 | $query .= " AND used_for = %2"; |
414 | } |
415 | $params = array( |
416 | 1 => array($eventId, 'Integer'), |
417 | 2 => array($used_for, 'String') |
418 | ); |
419 | $dao = CRM_Core_DAO::executeQuery($query, $params); |
420 | $dao->fetch(); |
421 | } |
422 | return $dao; |
423 | } |
424 | |
425 | static public function getInterval($startDate, $endDate) { |
426 | if ($startDate && $endDate) { |
427 | $startDate = new DateTime($startDate); |
c5a70e15 |
428 | $endDate = new DateTime($endDate); |
d10273dc |
429 | |
c5a70e15 |
430 | return $startDate->diff($endDate); |
fd1abec4 |
431 | } |
fd1abec4 |
432 | } |
2eeee284 |
433 | |
ad82cae1 |
434 | static public function generateRecursions($recursionObj, $params = array(), $excludeDates = array()) { |
2eeee284 |
435 | $newParams = $recursionResult = array(); |
ad82cae1 |
436 | if ($recursionObj && !empty($params)) { |
437 | $initialCount = CRM_Utils_Array::value('start_action_offset', $params); |
d10273dc |
438 | $interval = CRM_Utils_Array::value('interval', $params); |
439 | |
440 | $count = 1; |
441 | while ($result = $recursionObj->next()) { |
442 | $recursionResult[$count]['start_date'] = CRM_Utils_Date::processDate($result->format('Y-m-d H:i:s')); |
443 | |
444 | if($interval){ |
445 | $endDate = new DateTime($recursionResult[$count]['start_date']); |
446 | $endDate->add($interval); |
447 | $recursionResult[$count]['end_date'] = CRM_Utils_Date::processDate($endDate->format('Y-m-d H:i:s')); |
448 | } |
449 | |
450 | $skip = FALSE; |
451 | foreach ($excludeDates as $date) { |
452 | $date = CRM_Utils_Date::processDate($date, NULL, FALSE, 'Ymd'); |
453 | if (($date == $result->format('Ymd')) || |
454 | ($endDate && ($date > $result->format('Ymd')) && ($date <= $endDate->format('Ymd'))) |
455 | ) { |
456 | $skip = TRUE; |
457 | break; |
ad82cae1 |
458 | } |
d10273dc |
459 | } |
ad82cae1 |
460 | |
d10273dc |
461 | if ($skip) { |
462 | unset($recursionResult[$count]); |
463 | if ($initialCount && ($initialCount > 0)) { |
464 | // lets increase the counter, so we get correct number of occurrences |
465 | $initialCount++; |
466 | $recursionObj->count($initialCount); |
ad82cae1 |
467 | } |
d10273dc |
468 | continue; |
2eeee284 |
469 | } |
d10273dc |
470 | $count++; |
2eeee284 |
471 | } |
472 | } |
473 | return $recursionResult; |
474 | } |
2eeee284 |
475 | |
8dc6e78a |
476 | |
477 | static public function delEntityRelations($entityId, $entityTable){ |
478 | if(!$entityId && !$entityTable){ |
479 | return FALSE; |
480 | } |
481 | $parentID = self::getParentFor($entityId, $entityTable); |
482 | if($parentID){ |
483 | $dao = new CRM_Core_DAO_RecurringEntity(); |
484 | $dao->parent_id = $parentID; |
485 | return $dao->delete(); |
486 | } |
487 | } |
62933949 |
488 | |
fd1abec4 |
489 | } |