X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FCore%2FBAO%2FActionSchedule.php;h=c8d76595d7bfc2a952eb06e5fa1b4885f9968feb;hb=553ffa22464ff37a28a070458bcd52097b54235f;hp=2b697c8071851f4c431500f60d824858f7309254;hpb=a6c01b45f0cdaee8677de72b8bf3e784d8b6b62a;p=civicrm-core.git diff --git a/CRM/Core/BAO/ActionSchedule.php b/CRM/Core/BAO/ActionSchedule.php old mode 100644 new mode 100755 index 2b697c8071..c8d76595d7 --- a/CRM/Core/BAO/ActionSchedule.php +++ b/CRM/Core/BAO/ActionSchedule.php @@ -24,7 +24,7 @@ | GNU Affero General Public License or the licensing of CiviCRM, | | see the CiviCRM license FAQ at http://civicrm.org/licensing | +--------------------------------------------------------------------+ -*/ + */ /** * @@ -71,7 +71,6 @@ class CRM_Core_BAO_ActionSchedule extends CRM_Core_DAO_ActionSchedule { /** * Get all fields of the type Date */ - public static function getDateFields() { $allFields = CRM_Core_BAO_CustomField::getFields(''); $dateFields = array('birth_date' => ts('Birth Date')); @@ -91,12 +90,11 @@ class CRM_Core_BAO_ActionSchedule extends CRM_Core_DAO_ActionSchedule { * * @return array * associated array of all the drop downs in the form - * @static */ public static function getSelection($id = NULL) { $mapping = self::getMapping(); $activityStatus = CRM_Core_PseudoConstant::activityStatus(); - $activityType = CRM_Core_PseudoConstant::activityType(TRUE, TRUE); + $activityType = CRM_Core_PseudoConstant::activityType(TRUE, TRUE); $participantStatus = CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label'); $event = CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )"); @@ -325,7 +323,6 @@ class CRM_Core_BAO_ActionSchedule extends CRM_Core_DAO_ActionSchedule { * * @return array * (reference) reminder list - * @static */ public static function &getList($namesOnly = FALSE, $entityValue = NULL, $id = NULL) { $activity_type = CRM_Core_PseudoConstant::activityType(TRUE, TRUE); @@ -431,13 +428,13 @@ AND cas.entity_value = $id AND $schedule = new CRM_Core_DAO_ActionSchedule(); $schedule->id = $scheduleID; - $domain = CRM_Core_BAO_Domain::getDomain(); - $result = NULL; + $domain = CRM_Core_BAO_Domain::getDomain(); + $result = NULL; $hookTokens = array(); if ($schedule->find(TRUE)) { - $body_text = $schedule->body_text; - $body_html = $schedule->body_html; + $body_text = $schedule->body_text; + $body_html = $schedule->body_html; $sms_body_text = $schedule->sms_body_text; $body_subject = $schedule->subject; if (!$body_text) { @@ -489,7 +486,10 @@ AND cas.entity_value = $id AND $smarty = CRM_Core_Smarty::singleton(); foreach (array( - 'text', 'html', 'sms_text') as $elem) { + 'text', + 'html', + 'sms_text', + ) as $elem) { $$elem = $smarty->fetch("string:{$$elem}"); } @@ -525,7 +525,11 @@ AND cas.entity_value = $id AND if ($schedule->mode == 'SMS' or $schedule->mode == 'User_Preference') { $session = CRM_Core_Session::singleton(); $userID = $session->get('userID') ? $session->get('userID') : $contactId; - $smsParams = array('To' => $phoneNumber, 'provider_id' => $schedule->sms_provider_id, 'activity_subject' => $messageSubject); + $smsParams = array( + 'To' => $phoneNumber, + 'provider_id' => $schedule->sms_provider_id, + 'activity_subject' => $messageSubject, + ); $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type', 'SMS', 'name' @@ -590,8 +594,6 @@ AND cas.entity_value = $id AND * The array that holds all the db ids. * * @return CRM_Core_DAO_ActionSchedule - * @static - * */ public static function add(&$params, $ids = array()) { $actionSchedule = new CRM_Core_DAO_ActionSchedule(); @@ -610,8 +612,8 @@ AND cas.entity_value = $id AND * @param array $values * (reference ) an assoc array to hold the flattened values. * - * @return CRM_Core_DAO_ActionSchedule object on success, null otherwise - * @static + * @return CRM_Core_DAO_ActionSchedule|null + * object on success, null otherwise */ public static function retrieve(&$params, &$values) { if (empty($params)) { @@ -637,7 +639,6 @@ AND cas.entity_value = $id AND * @param int $id * ID of the Reminder to be deleted. * - * @static */ public static function del($id) { if ($id) { @@ -661,7 +662,6 @@ AND cas.entity_value = $id AND * * @return Object * DAO object on success, null otherwise - * @static */ public static function setIsActive($id, $is_active) { return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_ActionSchedule', $id, 'is_active', $is_active); @@ -700,16 +700,16 @@ AND cas.entity_value = $id AND $activityStatusID = FALSE; if ($actionSchedule->record_activity) { if ($mapping->entity == 'civicrm_membership') { - $activityTypeID = - CRM_Core_OptionGroup::getValue('activity_type', 'Membership Renewal Reminder', 'name'); + $activityTypeID + = CRM_Core_OptionGroup::getValue('activity_type', 'Membership Renewal Reminder', 'name'); } else { - $activityTypeID = - CRM_Core_OptionGroup::getValue('activity_type', 'Reminder Sent', 'name'); + $activityTypeID + = CRM_Core_OptionGroup::getValue('activity_type', 'Reminder Sent', 'name'); } - $activityStatusID = - CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name'); + $activityStatusID + = CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name'); } if ($mapping->entity == 'civicrm_activity') { @@ -717,12 +717,12 @@ AND cas.entity_value = $id AND $tokenEntity = 'activity'; $tokenFields = array('activity_id', 'activity_type', 'subject', 'details', 'activity_date_time'); $extraSelect = ', ov.label as activity_type, e.id as activity_id'; - $extraJoin = " + $extraJoin = " INNER JOIN civicrm_option_group og ON og.name = 'activity_type' INNER JOIN civicrm_option_value ov ON e.activity_type_id = ov.value AND ov.option_group_id = og.id"; $extraOn = ' AND e.is_current_revision = 1 AND e.is_deleted = 0 '; if ($actionSchedule->limit_to == 0) { - $extraJoin = " + $extraJoin = " LEFT JOIN civicrm_option_group og ON og.name = 'activity_type' LEFT JOIN civicrm_option_value ov ON e.activity_type_id = ov.value AND ov.option_group_id = og.id"; } @@ -738,10 +738,25 @@ LEFT JOIN civicrm_option_value ov ON e.activity_type_id = ov.value AND ov.option if ($mapping->entity == 'civicrm_participant') { $tokenEntity = 'event'; - $tokenFields = array('event_type', 'title', 'event_id', 'start_date', 'end_date', 'summary', 'description', 'location', 'info_url', 'registration_url', 'fee_amount', 'contact_email', 'contact_phone', 'balance'); + $tokenFields = array( + 'event_type', + 'title', + 'event_id', + 'start_date', + 'end_date', + 'summary', + 'description', + 'location', + 'info_url', + 'registration_url', + 'fee_amount', + 'contact_email', + 'contact_phone', + 'balance', + ); $extraSelect = ', ov.label as event_type, ev.title, ev.id as event_id, ev.start_date, ev.end_date, ev.summary, ev.description, address.street_address, address.city, address.state_province_id, address.postal_code, email.email as contact_email, phone.phone as contact_phone '; - $extraJoin = " + $extraJoin = " INNER JOIN civicrm_event ev ON e.event_id = ev.id INNER JOIN civicrm_option_group og ON og.name = 'event_type' INNER JOIN civicrm_option_value ov ON ev.event_type_id = ov.value AND ov.option_group_id = og.id @@ -751,7 +766,7 @@ LEFT JOIN civicrm_email email ON email.id = lb.email_id LEFT JOIN civicrm_phone phone ON phone.id = lb.phone_id "; if ($actionSchedule->limit_to == 0) { - $extraJoin = " + $extraJoin = " LEFT JOIN civicrm_event ev ON e.event_id = ev.id LEFT JOIN civicrm_option_group og ON og.name = 'event_type' LEFT JOIN civicrm_option_value ov ON ev.event_type_id = ov.value AND ov.option_group_id = og.id @@ -767,12 +782,12 @@ LEFT JOIN civicrm_phone phone ON phone.id = lb.phone_id $tokenEntity = 'membership'; $tokenFields = array('fee', 'id', 'join_date', 'start_date', 'end_date', 'status', 'type'); $extraSelect = ', mt.minimum_fee as fee, e.id as id , e.join_date, e.start_date, e.end_date, ms.name as status, mt.name as type'; - $extraJoin = ' + $extraJoin = ' INNER JOIN civicrm_membership_type mt ON e.membership_type_id = mt.id INNER JOIN civicrm_membership_status ms ON e.status_id = ms.id'; if ($actionSchedule->limit_to == 0) { - $extraJoin = ' + $extraJoin = ' LEFT JOIN civicrm_membership_type mt ON e.membership_type_id = mt.id LEFT JOIN civicrm_membership_status ms ON e.status_id = ms.id'; } @@ -844,7 +859,7 @@ WHERE reminder.action_schedule_id = %1 AND reminder.action_date_time IS NULL } } - $isError = 0; + $isError = 0; $errorMsg = $toEmail = $toPhoneNumber = ''; if ($actionSchedule->mode == 'SMS' or $actionSchedule->mode == 'User_Preference') { @@ -864,8 +879,8 @@ WHERE reminder.action_schedule_id = %1 AND reminder.action_date_time IS NULL if ($toEmail || !(empty($toPhoneNumber) or $toDoNotSms)) { $to['email'] = $toEmail; $to['phone'] = $toPhoneNumber; - $result = - CRM_Core_BAO_ActionSchedule::sendReminder( + $result + = CRM_Core_BAO_ActionSchedule::sendReminder( $dao->contactID, $to, $actionSchedule->id, @@ -897,8 +912,7 @@ WHERE reminder.action_schedule_id = %1 AND reminder.action_date_time IS NULL $activityParams = array( 'subject' => $actionSchedule->title, 'details' => $actionSchedule->body_html, - 'source_contact_id' => - $session->get('userID') ? $session->get('userID') : $dao->contactID, + 'source_contact_id' => $session->get('userID') ? $session->get('userID') : $dao->contactID, 'target_contact_id' => $dao->contactID, 'activity_date_time' => date('YmdHis'), 'status_id' => $activityStatusID, @@ -947,6 +961,7 @@ WHERE reminder.action_schedule_id = %1 AND reminder.action_date_time IS NULL // $limitWhere - this filtering applies only for // 'limit to' option $select = $join = $where = $limitWhere = array(); + $selectColumns = "contact_id, entity_id, entity_table, action_schedule_id"; $limitTo = $actionSchedule->limit_to; $value = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($actionSchedule->entity_value, CRM_Core_DAO::VALUE_SEPARATOR) @@ -1083,6 +1098,13 @@ WHERE reminder.action_schedule_id = %1 AND reminder.action_date_time IS NULL $membershipStatus = CRM_Member_PseudoConstant::membershipStatus(NULL, "(is_current_member = 1 OR name = 'Expired')", 'id'); $mStatus = implode(',', $membershipStatus); $where[] = "e.status_id IN ({$mStatus})"; + + // We are not tracking the reference date for 'repeated' schedule reminders, + // for further details please check CRM-15376 + if ($actionSchedule->start_action_date && $actionSchedule->is_repeat == FALSE) { + $select[] = $dateField; + $selectColumns = "reference_date, " . $selectColumns; + } } if ($mapping->entity == 'civicrm_contact') { @@ -1236,18 +1258,59 @@ reminder.action_schedule_id = %1"; } $query = " -INSERT INTO civicrm_action_log (contact_id, entity_id, entity_table, action_schedule_id) +INSERT INTO civicrm_action_log ({$selectColumns}) {$selectClause} {$fromClause} {$joinClause} LEFT JOIN {$reminderJoinClause} {$whereClause} {$limitWhereClause} AND {$dateClause} {$notINClause} "; + + // In some cases reference_date got outdated due to many reason e.g. In Membership renewal end_date got extended + // which means reference date mismatches with the end_date where end_date may be used as the start_action_date + // criteria for some schedule reminder so in order to send new reminder we INSERT new reminder with new reference_date + // value via UNION operation + if (strpos($selectColumns, 'reference_date') !== FALSE) { + $dateClause = str_replace('reminder.id IS NULL', 'reminder.id IS NOT NULL', $dateClause); + $referenceQuery = " +INSERT INTO civicrm_action_log ({$selectColumns}) +{$selectClause} +{$fromClause} +{$joinClause} + LEFT JOIN {$reminderJoinClause} +{$whereClause} {$limitWhereClause} {$notINClause} AND {$dateClause} AND + reminder.action_date_time IS NOT NULL AND + (reminder.reference_date IS NOT NULL AND reminder.reference_date != {$dateField}) +LIMIT 0,1 +"; + + // As per the usage of UNION clause above we always INSERT a new reminder if reference_date (RD) + // got outdated or mismatches to start_action_date criteria so we need to update RD with actual + // start_action_date of already sent reminder, so to prevent redeundancy in sending new reminder + // due to above INSERT-UNION query + $updateQuery = "UPDATE civicrm_action_log reminder + INNER JOIN {$mapping->entity} e ON e.id = reminder.entity_id AND + reminder.reference_date IS NOT NULL AND reminder.action_date_time IS NOT NULL + INNER JOIN civicrm_action_log new_reminder ON + new_reminder.action_schedule_id = reminder.action_schedule_id AND + new_reminder.reference_date = {$dateField} AND + new_reminder.action_date_time IS NULL + SET reminder.reference_date = {$dateField} + WHERE reminder.action_schedule_id = %1 AND reminder.reference_date IS NOT NULL AND reminder.reference_date != {$dateField} +"; + } + CRM_Core_DAO::executeQuery($query, array(1 => array($actionSchedule->id, 'Integer'))); + + if (!empty($updateQuery)) { + CRM_Core_DAO::executeQuery($referenceQuery, array(1 => array($actionSchedule->id, 'Integer'))); + CRM_Core_DAO::executeQuery($updateQuery, array(1 => array($actionSchedule->id, 'Integer'))); + } + $isSendToAdditionalContacts = (!is_null($limitTo) && $limitTo == 0 && (!empty($addGroup) || !empty($addWhere))) ? TRUE : FALSE; if ($isSendToAdditionalContacts) { $contactTable = "civicrm_contact c"; - $addSelect = "SELECT c.id as contact_id, c.id as entity_id, 'civicrm_contact' as entity_table, {$actionSchedule->id} as action_schedule_id"; + $addSelect = "SELECT c.id as contact_id, c.id as entity_id, 'civicrm_contact' as entity_table, {$actionSchedule->id} as action_schedule_id"; $additionReminderClause = "civicrm_action_log reminder ON reminder.contact_id = c.id AND reminder.entity_id = c.id AND reminder.entity_table = 'civicrm_contact' AND @@ -1314,7 +1377,13 @@ INNER JOIN {$reminderJoinClause} {$groupByClause} {$havingClause}"; - $valsqlInsertValues = CRM_Core_DAO::executeQuery($sqlInsertValues, array(1 => array($actionSchedule->id, 'Integer'))); + $valsqlInsertValues = CRM_Core_DAO::executeQuery($sqlInsertValues, array( + 1 => array( + $actionSchedule->id, + 'Integer', + ), + ) + ); $arrValues = array(); while ($valsqlInsertValues->fetch()) { @@ -1467,4 +1536,5 @@ WHERE m.owner_membership_id IS NOT NULL AND return $options; } + }