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 gradereport_history;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
/**
22
 * Grade history report test class.
23
 *
24
 * @package    gradereport_history
25
 * @copyright  2014 Frédéric Massart - FMCorz.net
26
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 */
28
class report_test extends \advanced_testcase {
29
 
30
    /**
31
     * Create some grades.
32
     */
33
    public function test_query_db() {
34
        $this->resetAfterTest();
35
 
36
        // Making the setup.
37
        $c1 = $this->getDataGenerator()->create_course();
38
        $c2 = $this->getDataGenerator()->create_course();
39
        $c1ctx = \context_course::instance($c1->id);
40
        $c2ctx = \context_course::instance($c2->id);
41
 
42
        // Users.
43
        $u1 = $this->getDataGenerator()->create_user();
44
        $u2 = $this->getDataGenerator()->create_user();
45
        $u3 = $this->getDataGenerator()->create_user();
46
        $u4 = $this->getDataGenerator()->create_user();
47
        $u5 = $this->getDataGenerator()->create_user();
48
        $grader1 = $this->getDataGenerator()->create_user();
49
        $grader2 = $this->getDataGenerator()->create_user();
50
        self::getDataGenerator()->enrol_user($grader1->id, $c1->id, 'teacher');
51
        self::getDataGenerator()->enrol_user($grader2->id, $c1->id, 'teacher');
52
        self::getDataGenerator()->enrol_user($u2->id, $c1->id, 'student');
53
        self::getDataGenerator()->enrol_user($u3->id, $c1->id, 'student');
54
        self::getDataGenerator()->enrol_user($u4->id, $c1->id, 'student');
55
        self::getDataGenerator()->enrol_user($u5->id, $c1->id, 'student');
56
 
57
        self::getDataGenerator()->enrol_user($grader1->id, $c2->id, 'teacher');
58
        self::getDataGenerator()->enrol_user($u5->id, $c2->id, 'student');
59
 
60
        // Modules.
61
        $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
62
        $c1m2 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
63
        $c1m3 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
64
        $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
65
        $c2m2 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
66
 
67
        // Creating fake history data.
68
        $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign');
69
        $grades = array();
70
 
71
        $this->setUser($grader1);
72
 
73
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m1->id));
74
        $grades['c1m1u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
75
                'timemodified' => time() - 3600));
76
        $grades['c1m1u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id,
77
                'timemodified' => time() + 3600));
78
        $grades['c1m1u3'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id));
79
        $grades['c1m1u4'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id));
80
        $grades['c1m1u5'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id));
81
 
82
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m2->id));
83
        $grades['c1m2u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
84
        $grades['c1m2u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id));
85
 
86
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m3->id));
87
        $grades['c1m3u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
88
 
89
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c2m1->id));
90
        $grades['c2m1u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
91
            'usermodified' => $grader1->id));
92
        $grades['c2m1u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id,
93
            'usermodified' => $grader1->id));
94
        $grades['c2m1u3'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id,
95
            'usermodified' => $grader1->id));
96
        $grades['c2m1u4'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id,
97
            'usermodified' => $grader2->id));
98
 
99
        // Histories where grades have not been revised..
100
        $grades['c2m1u5a'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id,
101
            'timemodified' => time() - 60));
102
        $grades['c2m1u5b'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id,
103
            'timemodified' => time()));
104
        $grades['c2m1u5c'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id,
105
            'timemodified' => time() + 60));
106
 
107
        // Histories where grades have been revised and not revised.
108
        $now = time();
109
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c2m2->id));
110
        $grades['c2m2u1a'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
111
            'timemodified' => $now - 60, 'finalgrade' => 50));
112
        $grades['c2m2u1b'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
113
            'timemodified' => $now - 50, 'finalgrade' => 50));      // Not revised.
114
        $grades['c2m2u1c'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
115
            'timemodified' => $now, 'finalgrade' => 75));
116
        $grades['c2m2u1d'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
117
            'timemodified' => $now + 10, 'finalgrade' => 75));      // Not revised.
118
        $grades['c2m2u1e'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
119
            'timemodified' => $now + 60, 'finalgrade' => 25));
