Passed
Push — 1.11.x ( e630ed...205484 )
by Yannick
09:33
created

ScheduledAnnouncement   F

Complexity

Total Complexity 70

Size/Duplication

Total Lines 589
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 70
eloc 317
c 1
b 0
f 0
dl 0
loc 589
rs 2.8

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getGrid() 0 23 1
A get_all() 0 6 1
A get_count() 0 10 1
A allowed() 0 3 1
F sendPendingMessages() 0 219 43
A getAttachmentToString() 0 10 3
A getTags() 0 26 3
A getAttachment() 0 6 1
A returnSimpleForm() 0 47 3
F returnForm() 0 136 11
A setTagsInForm() 0 8 1

How to fix   Complexity   

Complex Class

Complex classes like ScheduledAnnouncement often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ScheduledAnnouncement, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
/**
6
 * Class ScheduledAnnouncement
7
 * Requires DB change:.
8
 *
9
 * CREATE TABLE scheduled_announcements (id INT AUTO_INCREMENT NOT NULL, subject VARCHAR(255) NOT NULL, message LONGTEXT NOT NULL, date DATETIME DEFAULT NULL, sent TINYINT(1) NOT NULL, session_id INT NOT NULL, c_id INT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
10
 *
11
 * Config setting:
12
 * $_configuration['allow_scheduled_announcements'] = true;
13
 *
14
 * Setup linux cron file:
15
 * main/cron/scheduled_announcement.php
16
 *
17
 * Requires:
18
 * composer update
19
 */
