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
declare(strict_types=1);
18
 
19
namespace core_reportbuilder\local\helpers;
20
 
21
use advanced_testcase;
22
use context_system;
23
use core_reportbuilder_generator;
24
use core_reportbuilder\reportbuilder\audience\manual;
25
use core_user\reportbuilder\datasource\users;
26
 
27
/**
28
 * Unit tests for audience helper
29
 *
30
 * @package     core_reportbuilder
31
 * @covers      \core_reportbuilder\local\helpers\audience
32
 * @copyright   2021 David Matamoros <davidmc@moodle.com>
33
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class audience_test extends advanced_testcase {
36
 
37
     /**
38
      * Test reports list is empty for a normal user without any audience records configured
39
      */
40
    public function test_reports_list_no_access(): void {
41
        $this->resetAfterTest();
42
 
43
        $reports = audience::user_reports_list();
44
        $this->assertEmpty($reports);
45
    }
46
 
47
    /**
48
     * Test get_base_records()
49
     */
50
    public function test_get_base_records(): void {
51
        $this->resetAfterTest();
52
 
53
        /** @var core_reportbuilder_generator $generator */
54
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
55
 
56
        // Report with no audiences.
57
        $report = $generator->create_report([
58
            'name' => 'My report',
59
            'source' => users::class,
60
            'default' => false,
61
        ]);
62
        $baserecords = audience::get_base_records($report->get('id'));
63
        $this->assertEmpty($baserecords);
64
 
65
        // Create a couple of manual audience types.
66
        $user1 = $this->getDataGenerator()->create_user();
67
        $user2 = $this->getDataGenerator()->create_user();
68
        $audience1 = $generator->create_audience([
69
            'reportid' => $report->get('id'),
70
            'classname' => manual::class,
71
            'configdata' => ['users' => [$user1->id, $user2->id]],
72
        ]);
73
 
74
        $user3 = $this->getDataGenerator()->create_user();
75
        $audience2 = $generator->create_audience([
76
            'reportid' => $report->get('id'),
77
            'classname' => manual::class,
78
            'configdata' => ['users' => [$user3->id]],
79
        ]);
80
 
81
        $baserecords = audience::get_base_records($report->get('id'));
82
        $this->assertCount(2, $baserecords);
83
        $this->assertContainsOnlyInstancesOf(manual::class, $baserecords);
84
 
85
        // Set invalid classname of first audience, should be excluded in subsequent request.
86
        $audience1->get_persistent()->set('classname', '\invalid')->save();
87
 
88
        $baserecords = audience::get_base_records($report->get('id'));
89
        $this->assertCount(1, $baserecords);
90
 
91
        $baserecord = reset($baserecords);
92
        $this->assertInstanceOf(manual::class, $baserecord);
93
        $this->assertEquals($audience2->get_persistent()->get('id'), $baserecord->get_persistent()->get('id'));
94
    }
95
 
96
    /**
97
     * Test get_allowed_reports()
98
     */
99
    public function test_get_allowed_reports(): void {
100
        $this->resetAfterTest();
101
 
102
        /** @var core_reportbuilder_generator $generator */
103
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
104
 
105
        $user1 = $this->getDataGenerator()->create_user();
106
        $user2 = $this->getDataGenerator()->create_user();
107
        self::setUser($user1);
108
 
109
        // No reports.
110
        $reports = audience::get_allowed_reports();
111
        $this->assertEmpty($reports);
112
 
113
        $report1 = $generator->create_report([
114
            'name' => 'My report',
115
            'source' => users::class,
116
            'default' => false,
117
        ]);
118
        $report2 = $generator->create_report([
119
            'name' => 'My report',
120
            'source' => users::class,
121
            'default' => false,
122
        ]);
123
        $report3 = $generator->create_report([
124
            'name' => 'My report',
125
            'source' => users::class,
126
            'default' => false,
127
        ]);
128
 
129
        // Reports with no audiences set.
130
        $reports = audience::get_allowed_reports();
131
        $this->assertEmpty($reports);
132
 
133
        $generator->create_audience([
134
            'reportid' => $report1->get('id'),
135
            'classname' => manual::class,
136
            'configdata' => ['users' => [$user1->id, $user2->id]],
137
        ]);
138
        $generator->create_audience([
139
            'reportid' => $report2->get('id'),
140
            'classname' => manual::class,
141
            'configdata' => ['users' => [$user2->id]],
142
        ]);
143
        $generator->create_audience([
144
            'reportid' => $report3->get('id'),
145
            'classname' => manual::class,
146
            'configdata' => ['users' => [$user1->id]],
147
        ]);
148
 
149
        // Purge cache, to ensure allowed reports are re-calculated.
150
        audience::purge_caches();
151
 
152
        $reports = audience::get_allowed_reports();
153
        $this->assertEqualsCanonicalizing([$report1->get('id'), $report3->get('id')], $reports);
154
 
155
        // User2 can access report1 and report2.
156
        $reports = audience::get_allowed_reports((int) $user2->id);
157
        $this->assertEqualsCanonicalizing([$report1->get('id'), $report2->get('id')], $reports);
158
 
159
        // Purge cache, to ensure allowed reports are re-calculated.
160
        audience::purge_caches();
161
 
162
        // Now delete one of our users, ensure they no longer have any allowed reports.
163
        delete_user($user2);
164
 
165
        $reports = audience::get_allowed_reports((int) $user2->id);
166
        $this->assertEmpty($reports);
167
    }