120
        $grades['c2m2u1f'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
121
            'timemodified' => $now + 70, 'finalgrade' => 25));      // Not revised.
122
 
123
        // TODO MDL-46736 Handle deleted/non-existing grade items.
124
        // Histories with missing grade items, considered as deleted.
125
        // $grades['c2x1u5'] = $this->create_grade_history($giparams + array('itemid' => -1, 'userid' => $u5->id, 'courseid' => $c1->id));
126
        // $grades['c2x2u5'] = $this->create_grade_history($giparams + array('itemid' => 999999, 'userid' => $u5->id, 'courseid' => $c1->id));
127
 
128
        // Basic filtering based on course id.
129
        $this->assertEquals(8, $this->get_tablelog_results($c1ctx, array(), true));
130
        $this->assertEquals(13, $this->get_tablelog_results($c2ctx, array(), true));
131
 
132
        // Filtering on 1 user the current user cannot access should return all records.
133
        $this->assertEquals(8, $this->get_tablelog_results($c1ctx, array('userids' => $u1->id), true));
134
 
135
        // Filtering on 2 users, only one of whom the current user can access.
136
        $this->assertEquals(1, $this->get_tablelog_results($c1ctx, ['userids' => "$u1->id,$u3->id"], true));
137
        $results = $this->get_tablelog_results($c1ctx, ['userids' => "$u1->id,$u3->id"]);
138
        $this->assertGradeHistoryIds([$grades['c1m1u3']->id], $results);
139
 
140
        // Filtering on 2 users, both of whom the current user can access.
141
        $this->assertEquals(3, $this->get_tablelog_results($c1ctx, ['userids' => "$u2->id,$u3->id"], true));
142
        $results = $this->get_tablelog_results($c1ctx, ['userids' => "$u2->id,$u3->id"]);
143
        $this->assertGradeHistoryIds([$grades['c1m1u2']->id, $grades['c1m1u3']->id, $grades['c1m2u2']->id], $results);
144
 
145
        // Filtering based on one grade item.
146
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m1->id));
147
        $this->assertEquals(5, $this->get_tablelog_results($c1ctx, array('itemid' => $gi->id), true));
148
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m3->id));
149
        $this->assertEquals(1, $this->get_tablelog_results($c1ctx, array('itemid' => $gi->id), true));
150
 
151
        // Filtering based on the grader.
152
        $this->assertEquals(3, $this->get_tablelog_results($c2ctx, array('grader' => $grader1->id), true));
153
        $this->assertEquals(1, $this->get_tablelog_results($c2ctx, array('grader' => $grader2->id), true));
154
 
155
        // Filtering based on date.
156
        $results = $this->get_tablelog_results($c1ctx, array('datefrom' => time() + 1800));
157
        $this->assertGradeHistoryIds(array($grades['c1m1u2']->id), $results);
158
        $results = $this->get_tablelog_results($c1ctx, array('datetill' => time() - 1800));
159
        $this->assertGradeHistoryIds(array($grades['c1m1u1']->id), $results);
160
        $results = $this->get_tablelog_results($c1ctx, array('datefrom' => time() - 1800, 'datetill' => time() + 1800));
161
        $this->assertGradeHistoryIds(array($grades['c1m1u3']->id, $grades['c1m1u4']->id, $grades['c1m1u5']->id,
162
            $grades['c1m2u1']->id, $grades['c1m2u2']->id, $grades['c1m3u1']->id), $results);
163
 
164
        // Filtering based on revised only.
165
        $this->assertEquals(3, $this->get_tablelog_results($c2ctx, array('userids' => $u5->id), true));
166
        $this->assertEquals(1, $this->get_tablelog_results($c2ctx, array('userids' => $u5->id, 'revisedonly' => true), true));
167
 
168
        // More filtering based on revised only.
169
        $gi = \grade_item::fetch($giparams + array('iteminstance' => $c2m2->id));
170
        $this->assertEquals(6, $this->get_tablelog_results($c2ctx, array('userids' => $u1->id, 'itemid' => $gi->id), true));
