PauseTraining   C
last analyzed

Complexity

Total Complexity 55

Size/Duplication

Total Lines 343
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 202
dl 0
loc 343
rs 6
c 0
b 0
f 0
wmc 55

7 Methods

Rating   Name   Duplication   Size   Complexity  
B updateUserPauseTraining() 0 63 9
A __construct() 0 9 1
F runCron() 0 196 39
A install() 0 28 1
A uninstall() 0 2 1
A runCronTest() 0 18 2
A create() 0 5 2

How to fix   Complexity   

Complex Class

Complex classes like PauseTraining 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 PauseTraining, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
class PauseTraining extends Plugin
6
{
7
    protected function __construct()
8
    {
9
        parent::__construct(
10
            '0.1',
11
            'Julio Montoya',
12
            [
13
                'allow_users_to_edit_pause_formation' => 'boolean',
14
                'cron_alert_users_if_inactive_days' => 'text', // Example: "5" or "5,10,15"
15
                'sender_id' => 'user',
16
            ]
17
        );
18
    }
19
20
    public static function create()
21
    {
22
        static $result = null;
23
24
        return $result ? $result : $result = new self();
25
    }
26
27
    public function updateUserPauseTraining($userId, $values)
28
    {
29
        $userInfo = api_get_user_info($userId);
30
        if (empty($userInfo)) {
31
            throw new Exception("User #$userId does not exists");
32
        }
33
34
        $variables = [
35
            'pause_formation',
36
            'start_pause_date',
37
            'end_pause_date',
38
            'disable_emails',
39
        ];
40
41
        $valuesToUpdate = [
42
            'item_id' => $userId,
43
        ];
44
45
        // Check if variables exist.
46
        foreach ($variables as $variable) {
47
            if (!isset($values[$variable])) {
48
                throw new Exception("Variable '$variable' is missing. Cannot updated.");
49
            }
50
51
            $valuesToUpdate['extra_'.$variable] = $values[$variable];
52
        }
53
54
        // Clean variables
55
        $pause = (int) $valuesToUpdate['extra_pause_formation'];
56
        if (empty($pause)) {
57
            $valuesToUpdate['extra_pause_formation'] = 0;
58
        } else {
59
            $valuesToUpdate['extra_pause_formation'] = [];
60
            $valuesToUpdate['extra_pause_formation']['extra_pause_formation'] = $pause;
61
        }
62
63
        $notification = (int) $valuesToUpdate['extra_disable_emails'];
64
        if (empty($notification)) {
65
            $valuesToUpdate['extra_disable_emails'] = 0;
66
        } else {
67
            $valuesToUpdate['extra_disable_emails'] = [];
68
            $valuesToUpdate['extra_disable_emails']['extra_disable_emails'] = $notification;
69
        }
70
71
        $check = DateTime::createFromFormat('Y-m-d H:i', $valuesToUpdate['extra_start_pause_date']);
72
73
        if (false === $check) {
74
            throw new Exception("start_pause_date is not valid date time format should be: Y-m-d H:i");
75
        }
76
77
        $check = DateTime::createFromFormat('Y-m-d H:i', $valuesToUpdate['extra_end_pause_date']);
78
        if (false === $check) {
79
            throw new Exception("end_pause_date is not valid date time format should be: Y-m-d H:i");
80
        }
81
82
        if (api_strtotime($valuesToUpdate['extra_start_pause_date']) > api_strtotime($valuesToUpdate['extra_end_pause_date'])) {
83
            throw new Exception("end_pause_date must be bigger than start_pause_date");
84
        }
85
86
        $extraField = new ExtraFieldValue('user');
87
        $extraField->saveFieldValues($valuesToUpdate, true, false, [], [], true);
88
89
        return (int) $userId;
90
    }
91
92
    public function runCron($date = '', $isTest = false)
93
    {
94
        $enable = $this->get('tool_enable');
95
        $senderId = $this->get('sender_id');
96
        $enableDays = $this->get('cron_alert_users_if_inactive_days');
97
98
        if ('true' !== $enable) {
99
            echo 'Plugin not enabled';
100
101
            return false;
102
        }
103
104
        if (empty($senderId)) {
105
            echo 'Sender id not configured';
106
107
            return false;
108
        }
109
110
        $senderInfo = api_get_user_info($senderId);
111
112
        if (empty($senderInfo)) {
113
            echo "Sender #$senderId not found in Chamilo";
114
115
            return false;
116
        }
117
118
        $enableDaysList = explode(',', $enableDays);
119
        rsort($enableDaysList);
120
121
        $track = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
122
        $login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
123
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
124
        $usersNotificationPerDay = [];
125
        $now = api_get_utc_datetime();
126
        if (!empty($date)) {
127
            $now = $date;
128
        }
129
130
        if ($isTest) {
131
            echo "-------------------------------------------".PHP_EOL;
132
            echo "----- Testing date $now ----".PHP_EOL;
133
            echo "-------------------------------------------".PHP_EOL;
134
        }
135
136
        $extraFieldValue = new ExtraFieldValue('user');
137
        $sql = "SELECT u.id
138
                FROM $userTable u
139
                WHERE u.status <> ".ANONYMOUS." AND u.active = 1";
140
        $rs = Database::query($sql);
141
142
        $users = [];
143
        while ($user = Database::fetch_array($rs)) {
144
            $userId = $user['id'];
145
146
            $sql = "SELECT
147
                        MAX(t.logout_course_date) max_course_date,
148
                        MAX(l.logout_date) max_login_date
149
                    FROM $userTable u
150
                    LEFT JOIN $track t
151
                    ON (u.id = t.user_id)
152
                    LEFT JOIN $login l
153
                    ON (u.id = l.login_user_id)
154
                    WHERE
155
                        u.id = $userId
156
                    LIMIT 1
157
                    ";
158
            $result = Database::query($sql);
159
            $data = Database::fetch_array($result);
160
            $maxCourseDate = '';
161
            $maxLoginDate = '';
162
163
            // Take max date value.
164
            if ($data) {
165
                $maxCourseDate = $data['max_course_date'];
166
                $maxLoginDate = $data['max_login_date'];
167
            }
168
169
            $maxEndPause = null;
170
            $pause = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'pause_formation');
171
            if (!empty($pause) && isset($pause['value']) && 1 == $pause['value']) {
172
                $endDate = $extraFieldValue->get_values_by_handler_and_field_variable(
173
                    $userId,
174
                    'end_pause_date'
175
                );
176
                if (!empty($endDate) && isset($endDate['value']) && !empty($endDate['value'])) {
177
                    $maxEndPause = $endDate['value'];
178
                }
179
            }
180
181
            $maxDate = $maxCourseDate;
182
            if ($maxLoginDate > $maxCourseDate) {
183
                $maxDate = $maxLoginDate;
184
            }
185
186
            if ($maxEndPause > $maxDate) {
187
                $maxDate = $maxEndPause;
188
            }
189
190
            if (empty($maxDate)) {
191
                // Nothing found for that user, skip.
192
                continue;
193
            }
194
            $users[$userId] = $maxDate;
195
        }
196
197
        $extraFieldValue = new ExtraFieldValue('user');
198
        foreach ($enableDaysList as $day) {
199
            $day = (int) $day;
200
201
            if (0 === $day) {
202
                echo 'Day = 0 avoided '.PHP_EOL;
203
                continue;
204
            }
205
            $dayToCheck = $day + 1;
206
            $hourStart = $dayToCheck * 24;
207
            $hourEnd = ($dayToCheck - 1) * 24;
208
209
            $date = new DateTime($now);
210
            $date->sub(new DateInterval('PT'.$hourStart.'H'));
211
            $hourStart = $date->format('Y-m-d H:i:s');
212
213
            $date = new DateTime($now);
214
            $date->sub(new DateInterval('PT'.$hourEnd.'H'));
215
            $hourEnd = $date->format('Y-m-d H:i:s');
216
217
            echo "Processing day $day: $hourStart - $hourEnd ".PHP_EOL.PHP_EOL;
218
219
            foreach ($users as $userId => $maxDate) {
220
                if (!($maxDate > $hourStart && $maxDate < $hourEnd)) {
221
                    //echo "Message skipped for user #$userId because max date found: $maxDate not in range $hourStart - $hourEnd ".PHP_EOL;
222
                    continue;
223
                }
224
225
                // Check if user has selected to pause formation.
226
                $pause = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'pause_formation');
227
                if (!empty($pause) && isset($pause['value']) && 1 == $pause['value']) {
228
                    $startDate = $extraFieldValue->get_values_by_handler_and_field_variable(
229
                        $userId,
230
                        'start_pause_date'
231
                    );
232
                    $endDate = $extraFieldValue->get_values_by_handler_and_field_variable(
233
                        $userId,
234
                        'end_pause_date'
235
                    );
236
237
                    if (
238
                        !empty($startDate) && isset($startDate['value']) && !empty($startDate['value']) &&
239
                        !empty($endDate) && isset($endDate['value']) && !empty($endDate['value'])
240
                    ) {
241
                        $startDate = $startDate['value'];
242
                        $endDate = $endDate['value'];
243
244
                        if ($startDate > $hourStart && $startDate < $hourStart) {
245
                            //echo "Message skipped for user #$userId because process date $hourStart is in start pause in $startDate - $endDate ".PHP_EOL;
246
                            continue;
247
                        }
248
249
                        if ($endDate > $hourEnd && $endDate < $hourEnd) {
250
                            //echo "Message skipped for user #$userId because process date $hourEnd is in start pause in $startDate - $endDate ".PHP_EOL;
251
                            continue;
252
                        }
253
                    }
254
                }
255
256
                echo "User #$userId added to message queue because latest login is $maxDate between $hourStart AND $hourEnd".PHP_EOL;
257
                $users[] = $userId;
258
                $usersNotificationPerDay[$day][] = $userId;
259
            }
260
        }
