Passed
Pull Request — 1.11.x (#4244)
by Angel Fernando Quiroz
10:33
created

NotificationEvent::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
class NotificationEvent extends Model
5
{
6
    const ACCOUNT_EXPIRATION = 1;
7
    const JUSTIFICATION_EXPIRATION = 2;
8
    const GLOBAL_NOTIFICATION = 3;
9
    const SPECIFIC_USER = 4;
10
11
    public $table;
12
    public $columns = [
13
        'id',
14
        'title',
15
        'content',
16
        'link',
17
        'persistent',
18
        'day_diff',
19
        'event_type',
20
        'event_id',
21
    ];
22
    public $extraFieldName;
23
24
    /**
25
     * Constructor.
26
     */
27
    public function __construct()
28
    {
29
        parent::__construct();
30
        $this->table = 'notification_event';
31
        $this->extraFieldName = 'notification_event';
32
    }
33
34
    public function eventTypeToString($eventTypeId)
35
    {
36
        $list = $this->getEventsForSelect(false);
37
38
        return $list[$eventTypeId];
39
    }
40
41
    public function getEventsForSelect($onlyEnabled = true): array
42
    {
43
        $eventTypes = [
44
            self::ACCOUNT_EXPIRATION => get_lang('AccountExpiration'),
45
            self::GLOBAL_NOTIFICATION => get_lang('Global'),
46
            self::SPECIFIC_USER => get_lang('SpecificUsers'),
47
        ];
48
49
        if (!$onlyEnabled || api_get_plugin_setting('justification', 'tool_enable') === 'true') {
50
            $eventTypes[self::JUSTIFICATION_EXPIRATION] = get_lang('JustificationExpiration');
51
        }
52
53
        return $eventTypes;
54
    }
55
56
    /**
57
     * @throws Exception
58
     */
59
    public function getForm(FormValidator $form, $data = []): FormValidator
60
    {
61
        $options = $this->getEventsForSelect();
62
        $form->addSelect('event_type', get_lang('EventType'), $options);
63
        $form->freeze('event_type');
64
65
        $eventType = $data['event_type'];
66
        switch ($eventType) {
67
            case self::JUSTIFICATION_EXPIRATION:
68
                $list = [];
69
                if (api_get_plugin_setting('justification', 'tool_enable') === 'true'
70
                    && $list = Justification::create()->getList()
71
                ) {
72
                    $list = array_column($list, 'name', 'id');
73
                }
74
                $form->addSelect('event_id', get_lang('JustificationType'), $list);
75
                $form->freeze('event_id');
76
77
                break;
78
            default:
79
                break;
80
        }
81
82
        $form->addText('title', get_lang('Title'));
83
        $form->addTextarea('content', get_lang('Content'));
84
        $form->addText('link', get_lang('Link'), false);
85
        $form->addCheckBox('persistent', get_lang('Persistent'));
86
        $form->addNumeric('day_diff', get_lang('DaysDifference'), false);
87
88
        switch ($eventType) {
89
            case self::SPECIFIC_USER:
90
                $form->addSelectAjax(
91
                    'users',
92
                    get_lang('Users'),
93
                    $data['users'] ?? [],
94
                    [
95
                        'url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like',
96
                        'multiple' => 'multiple',
97
                    ]
98
                );
99
                //no break
100
            case self::GLOBAL_NOTIFICATION:
101
                $form->removeElement('day_diff');
102
                break;
103
        }
104
105
        return $form;
106
    }
107
108
    /**
109
     * @throws Exception
110
     */
111
    public function getAddForm(FormValidator $form): FormValidator
112
    {
113
        $options = $this->getEventsForSelect();
114
        $eventType = $form->getSubmitValue('event_type');
115
116
        $form->addSelect(
117
            'event_type',
118
            get_lang('EventType'),
119
            $options,
120
            ['placeholder' => get_lang('SelectAnOption'), 'onchange' => 'document.add.submit()']
121
        );
122
123
        if (!empty($eventType)) {
124
            $form->freeze('event_type');
125
            $form->addText('title', get_lang('Title'));
126
            $form->addTextarea('content', get_lang('Content'));
127
            $form->addText('link', get_lang('Link'), false);
128
            $form->addCheckBox('persistent', get_lang('Persistent'));
129
            $form->addNumeric('day_diff', get_lang('DaysDifference'), false);
130
131
            switch ($eventType) {
132
                case self::JUSTIFICATION_EXPIRATION:
133
                    $list = [];
134
                    if (api_get_plugin_setting('justification', 'tool_enable') === 'true'
135
                        && $list = Justification::create()->getList()
136
                    ) {
137
                        $list = array_column($list, 'name', 'id');
138
                    }
139
                    $form->addSelect('event_id', get_lang('JustificationType'), $list);
140
                    break;
141
                case self::SPECIFIC_USER:
142
                    $form->addSelectAjax(
143
                        'users',
144
                        get_lang('Users'),
145
                        [],
146
                        [
147
                            'url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like',
148
                            'multiple' => 'multiple',
149
                        ]
150
                    );
151
                    //no break
152
                case self::GLOBAL_NOTIFICATION:
153
                    $form->removeElement('day_diff');
154
                    break;
155
                default:
156
                    break;
157
            }
158
            $form->addButtonSave(get_lang('Save'));
159
        }
160
161
        return $form;
162
    }
163
164
    public function getUserExtraData($userId)
165
    {
166
        $data = UserManager::get_extra_user_data_by_field($userId, $this->extraFieldName);
167
168
        return $data['notification_event'] ?? '';
169
    }
170
171
    /**
172
     * @throws Exception
173
     */
174
    public function getNotificationsByUser(int $userId): array
175
    {
176
        $userInfo = api_get_user_info($userId);
177
        $events = $this->get_all();
178
        $extraFieldData = $this->getUserExtraData($userId);
179
180
        $notifications = [];
181
        foreach ($events as $event) {
182
            $days = (int) $event['day_diff'];
183
            $checkIsRead = $event['persistent'] == 0;
184
            $eventItemId = $event['event_id'];
185
186
            switch ($event['event_type']) {
187
                case self::ACCOUNT_EXPIRATION:
188
                    if (empty($userInfo['expiration_date'])) {
189
                        break;
190
                    }
191
192
                    $id = 'id_'.self::ACCOUNT_EXPIRATION.'_event_'.$event['id'].'_'.$userInfo['id'];
193
194
                    $read = false;
195
                    if ($checkIsRead) {
196
                        $read = $this->isRead($id, $extraFieldData);
197
                    }
198
199
                    $showNotification = $this->showNotification($userInfo['expiration_date'], $days);
200
                    if ($showNotification && $read === false) {
201
                        $notifications[] = [
202
                            'id' => $id,
203
                            'title' => $event['title'],
204
                            'content' => $event['content'],
205
                            'event_text' => get_lang('ExpirationDate').': '.api_get_local_time($userInfo['expiration_date']),
206
                            'link' => $event['link'],
207
                            'persistent' => $event['persistent'],
208
                        ];
209
                    }
210
                    break;
211
                case self::JUSTIFICATION_EXPIRATION:
212
                    if (api_get_plugin_setting('justification', 'tool_enable') !== 'true') {
213
                        break;
214
                    }
215
216
                    $plugin = Justification::create();
217
                    $userJustificationList = $plugin->getUserJustificationList($userId);
218
219
                    foreach ($userJustificationList as $userJustification) {
220
                        if (empty($userJustification['date_validity'])) {
221
                            continue;
222
                        }
223
224
                        if ($eventItemId != $userJustification['justification_document_id']) {
225
                            continue;
226
                        }
227
228
                        $showNotification = $this->showNotification($userJustification['date_validity'], $days);
229
230
                        $id = 'id_'.self::JUSTIFICATION_EXPIRATION.'_event_'.$event['id'].'_'.$userJustification['id'];
231
232
                        $fieldData = $plugin->getJustification($userJustification['justification_document_id']);
233
234
                        $read = false;
235
                        if ($checkIsRead) {
236
                            $read = $this->isRead($id, $extraFieldData);
237
                        }
238
239
                        $eventText = $plugin->get_lang('Justification').': '.$fieldData['name'].' <br />';
240
                        $eventText .= $plugin->get_lang('JustificationDate').': '.$userJustification['date_validity'];
241
242
                        $url = $event['link'];
243
                        if (empty($url)) {
244
                            $url = api_get_path(WEB_CODE_PATH).'auth/justification.php#'.$fieldData['code'];
245
                        }
246
247
                        if ($showNotification && $read === false) {
248
                            $notifications[] = [
249
                                'id' => $id,
250
                                'title' => $event['title'],
251
                                'content' => $event['content'],
252
                                'event_text' => $eventText,
253
                                'link' => $url,
254
                                'persistent' => $event['persistent'],
255
                            ];
256
                        }
257
                    }
258
                    break;
259
                case self::SPECIFIC_USER:
260
                    $assignedUsers = self::getAssignedUsers($event['id']);
261
                    $assignedUserIdList = array_keys($assignedUsers);
262
263
                    if (!in_array($userId, $assignedUserIdList)) {
264
                        break;
265
                    }
266
                    //no break
267
                case self::GLOBAL_NOTIFICATION:
268
                    $id = "id_{$event['event_type']}_event_{$event['id']}_$userId";
269
270
                    $wasRead = $checkIsRead && $this->isRead($id, $extraFieldData);
271
272
                    if (!$wasRead) {
273
                        $notifications[] = [
274
                            'id' => $id,
275
                            'title' => $event['title'],
276
                            'content' => $event['content'],
277
                            'event_text' => null,
278
                            'link' => $event['link'],
279
                            'persistent' => $event['persistent'],
280
                        ];
281
                    }
282
                    break;
283
            }
284
        }
285
286
        return $notifications;
287
    }
288
289
    public function isRead($id, $extraData): bool
290
    {
291
        $userId = api_get_user_id();
292
293
        if (empty($extraData)) {
294
            return false;
295
        }
296
297
        $data = $this->getUserExtraData($userId);
298
        if (empty($data)) {
299
            return false;
300
        }
301
302
        $data = json_decode($data);
303
304
        if (in_array($id, $data)) {
305
            return true;
306
        }
307
308
        return false;
309
    }
310
311
    public function markAsRead($id): bool
312
    {
313
        if (empty($id)) {
314
            return false;
315
        }
316
        $userId = api_get_user_id();
317
        $data = $this->getUserExtraData($userId);
318
        if (!empty($data)) {
319
            $data = json_decode($data);
320
        } else {
321
            $data = [];
322
        }
323
        $data[] = $id;
324
        $data = json_encode($data);
325
326
        UserManager::update_extra_field_value($userId, $this->extraFieldName, $data);
327
328
        return true;
329
    }
330
331
    /**
332
     * @throws Exception
333
     */
334
    public function showNotification($date, $dayDiff): bool
335
    {
336
        $today = api_get_utc_datetime();
337
        $expiration = api_get_utc_datetime($date, false, true);
338
        $interval = new DateInterval('P'.$dayDiff.'D');
339
        $diff = $expiration->sub($interval);
340
341
        if ($diff->format('Y-m-d H:i:s') < $today) {
342
            return true;
343
        }
344
345
        return false;
346
    }
347
348
    public function install()
349
    {
350
        $sql = "CREATE TABLE IF NOT EXISTS notification_event (
351
            id INT unsigned NOT NULL auto_increment PRIMARY KEY,
352
            title VARCHAR(255),
353
            content TEXT,
354
            link TEXT,
355
            persistent INT,
356
            day_diff INT,
357
            event_type VARCHAR(255)
358
        )";
359
        Database::query($sql);
360
    }
361
362
    public function save($params, $show_query = false)
363
    {
364
        $userIdList = [];
365
366
        if (isset($params['users'])) {
367
            $userIdList = $params['users'];
368
            unset($params['users']);
369
        }
370
371
        /** @var int|bool $saved */
372
        $saved = parent::save($params, $show_query);
373
374
        if (false !== $saved && !empty($userIdList)) {
375
            self::assignUserIdList($saved, $userIdList);
376
        }
377
378
        return $saved;
379
    }
380
381
    public function update($params, $showQuery = false): bool
382
    {
383
        $userIdList = [];
384
385
        if (isset($params['users'])) {
386
            $userIdList = $params['users'];
387
            unset($params['users']);
388
        }
389
390
        $updated = parent::update($params, $showQuery);
391
392
        self::deleteAssignedUsers($params['id']);
393
        self::assignUserIdList($params['id'], $userIdList);
394
395
        return $updated;
396
    }
397
398
    public function get($id)
399
    {
400
        $props = parent::get($id);
401
        $props['users'] = self::getAssignedUsers($id);
402
403
        return $props;
404
    }
405
406
    public static function assignUserIdList(int $eventId, array $userIdList)
407
    {
408
        foreach ($userIdList as $userId) {
409
            Database::insert(
410
                'notification_event_rel_user',
411
                [
412
                    'event_id' => $eventId,
413
                    'user_id' => (int) $userId,
414
                ]
415
            );
416
        }
417
    }
418
419
    public static function getAssignedUsers(int $eventId): array
420
    {
421
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
422
423
        $result = Database::select(
424
            'u.id, u.username, u.firstname, u.lastname',
425
            "notification_event_rel_user neru INNER JOIN $tblUser u ON neru.user_id = u.id",
426
            ['where' => ['neru.event_id = ?' => $eventId]]
427
        );
428
429
        $userList = [];
430
431
        foreach ($result as $userInfo) {
432
            $userList[$userInfo['id']] = api_get_person_name(
433
                $userInfo['firstname'],
434
                $userInfo['lastname'],
435
                null,
436
                null,
437
                null,
438
                $userInfo['username']
439
            );
440
        }
441
442
        return $userList;
443
    }
444
445
    public static function deleteAssignedUsers(int $eventId)
446
    {
447
        Database::delete(
448
            'notification_event_rel_user',
449
            ['event_id = ?' => $eventId]
450
        );
451
    }
452
}
453