Passed
Push — master ( c87549...c35fdc )
by Julito
09:10
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
        $this->table = Database::get_main_table(TABLE_NOTIFICATION);
63
        // Default no-reply email
64
        $this->adminEmail = api_get_setting('noreply_email_address');
65
        $this->adminName = api_get_setting('siteName');
66
        $this->titlePrefix = '['.api_get_setting('siteName').'] ';
67
68
        // If no-reply email doesn't exist use the admin name/email
69
        if (empty($this->adminEmail)) {
70
            $this->adminEmail = api_get_setting('emailAdministrator');
71
            $this->adminName = api_get_person_name(
72
                api_get_setting('administratorName'),
73
                api_get_setting('administratorSurname'),
74
                null,
75
                PERSON_NAME_EMAIL_ADDRESS
76
            );
77
        }
78
    }
79
80
    /**
81
     * @return string
82
     */
83
    public function getTitlePrefix()
84
    {
85
        return $this->titlePrefix;
86
    }
87
88
    /**
89
     * @return string
90
     */
91
    public function getDefaultPlatformSenderEmail()
92
    {
93
        return $this->adminEmail;
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    public function getDefaultPlatformSenderName()
100
    {
101
        return $this->adminName;
102
    }
103
104
    /**
105
     *  Send the notifications.
106
     *
107
     *  @param int $frequency notification frequency
108
     */
109
    public function send($frequency = 8)
110
    {
111
        $notifications = $this->find(
112
            'all',
113
            ['where' => ['sent_at IS NULL AND send_freq = ?' => $frequency]]
114
        );
115
116
        if (!empty($notifications)) {
117
            foreach ($notifications as $item_to_send) {
118
                // Sending email
119
                api_mail_html(
120
                    $item_to_send['dest_mail'],
121
                    $item_to_send['dest_mail'],
122
                    Security::filter_terms($item_to_send['title']),
123
                    Security::filter_terms($item_to_send['content']),
124
                    $this->adminName,
125
                    $this->adminEmail
126
                );
127
                if ($this->debug) {
128
                    error_log('Sending message to: '.$item_to_send['dest_mail']);
129
                }
130
131
                // Updating
132
                $item_to_send['sent_at'] = api_get_utc_datetime();
133
                $this->update($item_to_send);
134
                if ($this->debug) {
135
                    error_log('Updating record : '.print_r($item_to_send, 1));
136
                }
137
            }
138
        }
139
    }
140
141
    /**
142
     * @param string $title
143
     * @param array  $senderInfo
144
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
145
     *
146
     * @return string
147
     */
148
    public function formatTitle($title, $senderInfo, $forceTitleWhenSendingEmail = false)
149
    {
150
        $newTitle = $this->getTitlePrefix();
151
152
        switch ($this->type) {
153
            case self::NOTIFICATION_TYPE_MESSAGE:
154
                if (!empty($senderInfo)) {
155
                    $senderName = api_get_person_name(
156
                        $senderInfo['firstname'],
157
                        $senderInfo['lastname'],
158
                        null,
159
                        PERSON_NAME_EMAIL_ADDRESS
160
                    );
161
                    $newTitle .= sprintf(get_lang('You have a new message from %s'), $senderName);
162
                }
163
                break;
164
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
165
                $newTitle = $title;
166
                break;
167
            case self::NOTIFICATION_TYPE_INVITATION:
168
                if (!empty($senderInfo)) {
169
                    $senderName = api_get_person_name(
170
                        $senderInfo['firstname'],
171
                        $senderInfo['lastname'],
172
                        null,
173
                        PERSON_NAME_EMAIL_ADDRESS
174
                    );
175
                    $newTitle .= sprintf(get_lang('You have a new invitation from %s'), $senderName);
176
                }
177
                break;
178
            case self::NOTIFICATION_TYPE_GROUP:
179
                if (!empty($senderInfo)) {
180
                    $senderName = $senderInfo['group_info']['name'];
181
                    $newTitle .= sprintf(get_lang('You have received a new message in group %s'), $senderName);
182
                    $senderName = api_get_person_name(
183
                        $senderInfo['user_info']['firstname'],
184
                        $senderInfo['user_info']['lastname'],
185
                        null,
186
                        PERSON_NAME_EMAIL_ADDRESS
187
                    );
188
                    $newTitle .= $senderName;
189
                }
190
                break;
191
        }
192
193
        // The title won't be changed, it will be used as is
194
        if ($forceTitleWhenSendingEmail) {
195
            $newTitle = $title;
196
        }
197
198
        /*if (!empty($hook)) {
199
            $hook->setEventData(['title' => $newTitle]);
200
            $data = $hook->notifyNotificationTitle(HOOK_EVENT_TYPE_POST);
201
            if (isset($data['title'])) {
202
                $newTitle = $data['title'];
203
            }
204
        }*/
205
206
        return $newTitle;
207
    }
208
209
    /**
210
     * Save message notification.
211
     *
212
     * @param int    $type                       message type
213
     *                                           NOTIFICATION_TYPE_MESSAGE,
214
     *                                           NOTIFICATION_TYPE_INVITATION,
215
     *                                           NOTIFICATION_TYPE_GROUP
216
     * @param int    $messageId
217
     * @param array  $userList                   recipients: user list of ids
218
     * @param string $title
219
     * @param string $content
220
     * @param array  $senderInfo                 result of api_get_user_info() or GroupPortalManager:get_group_data()
221
     * @param array  $attachments
222
     * @param array  $smsParameters
223
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
224
     */
225
    public function saveNotification(
226
        $messageId,
227
        $type,
228
        $userList,
229
        $title,
230
        $content,
231
        $senderInfo = [],
232
        $attachments = [],
233
        $smsParameters = [],
234
        $forceTitleWhenSendingEmail = false
235
    ) {
236
        $this->type = (int) $type;
237
        $messageId = (int) $messageId;
238
        $content = $this->formatContent($messageId, $content, $senderInfo);
239
        $titleToNotification = $this->formatTitle($title, $senderInfo, $forceTitleWhenSendingEmail);
240
        $settingToCheck = '';
241
        $avoid_my_self = false;
242
243
        switch ($this->type) {
244
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
245
            case self::NOTIFICATION_TYPE_MESSAGE:
246
                $settingToCheck = 'mail_notify_message';
247
                $defaultStatus = self::NOTIFY_MESSAGE_AT_ONCE;
248
                break;
249
            case self::NOTIFICATION_TYPE_INVITATION:
250
                $settingToCheck = 'mail_notify_invitation';
251
                $defaultStatus = self::NOTIFY_INVITATION_AT_ONCE;
252
                break;
253
            case self::NOTIFICATION_TYPE_GROUP:
254
                $settingToCheck = 'mail_notify_group_message';
255
                $defaultStatus = self::NOTIFY_GROUP_AT_ONCE;
256
                $avoid_my_self = true;
257
                break;
258
            default:
259
                $defaultStatus = self::NOTIFY_MESSAGE_AT_ONCE;
260
                break;
261
        }
262
263
        $settingInfo = UserManager::get_extra_field_information_by_name($settingToCheck);
264
265
        if (!empty($userList)) {
266
            foreach ($userList as $user_id) {
267
                if ($avoid_my_self) {
268
                    if ($user_id == api_get_user_id()) {
269
                        continue;
270
                    }
271
                }
272
                $userInfo = api_get_user_info($user_id);
273
274
                // Extra field was deleted or removed? Use the default status.
275
                $userSetting = $defaultStatus;
276
277
                if (!empty($settingInfo)) {
278
                    $extra_data = UserManager::get_extra_user_data($user_id);
279
280
                    if (isset($extra_data[$settingToCheck])) {
281
                        $userSetting = $extra_data[$settingToCheck];
282
                    }
283
284
                    // Means that user extra was not set
285
                    // Then send email now.
286
                    if ('' === $userSetting) {
287
                        $userSetting = self::NOTIFY_MESSAGE_AT_ONCE;
288
                    }
289
                }
290
291
                $sendDate = null;
292
                switch ($userSetting) {
293
                    // No notifications
294
                    case self::NOTIFY_MESSAGE_NO:
295
                    case self::NOTIFY_INVITATION_NO:
296
                    case self::NOTIFY_GROUP_NO:
297
                        break;
298
                    // Send notification right now!
299
                    case self::NOTIFY_MESSAGE_AT_ONCE:
300
                    case self::NOTIFY_INVITATION_AT_ONCE:
301
                    case self::NOTIFY_GROUP_AT_ONCE:
302
                        $extraHeaders = [];
303
                        if (isset($senderInfo['email'])) {
304
                            $extraHeaders = [
305
                                'reply_to' => [
306
                                    'name' => $senderInfo['complete_name'],
307
                                    'mail' => $senderInfo['email'],
308
                                ],
309
                            ];
310
                        }
311
312
                        if (!empty($userInfo['email'])) {
313
                            api_mail_html(
314
                                $userInfo['complete_name'],
315
                                $userInfo['mail'],
316
                                Security::filter_terms($titleToNotification),
317
                                Security::filter_terms($content),
318
                                $this->adminName,
319
                                $this->adminEmail,
320
                                $extraHeaders,
321
                                $attachments,
322
                                false,
323
                                $smsParameters
324
                            );
325
                        }
326
                        $sendDate = api_get_utc_datetime();
327
                }
328
329
                // Saving the notification to be sent some day.
330
                $content = cut($content, $this->max_content_length);
331
                $params = [
332
                    'sent_at' => $sendDate,
333
                    'dest_user_id' => $user_id,
334
                    'dest_mail' => $userInfo['email'],
335
                    'title' => $title,
336
                    'content' => $content,
337
                    'send_freq' => $userSetting,
338
                ];
339
340
                $this->save($params);
341
            }
342
343
            self::sendPushNotification($userList, $title, $content);
344
        }
345
    }
346
347
    /**
348
     * Formats the content in order to add the welcome message,
349
     * the notification preference, etc.
350
     *
351
     * @param int    $messageId
352
     * @param string $content
353
     * @param array  $senderInfo result of api_get_user_info() or
354
     *                           GroupPortalManager:get_group_data()
355
     *
356
     * @return string
357
     * */
358
    public function formatContent($messageId, $content, $senderInfo)
359
    {
360
        $newMessageText = $linkToNewMessage = '';
361
        $showEmail = api_get_configuration_value('show_user_email_in_notification');
362
        $senderInfoName = '';
363
        if (!empty($senderInfo) && isset($senderInfo['complete_name'])) {
364
            $senderInfoName = $senderInfo['complete_name'];
365
            if ($showEmail && isset($senderInfo['complete_name_with_email_forced'])) {
366
                $senderInfoName = $senderInfo['complete_name_with_email_forced'];
367
            }
368
        }
369
370
        switch ($this->type) {
371
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
372
                $newMessageText = '';
373
                $linkToNewMessage = Display::url(
374
                    get_lang('See message'),
375
                    api_get_path(WEB_CODE_PATH).'messages/view_message.php?id='.$messageId
376
                );
377
                break;
378
            case self::NOTIFICATION_TYPE_MESSAGE:
379
                $allow = api_get_configuration_value('messages_hide_mail_content');
380
                if ($allow) {
381
                    $content = '';
382
                }
383
                if (!empty($senderInfo)) {
384
                    $newMessageText = sprintf(
385
                        get_lang('You have a new message from %s'),
386
                        $senderInfoName
387
                    );
388
                }
389
                $linkToNewMessage = Display::url(
390
                    get_lang('See message'),
391
                    api_get_path(WEB_CODE_PATH).'messages/view_message.php?id='.$messageId
392
                );
393
                break;
394
            case self::NOTIFICATION_TYPE_INVITATION:
395
                if (!empty($senderInfo)) {
396
                    $newMessageText = sprintf(
397
                        get_lang('You have a new invitation from %s'),
398
                        $senderInfoName
399
                    );
400
                }
401
                $linkToNewMessage = Display::url(
402
                    get_lang('See invitation'),
403
                    api_get_path(WEB_CODE_PATH).'social/invitations.php'
404
                );
405
                break;
406
            case self::NOTIFICATION_TYPE_GROUP:
407
                $topicPage = isset($_REQUEST['topics_page_nr']) ? (int) $_REQUEST['topics_page_nr'] : 0;
408
                if (!empty($senderInfo)) {
409
                    $senderName = $senderInfo['group_info']['name'];
410
                    $newMessageText = sprintf(get_lang('You have received a new message in group %s'), $senderName);
411
                    $senderName = Display::url(
412
                        $senderInfoName,
413
                        api_get_path(WEB_CODE_PATH).'social/profile.php?'.$senderInfo['user_info']['user_id']
414
                    );
415
                    $newMessageText .= '<br />'.get_lang('User').': '.$senderName;
416
                }
417
                $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;
418
                $linkToNewMessage = Display::url(get_lang('See message'), $groupUrl);
419
                break;
420
        }
421
        $preferenceUrl = api_get_path(WEB_CODE_PATH).'auth/profile.php';
422
423
        // You have received a new message text
424
        if (!empty($newMessageText)) {
425
            $content = $newMessageText.'<br /><hr><br />'.$content;
426
        }
427
428
        // See message with link text
429
        if (!empty($linkToNewMessage) && 'true' == api_get_setting('allow_message_tool')) {
430
            $content = $content.'<br /><br />'.$linkToNewMessage;
431
        }
432
433
        // You have received this message because you are subscribed text
434
        $content = $content.'<br /><hr><i>'.
435
            sprintf(
436
                get_lang('You have received this notification because you are subscribed or involved in it to change your notification preferences please click here: %s'),
437
                Display::url($preferenceUrl, $preferenceUrl)
438
            ).'</i>';
439
440
        /*if (!empty($hook)) {
441
            $hook->setEventData(['content' => $content]);
442
            $data = $hook->notifyNotificationContent(HOOK_EVENT_TYPE_POST);
443
            if (isset($data['content'])) {
444
                $content = $data['content'];
445
            }
446
        }*/
447
448
        return $content;
449
    }
450
451
    /**
452
     * Send the push notifications to Chamilo Mobile app.
453
     *
454
     * @param array  $userIds The IDs of users who will be notified
455
     * @param string $title   The notification title
456
     * @param string $content The notification content
457
     *
458
     * @return int The number of success notifications. Otherwise returns false
459
     */
460
    public static function sendPushNotification(array $userIds, $title, $content)
461
    {
462
        if ('true' !== api_get_setting('messaging_allow_send_push_notification')) {
463
            return false;
464
        }
465
466
        $gdcApiKey = api_get_setting('messaging_gdc_api_key');
467
468
        if (false === $gdcApiKey) {
469
            return false;
470
        }
471
472
        $content = strip_tags($content);
473
        $content = explode("\n", $content);
474
        $content = array_map('trim', $content);
475
        $content = array_filter($content);
476
        $content = implode(PHP_EOL, $content);
477
478
        $gcmRegistrationIds = [];
479
        foreach ($userIds as $userId) {
480
            $extraFieldValue = new ExtraFieldValue('user');
481
            $valueInfo = $extraFieldValue->get_values_by_handler_and_field_variable(
482
                $userId,
483
                Rest::EXTRA_FIELD_GCM_REGISTRATION
484
            );
485
486
            if (empty($valueInfo)) {
487
                continue;
488
            }
489
490
            $gcmRegistrationIds[] = $valueInfo['value'];
491
        }
492
493
        if (!$gcmRegistrationIds) {
494
            return 0;
495
        }
496
497
        $headers = [
498
            'Authorization: key='.$gdcApiKey,
499
            'Content-Type: application/json',
500
        ];
501
502
        $fields = json_encode([
503
            'registration_ids' => $gcmRegistrationIds,
504
            'data' => [
505
                'title' => $title,
506
                'message' => $content,
507
                'body' => $content,
508
                'sound' => 'default',
509
            ],
510
            'notification' => [
511
                'title' => $title,
512
                'body' => $content,
513
                'sound' => 'default',
514
            ],
515
            'collapse_key' => get_lang('Messages'),
516
        ]);
517
518
        $ch = curl_init();
519
        curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
520
        curl_setopt($ch, CURLOPT_POST, true);
521
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
522
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
523
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
524
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
525
        $result = curl_exec($ch);
526
        curl_close($ch);
527
528
        /** @var array $decodedResult */
529
        $decodedResult = json_decode($result, true);
530
531
        return intval($decodedResult['success']);
532
    }
533
}
534