171
        $results = $this->get_tablelog_results($c2ctx, array('userids' => $u1->id, 'itemid' => $gi->id, 'revisedonly' => true));
172
        $this->assertGradeHistoryIds(array($grades['c2m2u1a']->id, $grades['c2m2u1c']->id, $grades['c2m2u1e']->id), $results);
173
 
174
        // Checking the value of the previous grade.
175
        $this->assertEquals(null, $results[$grades['c2m2u1a']->id]->prevgrade);
176
        $this->assertEquals($grades['c2m2u1a']->finalgrade, $results[$grades['c2m2u1c']->id]->prevgrade);
177
        $this->assertEquals($grades['c2m2u1c']->finalgrade, $results[$grades['c2m2u1e']->id]->prevgrade);
178
 
179
        // Put course in separate groups mode, add grader1 and two students to the same group.
180
        $c1->groupmode = SEPARATEGROUPS;
181
        update_course($c1);
182
        $this->assertFalse(has_capability('moodle/site:accessallgroups', \context_course::instance($c1->id)));
183
        $g1 = self::getDataGenerator()->create_group(['courseid' => $c1->id, 'name' => 'g1']);
184
        self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $grader1->id]);
185
        self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $u1->id]);
186
        self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $u2->id]);
187
        $this->assertEquals(2, $this->get_tablelog_results($c1ctx, array(), true));
188
 
189
        // Grader2 is not in any groups.
190
        $this->setUser($grader2);
191
        $this->assertEquals(0, $this->get_tablelog_results($c1ctx, array(), true));
192
    }
193
 
194
    /**
195
     * Test the get users helper method.
196
     */
197
    public function test_get_users() {
198
        $this->resetAfterTest();
199
 
200
        // Making the setup.
201
        $c1 = $this->getDataGenerator()->create_course();
202
        $c2 = $this->getDataGenerator()->create_course();
203
        $c1ctx = \context_course::instance($c1->id);
204
        $c2ctx = \context_course::instance($c2->id);
205
 
206
        $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
207
        $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
208
 
209
        // Users.
210
        $u1 = $this->getDataGenerator()->create_user(array('firstname' => 'Eric', 'lastname' => 'Cartman'));
211
        $u2 = $this->getDataGenerator()->create_user(array('firstname' => 'Stan', 'lastname' => 'Marsh'));
212
        $u3 = $this->getDataGenerator()->create_user(array('firstname' => 'Kyle', 'lastname' => 'Broflovski'));
213
        $u4 = $this->getDataGenerator()->create_user(array('firstname' => 'Kenny', 'lastname' => 'McCormick'));
214
 
215
        // Creating grade history for some users.
216
        $gi = \grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
217
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
218
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id));
219
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id));
220
 
221
        $gi = \grade_item::fetch(array('iteminstance' => $c2m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
222
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id));
223
 
224
        // Checking fetching some users.
225
        $users = \gradereport_history\helper::get_users($c1ctx);
226
        $this->assertCount(3, $users);
227
        $this->assertArrayHasKey($u3->id, $users);
228
        $users = \gradereport_history\helper::get_users($c2ctx);
229
        $this->assertCount(1, $users);
230
        $this->assertArrayHasKey($u4->id, $users);
231
        $users = \gradereport_history\helper::get_users($c1ctx, 'c');
232
        $this->assertCount(1, $users);
233
        $this->assertArrayHasKey($u1->id, $users);
234
        $users = \gradereport_history\helper::get_users($c1ctx, '', 0, 2);
235
        $this->assertCount(2, $users);
236
        $this->assertArrayHasKey($u3->id, $users);
237
        $this->assertArrayHasKey($u1->id, $users);
238
        $users = \gradereport_history\helper::get_users($c1ctx, '', 1, 2);
239
        $this->assertCount(1, $users);
240
        $this->assertArrayHasKey($u2->id, $users);
241
 
242
        // Checking the count of users.
243
        $this->assertEquals(3, \gradereport_history\helper::get_users_count($c1ctx));
244
        $this->assertEquals(1, \gradereport_history\helper::get_users_count($c2ctx));
