Skip to content

Commit

Permalink
Merge branch 'hotfix' into develop-39188
Browse files Browse the repository at this point in the history
  • Loading branch information
Chang Shu-Huai committed Nov 28, 2024
2 parents 9148a83 + ebf8fdb commit 216554d
Show file tree
Hide file tree
Showing 72 changed files with 950 additions and 116 deletions.
114 changes: 104 additions & 10 deletions CRM/Activity/BAO/Activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,6 @@ public static function sendSMS(
$activityParams['activity_type_id'] = CRM_Utils_Array::key('SMS', CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'name', TRUE));
}


// CRM-4575
// token replacement of addressee/email/postal greetings
// get the tokens added in subject and message
Expand Down Expand Up @@ -1591,8 +1590,28 @@ public static function sendSMS(
unset($details["{$contactId}"]['phone_type_id']);
$values = array_merge($values, $details["{$contactId}"]);
}
$eachActivityParams['source_contact_id'] = $userID;
$eachActivityParams['activity_date_time'] = date('YmdHis');
$eachActivityParams['status_id'] = CRM_Utils_Array::key('Scheduled', CRM_Core_PseudoConstant::activityStatus('name'));
$activity = self::create($eachActivityParams);

CRM_Utils_Hook::tokenValues($values, $contactId, NULL, $messageToken, 'CRM_Activity_BAO_Activity::sendSMS');
$tokenDetail = array(
0 => array(),
$contactId => $values,
);
$values[0]['activity'] = array();
$values[0]['activity']['id'] = $activity->id;
$values[0]['activity']['parent_id'] = $eachActivityParams['parent_id'];
foreach($activityParams as $idx => $val) {
if (isset($activity->$idx)) {
$tokenDetail[0]['activity'][$idx] = $activity->$idx;
}
}
$tokenContact = array(
$contactId,
);
CRM_Utils_Hook::tokenValues($tokenDetail, $tokenContact, NULL, $messageToken, __CLASS__.'::'.__METHOD__);
$values = $tokenDetail[$contactId];

