mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-09-04 10:14:13 +08:00
391 lines
13 KiB
PHP
391 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
|
|
* Copyright (C) 2023 SalesAgility Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License version 3 as published by the
|
|
* Free Software Foundation with the addition of the following permission added
|
|
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
|
|
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
|
|
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see http://www.gnu.org/licenses.
|
|
*
|
|
* In accordance with Section 7(b) of the GNU Affero General Public License
|
|
* version 3, these Appropriate Legal Notices must retain the display of the
|
|
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
|
|
* feasible for technical reasons, the Appropriate Legal Notices must display
|
|
* the words "Supercharged by SuiteCRM".
|
|
*/
|
|
|
|
require_once __DIR__ . '/AddAlert.php';
|
|
|
|
class AddScheduledReminderAlerts
|
|
{
|
|
|
|
/**
|
|
* @var AddAlert
|
|
*/
|
|
protected $addAlertService;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->addAlertService = new AddAlert();
|
|
}
|
|
|
|
/**
|
|
* @param $checkDecline bool
|
|
* @return void
|
|
*/
|
|
public function run($checkDecline = true): void
|
|
{
|
|
global $current_user, $timedate, $app_strings;
|
|
|
|
if (empty($current_user->id)) {
|
|
return;
|
|
}
|
|
|
|
[$dateTimeMaxStamp, $dateTimeNowStamp] = $this->getDateRange();
|
|
|
|
// Original jsAlert used to a meeting integration.
|
|
$meetingIntegration = $this->getMeetingIntegration();
|
|
|
|
$popupReminders = $this->getScheduledReminders($dateTimeNowStamp, $dateTimeMaxStamp);
|
|
|
|
if (empty($popupReminders)) {
|
|
return;
|
|
}
|
|
|
|
$i_runs = 0;
|
|
foreach ($popupReminders as $popupReminder) {
|
|
|
|
$relatedEventModule = $popupReminder->related_event_module ?? '';
|
|
|
|
$relatedEvent = BeanFactory::getBean(
|
|
$relatedEventModule,
|
|
$popupReminder->related_event_module_id
|
|
);
|
|
$dateTime = DateTime::createFromFormat($timedate->get_date_time_format(), $relatedEvent->date_start);
|
|
$relatedEventStart = $dateTime ? $dateTime->getTimestamp() : $dateTime;
|
|
|
|
if ($this->shouldUpdateExecutionTime($i_runs, $popupReminder)) {
|
|
$this->updateReminderExecutionTime($popupReminder, $relatedEventStart);
|
|
$i_runs++;
|
|
}
|
|
|
|
if (!$relatedEvent) {
|
|
continue;
|
|
}
|
|
|
|
$status = $relatedEvent->status ?? '';
|
|
if ($status !== '' && $relatedEvent->status !== 'Planned') {
|
|
continue;
|
|
}
|
|
|
|
$relatedEventStart -= $popupReminder->timer_popup;
|
|
|
|
if (!$this->isWithinExecutionDateRange($relatedEventStart, $dateTimeNowStamp, $dateTimeMaxStamp)) {
|
|
continue;
|
|
}
|
|
|
|
$user = BeanFactory::getBean('Users', $current_user->id);
|
|
if ($checkDecline && Reminder::isDecline($relatedEvent, $user)) {
|
|
continue;
|
|
}
|
|
|
|
// The original popup/alert reminders check the accept_status field in related users/leads/contacts etc. and filtered these users who not decline this event.
|
|
$invitees = $this->getInvitees($popupReminder, $current_user);
|
|
if (!$invitees) {
|
|
continue;
|
|
}
|
|
|
|
$url = $this->getURL($popupReminder);
|
|
$instructions = $this->getInstructions($app_strings['MSG_JS_ALERT_MTG_REMINDER_MEETING_MSG']);
|
|
|
|
if ($popupReminder->related_event_module === 'Meetings') {
|
|
[$url, $instructions] = $this->addMeetingOverrides($meetingIntegration, $popupReminder, $url,
|
|
$instructions);
|
|
}
|
|
|
|
$alertTitle = $this->getMeetingName($relatedEvent);
|
|
$location = $this->getLocation($relatedEvent);
|
|
|
|
$relatedToMeeting = $this->getRelatedName($popupReminder);
|
|
|
|
$description = $this->getDescription($relatedEvent, $app_strings, $relatedToMeeting);
|
|
|
|
|
|
$time = $this->getAlertTime($relatedEvent);
|
|
|
|
$alertSubtitle = $app_strings['MSG_JS_ALERT_MTG_REMINDER_TIME'] . $time;
|
|
$alertDescription = $app_strings['MSG_JS_ALERT_MTG_REMINDER_LOC'] . $location . $description . $instructions;
|
|
$this->addAlertService->run(
|
|
BeanFactory::getBeanName($relatedEvent->module_name) ?? '',
|
|
$alertTitle,
|
|
$alertDescription,
|
|
$url,
|
|
$time,
|
|
$popupReminder->id
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return array|null
|
|
*/
|
|
protected function getMeetingIntegration(): ?array
|
|
{
|
|
global $sugar_config;
|
|
$meetingIntegration = null;
|
|
if (isset($sugar_config['meeting_integration']) && !empty($sugar_config['meeting_integration'])) {
|
|
if (!class_exists($sugar_config['meeting_integration'])) {
|
|
require_once("modules/{$sugar_config['meeting_integration']}/{$sugar_config['meeting_integration']}.php");
|
|
}
|
|
$meetingIntegration = new $sugar_config['meeting_integration']();
|
|
}
|
|
|
|
return $meetingIntegration;
|
|
}
|
|
|
|
/**
|
|
* @param $dateTimeNowStamp
|
|
* @param $dateTimeMaxStamp
|
|
* @return SugarBean[]|null
|
|
*/
|
|
protected function getScheduledReminders($dateTimeNowStamp, $dateTimeMaxStamp): ?array
|
|
{
|
|
$popupReminders = BeanFactory::getBean('Reminders')->get_full_list(
|
|
'',
|
|
"reminders.popup = 1 AND
|
|
reminders.popup_viewed = 0 AND
|
|
(
|
|
reminders.date_willexecute = -1 OR
|
|
reminders.date_willexecute BETWEEN " . $dateTimeNowStamp . " AND " . $dateTimeMaxStamp . "
|
|
)"
|
|
);
|
|
|
|
return $popupReminders;
|
|
}
|
|
|
|
/**
|
|
* @param $relatedEvent
|
|
* @return string
|
|
*/
|
|
protected function getMeetingName($relatedEvent): string
|
|
{
|
|
global $app_strings;
|
|
$default = $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_EVENT_NAME'];
|
|
|
|
return from_html($relatedEvent->name ?? $default);
|
|
}
|
|
|
|
/**
|
|
* @param $relatedEvent
|
|
* @param array $app_strings
|
|
* @param string $relatedToMeeting
|
|
* @return string
|
|
*/
|
|
protected function getDescription($relatedEvent, array $app_strings, string $relatedToMeeting): string
|
|
{
|
|
$desc1 = from_html($relatedEvent->description ?? $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_DESCRIPTION']);
|
|
$description = empty($desc1) ? '' : $app_strings['MSG_JS_ALERT_MTG_REMINDER_AGENDA'] . $desc1 . "\n";
|
|
$description .= "\n" . $app_strings['MSG_JS_ALERT_MTG_REMINDER_STATUS'] . (isset($relatedEvent->status) ? $relatedEvent->status : '') . "\n" . $app_strings['MSG_JS_ALERT_MTG_REMINDER_RELATED_TO'] . $relatedToMeeting;
|
|
|
|
return $description;
|
|
}
|
|
|
|
/**
|
|
* @param $relatedEvent
|
|
* @return string
|
|
*/
|
|
protected function getLocation($relatedEvent): string
|
|
{
|
|
global $app_strings;
|
|
$default = $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_LOCATION'];
|
|
|
|
return from_html($relatedEvent->location ?? $default);
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $popupReminder
|
|
* @param $current_user
|
|
* @return SugarBean[]|null
|
|
*/
|
|
protected function getInvitees(SugarBean $popupReminder, $current_user): ?array
|
|
{
|
|
$invitees = BeanFactory::getBean('Reminders_Invitees')->get_full_list(
|
|
'',
|
|
"reminders_invitees.reminder_id = '{$popupReminder->id}' AND reminders_invitees.related_invitee_module_id = '{$current_user->id}'"
|
|
);
|
|
|
|
return $invitees;
|
|
}
|
|
|
|
/**
|
|
* To return the name of parent bean.
|
|
* @param $popupReminder
|
|
* @return string
|
|
*/
|
|
protected function getRelatedName($popupReminder): string
|
|
{
|
|
$parentType = $popupReminder->related_event_module;
|
|
$parentId = $popupReminder->related_event_module_id;
|
|
|
|
if (!empty($parentType) && !empty($parentId)) {
|
|
$parentBean = BeanFactory::getBean($parentType, $parentId);
|
|
if (($parentBean instanceof SugarBean) && isset($parentBean->name)) {
|
|
return $parentBean->name;
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Get date range
|
|
* @return array
|
|
*/
|
|
protected function getDateRange(): array
|
|
{
|
|
global $timedate, $app_list_strings;
|
|
|
|
$reminder_max_time = $app_list_strings['reminder_max_time'] ?? 0;
|
|
|
|
$dateTimeMax = $timedate->getNow(true)->modify("+{$reminder_max_time} seconds")->asDb(false);
|
|
|
|
$dateTimeNow = $timedate->getNow(true)->asDb(false);
|
|
|
|
$dateTimeNowStamp = strtotime(Reminder::unQuoteTime($dateTimeNow));
|
|
$dateTimeMaxStamp = strtotime(Reminder::unQuoteTime($dateTimeMax));
|
|
|
|
return [$dateTimeMaxStamp, $dateTimeNowStamp];
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $popupReminder
|
|
* @param $relatedEventStart
|
|
* @return void
|
|
*/
|
|
protected function updateReminderExecutionTime(SugarBean $popupReminder, $relatedEventStart): void
|
|
{
|
|
//we have column to save data
|
|
if (!$relatedEventStart) {
|
|
$popupReminder->date_willexecute = -2;
|
|
} else {
|
|
$popupReminder->date_willexecute = $relatedEventStart;
|
|
}
|
|
$popupReminder->save();
|
|
}
|
|
|
|
/**
|
|
* @param int $i_runs
|
|
* @param SugarBean $popupReminder
|
|
* @return bool
|
|
*/
|
|
protected function shouldUpdateExecutionTime(int $i_runs, SugarBean $popupReminder): bool
|
|
{
|
|
return $i_runs < 1000 &&
|
|
isset($popupReminder->fetched_row['date_willexecute']) &&
|
|
$popupReminder->fetched_row['date_willexecute'] == -1;
|
|
}
|
|
|
|
/**
|
|
* @param $relatedEventStart
|
|
* @param $dateTimeNowStamp
|
|
* @param $dateTimeMaxStamp
|
|
* @return bool
|
|
*/
|
|
protected function isWithinExecutionDateRange($relatedEventStart, $dateTimeNowStamp, $dateTimeMaxStamp): bool
|
|
{
|
|
if (empty($relatedEventStart)) {
|
|
return false;
|
|
}
|
|
|
|
//increase time by 10 secs to make sure we calculate within the correct minute
|
|
if (($dateTimeNowStamp + 10) < $relatedEventStart) {
|
|
return false;
|
|
}
|
|
|
|
if ($relatedEventStart > $dateTimeMaxStamp) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param $relatedEvent
|
|
* @return mixed|string
|
|
*/
|
|
protected function getAlertTime($relatedEvent)
|
|
{
|
|
global $app_strings, $timedate, $db;
|
|
|
|
$default = $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_START_DATE'];
|
|
$dateStart = $relatedEvent->date_start ?? '';
|
|
|
|
if (!empty($dateStart)) {
|
|
$time_dbFromConvert = $db->fromConvert($dateStart, 'datetime');
|
|
$time = $timedate->to_display_date_time($time_dbFromConvert);
|
|
if (!$time) {
|
|
$time = $dateStart;
|
|
}
|
|
if (!$time) {
|
|
$time = $default;
|
|
}
|
|
} else {
|
|
$time = $default;
|
|
}
|
|
|
|
return $time;
|
|
}
|
|
|
|
/**
|
|
* @param SugarBean $popupReminder
|
|
* @return string
|
|
*/
|
|
protected function getURL(SugarBean $popupReminder): string
|
|
{
|
|
return Reminder::makeAlertURL(
|
|
$popupReminder->related_event_module,
|
|
$popupReminder->related_event_module_id
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param $MSG_JS_ALERT_MTG_REMINDER_MEETING_MSG
|
|
* @return mixed
|
|
*/
|
|
protected function getInstructions($MSG_JS_ALERT_MTG_REMINDER_MEETING_MSG)
|
|
{
|
|
return $MSG_JS_ALERT_MTG_REMINDER_MEETING_MSG;
|
|
}
|
|
|
|
/**
|
|
* @param array|null $meetingIntegration
|
|
* @param SugarBean $popupReminder
|
|
* @param $url
|
|
* @param $instructions
|
|
* @return array
|
|
*/
|
|
protected function addMeetingOverrides(
|
|
?array $meetingIntegration,
|
|
SugarBean $popupReminder,
|
|
$url,
|
|
$instructions
|
|
): array {
|
|
if (!empty($meetingIntegration) && $meetingIntegration->isIntegratedMeeting($popupReminder->related_event_module_id)) {
|
|
$url = $meetingIntegration->miUrlGetJsAlert((array)$popupReminder);
|
|
$instructions = $meetingIntegration->miGetJsAlertInstructions();
|
|
}
|
|
|
|
return [$url, $instructions];
|
|
}
|
|
}
|