245
        $this->assertEquals(1, \gradereport_history\helper::get_users_count($c1ctx, 'c'));
246
    }
247
 
248
    /**
249
     * Data provider for \gradereport_history_report_testcase::test_get_users_with_profile_fields()
250
     * Testing get_users() and get_users_count() test cases.
251
     *
252
     * @return array List of data sets (test cases)
253
     */
254
    public function get_users_with_profile_fields_provider(): array {
255
        return [
256
            // User identity check boxes, 'email', 'profile_field_lang' and 'profile_field_height' are checked.
257
                'show email,lang and height;search for all users' =>
258
                        ['email,profile_field_lang,profile_field_height', '', ['u1', 'u2', 'u3', 'u4']],
259
                'show email,lang and height;search for users on .org ' =>
260
                        ['email,profile_field_lang,profile_field_height', '.org', ['u1', 'u2', 'u4']],
261
                'show email,lang and height;search for users on .com ' =>
262
                        ['email,profile_field_lang,profile_field_height', '.com', []],
263
                'show email,lang and height;search for users on .uk ' =>
264
                        ['email,profile_field_lang,profile_field_height', '.uk', ['u3']],
265
                'show email,lang and height,search for Spanish speakers' =>
266
                        ['email,profile_field_lang,profile_field_height', 'spanish', ['u1', 'u4']],
267
                'show email,lang and height,search for Spanish speakers' =>
268
                        ['email,profile_field_lang,profile_field_height', 'spa', ['u1', 'u4']],
269
                'show email,lang and height,search for German speakers' =>
270
                        ['email,profile_field_lang,profile_field_height', 'german', ['u2']],
271
                'show email,lang and height,search for German speakers' =>
272
                        ['email,profile_field_lang,profile_field_height', 'ger', ['u2']],
273
                'show email,lang and height,search for English speakers' =>
274
                        ['email,profile_field_lang,profile_field_height', 'english', ['u3']],
275
                'show email,lang and height,search for English speakers' =>
276
                        ['email,profile_field_lang,profile_field_height', 'eng', ['u3']],
277
                'show email,lang and height,search for English speakers' =>
278
                        ['email,profile_field_lang,profile_field_height', 'ish', ['u3']],
279
                'show email,lang and height,search for users with height 180cm' =>
280
                        ['email,profile_field_lang,profile_field_height', '180cm', ['u2', 'u3', 'u4']],
281
                'show email,lang and height,search for users with height 180cm' =>
282
                        ['email,profile_field_lang,profile_field_height', '180', ['u2', 'u3', 'u4']],
283
                'show email,lang and height,search for users with height 170cm' =>
284
                        ['email,profile_field_lang,profile_field_height', '170cm', ['u1']],
285
                'show email,lang and height,search for users with height 170cm' =>
286
                        ['email,profile_field_lang,profile_field_height', '170', ['u1']],
287
 
288
            // User identity check boxes, 'email' and 'profile_field_height' are checked.
289
                'show email and height;search for users on .org' =>
290
                        ['email,profile_field_height', '.org', ['u1', 'u2', 'u4']],
291
                'show email and height;search for users on .com' =>
292
                        ['email,profile_field_height', '.com', []],
293
                'show email and height;search for users on .co' =>
294
                        ['email,profile_field_height', '.co', ['u3']],
295
                'show email and height,search for Spanish/German/English speakers' =>
296
                        ['email,profile_field_height', 'spanish', []],
297
                'show email and height,search for Spanish/German/English speakers' =>
298
                        ['email,profile_field_height', 'german', []],
299
                'show email and height,search for Spanish/German/English speakers' =>
300
                        ['email,profile_field_height', 'english', []],
301
                'show email,lang and height,search for English speakers' =>
302
                        ['email,profile_field_height', 'english', []],
303
                'show email and height,search for English speakers' =>
304
                        ['email,profile_field_height', 'eng', []],
305
                'show email and height,search for English speakers' =>
306
                        ['email,profile_field_height', 'ish', []],
307
                'show email and height,search for users with height 180cm' =>
308
                        ['email,profile_field_height', '180cm', ['u2', 'u3', 'u4']],
309
                'show email,lang and height,search for users with height 180cm' =>
310
                        ['email,profile_field_height', '180', ['u2', 'u3', 'u4']],
311
                'show email,lang and height,search for users with height 170cm' =>
312
                        ['email,profile_field_height', '170cm', ['u1']],
313
                'show email,lang and height,search for users with height 170cm' =>
314
                        ['email,profile_field_height', '170', ['u1']],
315
 
316
            // User identity check boxes, only 'email' is checked.
317
                'show email only;search for users on .org' => ['email', '.org', ['u1', 'u2', 'u4']],
318
                'show email only;search for users on .com' => ['email', '.com', []],
319
                'show email only;search for users on .co.uk' => ['email', 'co.uk', ['u3']],
320
                'show email only;search for users on .uk' => ['email', '.uk', ['u3']],
321
                'show email only;search for users on .co' => ['email', '.co', ['u3']],
322
                'show email only;search for Spanish speakers' => ['email', 'spanish', []],
323
                'show email only;search for German speakers' => ['email', 'german', []],
324
                'show email only;search for English speakers' => ['email', 'english', []],
325
                'show email only;search for users with height 180cm' => ['email', '180cm', []],
326
                'show email only;search for users with height 180cm' => ['email', '180', []],
327
                'show email only;search for users with height 170cm' => ['email', '170cm', []],
328
                'show email only;search for users with height 170cm' => ['email', '170', []],
329
        ];
330
    }