168
 
169
    /**
170
     * Test user_reports_list()
171
     */
172
    public function test_user_reports_list(): void {
173
        $this->resetAfterTest();
174
 
175
        /** @var core_reportbuilder_generator $generator */
176
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
177
 
178
        $user1 = $this->getDataGenerator()->create_user();
179
        $user2 = $this->getDataGenerator()->create_user();
180
        $user3 = $this->getDataGenerator()->create_user();
181
        self::setUser($user1);
182
 
183
        $reports = audience::user_reports_list();
184
        $this->assertEmpty($reports);
185
 
186
        $report1 = $generator->create_report([
187
            'name' => 'My report',
188
            'source' => users::class,
189
            'default' => false,
190
        ]);
191
        $report2 = $generator->create_report([
192
            'name' => 'My report',
193
            'source' => users::class,
194
            'default' => false,
195
        ]);
196
        $report3 = $generator->create_report([
197
            'name' => 'My report',
198
            'source' => users::class,
199
            'default' => false,
200
        ]);
201
 
202
        $generator->create_audience([
203
            'reportid' => $report1->get('id'),
204
            'classname' => manual::class,
205
            'configdata' => ['users' => [$user1->id, $user2->id]],
206
        ]);
207
        $generator->create_audience([
208
            'reportid' => $report2->get('id'),
209
            'classname' => manual::class,
210
            'configdata' => ['users' => [$user2->id]],
211
        ]);
212
        $generator->create_audience([
213
            'reportid' => $report3->get('id'),
214
            'classname' => manual::class,
215
            'configdata' => ['users' => [$user1->id]],
216
        ]);
217
 
218
        // Purge cache, to ensure allowed reports are re-calculated.
219
        audience::purge_caches();
220
 
221
        // User1 can access report1 and report3.
222
        $reports = audience::user_reports_list();
223
        $this->assertEqualsCanonicalizing([$report1->get('id'), $report3->get('id')], $reports);
224
 
225
        // User2 can access report1 and report2.
226
        $reports = audience::user_reports_list((int) $user2->id);
227
        $this->assertEqualsCanonicalizing([$report1->get('id'), $report2->get('id')], $reports);
228
 
229
        // User3 can not access any report.
230
        $reports = audience::user_reports_list((int) $user3->id);
231
        $this->assertEmpty($reports);
232
    }
233
 
234
    /**
235
     * Test retrieving full list of reports that user can access
236
     */
