Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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_feedback;
18
 
19
use mod_feedback_completion;
20
 
21
defined('MOODLE_INTERNAL') || die();
22
 
23
global $CFG;
24
 
25
require_once($CFG->dirroot . '/mod/feedback/lib.php');
26
 
27
/**
28
 * Unit tests to check group membership for teacher access to responses.
29
 * @package    mod_feedback
30
 * @copyright  2024 Leon Stringer
31
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32
 */
33
final class access_test extends \advanced_testcase {
34
    public function setUp(): void {
35
        parent::setUp();
36
        $this->resetAfterTest();
37
    }
38
 
39
    /**
40
     * Submit feedback response.
41
     * @param \stdClass $feedback Mod_feedback instance.
42
     * @param \stdClass $cm Course module.
43
     * @param int $itemid ID of a textfield on the form to complete.
44
     * @param int $userid ID of the user submitting the response.
45
     * @return mod_feedback_completion
46
     */
47
    private function student_response(\stdClass $feedback, \stdClass $cm, int $itemid, int $userid): mod_feedback_completion {
48
        $completion = new mod_feedback_completion($feedback, $cm,
49
                    $cm->course, false, null, $userid, $userid);
50
        $answers = ['textfield_' . $itemid => "test"];
51
        $completion->save_response_tmp((object) $answers);
52
        $completion->save_response();
53
        return $completion;
54
    }
55
 
56
    /**
57
     * Test access to feedback responses is allowed or denied correctly for
58
     * activity group mode and users group membership.
59
     * @param int $groupmode NOGROUPS, SEPARATEGROUPS, etc.
60
     * @param int $anonymous FEEDBACK_ANONYMOUS_NO or FEEDBACK_ANONYMOUS_YES.
61
     * @param array $studentgroups Zero or more names of groups to add the
62
     * student to, for example, ['group1'].
63
     * @param array $teacheraccess List of teachers' usernames and whether they
64
     * should be able to access the submitted feedback, for example,
65
     * ['teacher1' => true, 'teacher2' => false, ...].
66
     * @dataProvider response_access_provider
67
     */
68
    public function test_response_access(int $groupmode, int $anonymous, array $studentgroups, array $teacheraccesses): void {
69
        global $DB;
70
 
71
        $course = $this->getDataGenerator()->create_course([
72
            'groupmode' => $groupmode,
73
            'groupmodeforce' => true,
74
        ]);
75
        $groups['group1'] = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
76
        $groups['group2'] = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
77
 
78
        /*
79
         * Participant:  Role:           Groups:
80
         * teacher1      editingteacher  group1
81
         * teacher2      teacher         group1
82
         * teacher3      teacher         (no group)
83
         * teacher4      editingteacher  (no group)
84
         * student       student         Set by data provider
85
         */
86
        $teachers['teacher1'] = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
87
        $this->getDataGenerator()->create_group_member(['groupid' => $groups['group1']->id, 'userid' => $teachers['teacher1']->id]);
88
        $teachers['teacher2'] = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
89
        $this->getDataGenerator()->create_group_member(['groupid' => $groups['group1']->id, 'userid' => $teachers['teacher2']->id]);
90
        $teachers['teacher3'] = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
91
        $teachers['teacher4'] = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
92
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
93
 
94
        foreach ($studentgroups as $group) {
95
            $this->getDataGenerator()->create_group_member(['groupid' => $groups[$group]->id, 'userid' => $student->id]);
96
        }
97
 
98
        $feedback = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id, 'anonymous' => $anonymous]);
99
        $cm = get_coursemodule_from_instance('feedback', $feedback->id);
100
 
101
        $feedbackgenerator = $this->getDataGenerator()->get_plugin_generator('mod_feedback');
102
        $item = $feedbackgenerator->create_item_textfield($feedback);
103
        $completion = $this->student_response($feedback, $cm, $item->id, $student->id);
104
        $showcompleted = $completion->get_completed()->id;
105
        $userid = '';   // Value used on mod/feedback/show_entries.php.
106
 
107
        foreach ($teacheraccesses as $teacher => $access) {
108
            $this->setUser($teachers[$teacher]);
109
 
110
            // moodle_exception should be thrown if teacher doesn't have
111
            // access.
112
            try {
113
                new mod_feedback_completion($feedback, $cm, 0, true, $showcompleted, $userid);
114
                $this->assertTrue($access);
115
            } catch (\moodle_exception $ex) {
116
                $this->assertTrue(!$access);
117
            }
118
        }
119
    }
120
 
121
    /**
122
     * Group mode and group membership combinations.
123
     * @return array
124
     */
