Merge branch 'wip-MDL-57456-master' of git://github.com/marinaglancy/moodle

This commit is contained in:
David Monllao 2017-04-19 15:42:29 +08:00
commit c2118c8902
21 changed files with 424 additions and 9 deletions

View File

@ -53,6 +53,9 @@ class backup_glossary_activity_structure_step extends backup_activity_structure_
'teacherentry', 'sourceglossaryid', 'usedynalink', 'casesensitive',
'fullmatch', 'approved'));
$tags = new backup_nested_element('entriestags');
$tag = new backup_nested_element('tag', array('id'), array('itemid', 'rawname'));
$aliases = new backup_nested_element('aliases');
$alias = new backup_nested_element('alias', array('id'), array(
@ -77,6 +80,9 @@ class backup_glossary_activity_structure_step extends backup_activity_structure_
$glossary->add_child($entries);
$entries->add_child($entry);
$glossary->add_child($tags);
$tags->add_child($tag);
$entry->add_child($aliases);
$aliases->add_child($alias);
@ -108,6 +114,18 @@ class backup_glossary_activity_structure_step extends backup_activity_structure_
$rating->set_source_alias('rating', 'value');
$categoryentry->set_source_table('glossary_entries_categories', array('categoryid' => backup::VAR_PARENTID));
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
$tag->set_source_sql('SELECT t.id, ti.itemid, t.rawname
FROM {tag} t
JOIN {tag_instance} ti ON ti.tagid = t.id
WHERE ti.itemtype = ?
AND ti.component = ?
AND ti.contextid = ?', array(
backup_helper::is_sqlparam('glossary_entries'),
backup_helper::is_sqlparam('mod_glossary'),
backup::VAR_CONTEXTID));
}
}
// Define id annotations

View File