20
class ScheduledAnnouncement extends Model
21
{
22
    public $table;
23
    public $columns = ['id', 'subject', 'message', 'date', 'sent', 'session_id'];
24
25
    /**
26
     * Constructor.
27
     */
28
    public function __construct()
29
    {
30
        parent::__construct();
31
        $this->table = 'scheduled_announcements';
32
    }
33
34
    /**
35
     * @param array $where_conditions
36
     *
37
     * @return array
38
     */
39
    public function get_all($where_conditions = [])
40
    {
41
        return Database::select(
42
            '*',
43
            $this->table,
44
            ['where' => $where_conditions, 'order' => 'subject ASC']
45
        );
46
    }
47
48
    /**
49
     * @return mixed
50
     */
51
    public function get_count()
52
    {
53
        $row = Database::select(
54
            'count(*) as count',
55
            $this->table,
56
            [],
57
            'first'
58
        );
59
60
        return $row['count'];
61
    }
62
63
    /**
64
     * Displays the title + grid.
65
     *
66
     * @param int $sessionId
67
     *
68
     * @return string
69
     */
70
    public function getGrid($sessionId)
71
    {
72
        // action links
73
        $action = '<div class="actions" style="margin-bottom:20px">';
74
        $action .= Display::url(
75
            Display::return_icon('back.png', get_lang('Back'), '', ICON_SIZE_MEDIUM),
76
            api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$sessionId
77
        );
78
79
        $action .= '<a href="'.api_get_self().'?action=add&session_id='.$sessionId.'">'.
80
            Display::return_icon('add.png', get_lang('Add'), '', ICON_SIZE_MEDIUM).'</a>';
81
        $action .= '<a href="scheduled_announcement.php?action=run&session_id='.$sessionId.'">'.
82
            Display::return_icon('tuning.png', get_lang('SendManuallyPendingAnnouncements'), '', ICON_SIZE_MEDIUM).
83
            '</a>';
84
85
        $action .= '</div>';
86
87
        $html = $action;
88
        $html .= '<div id="session-table" class="table-responsive">';
89
        $html .= Display::grid_html('programmed');
90
        $html .= '</div>';
91
92
        return $html;
93
    }
94
95
    /**
96
     * Returns a Form validator Obj.
97
     *
98
     * @param int    $id
99
     * @param string $url
100
     * @param string $action      add, edit
101
     * @param array  $sessionInfo
102
     *
103
     * @return FormValidator form validator obj
104
     */
105
    public function returnSimpleForm($id, $url, $action, $sessionInfo = [])
106
    {
107
        $form = new FormValidator(
108
            'announcement',
109
            'post',
110
            $url
111
        );
112
113
        $form->addHidden('session_id', $sessionInfo['id']);
114
        $form->addDateTimePicker('date', get_lang('Date'));
115
116
        $useBaseProgress = api_get_configuration_value('scheduled_announcements_use_base_progress');
117
        if ($useBaseProgress) {
118
            $extraFieldValue = new ExtraFieldValue('scheduled_announcement');
119
            $baseProgress = $extraFieldValue->get_values_by_handler_and_field_variable(
120
                $id,
121
                'use_base_progress'
122
            );
123
            $form->addNumeric ('progress',
124
                get_lang('Progress'),
125
                [
126
                    'step' => 1,
127
                    'min' => 1,
128
                    'max' => 100,
129
                    'value' => $baseProgress['value'],
130
                ],
131
                true
132
            );
133
        }
134
135
        $form->addText('subject', get_lang('Subject'));
136
        $form->addHtmlEditor('message', get_lang('Message'));
137
138
        $extraField = new ExtraField('scheduled_announcement');
139
        $extra = $extraField->addElements($form, $id);
140
        $js = $extra['jquery_ready_content'];
141
        $form->addHtml("<script> $(function() { $js }); </script> ");
142
143
        $this->setTagsInForm($form);
144
145
        $form->addCheckBox('sent', null, get_lang('MessageSent'));
146
147
        if ('edit' === $action) {
148
            $form->addButtonUpdate(get_lang('Modify'));
149
        }
150
151
        return $form;
152
    }
153
154
    /**
155
     * Returns a Form validator Obj.
156
     *
157
     * @todo the form should be auto generated
158
     *
159
     * @param string $url
160
     * @param string $action add, edit
161
     * @param array
162
     *
163
     * @return FormValidator form validator obj
164
     */
165
    public function returnForm($url, $action, $sessionInfo = [])
166
    {
167
        // Setting the form elements
168
        $header = get_lang('Add');
169
170
        if ('edit' === $action) {
171
            $header = get_lang('Modify');
172
        }
173
174
        $form = new FormValidator(
175
            'announcement',
176
            'post',
177
            $url
178
        );
179
180
        $form->addHeader($header);
181
        if ('add' === $action) {
182
            $form->addHtml(
183
                Display::return_message(
184
                    nl2br(get_lang('ScheduleAnnouncementDescription')),
185
                    'normal',
186
                    false
187
                )
188
            );
189
        }
190
        $form->addHidden('session_id', $sessionInfo['id']);
191
192
        $useBaseDate = false;
193
        $startDate = $sessionInfo['access_start_date'];
194
        $endDate = $sessionInfo['access_end_date'];
195
196
        if (!empty($startDate) || !empty($endDate)) {
197
            $useBaseDate = true;
198
        }
199
200
        $typeOptions = [
201
            'specific_date' => get_lang('SpecificDate'),
202
        ];
203
204
        if ($useBaseDate) {
205
            $typeOptions['base_date'] = get_lang('BaseDate');
206
        }
207
208
        $useBaseProgress = api_get_configuration_value('scheduled_announcements_use_base_progress');
209
        if ($useBaseProgress) {
210
            $typeOptions['base_progress'] = get_lang('BaseProgress');
211
        }
212
213
        $form->addSelect(
214
            'type',
215
            get_lang('Type'),
216
            $typeOptions,
217
            [
218
                'onchange' => "javascript:
219
                    if (this.options[this.selectedIndex].value == 'base_date') {
220
                        document.getElementById('options').style.display = 'block';
221
                        document.getElementById('specific_date').style.display = 'none';
222
                        document.getElementById('base_progress').style.display = 'none';
223
                    } else if (this.options[this.selectedIndex].value == 'specific_date') {
224
                        document.getElementById('options').style.display = 'none';
225
                        document.getElementById('specific_date').style.display = 'block';
226
                        document.getElementById('base_progress').style.display = 'none';
227
                    } else {
228
                        document.getElementById('options').style.display = 'block';
229
                        document.getElementById('specific_date').style.display = 'none';
230
                        document.getElementById('base_progress').style.display = 'block';
231
                    }
232
            ", ]
233
        );
234
235
        $form->addHtml('<div id="specific_date">');
236
        $form->addDateTimePicker('date', get_lang('Date'));
237
        $form->addHtml('</div>');
238
239
        $form->addHtml('<div id="base_progress" style="display:none">');
240
        $form->addNumeric ('progress',
241
            get_lang('Progress'),
242
            [
243
                'step' => 1,
244
                'min' => 1,
245
                'max' => 100,
246
                'value' => 100,
247
            ],
248
            true
249
        );
250
        $form->addHtml('</div>');
251
252
        $form->addHtml('<div id="options" style="display:none">');
253
254
        $startDate = $sessionInfo['access_start_date'];
255
        $endDate = $sessionInfo['access_end_date'];
256
257
        $form->addText(
258
            'days',
259
            get_lang('Days'),
260
            false
261
        );
262
263
        $form->addSelect(
264
            'moment_type',
265
            get_lang('AfterOrBefore'),
266
            [
267
                'after' => get_lang('After'),
268
                'before' => get_lang('Before'),
269
            ]
270
        );
271
272
        if (!empty($startDate)) {
273
            $options['start_date'] = get_lang('StartDate').' - '.$startDate;
274
        }
275
276
        if (!empty($endDate)) {
277
            $options['end_date'] = get_lang('EndDate').' - '.$endDate;
278
        }
279
        if (!empty($options)) {
280
            $form->addSelect('base_date', get_lang('BaseDate'), $options);
281
        }
282
283
        $form->addHtml('</div>');
284
        $form->addText('subject', get_lang('Subject'));
285
        $form->addHtmlEditor('message', get_lang('Message'));
286
287
        $extraField = new ExtraField('scheduled_announcement');
288
        $extra = $extraField->addElements($form);
289
        $js = $extra['jquery_ready_content'];
290
        $form->addHtml("<script> $(function() { $js }); </script> ");
291
292
        $this->setTagsInForm($form);
293
294
        if ('edit' === $action) {
295
            $form->addButtonUpdate(get_lang('Modify'));
296
        } else {
297
            $form->addButtonCreate(get_lang('Add'));
298
        }
299
300
        return $form;
301
    }
302
303
    /**
304
     * @param int $id
305
     *
306
     * @return string
307
     */
308
    public function getAttachmentToString($id)
309
    {
310
        $file = $this->getAttachment($id);
311
        if (!empty($file) && !empty($file['value'])) {
312
            $url = api_get_path(WEB_UPLOAD_PATH).$file['value'];
313
314
            return get_lang('Attachment').': '.Display::url(basename($file['value']), $url, ['target' => '_blank']);
315
        }
316
317
        return '';
318
    }
319
320
    /**
321
     * @param int $id
322
     *
323
     * @return array
324
     */
325
    public function getAttachment($id)
326
    {
327
        $extraFieldValue = new ExtraFieldValue('scheduled_announcement');
328
        $attachment = $extraFieldValue->get_values_by_handler_and_field_variable($id, 'attachment');
329
330
        return $attachment;
331
    }
332
333
    /**
334
     * @param int $urlId
335
     *
336
     * @return int
337
     */
338
    public function sendPendingMessages($urlId = 0)
339
    {
340
        if (!$this->allowed()) {
341
            return 0;
342
        }
343
344
        $messagesSent = 0;
345
        $now = api_get_utc_datetime();
346
        $result = $this->get_all();
347
        $extraFieldValue = new ExtraFieldValue('scheduled_announcement');
348
349
        // get user extra fields list (only visible to self and filter-able)
350
        $extraField = new ExtraField('user');
351
        $extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
352
353
        foreach ($result as $result) {
354
            if (empty($result['sent'])) {
355
                if (!empty($result['date']) && $result['date'] < $now) {
356
                    $sessionId = $result['session_id'];
357
                    $sessionInfo = api_get_session_info($sessionId);
358
                    if (empty($sessionInfo)) {
359
                        continue;
360
                    }
361
                    $users = SessionManager::get_users_by_session(
362
                        $sessionId,
363
                        0,
364
                        false,
365
                        $urlId
366
                    );
367
368
                    $coachId = $sessionInfo['id_coach'];
369
370
                    if (empty($users) || empty($coachId)) {
371
                        continue;
372
                    }
373
374
                    $coachList = [];
375
                    if ($users) {
376
                        $sendToCoaches = $extraFieldValue->get_values_by_handler_and_field_variable(
377
                            $result['id'],
378
                            'send_to_coaches'
379
                        );
380
                        $courseList = SessionManager::getCoursesInSession($sessionId);
381
                        if (!empty($sendToCoaches) && !empty($sendToCoaches['value']) && 1 == $sendToCoaches['value']) {
382
                            foreach ($courseList as $courseItemId) {
383
                                $coaches = SessionManager::getCoachesByCourseSession(
384
                                    $sessionId,
385
                                    $courseItemId
386
                                );
387
                                $coachList = array_merge($coachList, $coaches);
388
                            }
389
                            $coachList = array_unique($coachList);
390
                        }
391
392
                        $useBaseProgress = api_get_configuration_value('scheduled_announcements_use_base_progress');
393
                        if ($useBaseProgress) {
394
                            $baseProgress = $extraFieldValue->get_values_by_handler_and_field_variable(
395
                                $result['id'],
396
                                'use_base_progress'
397
                            );
398
                            if (empty($baseProgress) || empty($baseProgress['value']) || $baseProgress['value'] < 1) {
399
                                $this->update(['id' => $result['id'], 'sent' => 1]);
400
                            }
401
                        } else {
402
                            $this->update(['id' => $result['id'], 'sent' => 1]);
403
                        }
404
405
                        $attachments = $this->getAttachmentToString($result['id']);
406
                        $subject = $result['subject'];
407
408
                        $courseInfo = [];
409
                        if (!empty($courseList)) {
410
                            $courseId = current($courseList);
411
                            $courseInfo = api_get_course_info_by_id($courseId);
412
                        }
413
414
                        $message = '';
415
                        foreach ($users as $user) {
416
                            // Take original message
417
                            $message = $result['message'];
418
                            $userInfo = api_get_user_info($user['user_id']);
419
                            $userPicture = UserManager::getUserPicture($user['user_id'], USER_IMAGE_SIZE_ORIGINAL);
420
421
                            $progress = '';
422
                            if (!empty($sessionInfo) && !empty($courseInfo)) {
423
                                $progress = Tracking::get_avg_student_progress(
424
                                    $user['user_id'],
425
                                    $courseInfo['code'],
426
                                    [],
427
                                    $sessionId
428
                                );
429
                            }
430
431
                            if ($useBaseProgress) {
432
                                $baseProgress = $extraFieldValue->get_values_by_handler_and_field_variable(
433
                                    $result['id'],
434
                                    'use_base_progress'
435
                                );
436
                                if (!empty($baseProgress) && !empty($baseProgress['value']) && $baseProgress['value'] >= 1) {
437
                                    if ((is_numeric($progress) && $progress > $baseProgress['value']) || !is_numeric($progress)) {
438
                                        continue;
439
                                    } else {
440
                                        $comment = json_decode($baseProgress['comment'], true);
441
                                        if ($comment !== null && is_array($comment)) {
442
                                            if (isset($comment['sended']) && is_array($comment['sended'])) {
443
                                                $userFound = false;
444
                                                foreach ($comment['sended'] as $item) {
445
                                                    if (isset($item['user']) && $item['user'] === $user['user_id']) {
446
                                                        $userFound = true;
447
                                                        break;
448
                                                    }
449
                                                }
450
                                                if ($userFound) {
451
                                                    continue;
452
                                                } else {
453
                                                    $comment['sended'][] = ['user' => $user['user_id'], 'send_date' => time(), 'progress_user' => $progress, 'progress_mark' => $baseProgress['value']];
454
                                                    $newExtraFieldParams = $baseProgress;
455
                                                    $newExtraFieldParams['comment'] = json_encode($comment);
456
                                                    $extraFieldValue->save($newExtraFieldParams);
457
                                                }
458
                                            }
459
                                        } else {
460
                                            $comment['sended'][] = ['user' => $user['user_id'], 'send_date' => time(), 'progress_user' => $progress, 'progress_mark' => $baseProgress['value']];
461
                                            $newExtraFieldParams = $baseProgress;
462
                                            $newExtraFieldParams['comment'] = json_encode($comment);
463
                                            $extraFieldValue->save($newExtraFieldParams);
464
                                        }
465
                                    }
466
                                }
467
                            }
468
469
                            if (is_numeric($progress)) {
470
                                $progress = $progress.'%';
471
                            } else {
472
                                $progress = '0%';
473
                            }
474
475
                            $startTime = api_get_local_time(
476
                                $sessionInfo['access_start_date'],
477
                                null,
478
                                null,
479
                                true
480
                            );
481
                            $endTime = api_get_local_time(
482
                                $sessionInfo['access_end_date'],
483
                                null,
484
                                null,
485
                                true
486
                            );
487
488
                            $generalCoach = '';
489
                            $generalCoachEmail = '';
490
                            if (!empty($coachId)) {
491
                                $coachInfo = api_get_user_info($coachId);
492
                                if (!empty($coachInfo)) {
493
                                    $generalCoach = $coachInfo['complete_name'];
494
                                    $generalCoachEmail = $coachInfo['email'];
495
                                }
496
                            }
497
498
                            $tags = [
499
                                '((session_name))' => $sessionInfo['name'],
500
                                '((session_start_date))' => $startTime,
501
                                '((general_coach))' => $generalCoach,
502
                                '((general_coach_email))' => $generalCoachEmail,
503
                                '((session_end_date))' => $endTime,
504
                                '((user_username))' => $userInfo['username'],
505
                                '((user_complete_name))' => $userInfo['complete_name'],
506
                                '((user_firstname))' => $userInfo['firstname'],
507
                                '((user_lastname))' => $userInfo['lastname'],
508
                                '((user_first_name))' => $userInfo['firstname'],
509
                                '((user_last_name))' => $userInfo['lastname'],
510
                                '((user_official_code))' => $userInfo['official_code'],
511
                                '((user_picture))' => $userPicture,
512
                                '((lp_progress))' => $progress,
513
                            ];
514
515
                            if (!empty($extraFields)) {
516
                                $efv = new ExtraFieldValue('user');
517
518
                                foreach ($extraFields as $extraField) {
519
                                    $valueExtra = $efv->get_values_by_handler_and_field_variable(
520
                                        $user['user_id'],
521
                                        $extraField['variable'],
522
                                        true
523
                                    );
524
                                    $tags['(('.strtolower($extraField['variable']).'))'] = $valueExtra['value'];
525
                                }
526
                            }
527
528
                            $message = str_replace(array_keys($tags), $tags, $message);
529
                            $message .= $attachments;
530
531
                            MessageManager::send_message_simple(
532
                                $userInfo['user_id'],
533
                                $subject,
534
                                $message,
535
                                $coachId
536
                            );
537
                        }
538
539
                        $message = get_lang('YouAreReceivingACopyBecauseYouAreACourseCoach').'<br /><br />'.$message;
540
541
                        foreach ($coachList as $courseCoachId) {
542
                            MessageManager::send_message_simple(
543
                                $courseCoachId,
544
                                get_lang('YouAreReceivingACopyBecauseYouAreACourseCoach').'&nbsp;'.$subject,
545
                                $message,
546
                                $coachId
547
                            );
548
                        }
549
                    }
550
551
                    $messagesSent++;
552
                }
553
            }
554
        }
555
556
        return $messagesSent;
557
    }
558
559
    /**
560
     * @return array
561
     */
562
    public function getTags()
563
    {
564
        $tags = [
565
            '((session_name))',
566
            '((session_start_date))',
567
            '((session_end_date))',
568
            '((general_coach))',
569
            '((general_coach_email))',
570
            '((user_username))',
571
            '((user_complete_name))',
572
            '((user_first_name))',
573
            '((user_last_name))',
574
            '((user_picture))',
575
            '((lp_progress))',
576
            '((user_official_code))',
577
        ];
578
        // get user extra fields list (only visible to self and filter-able)
579
        $extraField = new ExtraField('user');
580
        $extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
581
        if (!empty($extraFields)) {
582
            foreach ($extraFields as $extraField) {
583
                $tags[] = '(('.strtolower($extraField['variable']).'))';
584
            }
585
        }
586
587
        return $tags;
588
    }
589
590
    /**
591
     * @return bool
592
     */
593
    public function allowed()
594
    {
595
        return api_get_configuration_value('allow_scheduled_announcements');
596
    }
597
598
    /**
599
     * @param FormValidator $form
600
     */
601
    private function setTagsInForm(&$form)
602
    {
603
        $form->addLabel(
604
            get_lang('Tags'),
605
            Display::return_message(
606
                implode('<br />', $this->getTags()),
607
                'normal',
608
                false
609
            )
610
        );
611
    }
612
}
613