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. ![]() |
|||
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.