This commit is contained in:
Andrew Nicols 2023-07-09 22:23:29 +08:00
commit 3d5afd6061
No known key found for this signature in database
GPG Key ID: 6D1E3157C8CFBF14
12 changed files with 413 additions and 92 deletions

View File

@ -22,6 +22,7 @@ use lang_string;
use core_reportbuilder\datasource;
use core_reportbuilder\local\entities\{course, user};
use core_badges\reportbuilder\local\entities\{badge, badge_issued};
use core_tag\reportbuilder\local\entities\tag;
/**
* Badges datasource
@ -49,9 +50,15 @@ class badges extends datasource {
$badgealias = $badgeentity->get_table_alias('badge');
$this->set_main_table('badge', $badgealias);
$this->add_entity($badgeentity);
// Join the tag entity.
$tagentity = (new tag())
->set_table_alias('tag', $badgeentity->get_table_alias('tag'))
->set_entity_title(new lang_string('badgetags', 'core_badges'));
$this->add_entity($tagentity
->add_joins($badgeentity->get_tag_joins()));
// Join the badge issued entity to the badge entity.
$badgeissuedentity = new badge_issued();
$badgeissuedalias = $badgeissuedentity->get_table_alias('badge_issued');
@ -81,7 +88,16 @@ class badges extends datasource {
);
// Add report elements from each of the entities we added to the report.
$this->add_all_from_entities();
$this->add_all_from_entity($badgeentity->get_entity_name());
// Add specific tag entity elements.
$this->add_columns_from_entity($tagentity->get_entity_name(), ['name', 'namewithlink']);
$this->add_filter($tagentity->get_filter('name'));
$this->add_condition($tagentity->get_condition('name'));
$this->add_all_from_entity($badgeissuedentity->get_entity_name());
$this->add_all_from_entity($userentity->get_entity_name());
$this->add_all_from_entity($courseentity->get_entity_name());
}
/**

View File

@ -18,10 +18,12 @@ declare(strict_types=1);
namespace core_badges\reportbuilder\datasource;
use lang_string;
use core_reportbuilder\datasource;
use core_reportbuilder\local\entities\{course, user};
use core_reportbuilder\local\helpers\database;
use core_badges\reportbuilder\local\entities\{badge, badge_issued};
use core_tag\reportbuilder\local\entities\tag;
/**
* User badges datasource
@ -48,17 +50,16 @@ class users extends datasource {
global $CFG;
$userentity = new user();
$useralias = $userentity->get_table_alias('user');
$this->set_main_table('user', $useralias);
$this->add_entity($userentity);
$paramguest = database::generate_param_name();
$this->add_base_condition_sql("{$useralias}.id != :{$paramguest} AND {$useralias}.deleted = 0", [
$paramguest => $CFG->siteguest,
]);
$this->add_entity($userentity);
// Join the badge issued entity to the user entity.
$badgeissuedentity = new badge_issued();
$badgeissuedalias = $badgeissuedentity->get_table_alias('badge_issued');
@ -71,6 +72,14 @@ class users extends datasource {
->add_joins($badgeissuedentity->get_joins())
->add_join("LEFT JOIN {badge} {$badgealias} ON {$badgealias}.id = {$badgeissuedalias}.badgeid"));
// Join the tag entity.
$tagentity = (new tag())
->set_table_alias('tag', $badgeentity->get_table_alias('tag'))
->set_entity_title(new lang_string('badgetags', 'core_badges'));
$this->add_entity($tagentity
->add_joins($badgeentity->get_joins())
->add_joins($badgeentity->get_tag_joins()));
// Join the course entity to the badge entity, coalescing courseid with the siteid for site badges.
$courseentity = new course();
$coursealias = $courseentity->get_table_alias('course');
@ -80,7 +89,16 @@ class users extends datasource {
CASE WHEN {$badgealias}.id IS NULL THEN 0 ELSE COALESCE({$badgealias}.courseid, 1) END"));
// Add report elements from each of the entities we added to the report.
$this->add_all_from_entities();
$this->add_all_from_entity($userentity->get_entity_name());
$this->add_all_from_entity($badgeissuedentity->get_entity_name());
$this->add_all_from_entity($badgeentity->get_entity_name());
// Add specific tag entity elements.
$this->add_columns_from_entity($tagentity->get_entity_name(), ['name', 'namewithlink']);
$this->add_filter($tagentity->get_filter('name'));
$this->add_condition($tagentity->get_condition('name'));
$this->add_all_from_entity($courseentity->get_entity_name());
}
/**

View File

@ -52,6 +52,8 @@ class badge extends base {
return [
'badge' => 'b',
'context' => 'bctx',
'tag_instance' => 'bti',
'tag' => 'bt',
];
}
@ -303,4 +305,13 @@ class badge extends base {
return $filters;
}
/**
* Return joins necessary for retrieving tags
*
* @return string[]
*/
public function get_tag_joins(): array {
return $this->get_tag_joins_for_entity('core_badges', 'badge', $this->get_table_alias('badge') . '.id');
}
}

