Skip to content

Commit

Permalink
MDL-63805 glossary: Glossary API refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
jleyva committed Oct 14, 2020
1 parent b5b9bbc commit 3f5d990
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 17 deletions.
21 changes: 4 additions & 17 deletions mod/glossary/edit.php
Expand Up @@ -38,23 +38,10 @@
print_error('invalidentry');
}

$ineditperiod = ((time() - $entry->timecreated < $CFG->maxeditingtime) || $glossary->editalways);
if (!has_capability('mod/glossary:manageentries', $context) and !($entry->userid == $USER->id and ($ineditperiod and has_capability('mod/glossary:write', $context)))) {
if ($USER->id != $entry->userid) {
print_error('errcannoteditothers', 'glossary', "view.php?id=$cm->id&amp;mode=entry&amp;hook=$id");
} elseif (!$ineditperiod) {
print_error('erredittimeexpired', 'glossary', "view.php?id=$cm->id&amp;mode=entry&amp;hook=$id");
}
}

//prepare extra data
if ($aliases = $DB->get_records_menu("glossary_alias", array("entryid"=>$id), '', 'id, alias')) {
$entry->aliases = implode("\n", $aliases) . "\n";
}
if ($categoriesarr = $DB->get_records_menu("glossary_entries_categories", array('entryid'=>$id), '', 'id, categoryid')) {
// TODO: this fetches cats from both main and secondary glossary :-(
$entry->categories = array_values($categoriesarr);
}
// Check if the user can update the entry (trigger exception if he can't).
mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false);
// Prepare extra data.
$entry = mod_glossary_prepare_entry_for_edition($entry);

} else { // new entry
require_capability('mod/glossary:write', $context);
Expand Down
57 changes: 57 additions & 0 deletions mod/glossary/lib.php
Expand Up @@ -4455,3 +4455,60 @@ function mod_glossary_delete_entry($entry, $glossary, $cm, $context, $course, $h
\mod_glossary\local\concept_cache::reset_glossary($glossary);
}
}

/**
* Checks if the current user can update the given glossary entry.
*
* @since Moodle 3.10
* @param stdClass $entry the entry database object
* @param stdClass $glossary the glossary database object
* @param stdClass $context the glossary context
* @param object $cm the course module object (cm record or cm_info instance)
* @param bool $return Whether to return a boolean value or stop the execution (exception)
* @return bool if the user can update the entry
* @throws moodle_exception
*/
function mod_glossary_can_update_entry(stdClass $entry, stdClass $glossary, stdClass $context, object $cm,
bool $return = true): bool {

global $USER, $CFG;

$ineditperiod = ((time() - $entry->timecreated < $CFG->maxeditingtime) || $glossary->editalways);
if (!has_capability('mod/glossary:manageentries', $context) and
!($entry->userid == $USER->id and ($ineditperiod and has_capability('mod/glossary:write', $context)))) {

if ($USER->id != $entry->userid) {
if ($return) {
return false;
}
throw new moodle_exception('errcannoteditothers', 'glossary', "view.php?id=$cm->id&amp;mode=entry&amp;hook=$entry->id");
} else if (!$ineditperiod) {
if ($return) {
return false;
}
throw new moodle_exception('erredittimeexpired', 'glossary', "view.php?id=$cm->id&amp;mode=entry&amp;hook=$entry->id");
}
}

return true;
}

/**
* Prepares an entry for editing, adding aliases and category information.
*
* @param stdClass $entry the entry being edited
* @return stdClass the entry with the additional data
*/
function mod_glossary_prepare_entry_for_edition(stdClass $entry): stdClass {
global $DB;

if ($aliases = $DB->get_records_menu("glossary_alias", ["entryid" => $entry->id], '', 'id, alias')) {
$entry->aliases = implode("\n", $aliases) . "\n";
}
if ($categoriesarr = $DB->get_records_menu("glossary_entries_categories", ['entryid' => $entry->id], '', 'id, categoryid')) {
// TODO: this fetches cats from both main and secondary glossary :-(
$entry->categories = array_values($categoriesarr);
}

return $entry;
}
96 changes: 96 additions & 0 deletions mod/glossary/tests/lib_test.php
Expand Up @@ -670,4 +670,100 @@ public function test_mod_glossary_delete_entry_imported() {
// Tags.
$this->assertEmpty(core_tag_tag::get_by_name(0, 'Cats'));
}

public function test_mod_glossary_can_update_entry_users() {
$this->resetAfterTest();

// Create required data.
$course = $this->getDataGenerator()->create_course();
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
$anotherstudent = $this->getDataGenerator()->create_and_enrol($course, 'student');
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
$glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id));

$gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
$this->setUser($student);
$entry = $gg->create_content($glossary);
$context = context_module::instance($glossary->cmid);
$cm = get_coursemodule_from_instance('glossary', $glossary->id);

// Test student can update.
$this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Test teacher can update.
$this->setUser($teacher);
$this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Test admin can update.
$this->setAdminUser();
$this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Test a different student is not able to update.
$this->setUser($anotherstudent);
$this->assertFalse(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Test exception.
$this->expectExceptionMessage(get_string('errcannoteditothers', 'glossary'));
mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false);
}

public function test_mod_glossary_can_update_entry_edit_period() {
global $CFG;
$this->resetAfterTest();

// Create required data.
$course = $this->getDataGenerator()->create_course();
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
$glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id, 'editalways' => 1));

$gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
$this->setUser($student);
$entry = $gg->create_content($glossary);
$context = context_module::instance($glossary->cmid);
$cm = get_coursemodule_from_instance('glossary', $glossary->id);

// Test student can always update when edit always is set to 1.
$entry->timecreated = time() - 2 * $CFG->maxeditingtime;
$this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Test student cannot update old entries when edit always is set to 0.
$glossary->editalways = 0;
$this->assertFalse(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Test student can update recent entries when edit always is set to 0.
$entry->timecreated = time();
$this->assertTrue(mod_glossary_can_update_entry($entry, $glossary, $context, $cm));

// Check exception.
$entry->timecreated = time() - 2 * $CFG->maxeditingtime;
$this->expectExceptionMessage(get_string('erredittimeexpired', 'glossary'));
mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false);
}

public function test_prepare_entry_for_edition() {
global $USER;
$this->resetAfterTest(true);

$course = $this->getDataGenerator()->create_course();
$glossary = $this->getDataGenerator()->create_module('glossary', ['course' => $course->id]);
$gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');

$this->setAdminUser();
$aliases = ['alias1', 'alias2'];
$entry = $gg->create_content(
$glossary,
['approved' => 1, 'userid' => $USER->id],
$aliases
);

$cat1 = $gg->create_category($glossary, [], [$entry]);
$gg->create_category($glossary);

$entry = mod_glossary_prepare_entry_for_edition($entry);
$this->assertCount(1, $entry->categories);
$this->assertEquals($cat1->id, $entry->categories[0]);
$returnedaliases = array_values(explode("\n", trim($entry->aliases)));
sort($returnedaliases);
$this->assertEquals($aliases, $returnedaliases);
}
}

0 comments on commit 3f5d990

Please sign in to comment.