@ -40,6 +40,7 @@ class restore_glossary_activity_structure_step extends restore_activity_structur
$paths[] = new restore_path_element('glossary_category', '/activity/glossary/categories/category');
if ($userinfo) {
$paths[] = new restore_path_element('glossary_entry', '/activity/glossary/entries/entry');
$paths[] = new restore_path_element('glossary_entry_tag', '/activity/glossary/entriestags/tag');
$paths[] = new restore_path_element('glossary_alias', '/activity/glossary/entries/entry/aliases/alias');
$paths[] = new restore_path_element('glossary_rating', '/activity/glossary/entries/entry/ratings/rating');
$paths[] = new restore_path_element('glossary_category_entry',
@ -134,6 +135,23 @@ class restore_glossary_activity_structure_step extends restore_activity_structur
$newitemid = $DB->insert_record('rating', $data);
}
protected function process_glossary_entry_tag($data) {
$data = (object)$data;
if (!core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) { // Tags disabled in server, nothing to process.
return;
}
$tag = $data->rawname;
if (!$itemid = $this->get_mappingid('glossary_entry', $data->itemid)) {
// Some orphaned tag, we could not find the glossary entry for it - ignore.
return;
}
$context = context_module::instance($this->task->get_moduleid());
core_tag_tag::add_item_tag('mod_glossary', 'glossary_entries', $itemid, $context, $tag);
}
protected function process_glossary_category($data) {
global $DB;

35
mod/glossary/db/tag.php Normal file
View File

@ -0,0 +1,35 @@
<?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/>.
/**
* Tag areas in component mod_glossary
*
* @package mod_glossary
* @copyright 2017 Andrew Hancox <andrewdchancox@googlemail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$tagareas = array(
array(
'itemtype' => 'glossary_entries',
'component' => 'mod_glossary',
'callback' => 'mod_glossary_get_tagged_entries',
'callbackfile' => '/mod/glossary/locallib.php',
),
);

View File

@ -120,6 +120,8 @@ if ($confirm and confirm_sesskey()) { // the operation was confirmed.
glossary_rss_delete_file($glossary);
}
core_tag_tag::remove_all_item_tags('mod_glossary', 'glossary_entries', $origentry->id);
$event = \mod_glossary\event\entry_deleted::create(array(
'context' => $context,
'objectid' => $origentry->id,

View File

@ -81,8 +81,11 @@ if ($mform->is_cancelled()){
redirect("view.php?id=$cm->id");
}
} else if ($entry = $mform->get_data()) {
$entry = glossary_edit_entry($entry, $course, $cm, $glossary, $context);
} else if ($data = $mform->get_data()) {
$entry = glossary_edit_entry($data, $course, $cm, $glossary, $context);
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries') && isset($data->tags)) {
core_tag_tag::set_item_tags('mod_glossary', 'glossary_entries', $data->id, $context, $data->tags);
}
redirect("view.php?id=$cm->id&mode=entry&hook=$entry->id");
}
@ -98,6 +101,10 @@ if ($glossary->intro) {
echo $OUTPUT->box(format_module_intro('glossary', $glossary, $cm->id), 'generalbox', 'intro');
}
$data = new StdClass();
$data->tags = core_tag_tag::get_item_tags_array('mod_glossary', 'glossary_entries', $id);
$mform->set_data($data);
$mform->display();
echo $OUTPUT->footer();

View File

@ -78,6 +78,13 @@ class mod_glossary_entry_form extends moodleform {
$mform->setDefault('fullmatch', $CFG->glossary_fullmatch);
}
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
$mform->addElement('header', 'tagshdr', get_string('tags', 'tag'));
$mform->addElement('tags', 'tags', get_string('tags'),
array('itemtype' => 'glossary_entries', 'component' => 'mod_glossary'));
}
$mform->addElement('hidden', 'id');
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'cmid');

View File

@ -2,7 +2,7 @@
function glossary_show_entry_continuous($course, $cm, $glossary, $entry, $mode='', $hook='', $printicons=1, $aliases=false) {
global $USER;
global $USER, $OUTPUT;
echo '<table class="glossarypost continuous" cellspacing="0">';
echo '<tr valign="top">';
@ -13,6 +13,11 @@ function glossary_show_entry_continuous($course, $cm, $glossary, $entry, $mode='
echo '</div> ';
glossary_print_entry_definition($entry, $glossary, $cm);
glossary_print_entry_attachment($entry, $cm, 'html');
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
echo $OUTPUT->tag_list(core_tag_tag::get_item_tags(
'mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
$entry->alias = '';
echo '</td></tr>';

View File

@ -2,7 +2,7 @@
function glossary_show_entry_dictionary($course, $cm, $glossary, $entry, $mode='', $hook='', $printicons=1, $aliases=true) {
global $CFG, $USER;
global $CFG, $USER, $OUTPUT;
echo '<table class="glossarypost dictionary" cellspacing="0">';
echo '<tr valign="top">';
@ -13,6 +13,9 @@ function glossary_show_entry_dictionary($course, $cm, $glossary, $entry, $mode='
echo '</div> ';
glossary_print_entry_definition($entry, $glossary, $cm);
glossary_print_entry_attachment($entry, $cm, 'html');
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
echo $OUTPUT->tag_list(core_tag_tag::get_item_tags('mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
echo '</td></tr>';
echo '<tr valign="top"><td class="entrylowersection">';
glossary_print_entry_lower_section($course, $cm, $glossary, $entry, $mode, $hook, $printicons, $aliases);

View File

@ -40,6 +40,10 @@ function glossary_show_entry_encyclopedia($course, $cm, $glossary, $entry, $mode
glossary_print_entry_definition($entry, $glossary, $cm);
glossary_print_entry_attachment($entry, $cm, null);
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
echo $OUTPUT->tag_list(
core_tag_tag::get_item_tags('mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
if ($printicons or $aliases) {
echo '</td></tr>';

View File

@ -1,7 +1,7 @@
<?php
function glossary_show_entry_faq($course, $cm, $glossary, $entry, $mode="", $hook="", $printicons=1, $aliases=true) {
global $USER;
global $USER, $OUTPUT;
if ( $entry ) {
echo '<table class="glossarypost faq" cellspacing="0">';
@ -31,6 +31,11 @@ function glossary_show_entry_faq($course, $cm, $glossary, $entry, $mode="", $hoo
glossary_print_entry_definition($entry, $glossary, $cm);
glossary_print_entry_attachment($entry, $cm, 'html');
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
echo $OUTPUT->tag_list(
core_tag_tag::get_item_tags('mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
echo '</td></tr>';
echo '<tr valign="top"><td colspan="3" class="entrylowersection">';
glossary_print_entry_lower_section($course, $cm, $glossary, $entry, $mode, $hook, $printicons, $aliases);

View File

@ -42,6 +42,11 @@ function glossary_show_entry_fullwithauthor($course, $cm, $glossary, $entry, $mo
glossary_print_entry_definition($entry, $glossary, $cm);
glossary_print_entry_attachment($entry, $cm, 'html');
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
echo $OUTPUT->tag_list(
core_tag_tag::get_item_tags('mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
echo '</td></tr>';
echo '<tr valign="top">';
echo '<td class="left">&nbsp;</td>';

View File

@ -1,7 +1,7 @@
<?php
function glossary_show_entry_fullwithoutauthor($course, $cm, $glossary, $entry, $mode="", $hook="", $printicons=1, $aliases=true) {
global $CFG, $USER;
global $CFG, $USER, $OUTPUT;
if ($entry) {
@ -30,6 +30,11 @@ function glossary_show_entry_fullwithoutauthor($course, $cm, $glossary, $entry,
glossary_print_entry_definition($entry, $glossary, $cm);
glossary_print_entry_attachment($entry, $cm, 'html');
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
echo $OUTPUT->tag_list(
core_tag_tag::get_item_tags('mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
echo '</td></tr>';
echo '<tr valign="top"><td colspan="2" class="entrylowersection">';
glossary_print_entry_lower_section($course, $cm, $glossary, $entry, $mode, $hook, $printicons, $aliases);

View File

@ -269,6 +269,7 @@ $string['printviewnotallowed'] = 'Print view isn\'t allowed';
$string['question'] = 'Question';
$string['rejectedentries'] = 'Rejected entries';
$string['rejectionrpt'] = 'Rejection report';
$string['removeallglossarytags'] = 'Remove all glossary tags';
$string['resetglossaries'] = 'Delete entries from';
$string['resetglossariesall'] = 'Delete entries from all glossaries';
$string['rssarticles'] = 'Number of RSS recent articles';
@ -293,6 +294,9 @@ $string['sortchronogically'] = 'Sort chronologically';
$string['special'] = 'Special';
$string['standardview'] = 'Browse by alphabet';
$string['studentcanpost'] = 'Students can add entries';
$string['tagarea_glossary_entries'] = 'Glossary entries';
$string['tagsdeleted'] = 'Glossary tags have been deleted';
$string['tagtitle'] = 'See the "{$a}" tag';
$string['totalentries'] = 'Total entries';
$string['usedynalink'] = 'Automatically link glossary entries';
$string['usedynalink_help'] = 'If site-wide glossary auto-linking has been enabled by an administrator and this setting is enabled, the "Add a new entry" form includes the option to automatically link the entry wherever the concept words and phrases appear throughout the rest of the course.';

View File

@ -2173,7 +2173,7 @@ function glossary_print_entry_ratings($course, $entry) {
* @param int $displayformat
*/
function glossary_print_dynaentry($courseid, $entries, $displayformat = -1) {
global $USER,$CFG, $DB;
global $USER, $CFG, $DB, $OUTPUT;
echo '<div class="boxaligncenter">';
echo '<table class="glossarypopup" cellspacing="0"><tr>';

View File

@ -635,3 +635,118 @@ class glossary_file_info_container extends file_info {
return $this->browser->get_file_info($this->context);
}
}
/**
* Returns glossary entries tagged with a specified tag.
*
* This is a callback used by the tag area mod_glossary/glossary_entries to search for glossary entries
* tagged with a specific tag.
*
* @param core_tag_tag $tag
* @param bool $exclusivemode if set to true it means that no other entities tagged with this tag
* are displayed on the page and the per-page limit may be bigger
* @param int $fromctx context id where the link was displayed, may be used by callbacks
* to display items in the same context first
* @param int $ctx context id where to search for records
* @param bool $rec search in subcontexts as well
* @param int $page 0-based number of page being displayed
* @return \core_tag\output\tagindex
*/
function mod_glossary_get_tagged_entries($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0) {
global $OUTPUT;
$perpage = $exclusivemode ? 20 : 5;
// Build the SQL query.
$ctxselect = context_helper::get_preload_record_columns_sql('ctx');
$query = "SELECT ge.id, ge.concept, ge.glossaryid, ge.approved,
cm.id AS cmid, c.id AS courseid, c.shortname, c.fullname, $ctxselect
FROM {glossary_entries} ge
JOIN {glossary} g ON g.id = ge.glossaryid
JOIN {modules} m ON m.name='glossary'
JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = g.id
JOIN {tag_instance} tt ON ge.id = tt.itemid
JOIN {course} c ON cm.course = c.id
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :coursemodulecontextlevel
WHERE tt.itemtype = :itemtype AND tt.tagid = :tagid AND tt.component = :component
AND cm.deletioninprogress = 0
AND ge.id %ITEMFILTER% AND c.id %COURSEFILTER%";
$params = array('itemtype' => 'glossary_entries', 'tagid' => $tag->id, 'component' => 'mod_glossary',
'coursemodulecontextlevel' => CONTEXT_MODULE);
if ($ctx) {
$context = $ctx ? context::instance_by_id($ctx) : context_system::instance();
$query .= $rec ? ' AND (ctx.id = :contextid OR ctx.path LIKE :path)' : ' AND ctx.id = :contextid';
$params['contextid'] = $context->id;
$params['path'] = $context->path.'/%';
}
$query .= " ORDER BY ";
if ($fromctx) {
// In order-clause specify that modules from inside "fromctx" context should be returned first.
$fromcontext = context::instance_by_id($fromctx);
$query .= ' (CASE WHEN ctx.id = :fromcontextid OR ctx.path LIKE :frompath THEN 0 ELSE 1 END),';
$params['fromcontextid'] = $fromcontext->id;
$params['frompath'] = $fromcontext->path.'/%';
}
$query .= ' c.sortorder, cm.id, ge.id';
$totalpages = $page + 1;
// Use core_tag_index_builder to build and filter the list of items.
$builder = new core_tag_index_builder('mod_glossary', 'glossary_entries', $query, $params, $page * $perpage, $perpage + 1);
while ($item = $builder->has_item_that_needs_access_check()) {
context_helper::preload_from_record($item);
$courseid = $item->courseid;
if (!$builder->can_access_course($courseid)) {
$builder->set_accessible($item, false);
continue;
}
$modinfo = get_fast_modinfo($builder->get_course($courseid));
// Set accessibility of this item and all other items in the same course.
$builder->walk(function ($taggeditem) use ($courseid, $modinfo, $builder) {
if ($taggeditem->courseid == $courseid) {
$accessible = false;
if (($cm = $modinfo->get_cm($taggeditem->cmid)) && $cm->uservisible) {
if ($taggeditem->approved) {
$accessible = true;
} else {
$accessible = has_capability('mod/glossary:approve', context_module::instance($cm->id));
}
}
$builder->set_accessible($taggeditem, $accessible);
}
});
}
$items = $builder->get_items();
if (count($items) > $perpage) {
$totalpages = $page + 2; // We don't need exact page count, just indicate that the next page exists.
array_pop($items);
}
// Build the display contents.
if ($items) {
$tagfeed = new core_tag\output\tagfeed();
foreach ($items as $item) {
context_helper::preload_from_record($item);
$modinfo = get_fast_modinfo($item->courseid);
$cm = $modinfo->get_cm($item->cmid);
$pageurl = new moodle_url('/mod/glossary/showentry.php', array('eid' => $item->id, 'displayformat' => 'dictionary'));
$pagename = format_string($item->concept, true, array('context' => context_module::instance($item->cmid)));
$pagename = html_writer::link($pageurl, $pagename);
$courseurl = course_get_url($item->courseid, $cm->sectionnum);
$cmname = html_writer::link($cm->url, $cm->get_formatted_name());
$coursename = format_string($item->fullname, true, array('context' => context_course::instance($item->courseid)));
$coursename = html_writer::link($courseurl, $coursename);
$icon = html_writer::link($pageurl, html_writer::empty_tag('img', array('src' => $cm->get_icon_url())));
$tagfeed->add($icon, $pagename, $cmname.'<br>'.$coursename);
}
$content = $OUTPUT->render_from_template('core_tag/tagfeed',
$tagfeed->export_for_template($OUTPUT));
return new core_tag\output\tagindex($tag, 'mod_glossary', 'glossary_entries', $content,
$exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
}
}

View File

@ -73,6 +73,11 @@ if ($entries) {
$options->context = $context;
$entries[$key]->definition = format_text($definition, $entry->definitionformat, $options);
if (core_tag_tag::is_enabled('mod_glossary', 'glossary_entries')) {
$entries[$key]->definition .= $OUTPUT->tag_list(
core_tag_tag::get_item_tags('mod_glossary', 'glossary_entries', $entry->id), null, 'glossary-tags');
}
$entries[$key]->attachments = '';
if (!empty($entries[$key]->attachment)) {
$attachments = glossary_print_attachments($entry, $cm, 'html');

View File

@ -0,0 +1,76 @@
@mod @mod_glossary @core_tag @javascript
Feature: Edited glossary entries handle tags correctly
In order to get glossary entries properly labelled
As a user
I need to introduce the tags while editing
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And I log in as "teacher1"
And I follow "Course 1"
And I turn editing mode on
And I add a "Glossary" to section "1" and I fill the form with:
| Name | Test glossary |
| Description | A glossary about dreams! |
And I log out
Scenario: Glossary entry edition of custom tags works as expected
Given I log in as "teacher1"
And I follow "Course 1"
And I follow "Test glossary"
And I press "Add a new entry"
And I set the following fields to these values:
| Concept | Dummy first entry |
| Definition | Dream is the start of a journey |
| Tags | Example, Entry, Cool |
And I press "Save changes"
Then I should see "Example" in the ".glossary-tags" "css_element"
And I should see "Entry" in the ".glossary-tags" "css_element"
And I should see "Cool" in the ".glossary-tags" "css_element"
And I click on "Edit" "link" in the ".entrylowersection" "css_element"
And I expand all fieldsets
Then I should see "Example" in the ".form-autocomplete-selection" "css_element"
Then I should see "Entry" in the ".form-autocomplete-selection" "css_element"
Then I should see "Cool" in the ".form-autocomplete-selection" "css_element"
@javascript
Scenario: Glossary entry edition of standard tags works as expected
Given I log in as "admin"
And I navigate to "Appearance > Manage tags" in site administration
And I follow "Default collection"
And I follow "Add standard tags"
And I set the field "Enter comma-separated list of new tags" to "OT1, OT2, OT3"
And I press "Continue"
And I log out
And I log in as "teacher1"
And I follow "Course 1"
And I follow "Test glossary"
And I press "Add a new entry"
And I expand all fieldsets
And I click on ".form-autocomplete-downarrow" "css_element"
And I should see "OT1" in the ".form-autocomplete-suggestions" "css_element"
And I should see "OT2" in the ".form-autocomplete-suggestions" "css_element"
And I should see "OT3" in the ".form-autocomplete-suggestions" "css_element"
When I set the following fields to these values:
| Concept | Dummy first entry |
| Definition | Dream is the start of a journey |
| Tags | OT1, OT3 |
And I press "Save changes"
Then I should see "OT1" in the ".glossary-tags" "css_element"
And I should see "OT3" in the ".glossary-tags" "css_element"
And I should not see "OT2" in the ".glossary-tags" "css_element"
And I click on "Edit" "link" in the ".entrylowersection" "css_element"
And I expand all fieldsets
And I should see "OT1" in the ".form-autocomplete-selection" "css_element"
And I should see "OT3" in the ".form-autocomplete-selection" "css_element"
And I should not see "OT2" in the ".form-autocomplete-selection" "css_element"

View File

@ -145,6 +145,13 @@ class mod_glossary_generator extends testing_module_generator {
}
}
if (array_key_exists('tags', $record)) {
$tags = is_array($record['tags']) ? $record['tags'] : preg_split('/,/', $record['tags']);
core_tag_tag::set_item_tags('mod_glossary', 'glossary_entries', $id,
context_module::instance($glossary->cmid), $tags);
}
return $DB->get_record('glossary_entries', array('id' => $id), '*', MUST_EXIST);
}
}

View File

@ -64,12 +64,15 @@ class mod_glossary_generator_testcase extends advanced_testcase {
$glossarygenerator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
$entry1 = $glossarygenerator->create_content($glossary);
$entry2 = $glossarygenerator->create_content($glossary, array('concept' => 'Custom concept'), array('alias1', 'alias2'));
$entry2 = $glossarygenerator->create_content($glossary,
array('concept' => 'Custom concept', 'tags' => array('Cats', 'mice')), array('alias1', 'alias2'));
$records = $DB->get_records('glossary_entries', array('glossaryid' => $glossary->id), 'id');
$this->assertCount(2, $records);
$this->assertEquals($entry1->id, $records[$entry1->id]->id);
$this->assertEquals($entry2->id, $records[$entry2->id]->id);
$this->assertEquals('Custom concept', $records[$entry2->id]->concept);
$this->assertEquals(array('Cats', 'mice'),
array_values(core_tag_tag::get_item_tags_array('mod_glossary', 'glossary_entries', $entry2->id)));
$aliases = $DB->get_records_menu('glossary_alias', array('entryid' => $entry2->id), 'id ASC', 'id, alias');
$this->assertSame(array('alias1', 'alias2'), array_values($aliases));

View File

@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/glossary/lib.php');
require_once($CFG->dirroot . '/mod/glossary/locallib.php');
/**
* Glossary lib testcase.
@ -232,4 +233,94 @@ class mod_glossary_lib_testcase extends advanced_testcase {
$this->assertEquals(mod_glossary_get_completion_active_rule_descriptions($moddefaults), $activeruledescriptions);
$this->assertEquals(mod_glossary_get_completion_active_rule_descriptions(new stdClass()), []);
}
public function test_mod_glossary_get_tagged_entries() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$glossarygenerator = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
$course3 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course1 = $this->getDataGenerator()->create_course();
$glossary1 = $this->getDataGenerator()->create_module('glossary', array('course' => $course1->id));
$glossary2 = $this->getDataGenerator()->create_module('glossary', array('course' => $course2->id));
$glossary3 = $this->getDataGenerator()->create_module('glossary', array('course' => $course3->id));
$entry11 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats', 'Dogs')));
$entry12 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats', 'mice')));
$entry13 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats')));
$entry14 = $glossarygenerator->create_content($glossary1);
$entry15 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats')));
$entry16 = $glossarygenerator->create_content($glossary1, array('tags' => array('Cats'), 'approved' => false));
$entry21 = $glossarygenerator->create_content($glossary2, array('tags' => array('Cats')));
$entry22 = $glossarygenerator->create_content($glossary2, array('tags' => array('Cats', 'Dogs')));
$entry23 = $glossarygenerator->create_content($glossary2, array('tags' => array('mice', 'Cats')));
$entry31 = $glossarygenerator->create_content($glossary3, array('tags' => array('mice', 'Cats')));
$tag = core_tag_tag::get_by_name(0, 'Cats');
// Admin can see everything.
$res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$entry = */0);
$this->assertRegExp('/'.$entry11->concept.'</', $res->content);
$this->assertRegExp('/'.$entry12->concept.'</', $res->content);
$this->assertRegExp('/'.$entry13->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry14->concept.'</', $res->content);
$this->assertRegExp('/'.$entry15->concept.'</', $res->content);
$this->assertRegExp('/'.$entry16->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry21->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry22->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry23->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry31->concept.'</', $res->content);
$this->assertEmpty($res->prevpageurl);
$this->assertNotEmpty($res->nextpageurl);
$res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$entry = */1);
$this->assertNotRegExp('/'.$entry11->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry12->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry13->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry14->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry15->concept.'</', $res->content);
$this->assertNotRegExp('/'.$entry16->concept.'</', $res->content);
$this->assertRegExp('/'.$entry21->concept.'</', $res->content);
$this->assertRegExp('/'.$entry22->concept.'</', $res->content);
$this->assertRegExp('/'.$entry23->concept.'</', $res->content);
$this->assertRegExp('/'.$entry31->concept.'</', $res->content);
$this->assertNotEmpty($res->prevpageurl);
$this->assertEmpty($res->nextpageurl);
// Create and enrol a user.
$student = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual');
$this->setUser($student);
core_tag_index_builder::reset_caches();
// User can not see entries in course 3 because he is not enrolled.
$res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$entry = */1);
$this->assertRegExp('/'.$entry22->concept.'/', $res->content);
$this->assertRegExp('/'.$entry23->concept.'/', $res->content);
$this->assertNotRegExp('/'.$entry31->concept.'/', $res->content);
// User can search glossary entries inside a course.
$coursecontext = context_course::instance($course1->id);
$res = mod_glossary_get_tagged_entries($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */$coursecontext->id, /*$rec = */1, /*$entry = */0);
$this->assertRegExp('/'.$entry11->concept.'/', $res->content);
$this->assertRegExp('/'.$entry12->concept.'/', $res->content);
$this->assertRegExp('/'.$entry13->concept.'/', $res->content);
$this->assertNotRegExp('/'.$entry14->concept.'/', $res->content);
$this->assertRegExp('/'.$entry15->concept.'/', $res->content);
$this->assertNotRegExp('/'.$entry21->concept.'/', $res->content);
$this->assertNotRegExp('/'.$entry22->concept.'/', $res->content);
$this->assertNotRegExp('/'.$entry23->concept.'/', $res->content);
$this->assertEmpty($res->nextpageurl);
// User cannot see hidden entries.
$this->assertNotRegExp('/'.$entry16->concept.'/', $res->content);
}
}

View File

@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2016120500; // The current module version (Date: YYYYMMDDXX)
$plugin->version = 2016120502; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2016112900; // Requires this Moodle version
$plugin->component = 'mod_glossary'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 0;