Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
 
11 efrain 21
use context_module;
1 efrain 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
 
11 efrain 44
    #[\Override]
1 efrain 45
    public function get_name(): string {
46
        return get_string('notifyattemptsgradedtask', 'mod_quiz');
47
    }
48
 
49
    /**
50
     * To let this class be unit tested, we wrap all accesses to the current time in this method.
51
     *
52
     * @return int The current time.
53
     */
54
    protected function get_time(): int {
55
        if (PHPUNIT_TEST && $this->forcedtime !== null) {
56
            return $this->forcedtime;
57
        }
58
 
59
        return time();
60
    }
61
 
62
    /**
63
     * For testing only, pretend the current time is different.
64
     *
65
     * @param int $time The time to set as the current time.
66
     */
67
    public function set_time_for_testing(int $time): void {
68
        if (!PHPUNIT_TEST) {
69
            throw new \coding_exception('set_time_for_testing should only be used in unit tests.');
70
        }
71
        $this->forcedtime = $time;
72
    }
73
 
11 efrain 74
    #[\Override]
75
    public function execute(): void {
1 efrain 76
        global $DB;
77
 
78
        mtrace('Looking for quiz attempts which may need a graded notification sent...');
79
 
80
        $attempts = $this->get_list_of_attempts();
81
        $course = null;
82
        $quiz = null;
83
        $cm = null;
84
 
85
        foreach ($attempts as $attempt) {
86
            mtrace('Checking attempt ' . $attempt->id . ' at quiz ' . $attempt->quiz . '.');
87
 
88
            if (!$quiz || $attempt->quiz != $quiz->id) {
89
                $quiz = $DB->get_record('quiz', ['id' => $attempt->quiz], '*', MUST_EXIST);
90
                $cm = get_coursemodule_from_instance('quiz', $attempt->quiz);
11 efrain 91
                $quizcontext = context_module::instance($cm->id);
1 efrain 92
            }
93
 
94
            if (!$course || $course->id != $quiz->course) {
95
                $course = get_course($quiz->course);
96
            }
97
 
98
            $quiz = quiz_update_effective_access($quiz, $attempt->userid);
99
            $attemptobj = new quiz_attempt($attempt, $quiz, $cm, $course, false);
100
            $options = display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt));
101
 
102
            if ($options->manualcomment == question_display_options::HIDDEN) {
103
                // User cannot currently see the feedback, so don't message them.
104
                // However, this may change in future, so leave them on the list.
11 efrain 105
                mtrace('Not sending an email because manualcomment review option is not set.');
1 efrain 106
                continue;
107
            }
108
 
11 efrain 109
            if (!has_capability('mod/quiz:emailnotifyattemptgraded', $quizcontext, $attempt->userid, false)) {
1 efrain 110
                // User not eligible to get a notification. Mark them done while doing nothing.
11 efrain 111
                mtrace('Not sending an email because user does not have mod/quiz:emailnotifyattemptgraded capability.');
1 efrain 112
                $DB->set_field('quiz_attempts', 'gradednotificationsenttime', $attempt->timefinish, ['id' => $attempt->id]);
113
                continue;
114
            }
115
 
116
            // OK, send notification.
117
            mtrace('Sending email to user ' . $attempt->userid . '...');
118
            $ok = quiz_send_notify_manual_graded_message($attemptobj, core_user::get_user($attempt->userid));
119
            if ($ok) {
120
                mtrace('Send email successfully!');
121
                $attempt->gradednotificationsenttime = $this->get_time();
122
                $DB->set_field('quiz_attempts', 'gradednotificationsenttime', $attempt->gradednotificationsenttime,
123
                        ['id' => $attempt->id]);
124
                $attemptobj->fire_attempt_manual_grading_completed_event();
125
            }
126
        }
127
 
128
        $attempts->close();
129
    }
130
 
131
    /**
132
     * Get a number of records as an array of quiz_attempts using a SQL statement.
133
     *
134
     * @return moodle_recordset Of quiz_attempts that need to be processed.
135
     */
136
    public function get_list_of_attempts(): moodle_recordset {
137
        global $DB;
138
 
139
        $delaytime = $this->get_time() - get_config('quiz', 'notifyattemptgradeddelay');
140
 
141
        $sql = "SELECT qa.*
142
                  FROM {quiz_attempts} qa
143
                  JOIN {quiz} quiz ON quiz.id = qa.quiz
144
                 WHERE qa.state = 'finished'
145
                       AND qa.gradednotificationsenttime IS NULL
146
                       AND qa.sumgrades IS NOT NULL
147
                       AND qa.timemodified < :delaytime
148
              ORDER BY quiz.course, qa.quiz";
149
 
150
        return $DB->get_recordset_sql($sql, ['delaytime' => $delaytime]);
151
    }
152
}