Passed
Push — master ( a84711...82b6df )
by Julito
09:21
created

AnnouncementEmail::sendAnnouncementEmailToMySelf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 12
rs 9.9332
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Announcement Email.
6
 *
7
 * @author Laurent Opprecht <[email protected]> for the Univesity of Geneva
8
 * @author Julio Montoya <[email protected]> Adding session support
9
 */
10
class AnnouncementEmail
11
{
12
    public $session_id = null;
13
    public $logger;
14
    protected $course = null;
15
    protected $announcement = null;
16
17
    /**
18
     * @param array           $courseInfo
19
     * @param int             $sessionId
20
     * @param int             $announcementId
21
     * @param \Monolog\Logger $logger
22
     */
23
    public function __construct($courseInfo, $sessionId, $announcementId, $logger = null)
24
    {
25
        if (empty($courseInfo)) {
26
            $courseInfo = api_get_course_info();
27
        }
28
29
        $this->course = $courseInfo;
30
        $this->session_id = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
31
32
        if (is_numeric($announcementId)) {
33
            $this->announcement = AnnouncementManager::get_by_id($courseInfo['real_id'], $announcementId);
34
        }
35
        $this->logger = $logger;
36
    }
37
38
    /**
39
     * Course info.
40
     *
41
     * @param string $key
42
     *
43
     * @return string|null
44
     */
45
    public function course($key = '')
46
    {
47
        $result = $key ? $this->course[$key] : $this->course;
48
        $result = $key == 'id' ? intval($result) : $result;
49
50
        return $result;
51
    }
52
53
    /**
54
     * Announcement info.
55
     *
56
     * @param string $key
57
     *
58
     * @return array
59
     */
60
    public function announcement($key = '')
61
    {
62
        $result = $key ? $this->announcement[$key] : $this->announcement;
63
        $result = $key == 'id' ? intval($result) : $result;
64
65
        return $result;
66
    }
67
68
    /**
69
     * Returns either all course users or all session users depending on whether
70
     * session is turned on or not.
71
     *
72
     * @return array
73
     */
74
    public function all_users()
75
    {
76
        $courseCode = $this->course('code');
77
        if (empty($this->session_id)) {
78
            $group_id = api_get_group_id();
79
            if (empty($group_id)) {
80
                $userList = CourseManager::get_user_list_from_course_code($courseCode);
81
            } else {
82
                $userList = GroupManager::get_users($group_id);
83
                $new_user_list = [];
84
                foreach ($userList as $user) {
85
                    $new_user_list[] = ['user_id' => $user];
86
                }
87
                $userList = $new_user_list;
88
            }
89
        } else {
90
            $userList = CourseManager::get_user_list_from_course_code(
91
                $courseCode,
92
                $this->session_id
93
            );
94
        }
95
96
        return $userList;
97
    }
98
99
    /**
100
     * Returns users and groups an announcement item has been sent to.
101
     *
102
     * @return array Array of users and groups to whom the element has been sent
103
     */
104
    public function sent_to_info()
105
    {
106
        $result = [];
107
        $result['groups'] = [];
108
        $result['users'] = [];
109
110
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
111
        $tool = TOOL_ANNOUNCEMENT;
112
        $id = $this->announcement('id');
113
        $course_id = $this->course('real_id');
114
        $sessionCondition = api_get_session_condition($this->session_id);
115
116
        $sql = "SELECT to_group_id, to_user_id
117
                FROM $table
118
                WHERE
119
                    c_id = $course_id AND
120
                    tool = '$tool' AND
121
                    ref = $id
122
                    $sessionCondition";
123
124
        $rs = Database::query($sql);
125
126
        while ($row = Database::fetch_array($rs, 'ASSOC')) {
127
            // if to_user_id <> 0 then it is sent to a specific user
128
            $user_id = $row['to_user_id'];
129
            if (!empty($user_id)) {
130
                $result['users'][] = (int) $user_id;
131
                // If user is set then skip the group
132
                continue;
133
            }
134
135
            // if to_group_id is null then it is sent to a specific user
136
            // if to_group_id = 0 then it is sent to everybody
137
            $group_id = $row['to_group_id'];
138
            if (!empty($group_id)) {
139
                $result['groups'][] = (int) $group_id;
140
            }
141
        }
142
143
        return $result;
144
    }
145
146
    /**
147
     * Returns the list of user info to which an announcement was sent.
148
     * This function returns a list of actual users even when recipient
149
     * are groups.
150
     *
151
     * @return array
152
     */
153
    public function sent_to()
154
    {
155
        $sent_to = $this->sent_to_info();
156
        $users = $sent_to['users'];
157
        $users = $users ? $users : [];
158
        $groups = $sent_to['groups'];
159
160
        if ($users) {
161
            $users = UserManager::get_user_list_by_ids($users, true);
162
        }
163
164
        if (!empty($groups)) {
165
            $groupUsers = GroupManager::get_groups_users($groups);
166
            $groupUsers = UserManager::get_user_list_by_ids($groupUsers, true);
167
168
            if (!empty($groupUsers)) {
169
                $users = array_merge($users, $groupUsers);
170
            }
171
        }
172
173
        if (empty($users)) {
174
            if (!empty($this->logger)) {
175
                $this->logger->addInfo('User list is empty. No users found. Trying all_users()');
176
            }
177
            $users = self::all_users();
178
        }
179
180
        // Clean users just in case
181
        $newListUsers = [];
182
        if (!empty($users)) {
183
            foreach ($users as $user) {
184
                $newListUsers[$user['user_id']] = ['user_id' => $user['user_id']];
185
            }
186
        }
187
188
        return $newListUsers;
189
    }
190
191
    /**
192
     * Email subject.
193
     *
194
     * @return string
195
     */
196
    public function subject()
197
    {
198
        $result = $this->course('title').' - '.$this->announcement('title');
199
        $result = stripslashes($result);
200
201
        return $result;
202
    }
203
204
    /**
205
     * Email message.
206
     *
207
     * @param int $receiverUserId
208
     *
209
     * @return string
210
     */
211
    public function message($receiverUserId)
212
    {
213
        $content = $this->announcement('content');
214
        $session_id = $this->session_id;
215
        $courseCode = $this->course('code');
216
217
        $content = AnnouncementManager::parseContent(
218
            $receiverUserId,
219
            $content,
220
            $courseCode,
221
            $session_id
222
        );
223
224
        // Build the link by hand because api_get_cidreq() doesn't accept course params
225
        $course_param = 'cidReq='.$courseCode.'&id_session='.$session_id.'&gidReq='.api_get_group_id();
226
        $course_name = $this->course('title');
227
228
        $result = "<div>$content</div>";
229
230
        // Adding attachment
231
        $attachment = $this->attachment();
232
        if (!empty($attachment)) {
233
            $result .= '<br />';
234
            $result .= Display::url(
235
                $attachment['filename'],
236
                api_get_path(WEB_CODE_PATH).'announcements/download.php?file='.basename($attachment['path']).'&'.$course_param
237
            );
238
            $result .= '<br />';
239
        }
240
241
        $result .= '<hr />';
242
        $userInfo = api_get_user_info();
243
        if (!empty($userInfo)) {
244
            $result .= '<a href="mailto:'.$userInfo['mail'].'">'.$userInfo['complete_name'].'</a><br/>';
245
        }
246
        $result .= '<a href="'.api_get_path(WEB_CODE_PATH).'announcements/announcements.php?'.$course_param.'">'.$course_name.'</a><br/>';
247
248
        return $result;
249
    }
250
251
    /**
252
     * Returns the one file that can be attached to an announcement.
253
     *
254
     * @return array
255
     */
256
    public function attachment()
257
    {
258
        $result = [];
259
        $table = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
260
        $id = $this->announcement('id');
261
        $course_id = $this->course('real_id');
262
        $sql = "SELECT * FROM $table 
263
                WHERE c_id = $course_id AND announcement_id = $id ";
264
        $rs = Database::query($sql);
265
        $course_path = $this->course('directory');
266
        while ($row = Database::fetch_array($rs)) {
267
            $path = api_get_path(SYS_COURSE_PATH).$course_path.'/upload/announcements/'.$row['path'];
268
            $filename = $row['filename'];
269
            $result[] = ['path' => $path, 'filename' => $filename];
270
        }
271
272
        $result = $result ? reset($result) : [];
273
274
        return $result;
275
    }
276
277
    /**
278
     * Send announcement by email to myself.
279
     */
280
    public function sendAnnouncementEmailToMySelf()
281
    {
282
        $userId = api_get_user_id();
283
        $subject = $this->subject();
284
        $message = $this->message($userId);
285
        MessageManager::send_message_simple(
286
            $userId,
287
            $subject,
288
            $message,
289
            api_get_user_id(),
290
            false,
291
            true
292
        );
293
    }
294
295
    /**
296
     * Send emails to users.
297
     *
298
     * @param bool $sendToUsersInSession
299
     * @param bool $sendToDrhUsers       send a copy of the message to the DRH users
300
     * @param int  $senderId             related to the main user
301
     *
302
     * @return array
303
     */
304
    public function send($sendToUsersInSession = false, $sendToDrhUsers = false, $senderId = 0)
305
    {
306
        $senderId = empty($senderId) ? api_get_user_id() : (int) $senderId;
307
        $subject = $this->subject();
308
309
        // Send email one by one to avoid antispam
310
        $users = $this->sent_to();
311
312
        $batchSize = 20;
313
        $counter = 1;
314
        $em = Database::getManager();
315
316
        if (empty($users) && !empty($this->logger)) {
317
            $this->logger->addInfo('User list is empty. No emails will be sent.');
318
        }
319
        $messageSentTo = [];
320
        foreach ($users as $user) {
321
            $message = $this->message($user['user_id']);
322
            $wasSent = MessageManager::messageWasAlreadySent($senderId, $user['user_id'], $subject, $message);
323
            if ($wasSent === false) {
324
                if (!empty($this->logger)) {
325
                    $this->logger->addInfo(
326
                        'Announcement: #'.$this->announcement('id').'. Send email to user: #'.$user['user_id']
327
                    );
328
                }
329
330
                $messageSentTo[] = $user['user_id'];
331
                MessageManager::send_message_simple(
332
                    $user['user_id'],
333
                    $subject,
334
                    $message,
335
                    $senderId,
336
                    $sendToDrhUsers,
337
                    true
338
                );
339
            } else {
340
                if (!empty($this->logger)) {
341
                    $this->logger->addInfo(
342
                        'Message "'.$subject.'" was already sent. Announcement: #'.$this->announcement('id').'. 
343
                        User: #'.$user['user_id']
344
                    );
345
                }
346
            }
347
348
            if (($counter % $batchSize) === 0) {
349
                $em->flush();
350
                $em->clear();
351
            }
352
            $counter++;
353
        }
354
355
        if ($sendToUsersInSession) {
356
            $sessionList = SessionManager::get_session_by_course($this->course['real_id']);
357
            if (!empty($sessionList)) {
358
                foreach ($sessionList as $sessionInfo) {
359
                    $sessionId = $sessionInfo['id'];
360
                    $message = $this->message(null);
361
                    $userList = CourseManager::get_user_list_from_course_code(
362
                        $this->course['code'],
363
                        $sessionId
364
                    );
365
                    if (!empty($userList)) {
366
                        foreach ($userList as $user) {
367
                            $messageSentTo[] = $user['user_id'];
368
                            MessageManager::send_message_simple(
369
                                $user['user_id'],
370
                                $subject,
371
                                $message,
372
                                $senderId,
373
                                false,
374
                                true
375
                            );
376
                        }
377
                    }
378
                }
379
            }
380
        }
381
382
        $this->logMailSent();
383
        $messageSentTo = array_unique($messageSentTo);
384
385
        return $messageSentTo;
386
    }
387
388
    /**
389
     * Store that emails where sent.
390
     */
391
    public function logMailSent()
392
    {
393
        $id = $this->announcement('id');
394
        $courseId = $this->course('real_id');
395
        $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
396
        $sql = "UPDATE $table SET 
397
                email_sent = 1
398
                WHERE 
399
                    c_id = $courseId AND 
400
                    id = $id AND 
401
                    session_id = {$this->session_id} 
402
                ";
403
        Database::query($sql);
404
    }
405
}
406