331
 
332
    /**
333
     * Testing the search functionality on get_users() and get_users_count() and their inner methods.
334
     *
335
     * @dataProvider get_users_with_profile_fields_provider
336
     *
337
     * @param string $showuseridentity, list of user identities to be shown.
338
     * @param string $searchstring, the string to be searched.
339
     * @param array $expectedusernames, a list of expected usernames.
340
     * @return void
341
     */
342
    public function test_get_users_with_profile_fields(string $showuseridentity, string $searchstring,
343
            array $expectedusernames): void {
344
        global $CFG, $DB;
345
        require_once($CFG->dirroot . '/user/profile/lib.php');
346
        $this->resetAfterTest();
347
 
348
        // Create a couple of custom profile fields, which are in user identity.
349
        $generator = $this->getDataGenerator();
350
        $generator->create_custom_profile_field(['datatype' => 'text',
351
                'shortname' => 'lang', 'name' => 'Language']);
352
        $generator->create_custom_profile_field(['datatype' => 'text',
353
                'shortname' => 'height', 'name' => 'Height']);
354
 
355
        // Create a couple of test users.
356
        $u1 = $generator->create_user(['firstname' => 'Eduardo', 'lastname' => 'Gomes',
357
                'username' => 'u1', 'email' => 'u1@x.org', 'profile_field_lang' => 'Spanish',
358
                'profile_field_height' => '170cm']);
359
        $u2 = $generator->create_user(['firstname' => 'Dieter', 'lastname' => 'Schmitt',
360
                'username' => 'u2', 'email' => 'u2@x.org', 'profile_field_lang' => 'German',
361
                'profile_field_height' => '180cm']);
362
 
363
        $u3 = $generator->create_user(['firstname' => 'Peter', 'lastname' => 'Jones',
364
                'username' => 'u3', 'email' => 'u3@x.co.uk', 'profile_field_lang' => 'English',
365
                'profile_field_height' => '180cm']);
366
        $u4 = $generator->create_user(['firstname' => 'Pedro', 'lastname' => 'Gomes',
367
                'username' => 'u4', 'email' => 'u3@x.org', 'profile_field_lang' => 'Spanish',
368
                'profile_field_height' => '180cm']);
369
 
370
        // Do this as admin user.
371
        $this->setAdminUser();
372
 
373
        // Making the setup.
374
        $c1 = $this->getDataGenerator()->create_course();
375
        $c1ctx = \context_course::instance($c1->id);
376
        $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
377
 
378
        // Creating grade history for some users.
379
        $gi = \grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
380
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
381
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id));
382
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id));
383
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id));
384
 
385
        // Checking fetching some users with this config settings.
