Completed
Push — master ( 4fc9f8...d0e06e )
by Julito
12:04
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
        $hook = Container::instantiateHook(HookNotificationTitle::class);
155
        if (!empty($hook)) {
156
            $hook->setEventData(['title' => $title]);
157
            $data = $hook->notifyNotificationTitle(HOOK_EVENT_TYPE_PRE);
0 ignored issues
show
Bug introduced by
The method notifyNotificationTitle() does not exist on Chamilo\CoreBundle\Hook\...aces\HookEventInterface. It seems like you code against a sub-type of Chamilo\CoreBundle\Hook\...aces\HookEventInterface such as Chamilo\CoreBundle\Hook\...tionTitleEventInterface or Chamilo\CoreBundle\Hook\HookNotificationTitle. ( Ignorable by Annotation )

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

157
            /** @scrutinizer ignore-call */ 
158
            $data = $hook->notifyNotificationTitle(HOOK_EVENT_TYPE_PRE);
Loading history...
158
            if (isset($data['title'])) {
159
                $title = $data['title'];
160
            }
161
        }
162
163
        $newTitle = $this->getTitlePrefix();
164
165
        switch ($this->type) {
166
            case self::NOTIFICATION_TYPE_MESSAGE:
167
                if (!empty($senderInfo)) {
168
                    $senderName = api_get_person_name(
169
                        $senderInfo['firstname'],
170
                        $senderInfo['lastname'],
171
                        null,
172
                        PERSON_NAME_EMAIL_ADDRESS
173
                    );
174
                    $newTitle .= sprintf(get_lang('You have a new message from %s'), $senderName);
175
                }
176
                break;
177
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
178
                $newTitle = $title;
179
                break;
180
            case self::NOTIFICATION_TYPE_INVITATION:
181
                if (!empty($senderInfo)) {
182
                    $senderName = api_get_person_name(
183
                        $senderInfo['firstname'],
184
                        $senderInfo['lastname'],
185
                        null,
186
                        PERSON_NAME_EMAIL_ADDRESS
187
                    );
188
                    $newTitle .= sprintf(get_lang('You have a new invitation from %s'), $senderName);
189
                }
190
                break;
191
            case self::NOTIFICATION_TYPE_GROUP:
192
                if (!empty($senderInfo)) {
193
                    $senderName = $senderInfo['group_info']['name'];
194
                    $newTitle .= sprintf(get_lang('You have received a new message in group %s'), $senderName);
195
                    $senderName = api_get_person_name(
196
                        $senderInfo['user_info']['firstname'],
197
                        $senderInfo['user_info']['lastname'],
198
                        null,
199
                        PERSON_NAME_EMAIL_ADDRESS
200
                    );
201
                    $newTitle .= $senderName;
202
                }
203
                break;
204
        }
205
206
        // The title won't be changed, it will be used as is
207
        if ($forceTitleWhenSendingEmail) {
208
            $newTitle = $title;
209
        }
210
211
        if (!empty($hook)) {
212
            $hook->setEventData(['title' => $newTitle]);
213
            $data = $hook->notifyNotificationTitle(HOOK_EVENT_TYPE_POST);
214
            if (isset($data['title'])) {
215
                $newTitle = $data['title'];
216
            }
217
        }
218
219
        return $newTitle;
220
    }
221
222
    /**
223
     * Save message notification.
224
     *
225
     * @param int    $type                       message type
226
     *                                           NOTIFICATION_TYPE_MESSAGE,
227
     *                                           NOTIFICATION_TYPE_INVITATION,
228
     *                                           NOTIFICATION_TYPE_GROUP
229
     * @param int    $messageId
230
     * @param array  $userList                   recipients: user list of ids
231
     * @param string $title
232
     * @param string $content
233
     * @param array  $senderInfo                 result of api_get_user_info() or GroupPortalManager:get_group_data()
234
     * @param array  $attachments
235
     * @param array  $smsParameters
236
     * @param bool   $forceTitleWhenSendingEmail force the use of $title as subject instead of "You have a new message"
237
     */
