adamjakab /
SuiteCRM
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /********************************************************************************* |
||
| 3 | * SugarCRM Community Edition is a customer relationship management program developed by |
||
| 4 | * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. |
||
| 5 | * |
||
| 6 | * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
||
| 7 | * Copyright (C) 2011 - 2016 Salesagility Ltd. |
||
| 8 | * |
||
| 9 | * This program is free software; you can redistribute it and/or modify it under |
||
| 10 | * the terms of the GNU Affero General Public License version 3 as published by the |
||
| 11 | * Free Software Foundation with the addition of the following permission added |
||
| 12 | * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
||
| 13 | * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
||
| 14 | * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
||
| 15 | * |
||
| 16 | * This program is distributed in the hope that it will be useful, but WITHOUT |
||
| 17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
| 18 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
||
| 19 | * details. |
||
| 20 | * |
||
| 21 | * You should have received a copy of the GNU Affero General Public License along with |
||
| 22 | * this program; if not, see http://www.gnu.org/licenses or write to the Free |
||
| 23 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||
| 24 | * 02110-1301 USA. |
||
| 25 | * |
||
| 26 | * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
||
| 27 | * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
||
| 28 | * |
||
| 29 | * The interactive user interfaces in modified source and object code versions |
||
| 30 | * of this program must display Appropriate Legal Notices, as required under |
||
| 31 | * Section 5 of the GNU Affero General Public License version 3. |
||
| 32 | * |
||
| 33 | * In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
||
| 34 | * these Appropriate Legal Notices must retain the display of the "Powered by |
||
| 35 | * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
||
| 36 | * reasonably feasible for technical reasons, the Appropriate Legal Notices must |
||
| 37 | * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
||
| 38 | ********************************************************************************/ |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Reminder class |
||
| 42 | * |
||
| 43 | */ |
||
| 44 | class Reminder extends Basic |
||
| 45 | { |
||
| 46 | |||
| 47 | const UPGRADE_VERSION = '7.4.3'; |
||
| 48 | |||
| 49 | var $name; |
||
| 50 | |||
| 51 | var $new_schema = true; |
||
| 52 | var $module_dir = 'Reminders'; |
||
| 53 | var $object_name = 'Reminder'; |
||
| 54 | var $table_name = 'reminders'; |
||
| 55 | var $tracker_visibility = false; |
||
| 56 | var $importable = false; |
||
| 57 | var $disable_row_level_security = true; |
||
| 58 | |||
| 59 | var $popup; |
||
| 60 | var $email; |
||
| 61 | var $email_sent = false; |
||
| 62 | var $timer_popup; |
||
| 63 | var $timer_email; |
||
| 64 | var $related_event_module; |
||
| 65 | var $related_event_module_id; |
||
| 66 | |||
| 67 | private static $remindersData = array(); |
||
| 68 | |||
| 69 | 5 | public function __construct() |
|
| 70 | { |
||
| 71 | 5 | parent::__construct(); |
|
| 72 | 5 | } |
|
| 73 | |||
| 74 | 5 | public function bean_implements($interface) |
|
| 75 | { |
||
| 76 | switch ($interface) { |
||
| 77 | 5 | case 'ACL': |
|
| 78 | 5 | return true; |
|
| 79 | } |
||
| 80 | return false; |
||
| 81 | } |
||
| 82 | |||
| 83 | // ---- save and load remainders on EditViews |
||
| 84 | |||
| 85 | /** |
||
| 86 | * Save multiple reminders data from clients Meetings/Calls EditView. |
||
| 87 | * Call this static function in save action. |
||
| 88 | * |
||
| 89 | * @param string $eventModule Event Bean module name (e.g. Meetings, Calls) |
||
| 90 | * @param string $eventModuleId Event Bean GUID |
||
| 91 | * @param string $remindersDataJson Remainders data as Json string from POST data. |
||
| 92 | * @throws Exception throw an Exception if json format is invalid. |
||
| 93 | */ |
||
| 94 | public static function saveRemindersDataJson($eventModule, $eventModuleId, $remindersDataJson) |
||
| 95 | { |
||
| 96 | $reminderData = json_decode($remindersDataJson); |
||
| 97 | if (!json_last_error()) { |
||
| 98 | Reminder::saveRemindersData($eventModule, $eventModuleId, $reminderData); |
||
| 99 | } else { |
||
| 100 | throw new Exception(json_last_error_msg()); |
||
| 101 | } |
||
| 102 | } |
||
| 103 | |||
| 104 | private static function saveRemindersData($eventModule, $eventModuleId, $remindersData) |
||
| 105 | { |
||
| 106 | $savedReminderIds = array(); |
||
| 107 | foreach ($remindersData as $reminderData) { |
||
| 108 | if (isset($_POST['isDuplicate']) && $_POST['isDuplicate']) $reminderData->id = ''; |
||
| 109 | $reminderBean = BeanFactory::getBean('Reminders', $reminderData->id); |
||
| 110 | $reminderBean->popup = $reminderData->popup; |
||
| 111 | $reminderBean->email = $reminderData->email; |
||
| 112 | $reminderBean->timer_popup = $reminderData->timer_popup; |
||
| 113 | $reminderBean->timer_email = $reminderData->timer_email; |
||
| 114 | $reminderBean->related_event_module = $eventModule; |
||
| 115 | $reminderBean->related_event_module_id = $eventModuleId; |
||
| 116 | $reminderBean->save(); |
||
| 117 | $savedReminderIds[] = $reminderBean->id; |
||
| 118 | $reminderId = $reminderBean->id; |
||
| 119 | Reminder_Invitee::saveRemindersInviteesData($reminderId, $reminderData->invitees); |
||
| 120 | } |
||
| 121 | $reminders = BeanFactory::getBean('Reminders')->get_full_list("", "reminders.related_event_module = '$eventModule' AND reminders.related_event_module_id = '$eventModuleId'"); |
||
| 122 | if ($reminders) { |
||
| 123 | foreach ($reminders as $reminder) { |
||
| 124 | if (!in_array($reminder->id, $savedReminderIds)) { |
||
| 125 | Reminder_Invitee::deleteRemindersInviteesMultiple($reminder->id); |
||
| 126 | $reminder->mark_deleted($reminder->id); |
||
| 127 | $reminder->save(); |
||
| 128 | } |
||
| 129 | } |
||
| 130 | } |
||
| 131 | unset(self::$remindersData[$eventModule][$eventModuleId]); |
||
| 132 | } |
||
| 133 | |||
| 134 | /** |
||
| 135 | * Load multiple reminders JSON data for related Event module EditViews. |
||
| 136 | * Call this function in module display function. |
||
| 137 | * |
||
| 138 | * @param string $eventModule Related event module name (Meetings/Calls) |
||
| 139 | * @param string $eventModuleId Related event GUID |
||
| 140 | * @return string JSON string contains the remainders |
||
| 141 | * @throws Exception |
||
| 142 | */ |
||
| 143 | public static function loadRemindersDataJson($eventModule, $eventModuleId, $isDuplicate = false) |
||
| 144 | { |
||
| 145 | $remindersData = self::loadRemindersData($eventModule, $eventModuleId, $isDuplicate); |
||
| 146 | $remindersDataJson = json_encode($remindersData); |
||
| 147 | if (!$remindersDataJson && json_last_error()) { |
||
| 148 | throw new Exception(json_last_error_msg()); |
||
| 149 | } |
||
| 150 | return $remindersDataJson; |
||
| 151 | } |
||
| 152 | |||
| 153 | /** |
||
| 154 | * Load multiple reminders data for related Event module EditViews. |
||
| 155 | * Call this function in module display function. |
||
| 156 | * |
||
| 157 | * @param string $eventModule Related event module name (Meetings/Calls) |
||
| 158 | * @param string $eventModuleId Related event GUID |
||
| 159 | * @return array contains the remainders |
||
| 160 | * @throws Exception |
||
| 161 | */ |
||
| 162 | public static function loadRemindersData($eventModule, $eventModuleId, $isDuplicate = false) |
||
| 163 | { |
||
| 164 | if (!isset(self::$remindersData[$eventModule][$eventModuleId]) || !$eventModuleId || $isDuplicate) { |
||
| 165 | $ret = array(); |
||
| 166 | $reminders = BeanFactory::getBean('Reminders')->get_full_list("reminders.date_entered", "reminders.related_event_module = '$eventModule' AND reminders.related_event_module_id = '$eventModuleId'"); |
||
| 167 | if ($reminders) { |
||
| 168 | foreach ($reminders as $reminder) { |
||
| 169 | $ret[] = array( |
||
| 170 | 'id' => $isDuplicate ? null : $reminder->id, |
||
| 171 | 'popup' => $reminder->popup, |
||
| 172 | 'email' => $reminder->email, |
||
| 173 | 'timer_popup' => $reminder->timer_popup, |
||
| 174 | 'timer_email' => $reminder->timer_email, |
||
| 175 | 'invitees' => Reminder_Invitee::loadRemindersInviteesData($reminder->id, $isDuplicate), |
||
| 176 | ); |
||
| 177 | } |
||
| 178 | } |
||
| 179 | self::$remindersData[$eventModule][$eventModuleId] = $ret; |
||
| 180 | } |
||
| 181 | return self::$remindersData[$eventModule][$eventModuleId]; |
||
| 182 | } |
||
| 183 | |||
| 184 | // ---- sending email reminders |
||
| 185 | |||
| 186 | /** |
||
| 187 | * Sending multiple email reminders. |
||
| 188 | * Call in EmainReminder and use original EmailRemainder class for sending. |
||
| 189 | * |
||
| 190 | * @param EmailReminder $emailReminder Caller EmailReminder |
||
| 191 | * @param Administration $admin Administration module for EmailRemainder->sendReminders() function |
||
| 192 | * @param boolean $checkDecline (optional) Send email if user accept status is not decline. Default is TRUE. |
||
| 193 | */ |
||
| 194 | public static function sendEmailReminders(EmailReminder $emailReminder, Administration $admin, $checkDecline = true) |
||
| 195 | { |
||
| 196 | if ($reminders = self::getUnsentEmailReminders()) { |
||
| 197 | foreach ($reminders as $reminderId => $reminder) { |
||
| 198 | $recipients = self::getEmailReminderInviteesRecipients($reminderId, $checkDecline); |
||
| 199 | $eventBean = BeanFactory::getBean($reminder->related_event_module, $reminder->related_event_module_id); |
||
| 200 | if ($eventBean && $emailReminder->sendReminders($eventBean, $admin, $recipients)) { |
||
| 201 | $reminder->email_sent = 1; |
||
| 202 | $reminder->save(); |
||
| 203 | } |
||
| 204 | } |
||
| 205 | } |
||
| 206 | } |
||
| 207 | |||
| 208 | private static function getEmailReminderInviteesRecipients($reminderId, $checkDecline = true) |
||
| 209 | { |
||
| 210 | $emails = array(); |
||
| 211 | $reminder = BeanFactory::getBean('Reminders', $reminderId); |
||
| 212 | $eventModule = $reminder->related_event_module; |
||
| 213 | $eventModuleId = $reminder->related_event_module_id; |
||
| 214 | $event = BeanFactory::getBean($eventModule, $eventModuleId); |
||
| 215 | if ($event && (!isset($event->status) || $event->status != 'Held')) { |
||
| 216 | $invitees = BeanFactory::getBean('Reminders_Invitees')->get_full_list('', "reminders_invitees.reminder_id = '$reminderId'"); |
||
| 217 | foreach ($invitees as $invitee) { |
||
|
0 ignored issues
–
show
|
|||
| 218 | $inviteeModule = $invitee->related_invitee_module; |
||
| 219 | $inviteeModuleId = $invitee->related_invitee_module_id; |
||
| 220 | $personBean = BeanFactory::getBean($inviteeModule, $inviteeModuleId); |
||
| 221 | // The original email reminders check the accept_status field in related users/leads/contacts etc. and filtered these users who not decline this event. |
||
| 222 | if ($checkDecline && !self::isDecline($event, $personBean)) { |
||
| 223 | if (!empty($personBean->email1)) { |
||
| 224 | $arr = array( |
||
| 225 | 'type' => $inviteeModule, |
||
| 226 | 'name' => $personBean->full_name, |
||
| 227 | 'email' => $personBean->email1, |
||
| 228 | ); |
||
| 229 | $emails[] = $arr; |
||
| 230 | } |
||
| 231 | } |
||
| 232 | } |
||
| 233 | } |
||
| 234 | return $emails; |
||
| 235 | } |
||
| 236 | |||
| 237 | private static function getUnsentEmailReminders() |
||
| 238 | { |
||
| 239 | global $timedate; |
||
| 240 | $reminders = array(); |
||
| 241 | $reminderBeans = BeanFactory::getBean('Reminders')->get_full_list('', "reminders.email = 1 AND reminders.email_sent = 0"); |
||
| 242 | if (!empty($reminderBeans)) { |
||
| 243 | foreach ($reminderBeans as $reminderBean) { |
||
| 244 | $eventBean = BeanFactory::getBean($reminderBean->related_event_module, $reminderBean->related_event_module_id); |
||
| 245 | if($eventBean) { |
||
| 246 | $remind_ts = $timedate->fromUser($eventBean->date_start)->modify("-{$reminderBean->timer_email} seconds")->ts; |
||
| 247 | $now_ts = $timedate->getNow()->ts; |
||
| 248 | if ($now_ts >= $remind_ts) { |
||
| 249 | $reminders[$reminderBean->id] = $reminderBean; |
||
| 250 | } |
||
| 251 | } else { |
||
| 252 | $reminderBean->mark_deleted($reminderBean->id); |
||
| 253 | } |
||
| 254 | } |
||
| 255 | } |
||
| 256 | return $reminders; |
||
| 257 | } |
||
| 258 | |||
| 259 | // ---- popup and alert reminders |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Show a popup and/or desktop notification alert for related users with related Event information. |
||
| 263 | * Call in jsAlerts class and use original jsAlerts for show notifications. |
||
| 264 | * |
||
| 265 | * @global ??? $current_user |
||
| 266 | * @global ??? $timedate |
||
| 267 | * @global ??? $app_list_strings |
||
| 268 | * @global ??? $db |
||
| 269 | * @global ??? $sugar_config |
||
| 270 | * @global ??? $app_strings |
||
| 271 | * @param jsAlerts $alert caller jsAlerts object |
||
| 272 | * @param boolean $checkDecline (optional) Send email if user accept status is not decline. Default is TRUE. |
||
| 273 | * @return ??? |
||
|
0 ignored issues
–
show
The doc-type
??? could not be parsed: Unknown type name "???" at position 0. (view supported doc-types)
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types. Loading history...
|
|||
| 274 | */ |
||
| 275 | public static function addNotifications(jsAlerts $alert, $checkDecline = true) |
||
| 276 | { |
||
| 277 | global $current_user, $timedate, $app_list_strings, $db, $sugar_config, $app_strings; |
||
| 278 | |||
| 279 | if (empty($current_user->id)) { |
||
| 280 | return; |
||
| 281 | } |
||
| 282 | |||
| 283 | // Create separate variable to hold timedate value |
||
| 284 | // These timedates need to be in the user time zone as the |
||
| 285 | // datetime returned by the Bean below is in the user time zone |
||
| 286 | $alertDateTimeNow = $timedate->getNow(true)->asDb(false); |
||
| 287 | |||
| 288 | // cn: get a boundary limiter |
||
| 289 | $dateTimeMax = $timedate->getNow(true)->modify("+{$app_list_strings['reminder_max_time']} seconds")->asDb(false); |
||
| 290 | $dateTimeNow = $timedate->getNow(true)->asDb(false); |
||
| 291 | |||
| 292 | $dateTimeNow = $db->convert($db->quoted($dateTimeNow), 'datetime'); |
||
| 293 | $dateTimeMax = $db->convert($db->quoted($dateTimeMax), 'datetime'); |
||
| 294 | |||
| 295 | // Original jsAlert used to a meeting integration. |
||
| 296 | |||
| 297 | /////////////////////////////////////////////////////////////////////// |
||
| 298 | //// MEETING INTEGRATION |
||
| 299 | $meetingIntegration = null; |
||
| 300 | if (isset($sugar_config['meeting_integration']) && !empty($sugar_config['meeting_integration'])) { |
||
| 301 | if (!class_exists($sugar_config['meeting_integration'])) { |
||
| 302 | require_once("modules/{$sugar_config['meeting_integration']}/{$sugar_config['meeting_integration']}.php"); |
||
| 303 | } |
||
| 304 | $meetingIntegration = new $sugar_config['meeting_integration'](); |
||
| 305 | } |
||
| 306 | //// END MEETING INTEGRATION |
||
| 307 | /////////////////////////////////////////////////////////////////////// |
||
| 308 | |||
| 309 | $popupReminders = BeanFactory::getBean('Reminders')->get_full_list('', "reminders.popup = 1"); |
||
| 310 | |||
| 311 | if ($popupReminders) { |
||
| 312 | foreach ($popupReminders as $popupReminder) { |
||
| 313 | $relatedEvent = BeanFactory::getBean($popupReminder->related_event_module, $popupReminder->related_event_module_id); |
||
| 314 | if ($relatedEvent && |
||
| 315 | (!isset($relatedEvent->status) || $relatedEvent->status == 'Planned') && |
||
| 316 | (!isset($relatedEvent->date_start) || (strtotime($relatedEvent->date_start) >= strtotime(self::unQuoteTime($dateTimeNow)) && strtotime($relatedEvent->date_start) <= strtotime(self::unQuoteTime($dateTimeMax)))) && |
||
| 317 | (!$checkDecline || ($checkDecline && !self::isDecline($relatedEvent, BeanFactory::getBean('Users', $current_user->id)))) |
||
| 318 | ) { |
||
| 319 | // 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. |
||
| 320 | $invitees = BeanFactory::getBean('Reminders_Invitees')->get_full_list('', "reminders_invitees.reminder_id = '{$popupReminder->id}' AND reminders_invitees.related_invitee_module_id = '{$current_user->id}'"); |
||
| 321 | if ($invitees) { |
||
| 322 | foreach ($invitees as $invitee) { |
||
| 323 | // need to concatenate since GMT times can bridge two local days |
||
| 324 | $timeStart = strtotime($db->fromConvert(isset($relatedEvent->date_start) ? $relatedEvent->date_start : date(TimeDate::DB_DATETIME_FORMAT), 'datetime')); |
||
| 325 | $timeRemind = $popupReminder->timer_popup; |
||
| 326 | $timeStart -= $timeRemind; |
||
| 327 | |||
| 328 | $url = 'index.php?action=DetailView&module=' . $popupReminder->related_event_module . '&record=' . $popupReminder->related_event_module_id; |
||
| 329 | $instructions = $app_strings['MSG_JS_ALERT_MTG_REMINDER_MEETING_MSG']; |
||
| 330 | |||
| 331 | if ($popupReminder->related_event_module == 'Meetings') { |
||
| 332 | /////////////////////////////////////////////////////////////////// |
||
| 333 | //// MEETING INTEGRATION |
||
| 334 | if (!empty($meetingIntegration) && $meetingIntegration->isIntegratedMeeting($popupReminder->related_event_module_id)) { |
||
| 335 | $url = $meetingIntegration->miUrlGetJsAlert((array)$popupReminder); |
||
| 336 | $instructions = $meetingIntegration->miGetJsAlertInstructions(); |
||
| 337 | } |
||
| 338 | //// END MEETING INTEGRATION |
||
| 339 | /////////////////////////////////////////////////////////////////// |
||
| 340 | } |
||
| 341 | |||
| 342 | $meetingName = from_html(isset($relatedEvent->name) ? $relatedEvent->name : $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_EVENT_NAME']); |
||
| 343 | $desc1 = from_html(isset($relatedEvent->description) ? $relatedEvent->description : $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_DESCRIPTION']); |
||
| 344 | $location = from_html(isset($relatedEvent->location) ? $relatedEvent->location : $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_LOCATION']); |
||
| 345 | |||
| 346 | $relatedToMeeting = $alert->getRelatedName($popupReminder->related_event_module, $popupReminder->related_event_module_id); |
||
| 347 | |||
| 348 | $description = empty($desc1) ? '' : $app_strings['MSG_JS_ALERT_MTG_REMINDER_AGENDA'] . $desc1 . "\n"; |
||
| 349 | $description = $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; |
||
| 350 | |||
| 351 | |||
| 352 | if (isset($relatedEvent->date_start)) { |
||
| 353 | $time_dbFromConvert = $db->fromConvert($relatedEvent->date_start, 'datetime'); |
||
| 354 | $time = $timedate->to_display_date_time($time_dbFromConvert); |
||
| 355 | if (!$time) { |
||
| 356 | $time = $relatedEvent->date_start; |
||
| 357 | } |
||
| 358 | if (!$time) { |
||
| 359 | $time = $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_START_DATE']; |
||
| 360 | } |
||
| 361 | } else { |
||
| 362 | $time = $app_strings['MSG_JS_ALERT_MTG_REMINDER_NO_START_DATE']; |
||
| 363 | } |
||
| 364 | |||
| 365 | // standard functionality |
||
| 366 | $alert->addAlert($app_strings['MSG_JS_ALERT_MTG_REMINDER_MEETING'], $meetingName, |
||
| 367 | $app_strings['MSG_JS_ALERT_MTG_REMINDER_TIME'] . $time, |
||
| 368 | $app_strings['MSG_JS_ALERT_MTG_REMINDER_LOC'] . $location . |
||
| 369 | $description . |
||
| 370 | $instructions, |
||
| 371 | $timeStart - strtotime($alertDateTimeNow), |
||
| 372 | $url |
||
| 373 | ); |
||
| 374 | } |
||
| 375 | } |
||
| 376 | } |
||
| 377 | } |
||
| 378 | } |
||
| 379 | } |
||
| 380 | |||
| 381 | private static function unQuoteTime($timestr) |
||
| 382 | { |
||
| 383 | $ret = ''; |
||
| 384 | for ($i = 0; $i < strlen($timestr); $i++) { |
||
| 385 | if ($timestr[$i] != "'") $ret .= $timestr[$i]; |
||
| 386 | } |
||
| 387 | return $ret; |
||
| 388 | } |
||
| 389 | |||
| 390 | // --- test for accept status decline is? |
||
| 391 | |||
| 392 | private static function isDecline(SugarBean $event, SugarBean $person) |
||
| 393 | { |
||
| 394 | return self::testEventPersonAcceptStatus($event, $person, 'decline'); |
||
| 395 | } |
||
| 396 | |||
| 397 | private static function testEventPersonAcceptStatus(SugarBean $event, SugarBean $person, $acceptStatus = 'decline') |
||
| 398 | { |
||
| 399 | if ($acceptStats = self::getEventPersonAcceptStatus($event, $person)) { |
||
| 400 | $acceptStatusLower = strtolower($acceptStatus); |
||
| 401 | foreach ((array)$acceptStats as $acceptStat) { |
||
| 402 | if (strtolower($acceptStat) == $acceptStatusLower) { |
||
| 403 | return true; |
||
| 404 | } |
||
| 405 | } |
||
| 406 | } |
||
| 407 | return false; |
||
| 408 | } |
||
| 409 | |||
| 410 | private static function getEventPersonAcceptStatus(SugarBean $event, SugarBean $person) |
||
| 411 | { |
||
| 412 | global $db; |
||
| 413 | $rel_person_table_Key = "rel_{$person->table_name}_table"; |
||
| 414 | $rel_person_table_Value = "{$event->table_name}_{$person->table_name}"; |
||
| 415 | if (isset($event->$rel_person_table_Key) && $event->$rel_person_table_Key == $rel_person_table_Value) { |
||
| 416 | $query = self::getEventPersonQuery($event, $person); |
||
| 417 | $re = $db->query($query); |
||
| 418 | $ret = array(); |
||
| 419 | while ($row = $db->fetchByAssoc($re)) { |
||
| 420 | if (!isset($row['accept_status'])) { |
||
| 421 | return null; |
||
| 422 | } |
||
| 423 | $ret[] = $row['accept_status']; |
||
| 424 | } |
||
| 425 | return $ret; |
||
| 426 | } |
||
| 427 | return null; |
||
| 428 | } |
||
| 429 | |||
| 430 | private function upgradeEventPersonQuery(SugarBean $event, $person_table) |
||
| 431 | { |
||
| 432 | $eventIdField = strtolower($event->object_name) . '_id'; |
||
| 433 | $query = " |
||
| 434 | SELECT * FROM {$event->table_name}_{$person_table} |
||
| 435 | WHERE |
||
| 436 | {$eventIdField} = '{$event->id}' AND |
||
| 437 | deleted = 0 |
||
| 438 | "; |
||
| 439 | return $query; |
||
| 440 | } |
||
| 441 | |||
| 442 | private static function getEventPersonQuery(SugarBean $event, SugarBean $person) |
||
| 443 | { |
||
| 444 | $eventIdField = array_search($event->table_name, $event->relationship_fields); |
||
| 445 | if (!$eventIdField) { |
||
| 446 | $eventIdField = strtolower($event->object_name . '_id'); |
||
| 447 | } |
||
| 448 | $personIdField = strtolower($person->object_name) . '_id'; |
||
| 449 | $query = " |
||
| 450 | SELECT * FROM {$event->table_name}_{$person->table_name} |
||
| 451 | WHERE |
||
| 452 | {$eventIdField} = '{$event->id}' AND |
||
| 453 | {$personIdField} = '{$person->id}' AND |
||
| 454 | deleted = 0 |
||
| 455 | "; |
||
| 456 | return $query; |
||
| 457 | } |
||
| 458 | |||
| 459 | // --- user preferences as default values in reminders |
||
| 460 | |||
| 461 | /** |
||
| 462 | * Default values for Reminders from User Preferences |
||
| 463 | * @return string JSON encoded default values |
||
| 464 | * @throws Exception on json_encode error |
||
| 465 | */ |
||
| 466 | public static function loadRemindersDefaultValuesDataJson() |
||
| 467 | { |
||
| 468 | $ret = json_encode(self::loadRemindersDefaultValuesData()); |
||
| 469 | if (!$ret && json_last_error()) { |
||
| 470 | throw new Exception(json_last_error_msg()); |
||
| 471 | } |
||
| 472 | return $ret; |
||
| 473 | } |
||
| 474 | |||
| 475 | /** |
||
| 476 | * Default values for Reminders from User Preferences |
||
| 477 | * @return array default values |
||
| 478 | */ |
||
| 479 | public static function loadRemindersDefaultValuesData() |
||
| 480 | { |
||
| 481 | global $current_user; |
||
| 482 | |||
| 483 | $preferencePopupReminderTime = $current_user->getPreference('reminder_time'); |
||
| 484 | $preferenceEmailReminderTime = $current_user->getPreference('email_reminder_time'); |
||
| 485 | $preferencePopupReminderChecked = $current_user->getPreference('reminder_checked'); |
||
| 486 | $preferenceEmailReminderChecked = $current_user->getPreference('email_reminder_checked'); |
||
| 487 | |||
| 488 | return array( |
||
| 489 | 'popup' => $preferencePopupReminderChecked, |
||
| 490 | 'email' => $preferenceEmailReminderChecked, |
||
| 491 | 'timer_popup' => $preferencePopupReminderTime, |
||
| 492 | 'timer_email' => $preferenceEmailReminderTime, |
||
| 493 | ); |
||
| 494 | } |
||
| 495 | |||
| 496 | // --- upgrade |
||
| 497 | |||
| 498 | /** |
||
| 499 | * Reminders upgrade, old reminders migrate to multiple-reminders. |
||
| 500 | * @throws Exception unknown event type or any error |
||
| 501 | */ |
||
| 502 | public static function upgrade() |
||
| 503 | { |
||
| 504 | self::upgradeUserPreferences(); |
||
| 505 | self::upgradeEventReminders('Calls'); |
||
| 506 | self::upgradeEventReminders('Meetings'); |
||
| 507 | self::upgradeRestoreReminders(); |
||
| 508 | } |
||
| 509 | |||
| 510 | private static function upgradeRestoreReminders() |
||
| 511 | { |
||
| 512 | if ($reminders = BeanFactory::getBean('Reminders')->get_full_list('', 'reminders.deleted = 1')) { |
||
| 513 | foreach ($reminders as $reminder) { |
||
| 514 | $reminder->deleted = 0; |
||
| 515 | $reminder->save(); |
||
| 516 | } |
||
| 517 | } |
||
| 518 | if ($reminderInvitees = BeanFactory::getBean('Reminders_Invitees')->get_full_list('', 'reminders_invitees.deleted = 1')) { |
||
| 519 | foreach ($reminderInvitees as $invitee) { |
||
| 520 | $invitee->deleted = 0; |
||
| 521 | $invitee->save(); |
||
| 522 | } |
||
| 523 | } |
||
| 524 | global $db; |
||
| 525 | $q = "UPDATE reminders SET deleted = 0"; |
||
| 526 | $db->query($q); |
||
| 527 | $q = "UPDATE reminders_invitees SET deleted = 0"; |
||
| 528 | $db->query($q); |
||
| 529 | } |
||
| 530 | |||
| 531 | private static function upgradeUserPreferences() |
||
| 532 | { |
||
| 533 | $users = User::getActiveUsers(); |
||
| 534 | foreach ($users as $user_id => $user_name) { |
||
| 535 | $user = new User(); |
||
| 536 | $user->retrieve($user_id); |
||
| 537 | |||
| 538 | $preferencePopupReminderTime = $user->getPreference('reminder_time'); |
||
| 539 | $preferenceEmailReminderTime = $user->getPreference('email_reminder_time'); |
||
| 540 | |||
| 541 | $preferencePopupReminderChecked = $preferencePopupReminderTime > -1; |
||
| 542 | $preferenceEmailReminderChecked = $preferenceEmailReminderTime > -1; |
||
| 543 | $user->setPreference('reminder_checked', $preferencePopupReminderChecked); |
||
| 544 | $user->setPreference('email_reminder_checked', $preferenceEmailReminderChecked); |
||
| 545 | |||
| 546 | } |
||
| 547 | } |
||
| 548 | |||
| 549 | /** |
||
| 550 | * @param string $eventModule 'Calls' or 'Meetings' |
||
| 551 | */ |
||
| 552 | private static function upgradeEventReminders($eventModule) |
||
| 553 | { |
||
| 554 | |||
| 555 | $eventBean = BeanFactory::getBean($eventModule); |
||
| 556 | $events = BeanFactory::getBean($eventModule)->get_full_list('', "{$eventBean->table_name}.date_start > '2015-11-01 00:00:00' AND ({$eventBean->table_name}.reminder_time != -1 OR ({$eventBean->table_name}.email_reminder_time != -1 AND {$eventBean->table_name}.email_reminder_sent != 1))"); |
||
| 557 | if ($events) { |
||
| 558 | foreach ($events as $event) { |
||
| 559 | |||
| 560 | $oldReminderPopupChecked = false; |
||
| 561 | $oldReminderPopupTimer = null; |
||
| 562 | if ($event->reminder_time != -1) { |
||
| 563 | $oldReminderPopupChecked = true; |
||
| 564 | $oldReminderPopupTimer = $event->reminder_time; |
||
| 565 | } |
||
| 566 | |||
| 567 | $oldReminderEmailChecked = false; |
||
| 568 | $oldReminderEmailTimer = null; |
||
| 569 | if ($event->email_reminder_time != -1) { |
||
| 570 | $oldReminderEmailChecked = true; |
||
| 571 | $oldReminderEmailTimer = $event->email_reminder_time; |
||
| 572 | } |
||
| 573 | |||
| 574 | $oldReminderEmailSent = $event->email_reminder_sent; |
||
| 575 | |||
| 576 | if (($oldInvitees = self::getOldEventInvitees($event)) && ($event->reminder_time != -1 || ($event->email_reminder_time != -1 && $event->email_reminder_sent != 1))) { |
||
| 577 | |||
| 578 | self::migrateReminder( |
||
| 579 | $eventModule, |
||
| 580 | $event->id, |
||
| 581 | $oldReminderPopupChecked, |
||
| 582 | $oldReminderPopupTimer, |
||
| 583 | $oldReminderEmailChecked, |
||
| 584 | $oldReminderEmailTimer, |
||
| 585 | $oldReminderEmailSent, |
||
| 586 | $oldInvitees |
||
| 587 | ); |
||
| 588 | |||
| 589 | } |
||
| 590 | } |
||
| 591 | } |
||
| 592 | |||
| 593 | } |
||
| 594 | |||
| 595 | |||
| 596 | private static function getOldEventInvitees(SugarBean $event) |
||
| 597 | { |
||
| 598 | global $db; |
||
| 599 | $ret = array(); |
||
| 600 | $persons = array('users', 'contacts', 'leads'); |
||
| 601 | foreach ($persons as $person) { |
||
| 602 | $query = self::upgradeEventPersonQuery($event, $person); |
||
| 603 | $re = $db->query($query); |
||
| 604 | while ($row = $db->fetchByAssoc($re)) { |
||
| 605 | $ret[] = $row; |
||
| 606 | } |
||
| 607 | } |
||
| 608 | return $ret; |
||
| 609 | } |
||
| 610 | |||
| 611 | /** |
||
| 612 | * @param string $eventModule 'Calls' or 'Meetings' |
||
| 613 | * @param string $eventModuleId |
||
| 614 | * @param bool $oldReminderPopupChecked |
||
| 615 | * @param int $oldReminderPopupTimer |
||
| 616 | * @param bool $oldReminderEmailChecked |
||
| 617 | * @param int $oldReminderEmailTimer |
||
| 618 | * @param array $oldInvitees |
||
| 619 | */ |
||
| 620 | private static function migrateReminder($eventModule, $eventModuleId, $oldReminderPopupChecked, $oldReminderPopupTimer, $oldReminderEmailChecked, $oldReminderEmailTimer, $oldReminderEmailSent, $oldInvitees) |
||
| 621 | { |
||
| 622 | |||
| 623 | $reminder = BeanFactory::getBean('Reminders'); |
||
| 624 | $reminder->popup = $oldReminderPopupChecked; |
||
| 625 | $reminder->email = $oldReminderEmailChecked; |
||
| 626 | $reminder->email_sent = $oldReminderEmailSent; |
||
| 627 | $reminder->timer_popup = $oldReminderPopupTimer; |
||
| 628 | $reminder->timer_email = $oldReminderEmailTimer; |
||
| 629 | $reminder->related_event_module = $eventModule; |
||
| 630 | $reminder->related_event_module_id = $eventModuleId; |
||
| 631 | $reminder->save(); |
||
| 632 | $reminderId = $reminder->id; |
||
| 633 | self::migrateReminderInvitees($reminderId, $oldInvitees); |
||
| 634 | |||
| 635 | self::removeOldReminder($eventModule, $eventModuleId); |
||
| 636 | } |
||
| 637 | |||
| 638 | private static function migrateReminderInvitees($reminderId, $invitees) |
||
| 639 | { |
||
| 640 | $ret = array(); |
||
| 641 | foreach ((array)$invitees as $invitee) { |
||
| 642 | $newInvitee = BeanFactory::getBean('Reminders_Invitees'); |
||
| 643 | $newInvitee->reminder_id = $reminderId; |
||
| 644 | $newInvitee->related_invitee_module = self::getRelatedInviteeModuleFromInviteeArray($invitee); |
||
| 645 | $newInvitee->related_invitee_module_id = self::getRelatedInviteeModuleIdFromInviteeArray($invitee); |
||
| 646 | $newInvitee->save(); |
||
| 647 | } |
||
| 648 | return $ret; |
||
| 649 | } |
||
| 650 | |||
| 651 | private static function getRelatedInviteeModuleFromInviteeArray($invitee) |
||
| 652 | { |
||
| 653 | if (array_key_exists('user_id', $invitee)) { |
||
| 654 | return 'Users'; |
||
| 655 | } |
||
| 656 | if (array_key_exists('lead_id', $invitee)) { |
||
| 657 | return 'Leads'; |
||
| 658 | } |
||
| 659 | if (array_key_exists('contact_id', $invitee)) { |
||
| 660 | return 'Contacts'; |
||
| 661 | } |
||
| 662 | // TODO:!!!! |
||
| 663 | throw new Exception('Unknown invitee module type'); |
||
| 664 | //return null; |
||
| 665 | } |
||
| 666 | |||
| 667 | private static function getRelatedInviteeModuleIdFromInviteeArray($invitee) |
||
| 668 | { |
||
| 669 | if (array_key_exists('user_id', $invitee)) { |
||
| 670 | return $invitee['user_id']; |
||
| 671 | } |
||
| 672 | if (array_key_exists('lead_id', $invitee)) { |
||
| 673 | return $invitee['lead_id']; |
||
| 674 | } |
||
| 675 | if (array_key_exists('contact_id', $invitee)) { |
||
| 676 | return $invitee['contact_id']; |
||
| 677 | } |
||
| 678 | // TODO:!!!! |
||
| 679 | throw new Exception('Unknown invitee type'); |
||
| 680 | //return null; |
||
| 681 | } |
||
| 682 | |||
| 683 | /** |
||
| 684 | * @param string $eventModule 'Calls' or 'Meetings' |
||
| 685 | * @param string $eventModuleId |
||
| 686 | */ |
||
| 687 | private static function removeOldReminder($eventModule, $eventModuleId) |
||
| 688 | { |
||
| 689 | $event = BeanFactory::getBean($eventModule, $eventModuleId); |
||
| 690 | $event->reminder_time = -1; |
||
| 691 | $event->email_reminder_time = -1; |
||
| 692 | $event->email_reminder_sent = 0; |
||
| 693 | $event->save(); |
||
| 694 | } |
||
| 695 | |||
| 696 | // --- reminders list on detail views |
||
| 697 | |||
| 698 | /** |
||
| 699 | * Return a list of related reminders for specified event (Calls/Meetings). Call it from DetailViews. |
||
| 700 | * @param SugarBean $event a Call or Meeting Bean |
||
| 701 | * @return mixed|string|void output of list (html) |
||
| 702 | * @throws Exception on json error in Remainders |
||
| 703 | */ |
||
| 704 | public static function getRemindersListView(SugarBean $event) |
||
| 705 | { |
||
| 706 | global $mod_strings, $app_list_strings; |
||
| 707 | $tpl = new Sugar_Smarty(); |
||
| 708 | $tpl->assign('MOD', $mod_strings); |
||
| 709 | $tpl->assign('reminder_time_options', $app_list_strings['reminder_time_options']); |
||
| 710 | $tpl->assign('remindersData', Reminder::loadRemindersData($event->module_name, $event->id)); |
||
| 711 | $tpl->assign('remindersDataJson', Reminder::loadRemindersDataJson($event->module_name, $event->id)); |
||
| 712 | $tpl->assign('remindersDefaultValuesDataJson', Reminder::loadRemindersDefaultValuesDataJson()); |
||
| 713 | $tpl->assign('remindersDisabled', json_encode(true)); |
||
| 714 | return $tpl->fetch('modules/Reminders/tpls/reminders.tpl'); |
||
| 715 | } |
||
| 716 | |||
| 717 | /* |
||
| 718 | * @todo implenent it |
||
| 719 | */ |
||
| 720 | public static function getRemindersListInlineEditView(SugarBean $event) |
||
| 721 | { |
||
| 722 | // TODO: getEditFieldHTML() function in InlineEditing.php:218 doesn't pass the Bean ID to this custom inline edit view function but we have to know which Bean are in the focus to editing. |
||
| 723 | if (!$event->id) { |
||
| 724 | throw new Exception("No GUID for edit."); |
||
| 725 | } |
||
| 726 | } |
||
| 727 | |||
| 728 | } |
||
| 729 | |||
| 730 | ?> |
||
| 731 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.