386
        set_config('showuseridentity', $showuseridentity);
387
        $numberofexpectedusers = count($expectedusernames);
388
        $users = \gradereport_history\helper::get_users($c1ctx, $searchstring);
389
        $userscount = \gradereport_history\helper::get_users_count($c1ctx, $searchstring);
390
        $this->assertEquals($numberofexpectedusers, $userscount);
391
        $this->assertCount($numberofexpectedusers, $users);
392
        foreach ($users as $user) {
393
            if (in_array($user->username, $expectedusernames)) {
394
                $this->assertArrayHasKey($user->id, $users);
395
            } else {
396
                $this->assertArrayNotHasKey($user->id, $users);
397
            }
398
        }
399
    }
400
 
401
    /**
402
     * Data provider method for \gradereport_history_report_testcase::test_get_users_with_groups()
403
     */
404
    public function get_users_provider() {
405
        return [
406
            'Visible groups, non-editing teacher, not in any group' => [
407
                VISIBLEGROUPS, 'teacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5']
408
            ],
409
            'Visible groups, non-editing teacher' => [
410
                VISIBLEGROUPS, 'teacher', [], ['s1', 's2', 's3', 's4', 's5']
411
            ],
412
            'Visible groups, editing teacher' => [
413
                VISIBLEGROUPS, 'editingteacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5']
414
            ],
415
            'Separate groups, non-editing teacher' => [
416
                SEPARATEGROUPS, 'teacher', ['g1', 'g2'], ['s1', 's2']
417
            ],
418
            'Separate groups, non-editing teacher, not in any group' => [
419
                SEPARATEGROUPS, 'teacher', [], []
420
            ],
421
            'Separate groups, non-editing teacher and student share two groups' => [
422
                SEPARATEGROUPS, 'teacher', ['g4', 'g5'], ['s5']
423
            ],
424
            'Separate groups, editing teacher' => [
425
                SEPARATEGROUPS, 'editingteacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5']
426
            ],
427
        ];
428
    }
429
 
430
    /**
431
     * Test for helper::get_users() with course group mode set.
432
     *
433
     * @dataProvider get_users_provider
434
     * @param $groupmode
435
     * @param $teacherrole
436
     * @param $teachergroups
437
     * @param $expectedusers
438
     */
439
    public function test_get_users_with_groups($groupmode, $teacherrole, $teachergroups, $expectedusers) {
440
        global $DB;
441
        $this->resetAfterTest();
442
 
443
        $generator = $this->getDataGenerator();
444
 
445
        // Create a test course.
446
        $course = $generator->create_course(['groupmode' => $groupmode]);
447
 
448
        // Create an assignment module.
449
        $assign = $generator->create_module('assign', ['course' => $course]);
450
 
451
        // Fetch roles.
452
        $role = $DB->get_record('role', ['shortname' => $teacherrole], '*', MUST_EXIST);
453
        $studentrole =  $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
454
 
455
        // Create users.
456
        $t1 = $generator->create_user(['username' => 't1', 'email' => 't1@example.com']);
457
        $s1 = $generator->create_user(['username' => 's1', 'email' => 's1@example.com']);
458
        $s2 = $generator->create_user(['username' => 's2', 'email' => 's2@example.com']);
459
        $s3 = $generator->create_user(['username' => 's3', 'email' => 's3@example.com']);
460
        $s4 = $generator->create_user(['username' => 's4', 'email' => 's4@example.com']);
461
        $s5 = $generator->create_user(['username' => 's5', 'email' => 's5@example.com']);
462
 
463
        // Enrol users.
464
        $generator->enrol_user($t1->id, $course->id, $role->id);
465
        $generator->enrol_user($s1->id, $course->id, $studentrole->id);
466
        $generator->enrol_user($s2->id, $course->id, $studentrole->id);
467
        $generator->enrol_user($s3->id, $course->id, $studentrole->id);
468
        $generator->enrol_user($s4->id, $course->id, $studentrole->id);
469
        $generator->enrol_user($s5->id, $course->id, $studentrole->id);
470
 
471
        // Create groups.
472
        $groups = [];
473
        $groups['g1'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g1']);
474
        $groups['g2'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g2']);
475
        $groups['g3'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g3']);
476
        $groups['g4'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g4']);
477
        $groups['g5'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g5']);
478
 
479
        // Add teacher to the assigned groups.
480
        foreach ($teachergroups as $groupname) {
481
            $group = $groups[$groupname];
482
            $generator->create_group_member(['groupid' => $group->id, 'userid' => $t1->id]);
483
        }
484
 
485
        // Add students to groups.
486
        $generator->create_group_member(['groupid' => $groups['g1']->id, 'userid' => $s1->id]);
487
        $generator->create_group_member(['groupid' => $groups['g2']->id, 'userid' => $s2->id]);
488
        $generator->create_group_member(['groupid' => $groups['g3']->id, 'userid' => $s3->id]);
489
        $generator->create_group_member(['groupid' => $groups['g4']->id, 'userid' => $s5->id]);
490
        $generator->create_group_member(['groupid' => $groups['g5']->id, 'userid' => $s5->id]);
491
 
492
        // Creating grade history for the students.
493
        $gi = \grade_item::fetch(['iteminstance' => $assign->id, 'itemtype' => 'mod', 'itemmodule' => 'assign']);
494
        $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s1->id]);
495
        $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s2->id]);
496
        $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s3->id]);