261
262
        if (!empty($usersNotificationPerDay)) {
263
            echo PHP_EOL.'Now processing messages ...'.PHP_EOL;
264
265
            ksort($usersNotificationPerDay);
266
            foreach ($usersNotificationPerDay as $day => $userList) {
267
                $template = new Template(
268
                    '',
269
                    true,
270
                    true,
271
                    false,
272
                    false,
273
                    true,
274
                    false
275
                );
276
                $title = sprintf($this->get_lang('InactivityXDays'), $day);
277
278
                foreach ($userList as $userId) {
279
                    $userInfo = api_get_user_info($userId);
280
                    $template->assign('days', $day);
281
                    $template->assign('user', $userInfo);
282
                    $content = $template->fetch('PauseTraining/view/notification_content.tpl');
283
                    echo 'Ready to send a message "'.$title.'" to user #'.$userId.' '.$userInfo['complete_name'].PHP_EOL;
284
                    if (false === $isTest) {
285
                        MessageManager::send_message_simple($userId, $title, $content, $senderId);
286
                    } else {
287
                        echo 'Message not send because is in test mode.'.PHP_EOL;
288
                    }
289
                }
290
            }
291
        }
292
    }
293
294
    public function runCronTest()
295
    {
296
        $now = api_get_utc_datetime();
297
        $days = 15;
298
        $before = new DateTime($now);
299
        $before->sub(new DateInterval('P'.$days.'D'));
300
301
        $after = new DateTime($now);
302
        $after->add(new DateInterval('P'.$days.'D'));
303
304
        $period = new DatePeriod(
305
            $before,
306
            new DateInterval('P1D'),
307
            $after
308
        );
309
310
        foreach ($period as $key => $value) {
311
            self::runCron($value->format('Y-m-d H:i:s'), true);
312
        }
313
    }
314
315
    public function install()
316
    {
317
        UserManager::create_extra_field(
318
            'pause_formation',
319
            ExtraField::FIELD_TYPE_CHECKBOX,
320
            $this->get_lang('PauseFormation'),
321
            ''
322
        );
323
324
        UserManager::create_extra_field(
325
            'start_pause_date',
326
            ExtraField::FIELD_TYPE_DATETIME,
327
            $this->get_lang('StartPauseDateTime'),
328
            ''
329
        );
330
331
        UserManager::create_extra_field(
332
            'end_pause_date',
333
            ExtraField::FIELD_TYPE_DATETIME,
334
            $this->get_lang('EndPauseDateTime'),
335
            ''
336
        );
337
338
        UserManager::create_extra_field(
339
            'disable_emails',
340
            ExtraField::FIELD_TYPE_CHECKBOX,
341
            $this->get_lang('DisableEmails'),
342
            ''
343
        );
344
    }
345
346
    public function uninstall()
347
    {
348
    }
349
}
350