$tokenText = CRM_Utils_Token::replaceContactTokens($text, $values, FALSE, $messageToken, FALSE, $escapeSmarty);
$tokenText = CRM_Utils_Token::replaceComponentTokens($tokenText, $values, $messageToken, TRUE);
Expand All @@ -1607,16 +1626,12 @@ public static function sendSMS(
else {
$smsParams['phone'] = '';
}

$activity->details = ts("Body") . ": " . $smsMessage;
if (!empty($eachActivityParams['activity_subject']) && empty($eachActivityParams['subject'])) {
$eachActivityParams['subject'] = $eachActivityParams['activity_subject'];
$activity->subject = $eachActivityParams['activity_subject'];
}
$eachActivityParams['source_contact_id'] = $userID;
$eachActivityParams['activity_date_time'] = date('YmdHis');
$eachActivityParams['details'] = ts("Body") . ": " . $smsMessage;
$eachActivityParams['status_id'] = CRM_Utils_Array::key('Scheduled', CRM_Core_PseudoConstant::activityStatus('name'));

$activity = self::create($eachActivityParams);
// update body and subject after token replacement
$activity->save();

// add activity target record for every sms *BEFORE* sms send
$activityTargetParams = array(
Expand Down Expand Up @@ -1675,6 +1690,85 @@ public static function sendSMS(
}
}

/**
* Send SMS via specific template
*
* @param int $fromId
* @param int $toId
* @param int $templateId
* @param bool $check
* @param int $parentId
* @return bool
*/
public static function sendSMSTemplate(
$fromId,
$toId,
$templateId,
$check,
$parentId
) {
$providers = CRM_SMS_BAO_Provider::getProviders(NULL, NULL, TRUE, 'is_default desc');
if (empty($providers)) {
CRM_Core_Session::setStatus(ts("There is no SMS Provider Configured. You can add here <a href='%1'>Add SMS Provider</a>", CRM_Utils_System::url('civicrm/admin/sms/provider', 'reset=1')), TRUE, 'warning');
return FALSE;
}

$returnProperties = array(
'sort_name' => 1,
'phone' => 1,
'do_not_phone' => 1,
'is_deceased' => 1,
'display_name' => 1,
);
$getDetails = array($toId);
if (is_numeric($fromId)) {
$fromId = $fromId;
$getDetails[] = $fromId;
$from = NULL;
}
else {
$fromId = NULL;
}
list($details) = CRM_Mailing_BAO_Mailing::getDetails($getDetails, $returnProperties, FALSE, FALSE, NULL, TRUE);
if (!empty($details)) {
$toDetails = $details[$toId];
if ($check) {
if ($toDetails['do_not_phone'] || empty($toDetails['phone']) || !empty($toDetails['is_deceased'])) {
return FALSE;
}
}

$params = array('id' => $templateId);
$template = array();
CRM_Core_BAO_MessageTemplates::retrieve($params, $template);
$subject = $template['msg_subject'];
$text = !empty($template['msg_text']) ? $template['msg_text'] : '';
$activityParams = array(
'activity_subject' => $subject,
'sms_text_message' => $text,
);
if (!empty($parentId)) {
$activityParams['parent_id'] = $parentId;
}
$smsParams = array(
'provider_id' => '1',
);
$contactDetails = array($toId => $toDetails);
$contactIds = array($toId);
list($sent) = self::sendSMS(
$contactDetails,
$activityParams,
$smsParams,
$contactIds,
$fromId
);
if ($sent) {
return TRUE;
}
}
return FALSE;
}

/**
* Send an sms message to a specific phone or contact
*
Expand Down
2 changes: 1 addition & 1 deletion CRM/Activity/Form/ActivityLinks.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static function commonBuildQuickForm($self) {
$providersCount = CRM_SMS_BAO_Provider::activeProviderCount();
if ($providersCount) {
$phones = CRM_Core_BAO_Phone::allPhones($contactId, FALSE, ts('Mobile'));
if (count($phones)) {
if (!empty($phones)) {
$activityTypes[4] = ts('Send SMS');
}
}
Expand Down
5 changes: 5 additions & 0 deletions CRM/Activity/Page/Tab.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ function browse() {
$output = CRM_Core_Selector_Controller::SESSION;
require_once 'CRM/Activity/Selector/Activity.php';
$selector = new CRM_Activity_Selector_Activity($this->_contactId, $this->_permission);
$currentPath = CRM_Utils_System::currentPath();
if (!empty($this->_contactId) && strstr($currentPath, 'civicrm/contact/view')) {
$pagerURL = CRM_Utils_System::url('civicrm/contact/view/activity', "cid={$this->_contactId}&force=1");
$this->assign('pagerURL', $pagerURL);
}
$sortID = NULL;
if ($this->get(CRM_Utils_Sort::SORT_ID)) {
$sortID = CRM_Utils_Sort::sortIDValue($this->get(CRM_Utils_Sort::SORT_ID),
Expand Down
39 changes: 39 additions & 0 deletions CRM/Activity/PseudoConstant.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

class CRM_Activity_PseudoConstant extends CRM_Core_PseudoConstant {

/**
* Get all Activity Statuses.
*
* The static array activityStatus is returned
*
* @access public
* @static
*
* @return array - array reference of all activity statuses
*/
public static function &activityStatus($column = 'label') {
return parent::activityStatus($column);
}

/**
* Get all Activty types.
*
* The static array activityType is returned
*
* @param boolean $all - get All Activity types - default is to get only active ones.
*
* @access public
* @static
*
* @return array - array reference of all activty types.
*/
public static function &activityType($all = TRUE,
$includeCaseActivities = FALSE,
$reset = FALSE,
$returnColumn = 'label',
$includeCampaignActivities = FALSE
) {
return parent::activityType($all, $includeCaseActivities, $reset, $returnColumn, $includeCampaignActivities);
}
}
9 changes: 9 additions & 0 deletions CRM/Admin/Form/Setting/Receipt.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public function buildQuickForm() {
// Refs #38829, Add receipt Email Encryption option
$this->add('checkbox', 'receiptEmailEncryption', ts('Email Receipt Password'));
$this->addElement('text', 'receiptEmailEncryptionText', ts('Email Receipt Password Explanation Text'));
$this->addFormRule(array(get_class($this), 'formRule'));
}