238
    public function saveNotification(
239
        $messageId,
240
        $type,
241
        $userList,
242
        $title,
243
        $content,
244
        $senderInfo = [],
245
        $attachments = [],
246
        $smsParameters = [],
247
        $forceTitleWhenSendingEmail = false
248
    ) {
249
        $this->type = (int) $type;
250
        $messageId = (int) $messageId;
251
        $content = $this->formatContent($messageId, $content, $senderInfo);
252
        $titleToNotification = $this->formatTitle($title, $senderInfo, $forceTitleWhenSendingEmail);
253
        $settingToCheck = '';
254
        $avoid_my_self = false;
255
256
        switch ($this->type) {
257
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
258
            case self::NOTIFICATION_TYPE_MESSAGE:
259
                $settingToCheck = 'mail_notify_message';
260
                $defaultStatus = self::NOTIFY_MESSAGE_AT_ONCE;
261
                break;
262
            case self::NOTIFICATION_TYPE_INVITATION:
263
                $settingToCheck = 'mail_notify_invitation';
264
                $defaultStatus = self::NOTIFY_INVITATION_AT_ONCE;
265
                break;
266
            case self::NOTIFICATION_TYPE_GROUP:
267
                $settingToCheck = 'mail_notify_group_message';
268
                $defaultStatus = self::NOTIFY_GROUP_AT_ONCE;
269
                $avoid_my_self = true;
270
                break;
271
            default:
272
                $defaultStatus = self::NOTIFY_MESSAGE_AT_ONCE;
273
                break;
274
        }
275
276
        $settingInfo = UserManager::get_extra_field_information_by_name($settingToCheck);
277
278
        if (!empty($userList)) {
279
            foreach ($userList as $user_id) {
280
                if ($avoid_my_self) {
281
                    if ($user_id == api_get_user_id()) {
282
                        continue;
283
                    }
284
                }
285
                $userInfo = api_get_user_info($user_id);
286
287
                // Extra field was deleted or removed? Use the default status.
288
                $userSetting = $defaultStatus;
289
290
                if (!empty($settingInfo)) {
291
                    $extra_data = UserManager::get_extra_user_data($user_id);
292
293
                    if (isset($extra_data[$settingToCheck])) {
294
                        $userSetting = $extra_data[$settingToCheck];
295
                    }
296
297
                    // Means that user extra was not set
298
                    // Then send email now.
299
                    if ('' === $userSetting) {
300
                        $userSetting = self::NOTIFY_MESSAGE_AT_ONCE;
301
                    }
302
                }
303
304
                $sendDate = null;
305
                switch ($userSetting) {
306
                    // No notifications
307
                    case self::NOTIFY_MESSAGE_NO:
308
                    case self::NOTIFY_INVITATION_NO:
309
                    case self::NOTIFY_GROUP_NO:
310
                        break;
311
                    // Send notification right now!
312
                    case self::NOTIFY_MESSAGE_AT_ONCE:
313
                    case self::NOTIFY_INVITATION_AT_ONCE:
314
                    case self::NOTIFY_GROUP_AT_ONCE:
315
                        $extraHeaders = [];
316
                        if (isset($senderInfo['email'])) {
317
                            $extraHeaders = [
318
                                'reply_to' => [
319
                                    'name' => $senderInfo['complete_name'],
320
                                    'mail' => $senderInfo['email'],
321
                                ],
322
                            ];
323
                        }
324
325
                        if (!empty($userInfo['email'])) {
326
                            api_mail_html(
327
                                $userInfo['complete_name'],
328
                                $userInfo['mail'],
329
                                Security::filter_terms($titleToNotification),
330
                                Security::filter_terms($content),
331
                                $this->adminName,
332
                                $this->adminEmail,
333
                                $extraHeaders,
334
                                $attachments,
335
                                false,
336
                                $smsParameters
337
                            );
338
                        }
339
                        $sendDate = api_get_utc_datetime();
340
                }
341
342
                // Saving the notification to be sent some day.
343
                $content = cut($content, $this->max_content_length);
344
                $params = [
345
                    'sent_at' => $sendDate,
346
                    'dest_user_id' => $user_id,
347
                    'dest_mail' => $userInfo['email'],
348
                    'title' => $title,
349
                    'content' => $content,
350
                    'send_freq' => $userSetting,
351
                ];
352
353
                $this->save($params);
354
            }
355
356
            self::sendPushNotification($userList, $title, $content);
357
        }
358
    }