View File

@ -43,9 +43,10 @@ class core_badges_generator extends component_generator_base {
$record = (array) $record;
// Save badge image path for later.
// Save badge image/tags for later.
$badgeimage = $record['image'] ?? '';
unset($record['image']);
$badgetags = $record['tags'] ?? '';
unset($record['image'], $record['tags']);
$record = (object) array_merge([
'name' => 'Test badge',
@ -93,6 +94,14 @@ class core_badges_generator extends component_generator_base {
badges_process_badge_image($badge, $file->copy_content_to_temp());
}
// Process badge tags (if supplied).
if ($badgetags !== '') {
if (!is_array($badgetags)) {
$badgetags = preg_split('/\s*,\s*/', $badgetags, -1, PREG_SPLIT_NO_EMPTY);
}
core_tag_tag::set_item_tags('core_badges', 'badge', $badge->id, $badge->get_context(), $badgetags);
}
return $badge;
}

View File

@ -21,11 +21,13 @@ namespace core_badges\reportbuilder\datasource;
use core_badges_generator;
use core_reportbuilder_generator;
use core_reportbuilder_testcase;
use core_reportbuilder\local\filters\{boolean_select, date, select, tags, text};
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php");
require_once("{$CFG->libdir}/badgeslib.php");
/**
* Unit tests for badges datasource
@ -38,58 +40,287 @@ require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php");
class badges_test extends core_reportbuilder_testcase {
/**
* Load required test libraries
* Test default datasource
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once("{$CFG->libdir}/badgeslib.php");
}
/**
* Test datasource
*/
public function test_datasource(): void {
public function test_datasource_default(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Test users with a badge we can issue them with.
$user1 = $this->getDataGenerator()->create_user(['firstname' => 'Alan', 'lastname' => 'Apple']);
$user2 = $this->getDataGenerator()->create_user(['firstname' => 'Barry', 'lastname' => 'Banana']);
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$sitebadge = $generator->create_badge(['name' => 'Badge 1']);
$sitebadge->issue($user1->id, true);
$sitebadge->issue($user2->id, true);
$badgeone = $generator->create_badge(['name' => 'Badge 1', 'description' => 'My first badge']);
$badgeone->issue($user1->id, true);
$badgeone->issue($user2->id, true);
// Another badge, in a course, no issues.
// Second badge, not issued to any users.
$badgetwo = $generator->create_badge(['name' => 'Badge 2', 'description' => 'My second badge']);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report(['name' => 'Badges', 'source' => badges::class, 'default' => 1]);
$content = $this->get_custom_report_content($report->get('id'));
$this->assertCount(3, $content);
// Default columns are badge, description, user, issued time. Sorted by badge, user, issued time.
[$badgename, $badgedescription, $userfullname, $badgeissued] = array_values($content[0]);
$this->assertEquals($badgeone->name, $badgename);
$this->assertEquals($badgeone->description, $badgedescription);
$this->assertEquals(fullname($user1), $userfullname);
$this->assertNotEmpty($badgeissued);
[$badgename, $badgedescription, $userfullname, $badgeissued] = array_values($content[1]);
$this->assertEquals($badgeone->name, $badgename);
$this->assertEquals($badgeone->description, $badgedescription);
$this->assertEquals(fullname($user2), $userfullname);
$this->assertNotEmpty($badgeissued);
[$badgename, $badgedescription, $userfullname, $badgeissued] = array_values($content[2]);
$this->assertEquals($badgetwo->name, $badgename);
$this->assertEquals($badgetwo->description, $badgedescription);
$this->assertEmpty($userfullname);
$this->assertEmpty($badgeissued);
}
/**
* Test datasource columns that aren't added by default
*/
public function test_datasource_non_default_columns(): void {
global $DB;
$this->resetAfterTest();
$user1 = $this->getDataGenerator()->create_user(['firstname' => 'Alan', 'lastname' => 'Apple']);
$user2 = $this->getDataGenerator()->create_user(['firstname' => 'Barry', 'lastname' => 'Banana']);
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$badgeone = $generator->create_badge([
'name' => 'Badge 1',
'language' => 'de',
'expireperiod' => HOURSECS,
'tags' => ['cool'],
]);
$badgeone->issue($user1->id, true);
$badgeone->issue($user2->id, true);
// Course badge, not issued to any users.
$course = $this->getDataGenerator()->create_course();
$coursebadge = $generator->create_badge(['name' => 'Badge 2', 'type' => BADGE_TYPE_COURSE, 'courseid' => $course->id]);
$badgetwo = $generator->create_badge(['name' => 'Badge 2', 'type' => BADGE_TYPE_COURSE, 'courseid' => $course->id]);
// Create criteria for manually awarding by role.
$managerrole = $DB->get_field('role', 'id', ['shortname' => 'manager']);
$generator->create_criteria(['badgeid' => $badgeone->id, 'roleid' => $managerrole]);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
$report = $generator->create_report(['name' => 'Badges', 'source' => badges::class, 'default' => 0]);
// Badge course.
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname', 'sortenabled' => 1]);
// Badge name.
// These two columns have been asserted previously, we're only adding them for consistent sorting.
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:name', 'sortenabled' => 1]);
// User fullname.
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:fullname', 'sortenabled' => 1]);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:criteria']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:image']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:language']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:version']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:status']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:expiry']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge_issued:expire']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge_issued:visible']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']);
$content = $this->get_custom_report_content($report->get('id'));
$this->assertCount(3, $content);
$this->assertEquals([
['PHPUnit test site', $sitebadge->name, fullname($user1, true)],
['PHPUnit test site', $sitebadge->name, fullname($user2, true)],
[$course->fullname, $coursebadge->name, ''],
], array_map(static function(array $row): array {
return array_values($row);
}, $content));
// First badge, issued to user one.
[$badgename, $fullname, $criteria, $image, $language, $version, $status, $expiry, $tag, $expires, $visible, $coursename]
= array_values($content[0]);
$this->assertEquals($badgeone->name, $badgename);
$this->assertEquals(fullname($user1), $fullname);
$this->assertStringContainsString('Awarded by: Manager', $criteria);
$this->assertStringContainsString('Image caption', $image);
$this->assertEquals('German', $language);
$this->assertEquals(2, $version);
$this->assertEquals('Available (criteria locked)', $status);
$this->assertEquals('1 hour', $expiry);
$this->assertEquals('cool', $tag);
$this->assertNotEmpty($expires);
$this->assertEquals('Yes', $visible);
$this->assertEquals('PHPUnit test site', $coursename);
// First badge, issued to user two.
[$badgename, $fullname, $criteria, $image, $language, $version, $status, $expiry, $tag, $expires, $visible, $coursename]
= array_values($content[1]);
$this->assertEquals($badgeone->name, $badgename);
$this->assertEquals(fullname($user2), $fullname);
$this->assertStringContainsString('Awarded by: Manager', $criteria);
$this->assertStringContainsString('Image caption', $image);
$this->assertEquals('German', $language);
$this->assertEquals(2, $version);
$this->assertEquals('Available (criteria locked)', $status);
$this->assertEquals('1 hour', $expiry);
$this->assertEquals('cool', $tag);
$this->assertNotEmpty($expires);
$this->assertEquals('Yes', $visible);
$this->assertEquals('PHPUnit test site', $coursename);
// Course badge, not issues to any users.
[$badgename, $fullname, $criteria, $image, $language, $version, $status, $expiry, $tag, $expires, $visible, $coursename]
= array_values($content[2]);
$this->assertEquals($badgetwo->name, $badgename);
$this->assertEmpty($fullname);
$this->assertEquals('Criteria for this badge have not been set up yet.', $criteria);
$this->assertStringContainsString('Image caption', $image);
$this->assertEquals('English', $language);
$this->assertEquals(2, $version);
$this->assertEquals('Available', $status);
$this->assertEquals('Never', $expiry);
$this->assertEmpty($tag);
$this->assertEmpty($expires);
$this->assertEmpty($visible);
$this->assertEquals($course->fullname, $coursename);
}
/**
* Data provider for {@see test_datasource_filters}
*
* @return array[]
*/
public function datasource_filters_provider(): array {
return [
// Badge.
'Filter badge name' => ['badge:name', [
'badge:name_operator' => text::IS_EQUAL_TO,
'badge:name_value' => 'Course badge',
], true],
'Filter badge name (no match)' => ['badge:name', [
'badge:name_operator' => text::IS_EQUAL_TO,
'badge:name_value' => 'Other badge',
], false],
'Filter badge status' => ['badge:status', [
'badge:status_operator' => select::EQUAL_TO,
'badge:status_value' => BADGE_STATUS_ACTIVE_LOCKED,
], true],
'Filter badge status (no match)' => ['badge:status', [
'badge:status_operator' => select::EQUAL_TO,
'badge:status_value' => BADGE_STATUS_ACTIVE,
], false],
'Filter badge type' => ['badge:type', [
'badge:type_operator' => select::EQUAL_TO,
'badge:type_value' => BADGE_TYPE_COURSE,
], true],
'Filter badge type (no match)' => ['badge:type', [
'badge:type_operator' => select::EQUAL_TO,
'badge:type_value' => BADGE_TYPE_SITE,
], false],
// Badge tag.
'Filter tag name' => ['tag:name', [
'tag:name_operator' => tags::NOT_EMPTY,
], true],
'Filter tag name (no match)' => ['tag:name', [
'tag:name_operator' => tags::EQUAL_TO,
'tag:name_value' => [-1],
], false],
// User.
'Filter user fullname' => ['user:fullname', [
'user:fullname_operator' => text::IS_EQUAL_TO,
'user:fullname_value' => 'Zoe Zebra',
], true],
'Filter user fullname (no match)' => ['user:fullname', [
'user:fullname_operator' => text::IS_EQUAL_TO,
'user:fullname_value' => 'Alice Aardvark',
], false],
// Badge issued.
'Filter badge issued date' => ['badge_issued:issued', [
'badge_issued:issued_operator' => date::DATE_RANGE,
'badge_issued:issued_from' => 1622502000,
], true],
'Filter badge issued date (no match)' => ['badge_issued:issued', [
'badge_issued:issued_operator' => date::DATE_RANGE,
'badge_issued:issued_to' => 1622502000,
], false],
'Filter badge issued expires' => ['badge_issued:expires', [
'badge_issued:expires_operator' => date::DATE_RANGE,
'badge_issued:expires_from' => 1622502000,
], true],
'Filter badge issued expires (no match)' => ['badge_issued:expires', [
'badge_issued:expires_operator' => date::DATE_RANGE,
'badge_issued:expires_to' => 1622502000,
], false],
'Filter badge issued visible' => ['badge_issued:visible', [
'badge_issued:visible_operator' => boolean_select::CHECKED,
], true],
'Filter badge issued visible (no match)' => ['badge_issued:visible', [
'badge_issued:visible_operator' => boolean_select::NOT_CHECKED,
], false],
// Course.
'Filter course fullname' => ['course:fullname', [
'course:fullname_operator' => text::IS_EQUAL_TO,
'course:fullname_value' => 'Course 1',
], true],
'Filter course fullname (no match)' => ['course:fullname', [
'course:fullname_operator' => text::IS_EQUAL_TO,
'course:fullname_value' => 'Course 2',
], false],
];
}
/**
* Test datasource filters
*
* @param string $filtername
* @param array $filtervalues
* @param bool $expectmatch
*
* @dataProvider datasource_filters_provider
*/
public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course(['fullname' => 'Course 1']);
$user = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Zoe', 'lastname' => 'Zebra']);
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$badge = $generator->create_badge([
'name' => 'Course badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
'expireperiod' => HOURSECS,
'tags' => ['cool'],
]);
$badge->issue($user->id, true);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
// Create report containing single username column, and given filter.
$report = $generator->create_report(['name' => 'My report', 'source' => badges::class, 'default' => 0]);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:name']);
// Add filter, set it's values.
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
if ($expectmatch) {
$this->assertCount(1, $content);
$this->assertEquals($badge->name, reset($content[0]));
} else {
$this->assertEmpty($content);
}
}
/**

View File

@ -21,7 +21,7 @@ namespace core_badges\reportbuilder\datasource;
use core_badges_generator;
use core_reportbuilder_generator;
use core_reportbuilder_testcase;
use core_reportbuilder\local\filters\{boolean_select, date, select, text};
use core_reportbuilder\local\filters\{boolean_select, date, select, tags, text};
defined('MOODLE_INTERNAL') || die();
@ -94,10 +94,21 @@ class users_test extends core_reportbuilder_testcase {
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
($badgesite = $generator->create_badge(['name' => 'Badge 1', 'language' => 'de', 'expireperiod' => HOURSECS]))
->issue($user->id, true);
($badgecourse = $generator->create_badge(['name' => 'Badge 2', 'type' => BADGE_TYPE_COURSE, 'courseid' => $course->id]))
->issue($user->id, true);
$badgesite = $generator->create_badge([
'name' => 'Badge 1',
'language' => 'de',
'expireperiod' => HOURSECS,
'tags' => ['cool'],
]);
$badgecourse = $generator->create_badge([
'name' => 'Badge 2',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
]);
$badgesite->issue($user->id, true);
$badgecourse->issue($user->id, true);
// Create criteria for manually awarding by role.
$managerrole = $DB->get_field('role', 'id', ['shortname' => 'manager']);
@ -118,6 +129,8 @@ class users_test extends core_reportbuilder_testcase {
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:status']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:expiry']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'tag:name']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge_issued:expire']);
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge_issued:visible']);
@ -127,37 +140,49 @@ class users_test extends core_reportbuilder_testcase {
$this->assertCount(3, $content);
// Admin user, no badge issued.
[, , $criteria, $image, $language, $version, $status, $expiry, $expires, $visible, $coursename] = array_values($content[0]);
[$fullname, $badgename, $criteria, $image, $language, $version, $status, $expiry, $tag, $expires, $visible, $coursename]
= array_values($content[0]);
$this->assertEquals('Admin User', $fullname);
$this->assertEmpty($badgename);
$this->assertEmpty($criteria);
$this->assertEmpty($image);
$this->assertEmpty($language);
$this->assertEmpty($version);
$this->assertEmpty($status);
$this->assertEmpty($expiry);
$this->assertEmpty($tag);
$this->assertEmpty($expires);
$this->assertEmpty($visible);
$this->assertEmpty($coursename);
// Site badge issued.
[, , $criteria, $image, $language, $version, $status, $expiry, $expires, $visible, $coursename] = array_values($content[1]);
// User issued site badge.
[$fullname, $badgename, $criteria, $image, $language, $version, $status, $expiry, $tag, $expires, $visible, $coursename]
= array_values($content[1]);
$this->assertEquals(fullname($user), $fullname);
$this->assertEquals($badgesite->name, $badgename);
$this->assertStringContainsString('Awarded by: Manager', $criteria);
$this->assertStringContainsString('Image caption', $image);
$this->assertEquals('German', $language);
$this->assertEquals(2, $version);
$this->assertEquals('Available (criteria locked)', $status);
$this->assertEquals('1 hour', $expiry);
$this->assertEquals('cool', $tag);
$this->assertNotEmpty($expires);
$this->assertEquals('Yes', $visible);
$this->assertEquals('PHPUnit test site', $coursename);
// Course badge issued.
[, , $criteria, $image, $language, $version, $status, $expiry, $expires, $visible, $coursename] = array_values($content[2]);
// User issued site badge.
[$fullname, $badgename, $criteria, $image, $language, $version, $status, $expiry, $tag, $expires, $visible, $coursename]
= array_values($content[2]);
$this->assertEquals(fullname($user), $fullname);
$this->assertEquals($badgecourse->name, $badgename);
$this->assertEquals('Criteria for this badge have not been set up yet.', $criteria);
$this->assertStringContainsString('Image caption', $image);
$this->assertEquals('English', $language);
$this->assertEquals(2, $version);
$this->assertEquals('Available (criteria locked)', $status);
$this->assertEquals('Never', $expiry);
$this->assertEmpty($tag);
$this->assertEmpty($expires);
$this->assertEquals('Yes', $visible);
$this->assertEquals($course->fullname, $coursename);
@ -170,6 +195,16 @@ class users_test extends core_reportbuilder_testcase {
*/
public function datasource_filters_provider(): array {
return [
// User.
'Filter user fullname' => ['user:fullname', [
'user:fullname_operator' => text::IS_EQUAL_TO,
'user:fullname_value' => 'Zoe Zebra',
], true],
'Filter user fullname (no match)' => ['user:fullname', [
'user:fullname_operator' => text::IS_EQUAL_TO,
'user:fullname_value' => 'Alice Aardvark',
], false],
// Badge.
'Filter badge name' => ['badge:name', [
'badge:name_operator' => text::IS_EQUAL_TO,
@ -196,6 +231,15 @@ class users_test extends core_reportbuilder_testcase {
'badge:type_value' => BADGE_TYPE_SITE,
], false],
// Badge tag.
'Filter tag name' => ['tag:name', [
'tag:name_operator' => tags::NOT_EMPTY,
], true],
'Filter tag name (no match)' => ['tag:name', [
'tag:name_operator' => tags::EQUAL_TO,
'tag:name_value' => [-1],
], false],
// Badge issued.
'Filter badge issued date' => ['badge_issued:issued', [
'badge_issued:issued_operator' => date::DATE_RANGE,
@ -245,16 +289,18 @@ class users_test extends core_reportbuilder_testcase {
$this->resetAfterTest();
$course = $this->getDataGenerator()->create_course(['fullname' => 'Course 1']);
$user = $this->getDataGenerator()->create_and_enrol($course);
$user = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Zoe', 'lastname' => 'Zebra']);
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$generator->create_badge([
$badge = $generator->create_badge([
'name' => 'Course badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
'expireperiod' => HOURSECS,
])->issue($user->id, true);
'tags' => ['cool'],
]);
$badge->issue($user->id, true);
/** @var core_reportbuilder_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
@ -292,11 +338,8 @@ class users_test extends core_reportbuilder_testcase {
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$generator->create_badge([
'name' => 'Course badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
])->issue($user->id, true);
$badge = $generator->create_badge(['name' => 'Course badge', 'type' => BADGE_TYPE_COURSE, 'courseid' => $course->id]);
$badge->issue($user->id, true);
$this->datasource_stress_test_columns(users::class);
$this->datasource_stress_test_columns_aggregation(users::class);

View File

@ -305,17 +305,6 @@ class blog extends base {
* @return string[]
*/
public function get_tag_joins(): array {
$postalias = $this->get_table_alias('post');
$taginstancealias = $this->get_table_alias('tag_instance');
$tagalias = $this->get_table_alias('tag');
return [
"LEFT JOIN {tag_instance} {$taginstancealias}
ON {$taginstancealias}.component = 'core'
AND {$taginstancealias}.itemtype = 'post'
AND {$taginstancealias}.itemid = {$postalias}.id",
"LEFT JOIN {tag} {$tagalias}
ON {$tagalias}.id = {$taginstancealias}.tagid",
];
return $this->get_tag_joins_for_entity('core', 'post', $this->get_table_alias('post') . '.id');
}
}

View File

@ -167,6 +167,7 @@ $string['badgestatus_3'] = 'Available (criteria locked)';
$string['badgestatus_4'] = 'Archived';
$string['badgestoearn'] = 'Number of badges available: {$a}';
$string['badgesview'] = 'Course badges';
$string['badgetags'] = 'Badge tags';
$string['badgeurl'] = 'Issued badge link';
$string['bawards'] = 'Recipients ({$a})';
$string['bcriteria'] = 'Criteria';

View File

@ -215,6 +215,30 @@ abstract class base {
return array_values($this->joins);
}
/**
* Helper method for returning joins necessary for retrieving tags related to the current entity
*
* Both 'tag' and 'tag_instance' aliases must be returned by the entity {@see get_default_table_aliases} method
*
* @param string $component
* @param string $itemtype
* @param string $itemidfield
* @return string[]
*/
final protected function get_tag_joins_for_entity(string $component, string $itemtype, string $itemidfield): array {
$taginstancealias = $this->get_table_alias('tag_instance');
$tagalias = $this->get_table_alias('tag');
return [
"LEFT JOIN {tag_instance} {$taginstancealias}
ON {$taginstancealias}.component = '{$component}'
AND {$taginstancealias}.itemtype = '{$itemtype}'
AND {$taginstancealias}.itemid = {$itemidfield}",
"LEFT JOIN {tag} {$tagalias}
ON {$tagalias}.id = {$taginstancealias}.tagid",
];
}
/**
* Add a column to the entity
*

View File

@ -206,18 +206,7 @@ class course extends base {
* @return string[]
*/
public function get_tag_joins(): array {
$course = $this->get_table_alias('course');
$taginstance = $this->get_table_alias('tag_instance');
$tag = $this->get_table_alias('tag');
return [
"LEFT JOIN {tag_instance} {$taginstance}
ON {$taginstance}.component = 'core'
AND {$taginstance}.itemtype = 'course'
AND {$taginstance}.itemid = {$course}.id",
"LEFT JOIN {tag} {$tag}
ON {$tag}.id = {$taginstance}.tagid",
];
return $this->get_tag_joins_for_entity('core', 'course', $this->get_table_alias('course') . '.id');
}
/**

View File

@ -144,18 +144,7 @@ class user extends base {
* @return string[]
*/
public function get_tag_joins(): array {
$user = $this->get_table_alias('user');
$taginstance = $this->get_table_alias('tag_instance');
$tag = $this->get_table_alias('tag');
return [
"LEFT JOIN {tag_instance} {$taginstance}
ON {$taginstance}.component = 'core'
AND {$taginstance}.itemtype = 'user'
AND {$taginstance}.itemid = {$user}.id",
"LEFT JOIN {tag} {$tag}
ON {$tag}.id = {$taginstance}.tagid",
];
return $this->get_tag_joins_for_entity('core', 'user', $this->get_table_alias('user') . '.id');
}
/**

View File

@ -3,6 +3,7 @@ Information provided here is intended especially for developers.
=== 4.3 ===
* New `get_tag_joins_for_entity` helper in base entity class, for returning SQL joins necessary for retrieving tags
* New `set_is_deprecated` method in base `local\report\[column|filter]` classes to deprecate report entity columns and filters
* The following report entity columns have been deprecated, with replacements as follows:
- `enrolment:method` => `enrol:name` (plus enrolment formatter `enrolment_name` method)