MDL-83941 tags: prevent users from browsing unsearchable collections

This commit is contained in:
Marina Glancy
2025-02-04 02:40:20 +00:00
committed by Jenkins
parent fac52f6f86
commit 142012d312
4 changed files with 89 additions and 15 deletions
+3 -13
View File
@@ -77,24 +77,14 @@ class block_tags_edit_form extends block_edit_form {
* @param object $mform the form being built.
*/
protected function add_collection_selector($mform) {
$tagcolls = core_tag_collection::get_collections_menu(false, false, get_string('anycollection', 'block_tags'));
$tagcolls = core_tag_collection::get_collections_menu(false, true, get_string('anycollection', 'block_tags'));
if (count($tagcolls) <= 1) {
$mform->addElement('hidden', 'config_tagcoll', 0);
$mform->setType('config_tagcoll', PARAM_INT);
return;
}
$tagcollssearchable = core_tag_collection::get_collections_menu(false, true);
$hasunsearchable = false;
foreach ($tagcolls as $id => $name) {
if ($id && !array_key_exists($id, $tagcollssearchable)) {
$hasunsearchable = true;
$tagcolls[$id] = $name . '*';
}
}
$mform->addElement('select', 'config_tagcoll', get_string('tagcollection', 'block_tags'), $tagcolls);
if ($hasunsearchable) {
$mform->addHelpButton('config_tagcoll', 'tagcollection', 'block_tags');
}
$mform->setDefault('config_tagcoll', 0);
}
}
+30
View File
@@ -47,3 +47,33 @@ Feature: Block tags displaying tag cloud
And I should see "User interests" in the ".tag-index-items h3" "css_element"
And I should see "Teacher 1"
And I log out
@javascript
Scenario: Tag block configuration allows to select from searchable tag collections only
When I log in as "student1"
And I turn editing mode on
And I add the "Tags" block
And I configure the "Tags" block
Then I should not see "Tag collection"
And I press "Save changes"
And I log out
And I log in as "admin"
And I navigate to "Appearance > Manage tags" in site administration
And I follow "Add tag collection"
And I set the following fields to these values:
| Name | Collection1 |
| Searchable | 1 |
And I press "Create"
And I follow "Add tag collection"
And I set the following fields to these values:
| Name | Collection2 |
| Searchable | 0 |
And I press "Create"
And I log out
And I log in as "student1"
And I turn editing mode on
And I am on homepage
And I configure the "Tags" block
And the "Tag collection" select box should contain "Collection1"
And the "Tag collection" select box should not contain "Collection2"
And I press "Save changes"
+8 -2
View File
@@ -359,9 +359,15 @@ class core_tag_collection {
$fromclause = 'FROM {tag_instance} ti JOIN {tag} tg ON tg.id = ti.tagid';
$whereclause = 'WHERE ti.itemtype <> \'tag\'';
list($sql, $params) = $DB->get_in_or_equal($tagcollid ? array($tagcollid) :
array_keys(self::get_collections(true)));
// Get tags from all searchable tag collections, if $tagcollid is specifid, limit only to this collection.
$tagcollids = array_keys(self::get_collections(true));
if ($tagcollid) {
$tagcollids = array_intersect($tagcollids, [$tagcollid]);
}
list($sql, $params) = $DB->get_in_or_equal($tagcollids, SQL_PARAMS_QM, 'param', true, -1);
$whereclause .= ' AND tg.tagcollid ' . $sql;
if ($isstandard) {
$whereclause .= ' AND tg.isstandard = 1';
}
+48
View File
@@ -19,6 +19,7 @@ namespace core_tag;
use core_tag_area;
use core_tag_collection;
use core_tag_tag;
use core_tag;
/**
* Tag related unit tests.
@@ -1940,4 +1941,51 @@ final class taglib_test extends \advanced_testcase {
$record['id'] = $DB->insert_record('tag_instance', $record);
return (object) $record;
}
/**
* Checks the contents of the a tagcloud
*
* @param array $tags
* @param \core_tag\output\tagcloud $tagcloud
*/
protected function assert_tag_cloud_contains_tags(array $tags, \core_tag\output\tagcloud $tagcloud) {
global $PAGE;
$renderer = $PAGE->get_renderer('core', 'tag');
$result = $tagcloud->export_for_template($renderer);
$result = json_decode(json_encode($result), true);
$this->assertEqualsCanonicalizing($tags, array_values(array_column($result['tags'], 'name')));
}
public function test_get_tag_cloud(): void {
global $DB, $PAGE;
$this->resetAfterTest();
// Create a course and a user with tags.
$this->getDataGenerator()->create_course(['tags' => 'cats,animals']);
$this->getDataGenerator()->create_user(['interests' => 'dogs,animals']);
// Default tag cloud contains all three tags.
$tagcloud = core_tag_collection::get_tag_cloud(0);
$this->assert_tag_cloud_contains_tags(['animals', 'cats', 'dogs'], $tagcloud);
// Create two new tag collections, move course tags to C1 and user tags to C2.
$c1 = core_tag_collection::create((object)['name' => 'C1', 'searchable' => 1]);
$c2 = core_tag_collection::create((object)['name' => 'C2', 'searchable' => 1]);
$tagareacourse = $DB->get_record('tag_area', ['component' => 'core', 'itemtype' => 'course'], '*', MUST_EXIST);
core_tag_area::update($tagareacourse, ['tagcollid' => $c1->id]);
$tagareauser = $DB->get_record('tag_area', ['component' => 'core', 'itemtype' => 'user'], '*', MUST_EXIST);
core_tag_area::update($tagareauser, ['tagcollid' => $c2->id]);
// Tag cloud still has all tags and you can also search by a collection. Tag 'animals' now has two different view links.
$this->assert_tag_cloud_contains_tags(['animals', 'animals', 'cats', 'dogs'], core_tag_collection::get_tag_cloud(0));
$this->assert_tag_cloud_contains_tags(['animals', 'cats'], core_tag_collection::get_tag_cloud($c1->id));
$this->assert_tag_cloud_contains_tags(['animals', 'dogs'], core_tag_collection::get_tag_cloud($c2->id));
// Make user interest tag area not searchable.
core_tag_collection::update($c2, ['searchable' => 0]);
// Check that the user interest tags do not appear in the tagclouds.
$this->assert_tag_cloud_contains_tags(['animals', 'cats'], core_tag_collection::get_tag_cloud(0));
$this->assert_tag_cloud_contains_tags(['animals', 'cats'], core_tag_collection::get_tag_cloud($c1->id));
$this->assert_tag_cloud_contains_tags([], core_tag_collection::get_tag_cloud($c2->id));
}
}