Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * A scheduled task for emailing certificates.
19
 *
20
 * @package    mod_customcert
21
 * @copyright  2017 Mark Nelson <markn@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace mod_customcert\task;
25
 
26
use mod_customcert\helper;
27
 
28
/**
29
 * A scheduled task for emailing certificates.
30
 *
31
 * @package    mod_customcert
32
 * @copyright  2017 Mark Nelson <markn@moodle.com>
33
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class email_certificate_task extends \core\task\scheduled_task {
36
 
37
    /**
38
     * Get a descriptive name for this task (shown to admins).
39
     *
40
     * @return string
41
     */
42
    public function get_name() {
43
        return get_string('taskemailcertificate', 'customcert');
44
    }
45
 
46
    /**
47
     * Execute.
48
     */
49
    public function execute() {
50
        global $DB;
51
 
52
        // Get all the certificates that have requested someone get emailed.
53
        $emailotherslengthsql = $DB->sql_length('c.emailothers');
54
        $sql = "SELECT c.*, ct.id as templateid, ct.name as templatename, ct.contextid, co.id as courseid,
55
                       co.fullname as coursefullname, co.shortname as courseshortname
56
                  FROM {customcert} c
57
                  JOIN {customcert_templates} ct
58
                    ON c.templateid = ct.id
59
                  JOIN {course} co
60
                    ON c.course = co.id
61
                 WHERE (c.emailstudents = :emailstudents
62
                        OR c.emailteachers = :emailteachers
63
                        OR $emailotherslengthsql >= 3)";
64
        if (!$customcerts = $DB->get_records_sql($sql, ['emailstudents' => 1, 'emailteachers' => 1])) {
65
            return;
66
        }
67
 
68
        // The renderers used for sending emails.
69
        $page = new \moodle_page();
70
        $htmlrenderer = $page->get_renderer('mod_customcert', 'email', 'htmlemail');
71
        $textrenderer = $page->get_renderer('mod_customcert', 'email', 'textemail');
72
        foreach ($customcerts as $customcert) {
73
            // Do not process an empty certificate.
74
            $sql = "SELECT ce.*
75
                      FROM {customcert_elements} ce
76
                      JOIN {customcert_pages} cp
77
                        ON cp.id = ce.pageid
78
                      JOIN {customcert_templates} ct
79
                        ON ct.id = cp.templateid
80
                     WHERE ct.contextid = :contextid";
81
            if (!$DB->record_exists_sql($sql, ['contextid' => $customcert->contextid])) {
82
                continue;
83
            }
84
 
85
            // Get the context.
86
            $context = \context::instance_by_id($customcert->contextid);
87
 
88
            // Get the person we are going to send this email on behalf of.
89
            $userfrom = \core_user::get_noreply_user();
90
 
91
            // Store teachers for later.
92
            $teachers = get_enrolled_users($context, 'moodle/course:update');
93
 
94
            $courseshortname = format_string($customcert->courseshortname, true, ['context' => $context]);
95
            $coursefullname = format_string($customcert->coursefullname, true, ['context' => $context]);
96
            $certificatename = format_string($customcert->name, true, ['context' => $context]);
97
 
98
            // Used to create the email subject.
99
            $info = new \stdClass;
100
            $info->coursename = $courseshortname; // Added for BC, so users who have edited the string don't lose this value.
101
            $info->courseshortname = $courseshortname;
102
            $info->coursefullname = $coursefullname;
103
            $info->certificatename = $certificatename;
104
 
105
            // Get a list of all the issues.
106
            $userfields = helper::get_all_user_name_fields('u');
107
            $sql = "SELECT u.id, u.username, $userfields, u.email, ci.id as issueid, ci.emailed
108
                      FROM {customcert_issues} ci
109
                      JOIN {user} u
110
                        ON ci.userid = u.id
111
                     WHERE ci.customcertid = :customcertid";
112
            $issuedusers = $DB->get_records_sql($sql, ['customcertid' => $customcert->id]);
113
 
114
            // Now, get a list of users who can access the certificate but have not yet.
115
            $enrolledusers = get_enrolled_users(\context_course::instance($customcert->courseid), 'mod/customcert:view');
116
            foreach ($enrolledusers as $enroluser) {
117
                // Check if the user has already been issued.
118
                if (in_array($enroluser->id, array_keys((array) $issuedusers))) {
119
                    continue;
120
                }
121
 
122
                // Now check if the certificate is not visible to the current user.
123
                $cm = get_fast_modinfo($customcert->courseid, $enroluser->id)->instances['customcert'][$customcert->id];
124
                if (!$cm->uservisible) {
125
                    continue;
126
                }
127
 
128
                // Don't want to email those with the capability to manage the certificate.
129
                if (has_capability('mod/customcert:manage', $context, $enroluser->id)) {
130
                    continue;
131
                }
132
 
133
                // Only email those with the capability to receive the certificate.
134
                if (!has_capability('mod/customcert:receiveissue', $context, $enroluser->id)) {
135
                    continue;
136
                }
137
 
138
                // Check that they have passed the required time.
139
                if (!empty($customcert->requiredtime)) {
140
                    if (\mod_customcert\certificate::get_course_time($customcert->courseid,
141
                            $enroluser->id) < ($customcert->requiredtime * 60)) {
142
                        continue;
143
                    }
144
                }
145
 
146
                // Ensure the cert hasn't already been issued, e.g via the UI (view.php) - a race condition.
147
                $issueid = $DB->get_field('customcert_issues', 'id',
148
                    ['userid' => $enroluser->id, 'customcertid' => $customcert->id], IGNORE_MULTIPLE);
149
                if (empty($issueid)) {
150
                    // Ok, issue them the certificate.
151
                    $issueid = \mod_customcert\certificate::issue_certificate($customcert->id, $enroluser->id);
152
                }
153
 
154
                // Add them to the array so we email them.
155
                $enroluser->issueid = $issueid;
156
                $enroluser->emailed = 0;
157
                $issuedusers[] = $enroluser;
158
            }
159
 
160
            // Remove all the users who have already been emailed.
161
            foreach ($issuedusers as $key => $issueduser) {
162
                if ($issueduser->emailed) {
163
                    unset($issuedusers[$key]);
164
                }
165
            }
166
 
167
            // If there are no users to email we can return early.
168
            if (!$issuedusers) {
169
                continue;
170
            }
171
 
172
            // Create a directory to store the PDF we will be sending.
173
            $tempdir = make_temp_directory('certificate/attachment');
174
            if (!$tempdir) {
175
                return;
176
            }
177
 
178
            // Now, email the people we need to.
179
            foreach ($issuedusers as $user) {
180
                // Set up the user.
181
                \core\cron::setup_user($user);
182
 
183
                $userfullname = fullname($user);
184
                $info->userfullname = $userfullname;
185
 
186
                // Now, get the PDF.
187
                $template = new \stdClass();
188
                $template->id = $customcert->templateid;
189
                $template->name = $customcert->templatename;
190
                $template->contextid = $customcert->contextid;
191
                $template = new \mod_customcert\template($template);
192
                $filecontents = $template->generate_pdf(false, $user->id, true);
193
 
194
                // Set the name of the file we are going to send.
195
                $filename = $courseshortname . '_' . $certificatename;
196
                $filename = \core_text::entities_to_utf8($filename);
197
                $filename = strip_tags($filename);
198
                $filename = rtrim($filename, '.');
199
                $filename = str_replace('&', '_', $filename) . '.pdf';
200
 
201
                // Create the file we will be sending.
202
                $tempfile = $tempdir . '/' . md5(microtime() . $user->id) . '.pdf';
203
                file_put_contents($tempfile, $filecontents);
204
 
205
                if ($customcert->emailstudents) {
206
                    $renderable = new \mod_customcert\output\email_certificate(true, $userfullname, $courseshortname,
207
                        $coursefullname, $certificatename, $context->instanceid);
208
 
209
                    $subject = get_string('emailstudentsubject', 'customcert', $info);
210
                    $message = $textrenderer->render($renderable);
211
                    $messagehtml = $htmlrenderer->render($renderable);
212
                    email_to_user($user, $userfrom, html_entity_decode($subject, ENT_COMPAT), $message,
213
                        $messagehtml, $tempfile, $filename);
214
                }
215
 
216
                if ($customcert->emailteachers) {
217
                    $renderable = new \mod_customcert\output\email_certificate(false, $userfullname, $courseshortname,
218
                        $coursefullname, $certificatename, $context->instanceid);
219
 
220
                    $subject = get_string('emailnonstudentsubject', 'customcert', $info);
221
                    $message = $textrenderer->render($renderable);
222
                    $messagehtml = $htmlrenderer->render($renderable);
223
                    foreach ($teachers as $teacher) {
224
                        email_to_user($teacher, $userfrom, html_entity_decode($subject, ENT_COMPAT),
225
                            $message, $messagehtml, $tempfile, $filename);
226
                    }
227
                }
228
 
229
                if (!empty($customcert->emailothers)) {
230
                    $others = explode(',', $customcert->emailothers);
231
                    foreach ($others as $email) {
232
                        $email = trim($email);
233
                        if (validate_email($email)) {
234
                            $renderable = new \mod_customcert\output\email_certificate(false, $userfullname,
235
                                $courseshortname, $coursefullname, $certificatename, $context->instanceid);
236
 
237
                            $subject = get_string('emailnonstudentsubject', 'customcert', $info);
238
                            $message = $textrenderer->render($renderable);
239
                            $messagehtml = $htmlrenderer->render($renderable);
240
 
241
                            $emailuser = new \stdClass();
242
                            $emailuser->id = -1;
243
                            $emailuser->email = $email;
244
                            email_to_user($emailuser, $userfrom, html_entity_decode($subject, ENT_COMPAT), $message,
245
                                $messagehtml, $tempfile, $filename);
246
                        }
247
                    }
248
                }
249
 
250
                // Set the field so that it is emailed.
251
                $DB->set_field('customcert_issues', 'emailed', 1, ['id' => $user->issueid]);
252
            }
253
        }
254
    }
255
}