Skip to content

Commit

Permalink
MDL-67795 contentbank: delete content API
Browse files Browse the repository at this point in the history
  • Loading branch information
sarjona committed Apr 23, 2020
1 parent 7fc73af commit c0d615e
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 1 deletion.
53 changes: 53 additions & 0 deletions contentbank/classes/contenttype.php
Expand Up @@ -80,6 +80,25 @@ public function create_content(\stdClass $content = null): ?content {
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.
*
Expand Down Expand Up @@ -187,6 +206,40 @@ protected function is_upload_allowed(): bool {
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.
*
Expand Down
1 change: 1 addition & 0 deletions contentbank/contenttype/h5p/classes/content.php
Expand Up @@ -35,4 +35,5 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class content extends \core_contentbank\content {

}
15 changes: 15 additions & 0 deletions contentbank/contenttype/h5p/classes/contenttype.php
Expand Up @@ -36,6 +36,21 @@
*/
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.
*
Expand Down
41 changes: 41 additions & 0 deletions contentbank/contenttype/h5p/tests/contenttype_h5p_test.php
Expand Up @@ -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.
*
Expand Down
97 changes: 97 additions & 0 deletions contentbank/tests/contenttype_test.php
Expand Up @@ -46,6 +46,24 @@
*/
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.
*
Expand Down Expand Up @@ -157,4 +175,83 @@ public function test_create_content() {
$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);
}
}
4 changes: 4 additions & 0 deletions lang/en/contentbank.php
Expand Up @@ -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';
Expand Down
2 changes: 2 additions & 0 deletions lang/en/role.php
Expand Up @@ -151,6 +151,8 @@
$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';
Expand Down
22 changes: 21 additions & 1 deletion lib/db/access.php
Expand Up @@ -2501,5 +2501,25 @@
'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,
]
],
);

0 comments on commit c0d615e

Please sign in to comment.