359
360
    /**
361
     * Formats the content in order to add the welcome message,
362
     * the notification preference, etc.
363
     *
364
     * @param int    $messageId
365
     * @param string $content
366
     * @param array  $senderInfo result of api_get_user_info() or
367
     *                           GroupPortalManager:get_group_data()
368
     *
369
     * @return string
370
     * */
371
    public function formatContent($messageId, $content, $senderInfo)
372
    {
373
        $hook = Container::instantiateHook(HookNotificationContent::class);
374
        if (!empty($hook)) {
375
            $hook->setEventData(['content' => $content]);
376
            $data = $hook->notifyNotificationContent(HOOK_EVENT_TYPE_PRE);
0 ignored issues
show
Bug introduced by
The method notifyNotificationContent() does not exist on Chamilo\CoreBundle\Hook\...aces\HookEventInterface. It seems like you code against a sub-type of Chamilo\CoreBundle\Hook\...aces\HookEventInterface such as Chamilo\CoreBundle\Hook\...onContentEventInterface or Chamilo\CoreBundle\Hook\HookNotificationContent. ( Ignorable by Annotation )

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

376
            /** @scrutinizer ignore-call */ 
377
            $data = $hook->notifyNotificationContent(HOOK_EVENT_TYPE_PRE);
Loading history...
377
            if (isset($data['content'])) {
378
                $content = $data['content'];
379
            }
380
        }
381
382
        $newMessageText = $linkToNewMessage = '';
383
        $showEmail = api_get_configuration_value('show_user_email_in_notification');
384
        $senderInfoName = '';
385
        if (!empty($senderInfo) && isset($senderInfo['complete_name'])) {
386
            $senderInfoName = $senderInfo['complete_name'];
387
            if ($showEmail && isset($senderInfo['complete_name_with_email_forced'])) {
388
                $senderInfoName = $senderInfo['complete_name_with_email_forced'];
389
            }
390
        }
391
392
        switch ($this->type) {
393
            case self::NOTIFICATION_TYPE_DIRECT_MESSAGE:
394
                $newMessageText = '';
395
                $linkToNewMessage = Display::url(
396
                    get_lang('See message'),
397
                    api_get_path(WEB_CODE_PATH).'messages/view_message.php?id='.$messageId
398
                );
399
                break;
400
            case self::NOTIFICATION_TYPE_MESSAGE:
401
                $allow = api_get_configuration_value('messages_hide_mail_content');
402
                if ($allow) {
403
                    $content = '';
404
                }
405
                if (!empty($senderInfo)) {
406
                    $newMessageText = sprintf(
407
                        get_lang('You have a new message from %s'),
408
                        $senderInfoName
409
                    );
410
                }
411
                $linkToNewMessage = Display::url(
412
                    get_lang('See message'),
413
                    api_get_path(WEB_CODE_PATH).'messages/view_message.php?id='.$messageId
414
                );
415
                break;
416
            case self::NOTIFICATION_TYPE_INVITATION:
417
                if (!empty($senderInfo)) {
418
                    $newMessageText = sprintf(
419
                        get_lang('You have a new invitation from %s'),
420
                        $senderInfoName
421
                    );
422
                }
423
                $linkToNewMessage = Display::url(
424
                    get_lang('See invitation'),
425
                    api_get_path(WEB_CODE_PATH).'social/invitations.php'
426
                );
427
                break;
428
            case self::NOTIFICATION_TYPE_GROUP:
429
                $topicPage = isset($_REQUEST['topics_page_nr']) ? (int) $_REQUEST['topics_page_nr'] : 0;
430
                if (!empty($senderInfo)) {
431
                    $senderName = $senderInfo['group_info']['name'];
432
                    $newMessageText = sprintf(get_lang('You have received a new message in group %s'), $senderName);
433
                    $senderName = Display::url(
434
                        $senderInfoName,
435
                        api_get_path(WEB_CODE_PATH).'social/profile.php?'.$senderInfo['user_info']['user_id']
436
                    );
437
                    $newMessageText .= '<br />'.get_lang('User').': '.$senderName;
438
                }
439
                $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;
440
                $linkToNewMessage = Display::url(get_lang('See message'), $groupUrl);
441
                break;
442
        }
443
        $preferenceUrl = api_get_path(WEB_CODE_PATH).'auth/profile.php';
444
445
        // You have received a new message text
446
        if (!empty($newMessageText)) {
447
            $content = $newMessageText.'<br /><hr><br />'.$content;
448
        }
449
450
        // See message with link text
451
        if (!empty($linkToNewMessage) && 'true' == api_get_setting('allow_message_tool')) {
452
            $content = $content.'<br /><br />'.$linkToNewMessage;
453
        }
454
455
        // You have received this message because you are subscribed text
456
        $content = $content.'<br /><hr><i>'.
457
            sprintf(
458
                get_lang('You have received this notification because you are subscribed or involved in it to change your notification preferences please click here: %s'),
459
                Display::url($preferenceUrl, $preferenceUrl)
460
            ).'</i>';
461
462
        if (!empty($hook)) {
463
            $hook->setEventData(['content' => $content]);
464
            $data = $hook->notifyNotificationContent(HOOK_EVENT_TYPE_POST);
465
            if (isset($data['content'])) {
466
                $content = $data['content'];
467
            }
468
        }
469
470
        return $content;
471
    }
