mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-53598 block_glossary_random: do not fail if glossary was deleted
This commit refactors how associated glossary is searched for and removes unnecessary DB queries. Also prevents from situations when the global glossary or course have been deleted
This commit is contained in:
parent
6a74e76fb8
commit
9c3710854b
@ -60,19 +60,27 @@ class restore_glossary_random_block_task extends restore_block_task {
|
||||
if ($configdata = $DB->get_field('block_instances', 'configdata', array('id' => $blockid))) {
|
||||
$config = unserialize(base64_decode($configdata));
|
||||
if (!empty($config->glossary)) {
|
||||
// Get glossary mapping and replace it in config
|
||||
if ($glossarymap = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'glossary', $config->glossary)) {
|
||||
$mappedglossary = $DB->get_record('glossary', array('id' => $glossarymap->newitemid),
|
||||
'id,course,globalglossary', MUST_EXIST);
|
||||
$config->glossary = $mappedglossary->id;
|
||||
$config->courseid = $mappedglossary->course;
|
||||
$config->globalglossary = $mappedglossary->globalglossary;
|
||||
$configdata = base64_encode(serialize($config));
|
||||
$DB->set_field('block_instances', 'configdata', $configdata, array('id' => $blockid));
|
||||
// Get glossary mapping and replace it in config
|
||||
$config->glossary = $glossarymap->newitemid;
|
||||
} else if ($this->is_samesite()) {
|
||||
// We are restoring on the same site, check if glossary can be used in the block in this course.
|
||||
$glossaryid = $DB->get_field_sql("SELECT id FROM {glossary} " .
|
||||
"WHERE id = ? AND (course = ? OR globalglossary = 1)",
|
||||
[$config->glossary, $this->get_courseid()]);
|
||||
if (!$glossaryid) {
|
||||
unset($config->glossary);
|
||||
}
|
||||
} else {
|
||||
// The block refers to a glossary not present in the backup file.
|
||||
$DB->set_field('block_instances', 'configdata', '', array('id' => $blockid));
|
||||
unset($config->glossary);
|
||||
}
|
||||
// Unset config variables that are no longer used.
|
||||
unset($config->globalglossary);
|
||||
unset($config->courseid);
|
||||
// Save updated config.
|
||||
$configdata = base64_encode(serialize($config));
|
||||
$DB->set_field('block_instances', 'configdata', $configdata, array('id' => $blockid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,12 @@ define('BGR_NEXTALPHA', '3');
|
||||
|
||||
class block_glossary_random extends block_base {
|
||||
|
||||
/**
|
||||
* @var cm_info|stdClass has properties 'id' (course module id) and 'uservisible'
|
||||
* (whether the glossary is visible to the current user)
|
||||
*/
|
||||
protected $glossarycm = null;
|
||||
|
||||
function init() {
|
||||
$this->title = get_string('pluginname','block_glossary_random');
|
||||
}
|
||||
@ -58,6 +64,11 @@ class block_glossary_random extends block_base {
|
||||
//check if it's time to put a new entry in cache
|
||||
if (time() > $this->config->nexttime) {
|
||||
|
||||
if (!($cm = $this->get_glossary_cm()) || !$cm->uservisible) {
|
||||
// Skip generating of the cache if we can't display anything to the current user.
|
||||
return false;
|
||||
}
|
||||
|
||||
// place glossary concept and definition in $pref->cache
|
||||
if (!$numberofentries = $DB->count_records('glossary_entries',
|
||||
array('glossaryid'=>$this->config->glossary, 'approved'=>1))) {
|
||||
@ -65,20 +76,6 @@ class block_glossary_random extends block_base {
|
||||
$this->instance_config_commit();
|
||||
}
|
||||
|
||||
// Get glossary instance, if not found then return without error, as this will be handled in get_content.
|
||||
if (!$glossary = $DB->get_record('glossary', array('id' => $this->config->glossary))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->config->globalglossary = $glossary->globalglossary;
|
||||
|
||||
// Save course id in config, so we can get correct course module.
|
||||
$this->config->courseid = $glossary->course;
|
||||
|
||||
// Get module and context, to be able to rewrite urls
|
||||
if (! $cm = get_coursemodule_from_instance('glossary', $glossary->id, $this->config->courseid)) {
|
||||
return false;
|
||||
}
|
||||
$glossaryctx = context_module::instance($cm->id);
|
||||
|
||||
$limitfrom = 0;
|
||||
@ -156,6 +153,67 @@ class block_glossary_random extends block_base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the instance's configuration data with those currently in $this->config;
|
||||
*/
|
||||
function instance_config_commit($nolongerused = false) {
|
||||
// Unset config variables that are no longer used.
|
||||
unset($this->config->globalglossary);
|
||||
unset($this->config->courseid);
|
||||
parent::instance_config_commit($nolongerused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if glossary is available - it should be either located in the same course or be global
|
||||
*
|
||||
* @return null|cm_info|stdClass object with properties 'id' (course module id) and 'uservisible'
|
||||
*/
|
||||
protected function get_glossary_cm() {
|
||||
global $DB;
|
||||
if (empty($this->config->glossary)) {
|
||||
// No glossary is configured.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!empty($this->glossarycm)) {
|
||||
return $this->glossarycm;
|
||||
}
|
||||
|
||||
if (!empty($this->page->course->id)) {
|
||||
// First check if glossary belongs to the current course (we don't need to make any DB queries to find it).
|
||||
$modinfo = get_fast_modinfo($this->page->course);
|
||||
if (isset($modinfo->instances['glossary'][$this->config->glossary])) {
|
||||
$this->glossarycm = $modinfo->instances['glossary'][$this->config->glossary];
|
||||
if ($this->glossarycm->uservisible) {
|
||||
// The glossary is in the same course and is already visible to the current user,
|
||||
// no need to check if it is global, save on DB query.
|
||||
return $this->glossarycm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find course module id for the given glossary, only if it is global.
|
||||
$cm = $DB->get_record_sql("SELECT cm.id, cm.visible AS uservisible
|
||||
FROM {course_modules} cm
|
||||
JOIN {modules} md ON md.id = cm.module
|
||||
JOIN {glossary} g ON g.id = cm.instance
|
||||
WHERE g.id = :instance AND md.name = :modulename AND g.globalglossary = 1",
|
||||
['instance' => $this->config->glossary, 'modulename' => 'glossary']);
|
||||
|
||||
if ($cm) {
|
||||
// This is a global glossary, create an object with properties 'id' and 'uservisible'. We don't need any
|
||||
// other information so why bother retrieving it. Full access check is skipped for global glossaries for
|
||||
// performance reasons.
|
||||
$this->glossarycm = $cm;
|
||||
} else if (empty($this->glossarycm)) {
|
||||
// Glossary does not exist. Remove it in the config so we don't repeat this check again later.
|
||||
$this->config->glossary = 0;
|
||||
$this->instance_config_commit();
|
||||
}
|
||||
|
||||
return $this->glossarycm;
|
||||
}
|
||||
|
||||
function instance_allow_multiple() {
|
||||
// Are you going to allow multiple instances of each block?
|
||||
// If yes, then it is assumed that the block WILL USE per-instance configuration
|
||||
@ -163,81 +221,35 @@ class block_glossary_random extends block_base {
|
||||
}
|
||||
|
||||
function get_content() {
|
||||
global $USER, $CFG, $DB;
|
||||
|
||||
if (empty($this->config->glossary)) {
|
||||
$this->content = new stdClass();
|
||||
if ($this->user_can_edit()) {
|
||||
$this->content->text = get_string('notyetconfigured','block_glossary_random');
|
||||
} else {
|
||||
$this->content->text = '';
|
||||
}
|
||||
$this->content->footer = '';
|
||||
if ($this->content !== null) {
|
||||
return $this->content;
|
||||
}
|
||||
$this->content = (object)['text' => '', 'footer' => ''];
|
||||
|
||||
require_once($CFG->dirroot.'/course/lib.php');
|
||||
|
||||
// If $this->config->globalglossary is not set then get glossary info from db.
|
||||
if (!isset($this->config->globalglossary)) {
|
||||
if (!$glossary = $DB->get_record('glossary', array('id' => $this->config->glossary))) {
|
||||
return '';
|
||||
} else {
|
||||
$this->config->courseid = $glossary->course;
|
||||
$this->config->globalglossary = $glossary->globalglossary;
|
||||
$this->instance_config_commit();
|
||||
}
|
||||
}
|
||||
|
||||
$modinfo = get_fast_modinfo($this->config->courseid);
|
||||
// If deleted glossary or non-global glossary on different course page, then reset.
|
||||
if (!isset($modinfo->instances['glossary'][$this->config->glossary])
|
||||
|| ((empty($this->config->globalglossary) && ($this->config->courseid != $this->page->course->id)))) {
|
||||
$this->config->glossary = 0;
|
||||
$this->config->cache = '';
|
||||
$this->instance_config_commit();
|
||||
|
||||
$this->content = new stdClass();
|
||||
if (!$cm = $this->get_glossary_cm()) {
|
||||
if ($this->user_can_edit()) {
|
||||
$this->content->text = get_string('notyetconfigured','block_glossary_random');
|
||||
} else {
|
||||
$this->content->text = '';
|
||||
$this->content->text = get_string('notyetconfigured', 'block_glossary_random');
|
||||
}
|
||||
$this->content->footer = '';
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
$cm = $modinfo->instances['glossary'][$this->config->glossary];
|
||||
if (!has_capability('mod/glossary:view', context_module::instance($cm->id))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (empty($this->config->cache)) {
|
||||
$this->config->cache = '';
|
||||
}
|
||||
|
||||
if ($this->content !== NULL) {
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
$this->content = new stdClass();
|
||||
|
||||
// Show glossary if visible and place links in footer.
|
||||
if ($cm->visible) {
|
||||
if ($cm->uservisible) {
|
||||
// Show glossary if visible and place links in footer.
|
||||
$this->content->text = $this->config->cache;
|
||||
if (has_capability('mod/glossary:write', context_module::instance($cm->id))) {
|
||||
$this->content->footer = '<a href="'.$CFG->wwwroot.'/mod/glossary/edit.php?cmid='.$cm->id
|
||||
.'" title="'.$this->config->addentry.'">'.$this->config->addentry.'</a><br />';
|
||||
} else {
|
||||
$this->content->footer = '';
|
||||
$this->content->footer = html_writer::link(new moodle_url('/mod/glossary/edit.php', ['cmid' => $cm->id]),
|
||||
format_string($this->config->addentry)) . '<br/>';
|
||||
}
|
||||
|
||||
$this->content->footer .= '<a href="'.$CFG->wwwroot.'/mod/glossary/view.php?id='.$cm->id
|
||||
.'" title="'.$this->config->viewglossary.'">'.$this->config->viewglossary.'</a>';
|
||||
|
||||
// Otherwise just place some text, no link.
|
||||
$this->content->footer .= html_writer::link(new moodle_url('/mod/glossary/view.php', ['id' => $cm->id]),
|
||||
format_string($this->config->viewglossary));
|
||||
} else {
|
||||
$this->content->footer = $this->config->invisible;
|
||||
// Otherwise just place some text, no link.
|
||||
$this->content->footer = format_string($this->config->invisible);
|
||||
}
|
||||
|
||||
return $this->content;
|
||||
|
@ -0,0 +1,84 @@
|
||||
@block @block_glossary_random
|
||||
Feature: Random glossary entry block linking to global glossary
|
||||
In order to show the entries from glossary
|
||||
As a teacher
|
||||
I can add the random glossary entry to a course page
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
| Course 2 | C2 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber | globalglossary | defaultapproval |
|
||||
| glossary | Tips and Tricks | Frontpage glossary description | C2 | glossary0 | 1 | 1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Sam1 | Student1 | student1@example.com |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
Scenario: View random (last) entry in the global glossary
|
||||
When I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I follow "Course 2"
|
||||
And I follow "Tips and Tricks"
|
||||
And I press "Add a new entry"
|
||||
And I set the following fields to these values:
|
||||
| Concept | Never come late |
|
||||
| Definition | Come in time for your classes |
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
# As a teacher add a block to the course page linking to the global glossary.
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add the "Random glossary entry" block
|
||||
And I configure the "block_glossary_random" block
|
||||
And I set the following fields to these values:
|
||||
| Title | Tip of the day |
|
||||
| Take entries from this glossary | Tips and Tricks |
|
||||
| How a new entry is chosen | Last modified entry |
|
||||
And I press "Save changes"
|
||||
Then I should see "Never come late" in the "Tip of the day" "block"
|
||||
And I should not see "Add a new entry" in the "Tip of the day" "block"
|
||||
And I should see "View all entries" in the "Tip of the day" "block"
|
||||
And I log out
|
||||
# Student who can't see the module is still able to view entries in this block (because the glossary was marked as global)
|
||||
And I log in as "student1"
|
||||
And I follow "Course 1"
|
||||
And I should see "Never come late" in the "Tip of the day" "block"
|
||||
And I should not see "Add a new entry" in the "Tip of the day" "block"
|
||||
And I should see "View all entries" in the "Tip of the day" "block"
|
||||
And I log out
|
||||
|
||||
Scenario: Removing the global glossary that is used in random glossary block
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add the "Random glossary entry" block
|
||||
And I configure the "block_glossary_random" block
|
||||
And I set the following fields to these values:
|
||||
| Title | Tip of the day |
|
||||
| Take entries from this glossary | Tips and Tricks |
|
||||
| How a new entry is chosen | Last modified entry |
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I follow "Course 2"
|
||||
And I follow "Tips and Tricks"
|
||||
And I follow "Edit settings"
|
||||
And I set the field "globalglossary" to "0"
|
||||
And I press "Save and return to course"
|
||||
And I am on site homepage
|
||||
And I follow "Course 1"
|
||||
Then I should see "Please configure this block using the edit icon." in the "Tip of the day" "block"
|
||||
And I log out
|
||||
And I log in as "student1"
|
||||
And I follow "Course 1"
|
||||
And "Tip of the day" "block" should not exist
|
||||
And I log out
|
Loading…
x
Reference in New Issue
Block a user