Passed
Push — webservicelpcreate ( d8cb35 )
by
unknown
13:48
created

Notification::saveNotification()   F

Complexity

Conditions 20
Paths 815

Size

Total Lines 119
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 20
eloc 76
c 0
b 0
f 0
nc 815
nop 9
dl 0
loc 119
rs 0.2569

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Notification class
6
 * This class provides methods for the Notification management.
7
 * Include/require it in your code to use its features.
8
 */
9
class Notification extends Model
10
{
11
    // mail_notify_message ("At once", "Daily", "No")
12
    const NOTIFY_MESSAGE_AT_ONCE = 1;
13
    const NOTIFY_MESSAGE_DAILY = 8;
14
    const NOTIFY_MESSAGE_WEEKLY = 12;
15
    const NOTIFY_MESSAGE_NO = 0;
16
17
    // mail_notify_invitation ("At once", "Daily", "No")
18
    const NOTIFY_INVITATION_AT_ONCE = 1;
19
    const NOTIFY_INVITATION_DAILY = 8;
20
    const NOTIFY_INVITATION_WEEKLY = 12;
21
    const NOTIFY_INVITATION_NO = 0;
22
23
    // mail_notify_group_message ("At once", "Daily", "No")
24
    const NOTIFY_GROUP_AT_ONCE = 1;
25
    const NOTIFY_GROUP_DAILY = 8;
26
    const NOTIFY_GROUP_WEEKLY = 12;
27
    const NOTIFY_GROUP_NO = 0;
28
29
    // Notification types
30
    const NOTIFICATION_TYPE_MESSAGE = 1;
31
    const NOTIFICATION_TYPE_INVITATION = 2;
32
    const NOTIFICATION_TYPE_GROUP = 3;
33
    const NOTIFICATION_TYPE_WALL_MESSAGE = 4;
34
    const NOTIFICATION_TYPE_DIRECT_MESSAGE = 5;
35
    public $table;
36
    public $columns = [
37
        'id',
38
        'dest_user_id',
39
        'dest_mail',
40
        'title',
41
        'content',
42
        'send_freq',
43
        'created_at',
44
        'sent_at',
45
    ];
46
47
    //Max length of the notification.content field
48
    public $max_content_length = 254;
49
    public $debug = false;
50
51
    /* message, invitation, group messages */
52
    public $type;
53
    public $adminName;
54
    public $adminEmail;
55
    public $titlePrefix;
56
57
    /**
58
     * Constructor.
59
     */
60
    public function __construct()
61
    {
62
        // Get config from mail.conf.php, as loaded by global.inc.php
63
        $platform_email = $GLOBALS['platform_email'];
64
        $this->table = Database::get_main_table(TABLE_NOTIFICATION);
65
        if (!empty($platform_email['SMTP_FROM_EMAIL'])) {
66
            $this->adminEmail = $platform_email['SMTP_FROM_EMAIL'];
67
            if (!empty($platform_email['SMTP_FROM_NAME'])) {
68
                $this->adminName = $platform_email['SMTP_FROM_NAME'];
69
            }
70
        } else {
71
            // Default no-reply email
72
            $this->adminEmail = api_get_setting('noreply_email_address');
73
            $this->adminName = api_get_setting('siteName');
74
            $this->titlePrefix = '['.api_get_setting('siteName').'] ';
75
76
            // If no-reply email doesn't exist use the admin name/email
77
            if (empty($this->adminEmail)) {
78
                $this->adminEmail = api_get_setting('emailAdministrator');
79
                $this->adminName = api_get_person_name(
80
                    api_get_setting('administratorName'),
81
                    api_get_setting('administratorSurname'),
82
                    null,
83
                    PERSON_NAME_EMAIL_ADDRESS
84
                );
85
            }
86
        }
87
    }
88
89
    /**
90
     * @return string
91
     */
92
    public function getTitlePrefix()
93
    {
94
        return $this->titlePrefix;
95
    }
96
97
    /**
98
     * @return string
99
     */
100
    public function getDefaultPlatformSenderEmail()
101
    {
102
        return $this->adminEmail;
103
    }
104
105
    /**
106
     * @return string
107
     */
108
    public function getDefaultPlatformSenderName()
109
    {
110
        return $this->adminName;
111
    }
112
113
    /**
114
     *  Send the notifications.
115
     *
116
     *  @param int $frequency notification frequency
117
     */
118
    public function send($frequency = 8)
119
    {
120
        $notifications = $this->find(
121
            'all',
122
            ['where' => ['sent_at IS NULL AND send_freq = ?' => $frequency]]
123
        );
124
125
        if (!empty($notifications)) {
126
            foreach ($notifications as $item_to_send) {
127
                // Sending email
128
                api_mail_html(
129
                    $item_to_send['dest_mail'],
130
                    $item_to_send['dest_mail'],
131
                    Security::filter_terms($item_to_send['title']),
132
                    Security::filter_terms($item_to_send['content']),
133
                    $this->adminName,
134
                    $this->adminEmail
135
                );
136
                if ($this->debug) {
137
                    error_log('Sending message to: '.$item_to_send['dest_mail']);
138
                }
139
140
                // Updating
141
                $item_to_send['sent_at'] = api_get_utc_datetime();
142
                $this->update($item_to_send);
143
                if ($this->debug) {
144
                    error_log('Updating record : '.print_r($item_to_send, 1));
0 ignored issues
show
Bug introduced by
Are you sure print_r($item_to_send, 1) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
                    error_log('Updating record : './** @scrutinizer ignore-type */ print_r($item_to_send, 1));
Loading history...
145
                }
146
            }
147
        }
148
    }
149
150
    /**
151
     * @param string $title
152
     * @param array  $senderInfo
153
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
154
     *
155
     * @return string
156
     */
157
    public function formatTitle($title, $senderInfo, $forceTitleWhenSendingEmail = false)
158
    {
159
        $hook = HookNotificationTitle::create();
160
        if (!empty($hook)) {
161
            $hook->setEventData(['title' => $title]);
162
            $data = $hook->notifyNotificationTitle(HOOK_EVENT_TYPE_PRE);
163
            if (isset($data['title'])) {
164
                $title = $data['title'];
165
            }
166
        }
167
168
        $newTitle = $this->getTitlePrefix();
169
170
        switch ($this->type) {
171
            case self::NOTIFICATION_TYPE_MESSAGE:
172
                if (!empty($senderInfo)) {
173
                    $senderName = api_get_person_name(
174
                        $senderInfo['firstname'],
175
                        $senderInfo['lastname'],
176
                        null,
177
                        PERSON_NAME_EMAIL_ADDRESS
178
                    );
179
                    $newTitle .= sprintf(get_lang('YouHaveANewMessageFromX'), $senderName);
180
                }
181
                break;
182
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
183
                $newTitle = $title;
184
                break;
185
            case self::NOTIFICATION_TYPE_INVITATION:
186
                if (!empty($senderInfo)) {
187
                    $senderName = api_get_person_name(
188
                        $senderInfo['firstname'],
189
                        $senderInfo['lastname'],
190
                        null,
191
                        PERSON_NAME_EMAIL_ADDRESS
192
                    );
193
                    $newTitle .= sprintf(get_lang('YouHaveANewInvitationFromX'), $senderName);
194
                }
195
                break;
196
            case self::NOTIFICATION_TYPE_GROUP:
197
                if (!empty($senderInfo)) {
198
                    $senderName = $senderInfo['group_info']['name'];
199
                    $newTitle .= sprintf(get_lang('YouHaveReceivedANewMessageInTheGroupX'), $senderName);
200
                    $senderName = api_get_person_name(
201
                        $senderInfo['user_info']['firstname'],
202
                        $senderInfo['user_info']['lastname'],
203
                        null,
204
                        PERSON_NAME_EMAIL_ADDRESS
205
                    );
206
                    $newTitle .= $senderName;
207
                }
208
                break;
209
        }
210
211
        // The title won't be changed, it will be used as is
212
        if ($forceTitleWhenSendingEmail) {
213
            $newTitle = $title;
214
        }
215
216
        if (!empty($hook)) {
217
            $hook->setEventData(['title' => $newTitle]);
218
            $data = $hook->notifyNotificationTitle(HOOK_EVENT_TYPE_POST);
219
            if (isset($data['title'])) {
220
                $newTitle = $data['title'];
221
            }
222
        }
223
224
        return $newTitle;
225
    }
226
227
    /**
228
     * Save message notification.
229
     *
230
     * @param int    $type                       message type
231
     *                                           NOTIFICATION_TYPE_MESSAGE,
232
     *                                           NOTIFICATION_TYPE_INVITATION,
233
     *                                           NOTIFICATION_TYPE_GROUP
234
     * @param int    $messageId
235
     * @param array  $userList                   recipients: user list of ids
236
     * @param string $title
237
     * @param string $content
238
     * @param array  $senderInfo                 result of api_get_user_info() or GroupPortalManager:get_group_data()
239
     * @param array  $attachments
240
     * @param array  $smsParameters
241
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
242
     */
243
    public function saveNotification(
244
        $messageId,
245
        $type,
246
        $userList,
247
        $title,
248
        $content,
249
        $senderInfo = [],
250
        $attachments = [],
251
        $smsParameters = [],
252
        $forceTitleWhenSendingEmail = false
253
    ) {
254
        $this->type = (int) $type;
255
        $messageId = (int) $messageId;
256
        $content = $this->formatContent($messageId, $content, $senderInfo);
257
        $titleToNotification = $this->formatTitle($title, $senderInfo, $forceTitleWhenSendingEmail);
258
        $settingToCheck = '';
259
        $avoid_my_self = false;
260
261
        switch ($this->type) {
262
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
263
            case self::NOTIFICATION_TYPE_MESSAGE:
264
                $settingToCheck = 'mail_notify_message';
265
                $defaultStatus = self::NOTIFY_MESSAGE_AT_ONCE;
266
                break;
267
            case self::NOTIFICATION_TYPE_INVITATION:
268
                $settingToCheck = 'mail_notify_invitation';
269
                $defaultStatus = self::NOTIFY_INVITATION_AT_ONCE;
270
                break;
271
            case self::NOTIFICATION_TYPE_GROUP:
272
                $settingToCheck = 'mail_notify_group_message';
273
                $defaultStatus = self::NOTIFY_GROUP_AT_ONCE;
274
                $avoid_my_self = true;
275
                break;
276
            default:
277
                $defaultStatus = self::NOTIFY_MESSAGE_AT_ONCE;
278
                break;
279
        }
280
281
        $settingInfo = UserManager::get_extra_field_information_by_name($settingToCheck);
282
283
        if (!empty($userList)) {
284
            foreach ($userList as $user_id) {
285
                if ($avoid_my_self) {
286
                    if ($user_id == api_get_user_id()) {
287
                        continue;
288
                    }
289
                }
290
                $userInfo = api_get_user_info($user_id);
291
292
                // Extra field was deleted or removed? Use the default status.
293
                $userSetting = $defaultStatus;
294
295
                if (!empty($settingInfo)) {
296
                    $extra_data = UserManager::get_extra_user_data($user_id);
297
298
                    if (isset($extra_data[$settingToCheck])) {
299
                        $userSetting = $extra_data[$settingToCheck];
300
                    }
301
302
                    // Means that user extra was not set
303
                    // Then send email now.
304
                    if ($userSetting === '') {
305
                        $userSetting = self::NOTIFY_MESSAGE_AT_ONCE;
306
                    }
307
                }
308
309
                $sendDate = null;
310
                switch ($userSetting) {
311
                    // No notifications
312
                    case self::NOTIFY_MESSAGE_NO:
313
                    case self::NOTIFY_INVITATION_NO:
314
                    case self::NOTIFY_GROUP_NO:
315
                        break;
316
                    // Send notification right now!
317
                    case self::NOTIFY_MESSAGE_AT_ONCE:
318
                    case self::NOTIFY_INVITATION_AT_ONCE:
319
                    case self::NOTIFY_GROUP_AT_ONCE:
320
                        $extraHeaders = [];
321
                        if (isset($senderInfo['email'])) {
322
                            $extraHeaders = [
323
                                'reply_to' => [
324
                                    'name' => $senderInfo['complete_name'],
325
                                    'mail' => $senderInfo['email'],
326
                                ],
327
                            ];
328
                        }
329
330
                        if (!empty($userInfo['email'])) {
331
                            api_mail_html(
332
                                $userInfo['complete_name'],
333
                                $userInfo['mail'],
334
                                Security::filter_terms($titleToNotification),
335
                                Security::filter_terms($content),
336
                                $this->adminName,
337
                                $this->adminEmail,
338
                                $extraHeaders,
339
                                $attachments,
340
                                false,
341
                                $smsParameters
342
                            );
343
                        }
344
                        $sendDate = api_get_utc_datetime();
345
                }
346
347
                // Saving the notification to be sent some day.
348
                $content = cut($content, $this->max_content_length);
349
                $params = [
350
                    'sent_at' => $sendDate,
351
                    'dest_user_id' => $user_id,
352
                    'dest_mail' => $userInfo['email'],
353
                    'title' => $title,
354
                    'content' => $content,
355
                    'send_freq' => $userSetting,
356
                ];
357
358
                $this->save($params);
359
            }
360
361
            self::sendPushNotification($userList, $title, $content);
362
        }
363
    }
364
365
    /**
366
     * Formats the content in order to add the welcome message,
367
     * the notification preference, etc.
368
     *
369
     * @param int    $messageId
370
     * @param string $content
371
     * @param array  $senderInfo result of api_get_user_info() or
372
     *                           GroupPortalManager:get_group_data()
373
     *
374
     * @return string
375
     * */
376
    public function formatContent($messageId, $content, $senderInfo)
377
    {
378
        $hook = HookNotificationContent::create();
379
        if (!empty($hook)) {
380
            $hook->setEventData(['content' => $content]);
381
            $data = $hook->notifyNotificationContent(HOOK_EVENT_TYPE_PRE);
382
            if (isset($data['content'])) {
383
                $content = $data['content'];
384
            }
385
        }
386
387
        $newMessageText = $linkToNewMessage = '';
388
        $showEmail = api_get_configuration_value('show_user_email_in_notification');
389
        $senderInfoName = '';
390
        if (!empty($senderInfo) && isset($senderInfo['complete_name'])) {
391
            $senderInfoName = $senderInfo['complete_name'];
392
            if ($showEmail && isset($senderInfo['complete_name_with_email_forced'])) {
393
                $senderInfoName = $senderInfo['complete_name_with_email_forced'];
394
            }
395
        }
396
397
        switch ($this->type) {
398
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
399
                $newMessageText = '';
400
                $linkToNewMessage = Display::url(
401
                    get_lang('SeeMessage'),
402
                    api_get_path(WEB_CODE_PATH).'messages/view_message.php?id='.$messageId
403
                );
404
                break;
405
            case self::NOTIFICATION_TYPE_MESSAGE:
406
                $allow = api_get_configuration_value('messages_hide_mail_content');
407
                if ($allow) {
408
                    $content = '';
409
                }
410
                if (!empty($senderInfo)) {
411
                    $newMessageText = sprintf(
412
                        get_lang('YouHaveANewMessageFromX'),
413
                        $senderInfoName
414
                    );
415
                }
416
                $linkToNewMessage = Display::url(
417
                    get_lang('SeeMessage'),
418
                    api_get_path(WEB_CODE_PATH).'messages/view_message.php?id='.$messageId
419
                );
420
                break;
421
            case self::NOTIFICATION_TYPE_INVITATION:
422
                if (!empty($senderInfo)) {
423
                    $newMessageText = sprintf(
424
                        get_lang('YouHaveANewInvitationFromX'),
425
                        $senderInfoName
426
                    );
427
                }
428
                $linkToNewMessage = Display::url(
429
                    get_lang('SeeInvitation'),
430
                    api_get_path(WEB_CODE_PATH).'social/invitations.php'
431
                );
432
                break;
433
            case self::NOTIFICATION_TYPE_GROUP:
434
                $topicPage = isset($_REQUEST['topics_page_nr']) ? (int) $_REQUEST['topics_page_nr'] : 0;
435
                if (!empty($senderInfo)) {
436
                    $senderName = $senderInfo['group_info']['name'];
437
                    $newMessageText = sprintf(get_lang('YouHaveReceivedANewMessageInTheGroupX'), $senderName);
438
                    $senderName = Display::url(
439
                        $senderInfoName,
440
                        api_get_path(WEB_CODE_PATH).'social/profile.php?'.$senderInfo['user_info']['user_id']
441
                    );
442
                    $newMessageText .= '<br />'.get_lang('User').': '.$senderName;
443
                }
444
                $groupUrl = api_get_path(WEB_CODE_PATH).'social/group_topics.php?id='.$senderInfo['group_info']['id'].'&topic_id='.$senderInfo['group_info']['topic_id'].'&msg_id='.$senderInfo['group_info']['msg_id'].'&topics_page_nr='.$topicPage;
445
                $linkToNewMessage = Display::url(get_lang('SeeMessage'), $groupUrl);
446
                break;
447
        }
448
        $preferenceUrl = api_get_path(WEB_CODE_PATH).'auth/profile.php';
449
450
        // You have received a new message text
451
        if (!empty($newMessageText)) {
452
            $content = $newMessageText.'<br /><hr><br />'.$content;
453
        }
454
455
        // See message with link text
456
        if (!empty($linkToNewMessage) && api_get_setting('allow_message_tool') == 'true') {
457
            $content = $content.'<br /><br />'.$linkToNewMessage;
458
        }
459
460
        // You have received this message because you are subscribed text
461
        $content = $content.'<br /><hr><i>'.
462
            sprintf(
463
                get_lang('YouHaveReceivedThisNotificationBecauseYouAreSubscribedOrInvolvedInItToChangeYourNotificationPreferencesPleaseClickHereX'),
464
                Display::url($preferenceUrl, $preferenceUrl)
465
            ).'</i>';
466
467
        if (!empty($hook)) {
468
            $hook->setEventData(['content' => $content]);
469
            $data = $hook->notifyNotificationContent(HOOK_EVENT_TYPE_POST);
470
            if (isset($data['content'])) {
471
                $content = $data['content'];
472
            }
473
        }
474
475
        return $content;
476
    }
477
478
    /**
479
     * Send the push notifications to Chamilo Mobile app.
480
     *
481
     * @param array  $userIds The IDs of users who will be notified
482
     * @param string $title   The notification title
483
     * @param string $content The notification content
484
     *
485
     * @return int The number of success notifications. Otherwise returns false
486
     */
487
    public static function sendPushNotification(array $userIds, $title, $content)
488
    {
489
        if (api_get_setting('messaging_allow_send_push_notification') !== 'true') {
490
            return false;
491
        }
492
493
        $gdcApiKey = api_get_setting('messaging_gdc_api_key');
494
495
        if ($gdcApiKey === false) {
496
            return false;
497
        }
498
499
        $content = strip_tags($content);
500
        $content = explode("\n", $content);
501
        $content = array_map('trim', $content);
502
        $content = array_filter($content);
503
        $content = implode(PHP_EOL, $content);
504
505
        $gcmRegistrationIds = [];
506
        foreach ($userIds as $userId) {
507
            $extraFieldValue = new ExtraFieldValue('user');
508
            $valueInfo = $extraFieldValue->get_values_by_handler_and_field_variable(
509
                $userId,
510
                Rest::EXTRA_FIELD_GCM_REGISTRATION
511
            );
512
513
            if (empty($valueInfo)) {
514
                continue;
515
            }
516
517
            $gcmRegistrationIds[] = $valueInfo['value'];
518
        }
519
520
        if (!$gcmRegistrationIds) {
521
            return 0;
522
        }
523
524
        $headers = [
525
            'Authorization: key='.$gdcApiKey,
526
            'Content-Type: application/json',
527
        ];
528
529
        $fields = json_encode([
530
            'registration_ids' => $gcmRegistrationIds,
531
            'data' => [
532
                'title' => $title,
533
                'message' => $content,
534
                'body' => $content,
535
                'sound' => 'default',
536
            ],
537
            'notification' => [
538
                'title' => $title,
539
                'body' => $content,
540
                'sound' => 'default',
541
            ],
542
            'collapse_key' => get_lang('Messages'),
543
        ]);
544
545
        $ch = curl_init();
546
        curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
547
        curl_setopt($ch, CURLOPT_POST, true);
548
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
549
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
550
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
551
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
552
        $result = curl_exec($ch);
553
        curl_close($ch);
554
555
        /** @var array $decodedResult */
556
        $decodedResult = json_decode($result, true);
557
558
        return intval($decodedResult['success']);
559
    }
560
}
561