function setDefaultValues() {
Expand Down Expand Up @@ -141,6 +142,14 @@ public function postProcess() {
parent::commonProcess($params);
}

static function formRule($fields, $files, $self) {
$errors = [];
if ((!empty($fields['receiptDisplayLegalID']) && $fields['receiptDisplayLegalID'] !== 'complete') && (!empty($fields['receiptEmailEncryption']) && $fields['receiptEmailEncryption'] === '1')) {
$errors['receiptEmailEncryption'] = ts('When the legal ID display option is not set to complete display, email receipt encryption cannot be enabled.');
}
return empty($errors) ? true : $errors;
}

/**
* Resize a premium image to a different size
*
Expand Down
89 changes: 81 additions & 8 deletions CRM/Batch/BAO/Batch.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ class CRM_Batch_BAO_Batch extends CRM_Batch_DAO_Batch {
*/
const EXPIRE_DAY = 8;

/**
* stuck expire hour
*/
const EXPIRE_HOUR = 4;

/**
* Batch id to load
* @var int
Expand Down Expand Up @@ -170,25 +175,23 @@ public static function runQueue() {
$message = ts('Success processing queuing batch.');
}
}
if (date('G') >= 3 && date('G') <= 6) {
self::expireBatch();
}
return $message;
}

/**
* Run last queuing batching
* Expire batches over expire days
* This will delete data column and purge download file to prevent db growing
*
* @return string
* message that indicate current running status
* message that indicate expires
*/
public static function expireBatch() {
$type = self::batchType();
$status = self::batchStatus();
unset($status['Running']);
unset($status['Pending']);
$purgeDay = self::EXPIRE_DAY*4;
$sql = "SELECT id FROM civicrm_batch WHERE type_id = %1 AND status_id IN (".CRM_Utils_Array::implode(',', $status).") AND DATE_ADD(modified_date, INTERVAL ".$purgeDay." DAY) < NOW() AND modified_date IS NOT NULL ORDER BY modified_date ASC";
$sql = "SELECT id FROM civicrm_batch WHERE type_id = %1 AND status_id IN (".CRM_Utils_Array::implode(',', $status).") AND DATE_ADD(modified_date, INTERVAL ".$purgeDay." DAY) < NOW() AND modified_date IS NOT NULL AND data IS NOT NULL ORDER BY modified_date ASC";
$dao = CRM_Core_DAO::executeQuery($sql, array(
1 => array($type['Auto'], 'Integer'),
));
Expand All @@ -202,10 +205,13 @@ public static function expireBatch() {
if ($batch->id) {
if (isset($batch->data['download']['file']) && file_exists($batch->data['download']['file'])) {
@unlink($batch->data['download']['file']);
$expires[] = $dao->id;
}
// $batch->delete(); // do not delete batch db record, purge file only
$expires[] = $dao->id;
CRM_Core_DAO::executeQuery("UPDATE civicrm_batch SET data = NULL WHERE id = %1", array(1 => array($dao->id, 'Integer')));
}
// refs #41959, free memory of batch result to prevent memory leak
$batch->free();
unset($batch);
}
if (count($expires)) {
$msg = 'Batch ids in '.CRM_Utils_Array::implode(",", $expires).' has been expires';
Expand All @@ -215,6 +221,73 @@ public static function expireBatch() {
return '';
}

/**
* Auto remove stuck batch
*
* @return null
*/
public static function cancelStuckBatch() {
$type = self::batchType();
$status = self::batchStatus();
$statusRunning = $status['Running'];
$statusCanceled = $status['Canceled'];

$sql = "SELECT id, data, modified_date, description FROM civicrm_batch WHERE type_id = %1 AND status_id = %2 ORDER BY created_date ASC LIMIT 1";
$dao = CRM_Core_DAO::executeQuery($sql, array(
1 => array($type['Auto'], 'Integer'),
2 => array($statusRunning, 'Integer'),
));
$dao->fetch();
if (!empty($dao->id)) {
if ($dao->data) {
$meta = unserialize($dao->data);
// after 4 hours without any progress, cancel it
if (is_array($meta) && empty($meta['processed']) && !empty($dao->modified_date)) {
$lastSuccessTime = strtotime($dao->modified_date);
if (CRM_REQUEST_TIME - $lastSuccessTime > 3600 * self::EXPIRE_HOUR) {
CRM_Core_Error::debug_log_message("Canceled running batch id {$dao->id} due to zero progress over ".self::EXPIRE_HOUR." hours.");
CRM_Core_DAO::executeQuery("UPDATE civicrm_batch SET status_id = %1, description = %2 WHERE id = %3", array(
1 => array($statusCanceled, 'Integer'),
2 => array(ts('Batch running failed. Contact the site administrator for assistance.'), 'String'),
3 => array($dao->id, 'Integer'),
));
}
}
elseif(!empty($meta['processed'])){
if (!empty($dao->description)) {
$processHistories = explode(':', $dao->description);
}
else {
$processHistories = array();
}
$stuck = 0;
foreach($processHistories as $lastProcessed) {
if ((int)$meta['processed'] == (int)$lastProcessed) {
$stuck++;
}
}
if ($stuck <= self::EXPIRE_HOUR) {
array_unshift($processHistories, $meta['processed']);
$processHistories = array_slice($processHistories, 0, self::EXPIRE_HOUR+2);
CRM_Core_DAO::executeQuery("UPDATE civicrm_batch SET description = %1 WHERE id = %2", array(
1 => array(implode(':', $processHistories), 'String'),
2 => array($dao->id, 'Integer'),
));
}
else {
// no progress after 4 times(have same processed records), cancel it
CRM_Core_Error::debug_log_message("Canceled running batch id {$dao->id} due to stuck in progress {$meta['processed']} for {$stuck} times.");
CRM_Core_DAO::executeQuery("UPDATE civicrm_batch SET status_id = %1, description = %2 WHERE id = %3", array(
1 => array($statusCanceled, 'Integer'),
2 => array(ts('Batch running failed. Contact the site administrator for assistance.').' ('.$dao->description.')', 'String'),
3 => array($dao->id, 'Integer'),
));
}
}
}
}
}

/**
* Constructor
*
Expand Down
2 changes: 1 addition & 1 deletion CRM/Contact/BAO/GroupContact.php
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ static function getGroupContacts(&$group,
civicrm_email.email as email";
}
else {
$query = "SELECT DISTINCT(contact_a.id) as contact_id , $grpStatus as status,";
$query = "SELECT DISTINCT(contact_a.id) as contact_id,";
$query .= CRM_Utils_Array::implode(',', $returnProperties);
}

Expand Down
7 changes: 6 additions & 1 deletion CRM/Contact/BAO/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -3939,7 +3939,12 @@ static function apiQuery($params = NULL,
$sql = "$select $from $where $having";
// add group by
if ($query->_useGroupBy || $groupBy) {
$sql .= ' GROUP BY contact_a.id';
if (isset($query->_groupByComponentClause) && !empty($query->_groupByComponentClause)) {
$sql .= $query->_groupByComponentClause;
}
else {
$sql .= ' GROUP BY contact_a.id';
}
}
if (!empty($sort)) {
$sql .= " ORDER BY $sort ";
Expand Down
Loading

0 comments on commit 216554d

Please sign in to comment.