497
        $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s4->id]);
498
        $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s5->id]);
499
 
500
        // Log in as the teacher.
501
        $this->setUser($t1);
502
 
503
        // Fetch the users.
504
        $users = \gradereport_history\helper::get_users(\context_course::instance($course->id));
505
        // Confirm that the number of users fetched is the same as the count of expected users.
506
        $this->assertCount(count($expectedusers), $users);
507
        foreach ($users as $user) {
508
            // Confirm that each user returned is in the list of expected users.
509
            $this->assertTrue(in_array($user->username, $expectedusers));
510
        }
511
    }
512
 
513
    /**
514
     * Test the get graders helper method.
515
     */
516
    public function test_graders() {
517
        $this->resetAfterTest();
518
 
519
        // Making the setup.
520
        $c1 = $this->getDataGenerator()->create_course();
521
        $c2 = $this->getDataGenerator()->create_course();
522
        $c3 = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS]);
523
 
524
        $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
525
        $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
526
        $c3m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c3));
527
 
528
        // Users.
529
        $u1 = $this->getDataGenerator()->create_user(array('firstname' => 'Eric', 'lastname' => 'Cartman'));
530
        $u2 = $this->getDataGenerator()->create_user(array('firstname' => 'Stan', 'lastname' => 'Marsh'));
531
        $u3 = $this->getDataGenerator()->create_user(array('firstname' => 'Kyle', 'lastname' => 'Broflovski'));
532
        $u4 = $this->getDataGenerator()->create_user(array('firstname' => 'Kenny', 'lastname' => 'McCormick'));
533
 
534
        foreach ([$c1, $c2, $c3] as $course) {
535
            foreach ([$u1, $u2, $u3, $u4] as $user) {
536
                self::getDataGenerator()->enrol_user($user->id, $course->id, 'student');
537
            }
538
        }
539
 
540
        // Creating grade history for some users.
541
        $gi = \grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
542
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u1->id));
543
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u2->id));
544
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u3->id));
545
 
546
        $gi = \grade_item::fetch(array('iteminstance' => $c2m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
547
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u4->id));
548
 
549
        $gi = \grade_item::fetch(array('iteminstance' => $c3m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
550
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u1->id));
551
        $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id, 'usermodified' => $u2->id));
552
 
553
        // Checking fetching some users.
554
        $graders = \gradereport_history\helper::get_graders($c1->id);
555
        $this->assertCount(4, $graders); // Including "all graders" .
556
        $this->assertArrayHasKey($u1->id, $graders);
557
        $this->assertArrayHasKey($u2->id, $graders);
558
        $this->assertArrayHasKey($u3->id, $graders);
559
        $graders = \gradereport_history\helper::get_graders($c2->id);
560
        $this->assertCount(2, $graders); // Including "all graders" .
