MDL-67795 contentbank: delete content API

This commit is contained in:
Sara Arjona 2020-04-16 12:11:28 +02:00
parent 7fc73af69b
commit c0d615e8f9
8 changed files with 234 additions and 1 deletions

View File

@ -80,6 +80,25 @@ abstract class contenttype {
return null;
}
/**
* Delete this content from the content_bank.
* This method can be overwritten by the plugins if they need to delete specific information.
*
* @param content $content The content to delete.
* @return boolean true if the content has been deleted; false otherwise.
*/
public function delete_content(content $content): bool {
global $DB;
// Delete the file if it exists.
if ($file = $content->get_file()) {
$file->delete();
}
// Delete the contentbank DB entry.
return $DB->delete_records('contentbank_content', ['id' => $content->get_id()]);
}
/**
* Returns the contenttype name of this content.
*
@ -187,6 +206,40 @@ abstract class contenttype {
return true;
}
/**
* Check if the user can delete this content.
*
* @param content $content The content to be deleted.
* @return bool True if content could be uploaded. False otherwise.
*/
final public function can_delete(content $content): bool {
global $USER;
if ($this->context->id != $content->get_content()->contextid) {
// The content has to have exactly the same context as this contenttype.
return false;
}
$hascapability = has_capability('moodle/contentbank:deleteanycontent', $this->context);
if ($content->get_content()->usercreated == $USER->id) {
// This content has been created by the current user; check if she can delete her content.
$hascapability = $hascapability || has_capability('moodle/contentbank:deleteowncontent', $this->context);
}
return $hascapability && $this->is_delete_allowed($content);
}
/**
* Returns if content allows deleting.
*
* @param content $content The content to be deleted.
* @return bool True if content allows uploading. False otherwise.
*/
protected function is_delete_allowed(content $content): bool {
// Plugins can overwrite this function to add any check they need.
return true;
}
/**
* Returns the plugin supports the feature.
*

View File

@ -35,4 +35,5 @@ use html_writer;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class content extends \core_contentbank\content {
}

View File

@ -36,6 +36,21 @@ use html_writer;
*/
class contenttype extends \core_contentbank\contenttype {
/**
* Delete this content from the content_bank and remove all the H5P related information.
*
* @param content $content The content to delete.
* @return boolean true if the content has been deleted; false otherwise.
*/
public function delete_content(\core_contentbank\content $content): bool {
// Delete the H5P content.
$factory = new \core_h5p\factory();
\core_h5p\api::delete_content_from_pluginfile_url($content->get_file_url(), $factory);
// Delete the content from the content_bank.
return parent::delete_content($content);
}
/**
* Returns the HTML content to add to view.php visualizer.
*

View File

@ -34,6 +34,47 @@
*/
class contenttype_h5p_contenttype_plugin_testcase extends advanced_testcase {
/**
* Test the behaviour of delete_content().
*/
public function test_delete_content() {
global $CFG, $USER, $DB;
$this->resetAfterTest();
$systemcontext = context_system::instance();
// Create users.
$roleid = $DB->get_field('role', 'id', array('shortname' => 'manager'));
$manager = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->role_assign($roleid, $manager->id);
$this->setUser($manager);
// Add an H5P file to the content bank.
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$contents = $generator->generate_contentbank_data('contenttype_h5p', 2, $USER->id, $systemcontext, true, $filepath);
$content1 = array_shift($contents);
$content2 = array_shift($contents);
// Load this H5P file though the player to create the H5P DB entries.
$h5pplayer = new \core_h5p\player($content1->get_file_url(), new \stdClass(), true);
$h5pplayer->add_assets_to_page();
$h5pplayer->output();
$h5pplayer = new \core_h5p\player($content2->get_file_url(), new \stdClass(), true);
$h5pplayer->add_assets_to_page();
$h5pplayer->output();
// Check the H5P content has been created.
$this->assertEquals(2, $DB->count_records('h5p'));
$this->assertEquals(2, $DB->count_records('contentbank_content'));
// Check the H5P content is removed after calling this method.
$contenttype = new \contenttype_h5p\contenttype($systemcontext);
$contenttype->delete_content($content1);
$this->assertEquals(1, $DB->count_records('h5p'));
$this->assertEquals(1, $DB->count_records('contentbank_content'));
}
/**
* Tests can_upload behavior.
*

View File

@ -46,6 +46,24 @@ use contenttype_testable\contenttype as contenttype;
*/
class core_contenttype_contenttype_testcase extends \advanced_testcase {
/** @var int Identifier for the manager role. */
protected $managerroleid;
/** @var stdClass Manager user. */
protected $manager1;
/** @var stdClass Manager user. */
protected $manager2;
/** @var stdClass User. */
protected $user;
/** @var array List of contents created (every user has a key with contents created by her). */
protected $contents = [];
/** @var contenttype The contenttype instance. */
protected $contenttype;
/**
* Tests get_contenttype_name result.
*
@ -157,4 +175,83 @@ class core_contenttype_contenttype_testcase extends \advanced_testcase {
$this->assertEquals('contenttype_testable', $content->get_content_type());
$this->assertInstanceOf('\\contenttype_testable\\content', $content);
}
/**
* Test the behaviour of can_delete().
*/
public function test_can_delete() {
global $DB;
$this->resetAfterTest();
$this->contenttype_setup_scenario_data();
$managercontent = array_shift($this->contents[$this->manager1->id]);
$usercontent = array_shift($this->contents[$this->user->id]);
// Check the content has been created as expected.
$records = $DB->count_records('contentbank_content');
$this->assertEquals(4, $records);
// Check user can only delete records created by her.
$this->setUser($this->user);
$this->assertFalse($this->contenttype->can_delete($managercontent));
$this->assertTrue($this->contenttype->can_delete($usercontent));
// Check manager can delete records all the records created.
$this->setUser($this->manager1);
$this->assertTrue($this->contenttype->can_delete($managercontent));
$this->assertTrue($this->contenttype->can_delete($usercontent));
// Unassign capability to manager role and check not can only delete their own records.
unassign_capability('moodle/contentbank:deleteanycontent', $this->managerroleid);
$this->assertTrue($this->contenttype->can_delete($managercontent));
$this->assertFalse($this->contenttype->can_delete($usercontent));
$this->setUser($this->manager2);
$this->assertFalse($this->contenttype->can_delete($managercontent));
$this->assertFalse($this->contenttype->can_delete($usercontent));
}
/**
* Test the behaviour of delete_content().
*/
public function test_delete_content() {
global $DB;
$this->resetAfterTest();
$this->contenttype_setup_scenario_data();
// Check the content has been created as expected.
$this->assertEquals(4, $DB->count_records('contentbank_content'));
// Check the content is deleted as expected.
$this->setUser($this->manager1);
$content = array_shift($this->contents[$this->manager1->id]);
$deleted = $this->contenttype->delete_content($content);
$this->assertTrue($deleted);
$this->assertEquals(3, $DB->count_records('contentbank_content'));
}
/**
* Helper function to setup 3 users (manager1, manager2 and user) and 4 contents (3 created by manager1 and 1 by user).
*/
protected function contenttype_setup_scenario_data(): void {
global $DB;
$systemcontext = context_system::instance();
// Create users.
$this->manager1 = $this->getDataGenerator()->create_user();
$this->manager2 = $this->getDataGenerator()->create_user();
$this->managerroleid = $DB->get_field('role', 'id', array('shortname' => 'manager'));
$this->getDataGenerator()->role_assign($this->managerroleid, $this->manager1->id);
$this->getDataGenerator()->role_assign($this->managerroleid, $this->manager2->id);
$this->user = $this->getDataGenerator()->create_user();
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$this->contents[$this->manager1->id] = $generator->generate_contentbank_data(null, 3, $this->manager1->id);
$this->contents[$this->user->id] = $generator->generate_contentbank_data(null, 1, $this->user->id);
$this->contenttype = new \contenttype_testable\contenttype($systemcontext);
}
}

View File

@ -23,6 +23,10 @@
*/
$string['author'] = 'Author';
$string['contentdeleted'] = 'The content has been deleted.';
$string['contentnotdeleted'] = 'An error was encountered while trying to delete the content.';
$string['deletecontent'] = 'Delete content';
$string['deletecontentconfirm'] = '<p>Are you sure you want to delete content <em>\'{$a->name}\'</em>? It will remove the content and all its files.</p><p>This operation can not be undone.</p>';
$string['file'] = 'Upload content';
$string['file_help'] = 'Files may be stored in the content bank for use in courses. Only files used by content types enabled on the site may be uploaded.';
$string['name'] = 'Content';

View File

@ -151,6 +151,8 @@ $string['confirmunassigntitle'] = 'Confirm role change';
$string['confirmunassignyes'] = 'Remove';
$string['confirmunassignno'] = 'Cancel';
$string['contentbank:access'] = 'Access the content bank';
$string['contentbank:deleteanycontent'] = 'Delete any content from the content bank on the site';
$string['contentbank:deleteowncontent'] = 'Delete content from the content bank created by the user';
$string['contentbank:upload'] = 'Upload new content in the content bank';
$string['context'] = 'Context';
$string['course:activityvisibility'] = 'Hide/show activities';

View File

@ -2501,5 +2501,25 @@ $capabilities = array(
'coursecreator' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
)
)
),
// Delete any content from the content bank.
'moodle/contentbank:deleteanycontent' => [
'riskbitmask' => RISK_DATALOSS,
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => [
'manager' => CAP_ALLOW,
'coursecreator' => CAP_ALLOW,
]
],
// Delete content created by yourself.
'moodle/contentbank:deleteowncontent' => [
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => [
'user' => CAP_ALLOW,
]
],
);