repeat mode dialog improvements
[civicrm-core.git] / CRM / Core / BAO / RecurringEntity.php
CommitLineData
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
36require_once 'packages/When/When.php';
37
38class 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) {
95 $mode = CRM_Core_DAO::singleValueQuery("SELECT cascade_type FROM civicrm_recurring_entity WHERE entity_id = %3 AND entity_table = %2", $queryParams);
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
153 //static public function copyCreateEntity('civicrm_event', array('id' => $params['parent_event_id'], $newParams) {
154 static public function copyCreateEntity($entityTable, $fromCriteria, $newParams, $createRecurringEntity = TRUE) {
155 $daoName = self::$_tableDAOMapper[$entityTable];
156 $newObject = CRM_Core_DAO::copyGeneric($daoName, $fromCriteria, $newParams);
157
158 if ($newObject->id && $createRecurringEntity) {
159 $object = new $daoName( );
160 foreach ($fromCriteria as $key => $value) {
161 $object->$key = $value;
162 }
163 $object->find(TRUE);
164
165 CRM_Core_BAO_RecurringEntity::quickAdd($object->id, $newObject->id, $entityTable);
166 }
167 return $newObject;
168 }
169
170 static public function triggerUpdate($obj) {
171 static $processedEntities = array();
172 if (empty($obj->id) || empty($obj->__table)) {
173 return FALSE;
174 }
175 $key = "{$obj->__table}_{$obj->id}";
176
177 if (array_key_exists($key, $processedEntities)) {
178 // already processed
179 return NULL;
180 }
181
182 // get related entities
36b8b5f3 183 $repeatingEntities = self::getEntitiesFor($obj->id, $obj->__table, FALSE, NULL);
62933949 184 if (empty($repeatingEntities)) {
185 // return if its not a recurring entity parent
186 return NULL;
187 }
36b8b5f3 188 // mark being processed
62933949 189 $processedEntities[$key] = 1;
190
36b8b5f3 191 // to make sure we not copying to source itself
192 unset($repeatingEntities[$key]);
193
194 foreach($repeatingEntities as $key => $val) {
62933949 195 $entityID = $val['id'];
196 $entityTable = $val['table'];
197
198 $processedEntities[$key] = 1;
199
200 if (array_key_exists($entityTable, self::$_tableDAOMapper)) {
201 $daoName = self::$_tableDAOMapper[$entityTable];
202
62933949 203 // FIXME: generalize me
204 $skipData = array('start_date' => NULL,
205 'end_date' => NULL,
206 );
207
36b8b5f3 208 $updateDAO = CRM_Core_DAO::cascadeUpdate($daoName, $obj->id, $entityID, $skipData);
209 CRM_Core_DAO::freeResult();
62933949 210 }
211 }
212 // done with processing. lets unset static var.
213 unset($processedEntities);
214 }
215
216 static function mapFormValuesToDB($formParams = array()){
217 $dbParams = array();
218 if(CRM_Utils_Array::value('used_for', $formParams)){
219 $dbParams['used_for'] = $formParams['used_for'];
220 }
221
222 if(CRM_Utils_Array::value('parent_event_id', $formParams)){
223 $dbParams['entity_value'] = $formParams['parent_event_id'];
224 }
225
226 if(CRM_Utils_Array::value('repetition_frequency_unit', $formParams)){
227 $dbParams['repetition_frequency_unit'] = $formParams['repetition_frequency_unit'];
228 }
229
230 if(CRM_Utils_Array::value('repetition_frequency_interval', $formParams)){
231 $dbParams['repetition_frequency_interval'] = $formParams['repetition_frequency_interval'];
232 }
233
234 //For Repeats on:(weekly case)
235 if($formParams['repetition_frequency_unit'] == 'week'){
236 if(CRM_Utils_Array::value('start_action_condition', $formParams)){
237 $repeats_on = CRM_Utils_Array::value('start_action_condition', $formParams);
238 $dbParams['start_action_condition'] = implode(",", array_keys($repeats_on));
239 }
240 }
241
242 //For Repeats By:(monthly case)
243 if($formParams['repetition_frequency_unit'] == 'month'){
244 if($formParams['repeats_by'] == 1){
245 if(CRM_Utils_Array::value('limit_to', $formParams)){
246 $dbParams['limit_to'] = $formParams['limit_to'];
247 }
248 }
249 if($formParams['repeats_by'] == 2){
250 if(CRM_Utils_Array::value('start_action_date_1', $formParams) && CRM_Utils_Array::value('start_action_date_2', $formParams)){
251 $dbParams['start_action_date'] = $formParams['start_action_date_1']." ".$formParams['start_action_date_2'];
252 }
253 }
254 }
255
256 //For "Ends" - After:
257 if($formParams['ends'] == 1){
258 if(CRM_Utils_Array::value('start_action_offset', $formParams)){
259 $dbParams['start_action_offset'] = $formParams['start_action_offset'];
260 }
261 }
262
263 //For "Ends" - On:
264 if($formParams['ends'] == 2){
265 if(CRM_Utils_Array::value('repeat_absolute_date', $formParams)){
266 $dbParams['absolute_date'] = CRM_Utils_Date::processDate($formParams['repeat_absolute_date']);
267 }
268 }
269 return $dbParams;
270 }
271
272 static public function getScheduleReminderDetailsById($scheduleReminderId){
273 $query = "SELECT *
274 FROM civicrm_action_schedule WHERE 1";
275 if($scheduleReminderId){
276 $query .= "
277 AND id = %1";
278 }
279 $dao = CRM_Core_DAO::executeQuery($query,
280 array(
281 1 => array($scheduleReminderId, 'Integer')
282 )
283 );
284 $dao->fetch();
285 return $dao;
286 }
287
288 static function getRecursionFromReminder($scheduleReminderId){
289 if($scheduleReminderId){
290 //Get all the details from schedule reminder table
291 $scheduleReminderDetails = self::getScheduleReminderDetailsById($scheduleReminderId);
292 $scheduleReminderDetails = (array) $scheduleReminderDetails;
293 $recursionDetails = self::getRecursionFromReminderByDBParams($scheduleReminderDetails);
294 }
295 return $recursionDetails;
296 }
297
298 static function getRecursionFromReminderByDBParams($scheduleReminderDetails = array()){
299 $r = new When();
300 //If there is some data for this id
301 if($scheduleReminderDetails['repetition_frequency_unit']){
302 $currDate = date("Y-m-d H:i:s");
303 $start = new DateTime($currDate);
304 if($scheduleReminderDetails['repetition_frequency_unit']){
305 $repetition_frequency_unit = $scheduleReminderDetails['repetition_frequency_unit'];
306 if($repetition_frequency_unit == "day"){
307 $repetition_frequency_unit = "dai";
308 }
309 $repetition_frequency_unit = $repetition_frequency_unit.'ly';
310 $r->recur($start, $repetition_frequency_unit);
311 }
312
313 if($scheduleReminderDetails['repetition_frequency_interval']){
314 $r->interval($scheduleReminderDetails['repetition_frequency_interval']);
fd1abec4 315 }else{
316 $r->errors[] = 'Repeats every: is a required field';
62933949 317 }
318
319 //week
320 if($scheduleReminderDetails['repetition_frequency_unit'] == 'week'){
321 if($scheduleReminderDetails['start_action_condition']){
322 $startActionCondition = $scheduleReminderDetails['start_action_condition'];
323 $explodeStartActionCondition = explode(',', $startActionCondition);
324 $buildRuleArray = array();
325 foreach($explodeStartActionCondition as $key => $val){
326 $buildRuleArray[] = strtoupper(substr($val, 0, 2));
327 }
62933949 328 $r->wkst('MO')->byday($buildRuleArray);
329 }
330 }
331
332 //month
333 if($scheduleReminderDetails['repetition_frequency_unit'] == 'month'){
334 if($scheduleReminderDetails['limit_to']){
335 $r->bymonthday(array($scheduleReminderDetails['limit_to']));
336 }
337 if($scheduleReminderDetails['start_action_date']){
338 $startActionDate = explode(" ", $scheduleReminderDetails['start_action_date']);
339 switch ($startActionDate[0]) {
340 case 'first':
341 $startActionDate1 = 1;
342 break;
343 case 'second':
344 $startActionDate1 = 2;
345 break;
346 case 'third':
347 $startActionDate1 = 3;
348 break;
349 case 'fourth':
350 $startActionDate1 = 4;
351 break;
352 case 'last':
353 $startActionDate1 = -1;
354 break;
355 }
356 $concatStartActionDateBits = $startActionDate1.strtoupper(substr($startActionDate[1], 0, 2));
357 $r->byday(array($concatStartActionDateBits));
358 }
359 }
360
361 //Ends
362 if($scheduleReminderDetails['start_action_offset']){
c828f12a 363 if($scheduleReminderDetails['start_action_offset'] > 30){
364 $r->errors[] = 'Occurrences should be less than or equal to 30';
365 }
62933949 366 $r->count($scheduleReminderDetails['start_action_offset']);
367 }
368
369 if($scheduleReminderDetails['absolute_date']){
370 $absoluteDate = CRM_Utils_Date::setDateDefaults($scheduleReminderDetails['absolute_date']);
371 $endDate = new DateTime($absoluteDate[0].' '.$absoluteDate[1]);
372 $r->until($endDate);
373 }
374
375 if(!$scheduleReminderDetails['start_action_offset'] && !$scheduleReminderDetails['absolute_date']){
fd1abec4 376 $r->errors[] = 'Ends: is a required field';
62933949 377 }
fd1abec4 378 }else{
379 $r->errors[] = 'Repeats: is a required field';
62933949 380 }
381 return $r;
382 }
383
fd1abec4 384 /*
385 * Get Reminder id based on event id
386 */
387 static public function getReminderDetailsByEventId($eventId, $used_for){
388 if($eventId){
389 $query = "
390 SELECT *
391 FROM civicrm_action_schedule
392 WHERE entity_value = %1";
393 if($used_for){
394 $query .= " AND used_for = %2";
395 }
396 $params = array(
397 1 => array($eventId, 'Integer'),
398 2 => array($used_for, 'String')
399 );
400 $dao = CRM_Core_DAO::executeQuery($query, $params);
401 $dao->fetch();
402 }
403 return $dao;
2eeee284 404 }
405
406 static public function generateRecursions($recursionObj, $params=array()){
407 $newParams = $recursionResult = array();
408 if($recursionObj && !empty($params)){
409 //Proceed only if these keys are found in array
410 if(CRM_Utils_Array::value('parent_event_start_date', $params) && CRM_Utils_Array::value('parent_event_id', $params)){
411 $count = 1;
412 while($result = $recursionObj->next()){
413 $newParams['start_date'] = CRM_Utils_Date::processDate($result->format('Y-m-d H:i:s'));
414 $parentStartDate = new DateTime($params['parent_event_start_date']);
415 //If events with end date
416 if(CRM_Utils_Array::value('parent_event_end_date', $params)){
417 $parentEndDate = new DateTime($params['parent_event_end_date']);
418 $interval = $parentStartDate->diff($parentEndDate);
419 $end_date = new DateTime($newParams['start_date']);
420 $end_date->add($interval);
421 $newParams['end_date'] = CRM_Utils_Date::processDate($end_date->format('Y-m-d H:i:s'));
422 $recursionResult[$count]['end_date'] = $newParams['end_date'];
423 }
424 $recursionResult[$count]['start_date'] = $newParams['start_date'];
425 $count++;
426 }
427 }
428 }
429 return $recursionResult;
430 }
431
432 static public function addEntityThroughRecursion($recursionResult = array(), $currEntityID){
433 if(!empty($recursionResult) && $currEntityID){
434 $parent_event_id = CRM_Core_BAO_RecurringEntity::getParentFor($currEntityID, 'civicrm_event');
435 if(!$parent_event_id){
436 $parent_event_id = $currEntityID;
437 }
438
439 // add first entry just for parent
440 CRM_Core_BAO_RecurringEntity::quickAdd($parent_event_id, $parent_event_id, 'civicrm_event');
441
442 foreach ($recursionResult as $key => $value) {
443 $newEventObj = CRM_Core_BAO_RecurringEntity::copyCreateEntity('civicrm_event',
444 array('id' => $parent_event_id),
445 $value);
446
447 CRM_Core_BAO_RecurringEntity::copyCreateEntity('civicrm_price_set_entity',
448 array(
449 'entity_id' => $parent_event_id,
450 'entity_table' => 'civicrm_event'
451 ),
452 array(
453 'entity_id' => $newEventObj->id
454 ),
455 FALSE
456 );
457
458 CRM_Core_BAO_RecurringEntity::copyCreateEntity('civicrm_uf_join',
459 array(
460 'entity_id' => $parent_event_id,
461 'entity_table' => 'civicrm_event'
462 ),
463 array(
464 'entity_id' => $newEventObj->id
465 ),
466 FALSE
467 );
468
469 CRM_Core_BAO_RecurringEntity::copyCreateEntity('civicrm_tell_friend',
470 array(
471 'entity_id' => $parent_event_id,
472 'entity_table' => 'civicrm_event'
473 ),
474 array(
475 'entity_id' => $newEventObj->id
476 )
477 );
478
479 CRM_Core_BAO_RecurringEntity::copyCreateEntity('civicrm_pcp_block',
480 array(
481 'entity_id' => $parent_event_id,
482 'entity_table' => 'civicrm_event'
483 ),
484 array(
485 'entity_id' => $newEventObj->id
486 )
487 );
488 }
489 }
490 }
62933949 491
fd1abec4 492}