472
473
    /**
474
     * Send the push notifications to Chamilo Mobile app.
475
     *
476
     * @param array  $userIds The IDs of users who will be notified
477
     * @param string $title   The notification title
478
     * @param string $content The notification content
479
     *
480
     * @return int The number of success notifications. Otherwise returns false
481
     */
482
    public static function sendPushNotification(array $userIds, $title, $content)
483
    {
484
        if ('true' !== api_get_setting('messaging_allow_send_push_notification')) {
485
            return false;
486
        }
487
488
        $gdcApiKey = api_get_setting('messaging_gdc_api_key');
489
490
        if (false === $gdcApiKey) {
491
            return false;
492
        }
493
494
        $content = strip_tags($content);
495
        $content = explode("\n", $content);
496
        $content = array_map('trim', $content);
497
        $content = array_filter($content);
498
        $content = implode(PHP_EOL, $content);
499
500
        $gcmRegistrationIds = [];
501
        foreach ($userIds as $userId) {
502
            $extraFieldValue = new ExtraFieldValue('user');
503
            $valueInfo = $extraFieldValue->get_values_by_handler_and_field_variable(
504
                $userId,
505
                Rest::EXTRA_FIELD_GCM_REGISTRATION
506
            );
507
508
            if (empty($valueInfo)) {
509
                continue;
510
            }
511
512
            $gcmRegistrationIds[] = $valueInfo['value'];
513
        }
514
515
        if (!$gcmRegistrationIds) {
516
            return 0;
517
        }
518
519
        $headers = [
520
            'Authorization: key='.$gdcApiKey,
521
            'Content-Type: application/json',
522
        ];
523
524
        $fields = json_encode([
525
            'registration_ids' => $gcmRegistrationIds,
526
            'data' => [
527
                'title' => $title,
528
                'message' => $content,
529
                'body' => $content,
530
                'sound' => 'default',
531
            ],
532
            'notification' => [
533
                'title' => $title,
534
                'body' => $content,
535
                'sound' => 'default',
536
            ],
537
            'collapse_key' => get_lang('Messages'),
538
        ]);
539
540
        $ch = curl_init();
541
        curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send');
542
        curl_setopt($ch, CURLOPT_POST, true);
543
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
544
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
545
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
546
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
547
        $result = curl_exec($ch);
548
        curl_close($ch);
549
550
        /** @var array $decodedResult */
551
        $decodedResult = json_decode($result, true);
552
553
        return intval($decodedResult['success']);
554
    }
555
}
556