mirror of
https://github.com/moodle/moodle.git
synced 2025-04-12 03:52:16 +02:00
Merge branch 'MDL-73842' of https://github.com/paulholden/moodle
This commit is contained in:
commit
fe08655918
@ -20,10 +20,12 @@ namespace core_reportbuilder\local\entities;
|
||||
|
||||
use context_course;
|
||||
use context_helper;
|
||||
use core_tag_tag;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\course_selector;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\helpers\custom_fields;
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
@ -58,6 +60,8 @@ class course extends base {
|
||||
return [
|
||||
'course' => 'c',
|
||||
'context' => 'cctx',
|
||||
'tag_instance' => 'ti',
|
||||
'tag' => 't',
|
||||
];
|
||||
}
|
||||
|
||||
@ -193,6 +197,26 @@ class course extends base {
|
||||
return $fieldtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return joins necessary for retrieving tags
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private 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",
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns.
|
||||
*
|
||||
@ -272,6 +296,22 @@ class course extends base {
|
||||
$columns[] = $column;
|
||||
}
|
||||
|
||||
// Tags.
|
||||
$tag = $this->get_table_alias('tag');
|
||||
$columns[] = (new column(
|
||||
'tags',
|
||||
new lang_string('tags'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_joins($this->get_tag_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$tag}.name, {$tag}.rawname")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function($value, stdClass $tag): string {
|
||||
return core_tag_tag::make_display_name($tag);
|
||||
});
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
@ -323,6 +363,22 @@ class course extends base {
|
||||
$filters[] = $filter;
|
||||
}
|
||||
|
||||
// Tags.
|
||||
$tag = $this->get_table_alias('tag');
|
||||
$filters[] = (new filter(
|
||||
tags::class,
|
||||
'tags',
|
||||
new lang_string('tags'),
|
||||
$this->get_entity_name(),
|
||||
"{$tag}.id"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_joins($this->get_tag_joins())
|
||||
->set_options([
|
||||
'component' => 'core',
|
||||
'itemtype' => 'course',
|
||||
]);
|
||||
|
||||
// We add our own custom course selector filter.
|
||||
$filters[] = (new filter(
|
||||
course_selector::class,
|
||||
|
@ -22,6 +22,7 @@ use context_helper;
|
||||
use context_system;
|
||||
use context_user;
|
||||
use core_component;
|
||||
use core_tag_tag;
|
||||
use html_writer;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
@ -30,6 +31,7 @@ use core_user\fields;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\user as user_filter;
|
||||
use core_reportbuilder\local\helpers\user_profile_fields;
|
||||
@ -57,6 +59,8 @@ class user extends base {
|
||||
return [
|
||||
'user' => 'u',
|
||||
'context' => 'uctx',
|
||||
'tag_instance' => 'ti',
|
||||
'tag' => 't',
|
||||
];
|
||||
}
|
||||
|
||||
@ -106,6 +110,26 @@ class user extends base {
|
||||
return $userprofilefields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return joins necessary for retrieving tags
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private 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",
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
@ -220,6 +244,22 @@ class user extends base {
|
||||
return !empty($row->id) ? $OUTPUT->user_picture($row, ['link' => false, 'alttext' => false]) : '';
|
||||
});
|
||||
|
||||
// Interests (tags).
|
||||
$tag = $this->get_table_alias('tag');
|
||||
$columns[] = (new column(
|
||||
'interests',
|
||||
new lang_string('interests'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_joins($this->get_tag_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_fields("{$tag}.name, {$tag}.rawname")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function($value, stdClass $tag): string {
|
||||
return core_tag_tag::make_display_name($tag);
|
||||
});
|
||||
|
||||
// Add all other user fields.
|
||||
$userfields = $this->get_user_fields();
|
||||
foreach ($userfields as $userfield => $userfieldlang) {
|
||||
@ -461,6 +501,22 @@ class user extends base {
|
||||
$filters[] = $filter;
|
||||
}
|
||||
|
||||
// Interests (tags).
|
||||
$tag = $this->get_table_alias('tag');
|
||||
$filters[] = (new filter(
|
||||
tags::class,
|
||||
'interests',
|
||||
new lang_string('interests'),
|
||||
$this->get_entity_name(),
|
||||
"{$tag}.id"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_joins($this->get_tag_joins())
|
||||
->set_options([
|
||||
'component' => 'core',
|
||||
'itemtype' => 'user',
|
||||
]);
|
||||
|
||||
// User select filter.
|
||||
$filters[] = (new filter(
|
||||
user_filter::class,
|
||||
|
133
reportbuilder/classes/local/filters/tags.php
Normal file
133
reportbuilder/classes/local/filters/tags.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?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\filters;
|
||||
|
||||
use coding_exception;
|
||||
use core_tag_tag;
|
||||
use lang_string;
|
||||
use MoodleQuickForm;
|
||||
use stdClass;
|
||||
use core_reportbuilder\local\helpers\database;
|
||||
|
||||
/**
|
||||
* Class containing logic for the tags filter
|
||||
*
|
||||
* The field SQL should be the field containing the ID of the {tag} table
|
||||
*
|
||||
* The following array properties must be passed to the {@see \core_reportbuilder\local\report\filter::set_options} method when
|
||||
* defining this filter, to define the component/itemtype you are using for tags:
|
||||
*
|
||||
* ['component' => 'core', 'itemtype' => 'user']
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @copyright 2022 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tags extends base {
|
||||
|
||||
/** @var int Any value */
|
||||
public const ANY_VALUE = 0;
|
||||
|
||||
/** @var int Tags are present */
|
||||
public const NOT_EMPTY = 1;
|
||||
|
||||
/** @var int Filter for selected tags */
|
||||
public const EQUAL_TO = 2;
|
||||
|
||||
/**
|
||||
* Returns an array of comparison operators
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_operators(): array {
|
||||
$operators = [
|
||||
self::ANY_VALUE => new lang_string('filterisanyvalue', 'core_reportbuilder'),
|
||||
self::NOT_EMPTY => new lang_string('filterisnotempty', 'core_reportbuilder'),
|
||||
self::EQUAL_TO => new lang_string('filterisequalto', 'core_reportbuilder'),
|
||||
];
|
||||
|
||||
return $this->filter->restrict_limited_operators($operators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup form
|
||||
*
|
||||
* @param MoodleQuickForm $mform
|
||||
* @throws coding_exception If component/itemtype options are missing
|
||||
*/
|
||||
public function setup_form(MoodleQuickForm $mform): void {
|
||||
global $DB;
|
||||
|
||||
$options = $this->filter->get_options();
|
||||
if (!array_key_exists('component', $options) || !array_key_exists('itemtype', $options)) {
|
||||
throw new coding_exception('Missing \'component\' and/or \'itemtype\' in filter options');
|
||||
}
|
||||
|
||||
$operatorlabel = get_string('filterfieldoperator', 'core_reportbuilder', $this->get_header());
|
||||
$mform->addElement('select', "{$this->name}_operator", $operatorlabel, $this->get_operators())
|
||||
->setHiddenLabel(true);
|
||||
|
||||
$sql = 'SELECT DISTINCT t.id, t.name, t.rawname
|
||||
FROM {tag} t
|
||||
JOIN {tag_instance} ti ON ti.tagid = t.id
|
||||
WHERE ti.component = :component AND ti.itemtype = :itemtype
|
||||
ORDER BY t.name';
|
||||
|
||||
// Transform tag records into appropriate display name, for selection in the autocomplete element.
|
||||
$tags = array_map(static function(stdClass $record): string {
|
||||
return core_tag_tag::make_display_name($record);
|
||||
}, $DB->get_records_sql($sql, ['component' => $options['component'], 'itemtype' => $options['itemtype']]));
|
||||
|
||||
$valuelabel = get_string('filterfieldvalue', 'core_reportbuilder', $this->get_header());
|
||||
$mform->addElement('autocomplete', "{$this->name}_value", $valuelabel, $tags, ['multiple' => true])
|
||||
->setHiddenLabel(true);
|
||||
$mform->hideIf("{$this->name}_value", "{$this->name}_operator", 'neq', self::EQUAL_TO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return filter SQL
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function get_sql_filter(array $values): array {
|
||||
global $DB;
|
||||
|
||||
$fieldsql = $this->filter->get_field_sql();
|
||||
$params = $this->filter->get_field_params();
|
||||
|
||||
$operator = (int) ($values["{$this->name}_operator"] ?? self::ANY_VALUE);
|
||||
$tags = (array) ($values["{$this->name}_value"] ?? []);
|
||||
|
||||
if ($operator === self::NOT_EMPTY) {
|
||||
$select = "{$fieldsql} IS NOT NULL";
|
||||
} else if ($operator === self::EQUAL_TO && !empty($tags)) {
|
||||
[$tagselect, $tagselectparams] = $DB->get_in_or_equal($tags, SQL_PARAMS_NAMED,
|
||||
database::generate_param_name() . '_');
|
||||
|
||||
$select = "{$fieldsql} {$tagselect}";
|
||||
$params = array_merge($params, $tagselectparams);
|
||||
} else {
|
||||
// Invalid/inactive (any value) filter..
|
||||
return ['', []];
|
||||
}
|
||||
|
||||
return [$select, $params];
|
||||
}
|
||||
}
|
@ -13,9 +13,9 @@ Feature: Manage custom report conditions
|
||||
| My report | user:fullname |
|
||||
| My report | user:email |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user01 | User | One | user01@example.com |
|
||||
| user02 | User | Two | user02@example.com |
|
||||
| username | firstname | lastname | email | interests |
|
||||
| user01 | User | One | user01@example.com | lionel, dancing |
|
||||
| user02 | User | Two | user02@example.com | |
|
||||
|
||||
Scenario: Add condition to report
|
||||
Given I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
@ -33,6 +33,20 @@ Feature: Manage custom report conditions
|
||||
And I should see "User One" in the "reportbuilder-table" "table"
|
||||
And I should not see "User Two" in the "reportbuilder-table" "table"
|
||||
|
||||
Scenario: Add tags condition to report
|
||||
Given the following "core_reportbuilder > Condition" exists:
|
||||
| report | My report |
|
||||
| uniqueidentifier | user:interests |
|
||||
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
|
||||
When I click on "Show/hide 'Conditions'" "button"
|
||||
And I set the following fields in the "Interests" "core_reportbuilder > Condition" to these values:
|
||||
| Interests operator | Is equal to |
|
||||
| Interests value | dancing |
|
||||
And I click on "Apply" "button" in the "[data-region='settings-conditions']" "css_element"
|
||||
Then I should see "Conditions applied"
|
||||
And I should see "User One" in the "reportbuilder-table" "table"
|
||||
And I should not see "User Two" in the "reportbuilder-table" "table"
|
||||
|
||||
Scenario: Move condition in report
|
||||
Given the following "core_reportbuilder > Conditions" exist:
|
||||
| report | uniqueidentifier |
|
||||
|
@ -27,6 +27,7 @@ use core_reportbuilder\manager;
|
||||
use core_reportbuilder\testable_system_report_table;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\helpers\user_filter_manager;
|
||||
@ -76,6 +77,7 @@ class course_test extends advanced_testcase {
|
||||
'calendartype' => 'Gregorian',
|
||||
'theme' => 'afterburner',
|
||||
'lang' => 'en',
|
||||
'tags' => ['dancing'],
|
||||
]);
|
||||
|
||||
$coursecategory2 = $this->getDataGenerator()->create_category();
|
||||
@ -154,6 +156,7 @@ class course_test extends advanced_testcase {
|
||||
$this->assertEquals('Gregorian', $courserow['calendartype']);
|
||||
$this->assertEquals('afterburner', $courserow['theme']);
|
||||
$this->assertEquals(get_string_manager()->get_list_of_translations()['en'], $courserow['lang']);
|
||||
$this->assertEquals('dancing', $courserow['tags']);
|
||||
$expected = '<a href="https://www.example.com/moodle/course/view.php?id=' . $course1->id . '">Course 1</a>';
|
||||
$this->assertEquals($expected, $courserow['coursefullnamewithlink']);
|
||||
$expected = '<a href="https://www.example.com/moodle/course/view.php?id=' . $course1->id . '">C1</a>';
|
||||
@ -171,6 +174,8 @@ class course_test extends advanced_testcase {
|
||||
* Test filtering report by course fields
|
||||
*/
|
||||
public function test_filters(): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
[$coursecategory1] = $this->generate_courses();
|
||||
@ -243,6 +248,15 @@ class course_test extends advanced_testcase {
|
||||
$this->assertEquals([
|
||||
'Course 1',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by tags field.
|
||||
$tablerows = $this->get_report_table_rows([
|
||||
'course:tags_operator' => tags::EQUAL_TO,
|
||||
'course:tags_value' => [
|
||||
$DB->get_field('tag', 'id', ['name' => 'dancing'], MUST_EXIST),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(['Course 1'], array_column($tablerows, 'fullname'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,7 @@ use core_reportbuilder\user_entity_report;
|
||||
use core_reportbuilder\local\filters\boolean_select;
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\tags;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\helpers\user_filter_manager;
|
||||
|
||||
@ -70,6 +71,7 @@ class user_test extends advanced_testcase {
|
||||
'suspended' => 1,
|
||||
'confirmed' => 0,
|
||||
'country' => 'ES',
|
||||
'interests' => ['dancing'],
|
||||
'profile_field_favcolor' => 'Blue',
|
||||
'profile_field_favsuperpower' => 'Time travel',
|
||||
]);
|
||||
@ -83,6 +85,7 @@ class user_test extends advanced_testcase {
|
||||
$this->assertEquals('Yes', $userrow['suspended']);
|
||||
$this->assertEquals('No', $userrow['confirmed']);
|
||||
$this->assertEquals('Spain', $userrow['country']);
|
||||
$this->assertEquals('dancing', $userrow['interests']);
|
||||
$this->assertEquals('Blue', $userrow['profilefield_favcolor']);
|
||||
$this->assertEquals('Time travel', $userrow['profilefield_favsuperpower']);
|
||||
}
|
||||
@ -138,10 +141,12 @@ class user_test extends advanced_testcase {
|
||||
* Test filtering report by user fields
|
||||
*/
|
||||
public function test_filters(): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->getDataGenerator()->create_user(['firstname' => 'Daffy', 'lastname' => 'Duck', 'email' => 'daffy@test.com',
|
||||
'city' => 'LA', 'lastaccess' => time() - YEARSECS, 'suspended' => 1]);
|
||||
'city' => 'LA', 'lastaccess' => time() - YEARSECS, 'suspended' => 1, 'interests' => ['dancing']]);
|
||||
$this->getDataGenerator()->create_user(['firstname' => 'Donald', 'lastname' => 'Duck', 'email' => 'donald@test.com',
|
||||
'city' => 'Chicago', 'lastaccess' => time(), 'suspended' => 0]);
|
||||
|
||||
@ -225,6 +230,15 @@ class user_test extends advanced_testcase {
|
||||
$this->assertEquals([
|
||||
'Daffy Duck',
|
||||
], array_column($tablerows, 'fullname'));
|
||||
|
||||
// Filter by interests (tags) field.
|
||||
$tablerows = $this->get_report_table_rows([
|
||||
'user:interests_operator' => tags::EQUAL_TO,
|
||||
'user:interests_value' => [
|
||||
$DB->get_field('tag', 'id', ['name' => 'dancing'], MUST_EXIST),
|
||||
],
|
||||
]);
|
||||
$this->assertEquals(['Daffy Duck'], array_column($tablerows, 'fullname'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
102
reportbuilder/tests/local/filters/tags_test.php
Normal file
102
reportbuilder/tests/local/filters/tags_test.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?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\filters;
|
||||
|
||||
use advanced_testcase;
|
||||
use lang_string;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
|
||||
/**
|
||||
* Unit tests for tags report filter
|
||||
*
|
||||
* @package core_reportbuilder
|
||||
* @covers \core_reportbuilder\local\filters\base
|
||||
* @covers \core_reportbuilder\local\filters\tags
|
||||
* @copyright 2022 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tags_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Data provider for {@see test_get_sql_filter}
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function get_sql_filter_provider(): array {
|
||||
return [
|
||||
'Any value' => [tags::ANY_VALUE, null, ['course01', 'course01', 'course02', 'course03']],
|
||||
'Not empty' => [tags::NOT_EMPTY, null, ['course01', 'course01', 'course02']],
|
||||
'Equal to unselected' => [tags::EQUAL_TO, null, ['course01', 'course01', 'course02', 'course03']],
|
||||
'Equal to selected tag' => [tags::EQUAL_TO, 'cat', ['course01']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting filter SQL
|
||||
*
|
||||
* @param int $operator
|
||||
* @param string|null $tagname
|
||||
* @param array $expectedcoursenames
|
||||
*
|
||||
* @dataProvider get_sql_filter_provider
|
||||
*/
|
||||
public function test_get_sql_filter(int $operator, ?string $tagname, array $expectedcoursenames): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$this->getDataGenerator()->create_course(['fullname' => 'course01', 'tags' => ['cat', 'dog']]);
|
||||
$this->getDataGenerator()->create_course(['fullname' => 'course02', 'tags' => ['fish']]);
|
||||
$this->getDataGenerator()->create_course(['fullname' => 'course03']);
|
||||
|
||||
$filter = (new filter(
|
||||
tags::class,
|
||||
'tags',
|
||||
new lang_string('tags'),
|
||||
'testentity',
|
||||
't.id'
|
||||
));
|
||||
|
||||
// Create instance of our filter, passing ID of the tag if specified.
|
||||
if ($tagname !== null) {
|
||||
$tagid = $DB->get_field('tag', 'id', ['name' => $tagname], MUST_EXIST);
|
||||
$value = [$tagid];
|
||||
} else {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
[$select, $params] = tags::create($filter)->get_sql_filter([
|
||||
$filter->get_unique_identifier() . '_operator' => $operator,
|
||||
$filter->get_unique_identifier() . '_value' => $value,
|
||||
]);
|
||||
|
||||
$sql = 'SELECT c.fullname
|
||||
FROM {course} c
|
||||
LEFT JOIN {tag_instance} ti ON ti.itemid = c.id
|
||||
LEFT JOIN {tag} t ON t.id = ti.tagid
|
||||
WHERE c.id != ' . SITEID;
|
||||
|
||||
if ($select) {
|
||||
$sql .= " AND {$select}";
|
||||
}
|
||||
|
||||
$courses = $DB->get_fieldset_sql($sql, $params);
|
||||
$this->assertEqualsCanonicalizing($expectedcoursenames, $courses);
|
||||
}
|
||||
}
|
@ -19,3 +19,4 @@ Information provided here is intended especially for developers.
|
||||
- `[require_]can_create_report`
|
||||
* New method `get_default_condition_values()` in base datasource class, to be overridden by sources that wish to
|
||||
define default values for conditions upon report creation.
|
||||
* New `tags` filter type for reports that contain entities with support for core_tag API
|
||||
|
Loading…
x
Reference in New Issue
Block a user