Skip to content

Commit

Permalink
MDL-67795 contentbank: new external for deleting content
Browse files Browse the repository at this point in the history
  • Loading branch information
sarjona committed Apr 23, 2020
1 parent c0d615e commit f627173
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 1 deletion.
133 changes: 133 additions & 0 deletions contentbank/classes/external/delete_content.php
@@ -0,0 +1,133 @@
<?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/>.

/**
* This is the external method for deleting a content.
*
* @package core_contentbank
* @since Moodle 3.9
* @copyright 2020 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace core_contentbank\external;

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->libdir . '/externallib.php');

use external_api;
use external_function_parameters;
use external_multiple_structure;
use external_single_structure;
use external_value;
use external_warnings;

/**
* This is the external method for deleting a content.
*
* @copyright 2020 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class delete_content extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'contentids' => new external_multiple_structure(
new external_value(PARAM_INT, 'The content id to delete', VALUE_REQUIRED)
)
]);
}

/**
* Delete content from the contentbank.
*
* @param array $contentids List of content ids to delete.
* @return array True if the content has been deleted; false and the warning, otherwise.
*/
public static function execute(array $contentids): array {
global $DB;

$result = false;
$warnings = [];

$params = self::validate_parameters(self::execute_parameters(), ['contentids' => $contentids]);
foreach ($params['contentids'] as $contentid) {
try {
$record = $DB->get_record('contentbank_content', ['id' => $contentid], '*', MUST_EXIST);
$contenttypeclass = "\\$record->contenttype\\contenttype";
if (class_exists($contenttypeclass)) {
$context = \context::instance_by_id($record->contextid, MUST_EXIST);
self::validate_context($context);
$contenttype = new $contenttypeclass($context);
$contentclass = "\\$record->contenttype\\content";
$content = new $contentclass($record);
// Check capability.
if ($contenttype->can_delete($content)) {
// This content can be deleted.
if (!$contenttype->delete_content($content)) {
$warnings[] = [
'item' => $contentid,
'warningcode' => 'contentnotdeleted',
'message' => get_string('contentnotdeleted', 'core_contentbank')
];
}
} else {
// The user has no permission to delete this content.
$warnings[] = [
'item' => $contentid,
'warningcode' => 'nopermissiontodelete',
'message' => get_string('nopermissiontodelete', 'core_contentbank')
];
}
}
} catch (\moodle_exception $e) {
// The content or the context don't exist.
$warnings[] = [
'item' => $contentid,
'warningcode' => 'exception',
'message' => $e->getMessage()
];
}
}

if (empty($warnings)) {
$result = true;
}

return [
'result' => $result,
'warnings' => $warnings
];
}

/**
* Return.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'result' => new external_value(PARAM_BOOL, 'The processing result'),
'warnings' => new external_warnings()
]);
}
}
112 changes: 112 additions & 0 deletions contentbank/tests/external/delete_content_test.php
@@ -0,0 +1,112 @@
<?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/>.

/**
* External function test for delete_content.
*
* @package core_contentbank
* @category external
* @since Moodle 3.9
* @copyright 2020 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace core_contentbank;

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');

use core_contentbank\external\delete_content;
use dml_missing_record_exception;
use external_api;
use externallib_advanced_testcase;

/**
* External function test for delete_content.
*
* @package core_contentbank
* @copyright 2020 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class delete_content_testcase extends externallib_advanced_testcase {

/**
* Test the behaviour of delete_content().
*/
public function test_delete_content() {
global $DB;
$this->resetAfterTest();
$records = [];

// Create users.
$user = $this->getDataGenerator()->create_user();
$roleid = $DB->get_field('role', 'id', array('shortname' => 'manager'));
$manager = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->role_assign($roleid, $manager->id);

// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
$records[$manager->id] = $generator->generate_contentbank_data('contenttype_testable', 4, $manager->id, null, false);
$records[$user->id] = $generator->generate_contentbank_data('contenttype_testable', 2, $user->id, null, false);

// Check the content has been created as expected.
$this->assertEquals(6, $DB->count_records('contentbank_content'));

// Check the content is deleted as expected by the user when the content has been created by herself.
$this->setUser($user);
$userrecord = array_shift($records[$user->id]);
$result = delete_content::execute([$userrecord->id]);
$result = external_api::clean_returnvalue(delete_content::execute_returns(), $result);
$this->assertTrue($result['result']);
$this->assertCount(0, $result['warnings']);
$this->assertEquals(5, $DB->count_records('contentbank_content'));

// Check the content is not deleted if the user hasn't created it and has only permission to delete her own content.
$userrecord = array_shift($records[$user->id]);
$managerrecord1 = array_shift($records[$manager->id]);
$result = delete_content::execute([$managerrecord1->id, $userrecord->id]);
$result = external_api::clean_returnvalue(delete_content::execute_returns(), $result);
$this->assertFalse($result['result']);
$this->assertCount(1, $result['warnings']);
$warning = array_shift($result['warnings']);
$this->assertEquals('nopermissiontodelete', $warning['warningcode']);
$this->assertEquals($managerrecord1->id, $warning['item']);
$this->assertEquals(4, $DB->count_records('contentbank_content'));

// Check the content is deleted as expected by the manager.
$this->setUser($manager);
$managerrecord2 = array_shift($records[$manager->id]);
$result = delete_content::execute([$managerrecord1->id, $managerrecord2->id]);
$result = external_api::clean_returnvalue(delete_content::execute_returns(), $result);
$this->assertTrue($result['result']);
$this->assertCount(0, $result['warnings']);
$this->assertEquals(2, $DB->count_records('contentbank_content'));

// Check an exception warning is returned if an unexisting contentid is deleted.
// Check also the other content is deleted (so the process continues after the exception is thrown).
$managerrecord3 = array_shift($records[$manager->id]);
$result = delete_content::execute([$managerrecord1->id, $managerrecord3->id]);
$result = external_api::clean_returnvalue(delete_content::execute_returns(), $result);
$this->assertFalse($result['result']);
$this->assertCount(1, $result['warnings']);
$warning = array_shift($result['warnings']);
$this->assertEquals('exception', $warning['warningcode']);
$this->assertEquals($managerrecord1->id, $warning['item']);
$this->assertEquals(1, $DB->count_records('contentbank_content'));
}
}
1 change: 1 addition & 0 deletions lang/en/contentbank.php
Expand Up @@ -30,6 +30,7 @@
$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';
$string['nopermissiontodelete'] = 'You have no permissions to delete the content.';
$string['privacy:metadata:userid'] = 'The ID of the user creating or modifying content bank content.';
$string['privacy:metadata:content:usercreated'] = 'The user has created the content.';
$string['privacy:metadata:content:usermodified'] = 'Last user has modified the content.';
Expand Down
9 changes: 9 additions & 0 deletions lib/db/services.php
Expand Up @@ -2764,6 +2764,15 @@
'capabilities' => '',
'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE],
],
'core_contentbank_delete_content' => [
'classname' => 'core_contentbank\external\delete_content',
'methodname' => 'execute',
'classpath' => '',
'description' => 'Delete a content from the content bank.',
'type' => 'write',
'ajax' => 'true',
'capabilities' => 'moodle/contentbank:deleteanycontent',
],
);

$services = array(
Expand Down
2 changes: 1 addition & 1 deletion version.php
Expand Up @@ -29,7 +29,7 @@

defined('MOODLE_INTERNAL') || die();

$version = 2020041700.01; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2020041700.02; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '3.9dev (Build: 20200417)'; // Human-friendly version name
Expand Down

0 comments on commit f627173

Please sign in to comment.