237
    public function test_user_reports_list_access_sql(): void {
238
        global $DB;
239
 
240
        $this->resetAfterTest();
241
 
242
        $userone = $this->getDataGenerator()->create_user();
243
        $usertwo = $this->getDataGenerator()->create_user();
244
        $userthree = $this->getDataGenerator()->create_user();
245
        $userfour = $this->getDataGenerator()->create_user();
246
 
247
        /** @var core_reportbuilder_generator $generator */
248
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
249
 
250
        // Manager role gives users one and two capability to create own reports.
251
        $managerrole = $DB->get_field('role', 'id', ['shortname' => 'manager']);
252
        role_assign($managerrole, $userone->id, context_system::instance());
253
        role_assign($managerrole, $usertwo->id, context_system::instance());
254
 
255
        // Admin creates a report, no audience.
256
        $this->setAdminUser();
257
        $useradminreport = $generator->create_report(['name' => 'Admin report', 'source' => users::class]);
258
 
259
        // User one creates a report, adds users two and three to audience.
260
        $this->setUser($userone);
261
        $useronereport = $generator->create_report(['name' => 'User one report', 'source' => users::class]);
262
        $generator->create_audience(['reportid' => $useronereport->get('id'), 'classname' => manual::class, 'configdata' => [
263
            'users' => [$usertwo->id, $userthree->id],
264
        ]]);
265
 
266
        // User two creates a report, no audience.
267
        $this->setUser($usertwo);
268
        $usertworeport = $generator->create_report(['name' => 'User two report', 'source' => users::class]);
269
 
270
        // User one sees only the report they created.
271
        [$where, $params] = audience::user_reports_list_access_sql('r', (int) $userone->id);
272
        $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
273
        $this->assertEquals([$useronereport->get('id')], $reports);
274
 
275
        // User two see the report they created and the one they are in the audience of.
276
        [$where, $params] = audience::user_reports_list_access_sql('r', (int) $usertwo->id);
277
        $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
278
        $this->assertEqualsCanonicalizing([$useronereport->get('id'), $usertworeport->get('id')], $reports);
279
 
280
        // User three sees the report they are in the audience of.
281
        [$where, $params] = audience::user_reports_list_access_sql('r', (int) $userthree->id);
282
        $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
283
        $this->assertEquals([$useronereport->get('id')], $reports);
284
 
285
        // User four sees no reports.
286
        [$where, $params] = audience::user_reports_list_access_sql('r', (int) $userfour->id);
287
        $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
288
        $this->assertEmpty($reports);
289
    }
290
 
291
    /**
292
     * Data provider for {@see test_user_reports_list_access_sql_with_capability}
293
     *
294
     * @return array[]
295
     */
296
    public static function user_reports_list_access_sql_with_capability_provider(): array {
297
        return [
298
            ['moodle/reportbuilder:editall'],
299
            ['moodle/reportbuilder:viewall'],
300
        ];
301
    }
302
 
303
    /**
304
     * Test retrieving list of reports that user can access observes capability to view all reports
305
     *
306
     * @param string $capability
307
     *
308
     * @dataProvider user_reports_list_access_sql_with_capability_provider
309
     */
310
    public function test_user_reports_list_access_sql_with_capability(string $capability): void {
311
        global $DB;
312
 
313
        $this->resetAfterTest();
314
 
315
        // Admin creates a report, no audience.
316
        $this->setAdminUser();
317
 
318
        /** @var core_reportbuilder_generator $generator */
319
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
320
        $report = $generator->create_report(['name' => 'Admin report', 'source' => users::class]);
321
 
322
        // Switch to new user, assign capability.
323
        $user = $this->getDataGenerator()->create_user();
324
        $this->setUser($user);
325
 
326
        $userrole = $DB->get_field('role', 'id', ['shortname' => 'user']);
327
        assign_capability($capability, CAP_ALLOW, $userrole, context_system::instance());
328
 
329
        [$where, $params] = audience::user_reports_list_access_sql('r');
330
        $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
331
        $this->assertEquals([$report->get('id')], $reports);
332
    }
333
 
334
    /**
335
     * Test getting list of audiences in use within schedules for a report
336
     */
337
    public function test_get_audiences_for_report_schedules(): void {
338
        $this->resetAfterTest();
339
 
340
        /** @var core_reportbuilder_generator $generator */
341
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
342
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
343
 
344
        $audienceone = $generator->create_audience(['reportid' => $report->get('id'), 'configdata' => []]);
345
        $audiencetwo = $generator->create_audience(['reportid' => $report->get('id'), 'configdata' => []]);
346
        $audiencethree = $generator->create_audience(['reportid' => $report->get('id'), 'configdata' => []]);
347
 
348
        // The first schedule contains audience one and two.
349
        $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'Schedule one', 'audiences' =>
350
            json_encode([$audienceone->get_persistent()->get('id'), $audiencetwo->get_persistent()->get('id')])
351
        ]);
352
 
353
        // Second schedule contains only audience one.
354
        $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'Schedule two', 'audiences' =>
355
            json_encode([$audienceone->get_persistent()->get('id')])
356
        ]);
357
 
358
        // The first two audiences should be returned, the third omitted.
359
        $audiences = audience::get_audiences_for_report_schedules($report->get('id'));
360
        $this->assertEqualsCanonicalizing([
361
            $audienceone->get_persistent()->get('id'),
362
            $audiencetwo->get_persistent()->get('id'),
363
        ], $audiences);
364
    }
365
}