125
    public static function response_access_provider(): array {
126
        return [
127
            /*
128
             * Student is in group1 so response should visible to:
129
             *   1. Teacher1 (same groups and has accessallgroups)
130
             *   2. Teachers (same group)
131
             *   3. Teacher4 (has accessallgroups)
132
             */
133
            'separate_groups_student1' => [
134
                'groupmode' => SEPARATEGROUPS,
135
                'anonymous' => FEEDBACK_ANONYMOUS_NO,
136
                'studentgroups' => ['group1'],
137
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => false, 'teacher4' => true],
138
            ],
139
 
140
            /*
141
             * Student is in group2 so response should visible to:
142
             *   1. Teacher1 (same groups and has accessallgroups)
143
             *   2. Teacher4 (has accessallgroups)
144
             */
145
            'separate_groups_student2' => [
146
                'groupmode' => SEPARATEGROUPS,
147
                'anonymous' => FEEDBACK_ANONYMOUS_NO,
148
                'studentgroups' => ['group2'],
149
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => false, 'teacher3' => false, 'teacher4' => true],
150
            ],
151
 
152
            /*
153
             * Student is in no groups so response should visible to:
154
             *   1. Teacher1 (same groups and has accessallgroups)
155
             *   2. Teacher4 (has accessallgroups)
156
             */
157
            'separate_groups_student3' => [
158
                'groupmode' => SEPARATEGROUPS,
159
                'anonymous' => FEEDBACK_ANONYMOUS_NO,
160
                'studentgroups' => [],
161
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => false, 'teacher3' => false, 'teacher4' => true],
162
            ],
163
 
164
            /*
165
             * Same three tests with FEEDBACK_ANONYMOUS_YES.
166
             */
167
            'separate_groups_anon_student1' => [
168
                'groupmode' => SEPARATEGROUPS,
169
                'anonymous' => FEEDBACK_ANONYMOUS_YES,
170
                'studentgroups' => ['group1'],
171
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => false, 'teacher4' => true],
172
            ],
173
            'separate_groups_anon_student2' => [
174
                'groupmode' => SEPARATEGROUPS,
175
                'anonymous' => FEEDBACK_ANONYMOUS_YES,
176
                'studentgroups' => ['group2'],
177
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => false, 'teacher3' => false, 'teacher4' => true],
178
            ],
179
            'separate_groups_anon_student3' => [
180
                'groupmode' => SEPARATEGROUPS,
181
                'anonymous' => FEEDBACK_ANONYMOUS_YES,
182
                'studentgroups' => [],
183
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => false, 'teacher3' => false, 'teacher4' => true],
184
            ],
185
 
186
            /*
187
             * Same three tests with NOGROUPS and FEEDBACK_ANONYMOUS_NO.
188
             */
189
            'no_groups_student1' => [
190
                'groupmode' => NOGROUPS,
191
                'anonymous' => FEEDBACK_ANONYMOUS_NO,
192
                'studentgroups' => ['group1'],
193
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => true, 'teacher4' => true],
194
            ],
195
            'no_groups_student2' => [
196
                'groupmode' => NOGROUPS,
197
                'anonymous' => FEEDBACK_ANONYMOUS_NO,
198
                'studentgroups' => ['group2'],
199
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => true, 'teacher4' => true],
200
            ],
201
            'no_groups_student3' => [
202
                'groupmode' => NOGROUPS,
203
                'anonymous' => FEEDBACK_ANONYMOUS_NO,
204
                'studentgroups' => [],
205
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => true, 'teacher4' => true],
206
            ],
207
 
208
            /*
209
             * Same three tests with NOGROUPS and FEEDBACK_ANONYMOUS_YES.
210
             */
211
            'no_groups_anon_student1' => [
212
                'groupmode' => NOGROUPS,
213
                'anonymous' => FEEDBACK_ANONYMOUS_YES,
214
                'studentgroups' => ['group1'],
215
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => true, 'teacher4' => true],
216
            ],
217
            'no_groups_anon_student2' => [
218
                'groupmode' => NOGROUPS,
219
                'anonymous' => FEEDBACK_ANONYMOUS_YES,
220
                'studentgroups' => ['group2'],
221
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => true, 'teacher4' => true],
222
            ],
223
            'no_groups_anon_student3' => [
224
                'groupmode' => NOGROUPS,
225
                'anonymous' => FEEDBACK_ANONYMOUS_YES,
226
                'studentgroups' => [],
227
                'teacheraccesses' => ['teacher1' => true, 'teacher2' => true, 'teacher3' => true, 'teacher4' => true],
228
            ],
229
        ];
230
    }
231
}