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