561
        $this->assertArrayHasKey($u4->id, $graders);
562
 
563
        // Third course is in separate groups mode. Only graders from the same group will be returned.
564
        $g = self::getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'g1']);
565
        self::getDataGenerator()->create_group_member(['groupid' => $g->id, 'userid' => $u1->id]);
566
        self::getDataGenerator()->create_group_member(['groupid' => $g->id, 'userid' => $u2->id]);
567
        $this->setUser($u1);
568
        $graders = \gradereport_history\helper::get_graders($c3->id);
569
        $this->assertCount(3, $graders); // Including "all graders" .
570
        $this->setUser($u3);
571
        $graders = \gradereport_history\helper::get_graders($c3->id);
572
        $this->assertCount(1, $graders); // Including "all graders" .
573
    }
574
 
575
    /**
576
     * Asserts that the array of grade objects contains exactly the right IDs.
577
     *
578
     * @param array $expectedids Array of expected IDs.
579
     * @param array $objects Array of objects returned by the table.
580
     */
581
    protected function assertGradeHistoryIds(array $expectedids, array $objects) {
582
        $this->assertCount(count($expectedids), $objects);
583
        $expectedids = array_flip($expectedids);
584
        foreach ($objects as $object) {
585
            $this->assertArrayHasKey($object->id, $expectedids);
586
            unset($expectedids[$object->id]);
587
        }
588
        $this->assertCount(0, $expectedids);
589
    }
590
 
591
    /**
592
     * Create a new grade history entry.
593
     *
594
     * @param array $params Of values.
595
     * @return object The grade object.
596
     */
597
    protected function create_grade_history($params) {
598
        global $DB;
599
        $params = (array) $params;
600
 
601
        if (!isset($params['itemid'])) {
602
            throw new \coding_exception('Missing itemid key.');
603
        }
604
        if (!isset($params['userid'])) {
605
            throw new \coding_exception('Missing userid key.');
606
        }
607
 
608
        // Default object.
609
        $grade = new \stdClass();
610
        $grade->itemid = 0;
611
        $grade->userid = 0;
612
        $grade->oldid = 123;
613
        $grade->rawgrade = 50;
614
        $grade->finalgrade = 50;
615
        $grade->timecreated = time();
616
        $grade->timemodified = time();
617
        $grade->information = '';
618
        $grade->informationformat = FORMAT_PLAIN;
619
        $grade->feedback = '';
620
        $grade->feedbackformat = FORMAT_PLAIN;
621
        $grade->usermodified = 2;
622
 
623
        // Merge with data passed.
624
        $grade = (object) array_merge((array) $grade, $params);
625
 
626
        // Insert record.
627
        $grade->id = $DB->insert_record('grade_grades_history', $grade);
628
 
629
        return $grade;
630
    }
631
 
632
    /**
633
     * Returns a table log object.
634
     *
635
     * @param context_course $coursecontext The course context.
636
     * @param array $filters An array of filters.
637
     * @param boolean $count When true, returns a count rather than an array of objects.
638
     * @return mixed Count or array of objects.
639
     */
640
    protected function get_tablelog_results($coursecontext, $filters = array(), $count = false) {
641
        $table = new gradereport_history_tests_tablelog('something', $coursecontext, new \moodle_url(''), $filters);
642
        return $table->get_test_results($count);
643
    }
644
 
645
}
646
 
647
/**
648
 * Extended table log class.
649
 */
650
class gradereport_history_tests_tablelog extends \gradereport_history\output\tablelog {
651
 
652
    /**
653
     * Get the test results.
654
     *
655
     * @param boolean $count Whether or not we want the count.
656
     * @return mixed Count or array of objects.
657
     */
658
    public function get_test_results($count = false) {
659
        global $DB;
660
        if ($count) {
661
            list($sql, $params) = $this->get_sql_and_params(true);
662
            return $DB->count_records_sql($sql, $params);
663
        } else {
664
            $this->setup();
665
            list($sql, $params) = $this->get_sql_and_params();
666
            return $DB->get_records_sql($sql, $params);
667
        }
668
    }
669
 
670
}