<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
declare(strict_types=1);
namespace core_reportbuilder\local\helpers;
use advanced_testcase;
use context_system;
use core_reportbuilder_generator;
use core_reportbuilder\reportbuilder\audience\manual;
use core_user\reportbuilder\datasource\users;
/**
* Unit tests for audience helper
*
* @package core_reportbuilder
* @covers \core_reportbuilder\local\helpers\audience
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class audience_test extends advanced_testcase {
/**
* Test reports list is empty for a normal user without any audience records configured
*/
public function test_reports_list_no_access(): void {
$this->resetAfterTest();
$reports = audience::user_reports_list();
$this->assertEmpty($reports);
}
/**
* Test get_base_records()
*/
public function test_get_base_records(): void {
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
// Report with no audiences.
$report = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$baserecords = audience::get_base_records($report->get('id'));
$this->assertEmpty($baserecords);
// Create a couple of manual audience types.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$audience1 = $generator->create_audience([
'reportid' => $report->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user1->id, $user2->id]],
]);
$user3 = $this->getDataGenerator()->create_user();
$audience2 = $generator->create_audience([
'reportid' => $report->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user3->id]],
]);
$baserecords = audience::get_base_records($report->get('id'));
$this->assertCount(2, $baserecords);
$this->assertContainsOnlyInstancesOf(manual::class, $baserecords);
// Set invalid classname of first audience, should be excluded in subsequent request.
$audience1->get_persistent()->set('classname', '\invalid')->save();
$baserecords = audience::get_base_records($report->get('id'));
$this->assertCount(1, $baserecords);
$baserecord = reset($baserecords);
$this->assertInstanceOf(manual::class, $baserecord);
$this->assertEquals($audience2->get_persistent()->get('id'), $baserecord->get_persistent()->get('id'));
}
/**
* Test get_allowed_reports()
*/
public function test_get_allowed_reports(): void {
$this->resetAfterTest();
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
self::setUser($user1);
// No reports.
$reports = audience::get_allowed_reports();
$this->assertEmpty($reports);
$report1 = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$report2 = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$report3 = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
// Reports with no audiences set.
$reports = audience::get_allowed_reports();
$this->assertEmpty($reports);
$generator->create_audience([
'reportid' => $report1->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user1->id, $user2->id]],
]);
$generator->create_audience([
'reportid' => $report2->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user2->id]],
]);
$generator->create_audience([
'reportid' => $report3->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user1->id]],
]);
// Purge cache, to ensure allowed reports are re-calculated.
audience::purge_caches();
$reports = audience::get_allowed_reports();
$this->assertEqualsCanonicalizing([$report1->get('id'), $report3->get('id')], $reports);
// User2 can access report1 and report2.
$reports = audience::get_allowed_reports((int) $user2->id);
$this->assertEqualsCanonicalizing([$report1->get('id'), $report2->get('id')], $reports);
>
}
> // Purge cache, to ensure allowed reports are re-calculated.
> audience::purge_caches();
/**
>
* Test user_reports_list()
> // Now delete one of our users, ensure they no longer have any allowed reports.
*/
> delete_user($user2);
public function test_user_reports_list(): void {
>
$this->resetAfterTest();
> $reports = audience::get_allowed_reports((int) $user2->id);
> $this->assertEmpty($reports);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
self::setUser($user1);
$reports = audience::user_reports_list();
$this->assertEmpty($reports);
$report1 = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$report2 = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$report3 = $generator->create_report([
'name' => 'My report',
'source' => users::class,
'default' => false,
]);
$generator->create_audience([
'reportid' => $report1->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user1->id, $user2->id]],
]);
$generator->create_audience([
'reportid' => $report2->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user2->id]],
]);
$generator->create_audience([
'reportid' => $report3->get('id'),
'classname' => manual::class,
'configdata' => ['users' => [$user1->id]],
]);
// Purge cache, to ensure allowed reports are re-calculated.
audience::purge_caches();
// User1 can access report1 and report3.
$reports = audience::user_reports_list();
$this->assertEqualsCanonicalizing([$report1->get('id'), $report3->get('id')], $reports);
// User2 can access report1 and report2.
$reports = audience::user_reports_list((int) $user2->id);
$this->assertEqualsCanonicalizing([$report1->get('id'), $report2->get('id')], $reports);
// User3 can not access any report.
$reports = audience::user_reports_list((int) $user3->id);
$this->assertEmpty($reports);
}
/**
< * Test get_all_audiences_menu_types()
> * Test retrieving full list of reports that user can access
*/
< public function test_get_all_audiences_menu_types(): void {
> public function test_user_reports_list_access_sql(): void {
> global $DB;
>
$this->resetAfterTest();
< // Test with user that has no permission to add audiences.
< $user1 = $this->getDataGenerator()->create_user();
< $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description');
< assign_capability('moodle/user:viewalldetails', CAP_PROHIBIT, $roleid, context_system::instance()->id);
< role_assign($roleid, $user1->id, context_system::instance()->id);
< self::setUser($user1);
< $categories = audience::get_all_audiences_menu_types();
< $this->assertEmpty($categories);
> $userone = $this->getDataGenerator()->create_user();
> $usertwo = $this->getDataGenerator()->create_user();
> $userthree = $this->getDataGenerator()->create_user();
> $userfour = $this->getDataGenerator()->create_user();
>
> /** @var core_reportbuilder_generator $generator */
> $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
>
> // Manager role gives users one and two capability to create own reports.
> $managerrole = $DB->get_field('role', 'id', ['shortname' => 'manager']);
> role_assign($managerrole, $userone->id, context_system::instance());
> role_assign($managerrole, $usertwo->id, context_system::instance());
>
> // Admin creates a report, no audience.
> $this->setAdminUser();
> $useradminreport = $generator->create_report(['name' => 'Admin report', 'source' => users::class]);
>
> // User one creates a report, adds users two and three to audience.
> $this->setUser($userone);
> $useronereport = $generator->create_report(['name' => 'User one report', 'source' => users::class]);
> $generator->create_audience(['reportid' => $useronereport->get('id'), 'classname' => manual::class, 'configdata' => [
> 'users' => [$usertwo->id, $userthree->id],
> ]]);
>
> // User two creates a report, no audience.
> $this->setUser($usertwo);
> $usertworeport = $generator->create_report(['name' => 'User two report', 'source' => users::class]);
>
> // Admin user sees all reports.
> $this->setAdminUser();
> [$where, $params] = audience::user_reports_list_access_sql('r');
> $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
> $this->assertEqualsCanonicalizing([
> $useradminreport->get('id'),
> $useronereport->get('id'),
> $usertworeport->get('id'),
> ], $reports);
>
> // User one sees only the report they created.
> [$where, $params] = audience::user_reports_list_access_sql('r', (int) $userone->id);
> $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
> $this->assertEquals([$useronereport->get('id')], $reports);
>
> // User two see the report they created and the one they are in the audience of.
> [$where, $params] = audience::user_reports_list_access_sql('r', (int) $usertwo->id);
> $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
> $this->assertEqualsCanonicalizing([$useronereport->get('id'), $usertworeport->get('id')], $reports);
>
> // User three sees the report they are in the audience of.
> [$where, $params] = audience::user_reports_list_access_sql('r', (int) $userthree->id);
> $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
> $this->assertEquals([$useronereport->get('id')], $reports);
>
> // User four sees no reports.
> [$where, $params] = audience::user_reports_list_access_sql('r', (int) $userfour->id);
> $reports = $DB->get_fieldset_sql("SELECT r.id FROM {reportbuilder_report} r WHERE {$where}", $params);
> $this->assertEmpty($reports);
> }
>
> /**
> * Test getting list of audiences in use within schedules for a report
> */
> public function test_get_audiences_for_report_schedules(): void {
> $this->resetAfterTest();
>
> /** @var core_reportbuilder_generator $generator */
> $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
> $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
>
> $audienceone = $generator->create_audience(['reportid' => $report->get('id'), 'configdata' => []]);
> $audiencetwo = $generator->create_audience(['reportid' => $report->get('id'), 'configdata' => []]);
> $audiencethree = $generator->create_audience(['reportid' => $report->get('id'), 'configdata' => []]);
>
> // The first schedule contains audience one and two.
> $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'Schedule one', 'audiences' =>
> json_encode([$audienceone->get_persistent()->get('id'), $audiencetwo->get_persistent()->get('id')])
> ]);
>
> // Second schedule contains only audience one.
> $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'Schedule two', 'audiences' =>
> json_encode([$audienceone->get_persistent()->get('id')])
> ]);
< self::setAdminUser();
< $categories = audience::get_all_audiences_menu_types();
< $category = array_filter($categories, function ($category) {
< return $category['name'] === 'Site';
< });
< $category = reset($category);
< // We don't use assertEqual here to avoid this test failing when more audience types get created.
< $this->assertGreaterThanOrEqual(3, $category['items']);
> // The first two audiences should be returned, the third omitted.
> $audiences = audience::get_audiences_for_report_schedules($report->get('id'));
> $this->assertEqualsCanonicalizing([
> $audienceone->get_persistent()->get('id'),
> $audiencetwo->get_persistent()->get('id'),
> ], $audiences);
}
}