Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
namespace mod_quiz\task;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
use context_course;
22
use core_user;
23
use mod_quiz\quiz_attempt;
24
use moodle_recordset;
25
use question_display_options;
26
use mod_quiz\question\display_options;
27
 
28
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
29
 
30
/**
31
 * Cron Quiz Notify Attempts Graded Task.
32
 *
33
 * @package    mod_quiz
34
 * @copyright  2021 The Open University
35
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36
 *
37
 */
38
class quiz_notify_attempt_manual_grading_completed extends \core\task\scheduled_task {
39
    /**
40
     * @var int|null For using in unit testing only. Override the time we consider as now.
41
     */
42
    protected $forcedtime = null;
43
 
44
    /**
45
     * Get name of schedule task.
46
     *
47
     * @return string
48
     */
49
    public function get_name(): string {
50
        return get_string('notifyattemptsgradedtask', 'mod_quiz');
51
    }
52
 
53
    /**
54
     * To let this class be unit tested, we wrap all accesses to the current time in this method.
55
     *
56
     * @return int The current time.
57
     */
58
    protected function get_time(): int {
59
        if (PHPUNIT_TEST && $this->forcedtime !== null) {
60
            return $this->forcedtime;
61
        }
62
 
63
        return time();
64
    }
65
 
66
    /**
67
     * For testing only, pretend the current time is different.
68
     *
69
     * @param int $time The time to set as the current time.
70
     */
71
    public function set_time_for_testing(int $time): void {
72
        if (!PHPUNIT_TEST) {
73
            throw new \coding_exception('set_time_for_testing should only be used in unit tests.');
74
        }
75
        $this->forcedtime = $time;
76
    }
77
 
78
    /**
79
     * Execute sending notification for manual graded attempts.
80
     */
81
    public function execute() {
82
        global $DB;
83
 
84
        mtrace('Looking for quiz attempts which may need a graded notification sent...');
85
 
86
        $attempts = $this->get_list_of_attempts();
87
        $course = null;
88
        $quiz = null;
89
        $cm = null;
90
 
91
        foreach ($attempts as $attempt) {
92
            mtrace('Checking attempt ' . $attempt->id . ' at quiz ' . $attempt->quiz . '.');
93
 
94
            if (!$quiz || $attempt->quiz != $quiz->id) {
95
                $quiz = $DB->get_record('quiz', ['id' => $attempt->quiz], '*', MUST_EXIST);
96
                $cm = get_coursemodule_from_instance('quiz', $attempt->quiz);
97
            }
98
 
99
            if (!$course || $course->id != $quiz->course) {
100
                $course = get_course($quiz->course);
101
                $coursecontext = context_course::instance($quiz->course);
102
            }
103
 
104
            $quiz = quiz_update_effective_access($quiz, $attempt->userid);
105
            $attemptobj = new quiz_attempt($attempt, $quiz, $cm, $course, false);
106
            $options = display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt));
107
 
108
            if ($options->manualcomment == question_display_options::HIDDEN) {
109
                // User cannot currently see the feedback, so don't message them.
110
                // However, this may change in future, so leave them on the list.
111
                continue;
112
            }
113
 
114
            if (!has_capability('mod/quiz:emailnotifyattemptgraded', $coursecontext, $attempt->userid, false)) {
115
                // User not eligible to get a notification. Mark them done while doing nothing.
116
                $DB->set_field('quiz_attempts', 'gradednotificationsenttime', $attempt->timefinish, ['id' => $attempt->id]);
117
                continue;
118
            }
119
 
120
            // OK, send notification.
121
            mtrace('Sending email to user ' . $attempt->userid . '...');
122
            $ok = quiz_send_notify_manual_graded_message($attemptobj, core_user::get_user($attempt->userid));
123
            if ($ok) {
124
                mtrace('Send email successfully!');
125
                $attempt->gradednotificationsenttime = $this->get_time();
126
                $DB->set_field('quiz_attempts', 'gradednotificationsenttime', $attempt->gradednotificationsenttime,
127
                        ['id' => $attempt->id]);
128
                $attemptobj->fire_attempt_manual_grading_completed_event();
129
            }
130
        }
131
 
132
        $attempts->close();
133
    }
134
 
135
    /**
136
     * Get a number of records as an array of quiz_attempts using a SQL statement.
137
     *
138
     * @return moodle_recordset Of quiz_attempts that need to be processed.
139
     */
140
    public function get_list_of_attempts(): moodle_recordset {
141
        global $DB;
142
 
143
        $delaytime = $this->get_time() - get_config('quiz', 'notifyattemptgradeddelay');
144
 
145
        $sql = "SELECT qa.*
146
                  FROM {quiz_attempts} qa
147
                  JOIN {quiz} quiz ON quiz.id = qa.quiz
148
                 WHERE qa.state = 'finished'
149
                       AND qa.gradednotificationsenttime IS NULL
150
                       AND qa.sumgrades IS NOT NULL
151
                       AND qa.timemodified < :delaytime
152
              ORDER BY quiz.course, qa.quiz";
153
 
154
        return $DB->get_recordset_sql($sql, ['delaytime' => $delaytime]);
155
    }
156
}