MDL-67795 contentbank: new external for deleting content
authorSara Arjona <sara@moodle.com>
Thu, 16 Apr 2020 10:47:38 +0000 (12:47 +0200)
committerSara Arjona <sara@moodle.com>
Thu, 23 Apr 2020 11:09:40 +0000 (13:09 +0200)
contentbank/classes/external/delete_content.php [new file with mode: 0644]
contentbank/tests/external/delete_content_test.php [new file with mode: 0644]
lang/en/contentbank.php
lib/db/services.php
version.php

diff --git a/contentbank/classes/external/delete_content.php b/contentbank/classes/external/delete_content.php
new file mode 100644 (file)
index 0000000..65846aa
--- /dev/null
@@ -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()
+        ]);
+    }
+}
diff --git a/contentbank/tests/external/delete_content_test.php b/contentbank/tests/external/delete_content_test.php
new file mode 100644 (file)
index 0000000..fd35f45
--- /dev/null
@@ -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'));
+    }
+}
index 29ace78..80b39b0 100644 (file)
@@ -30,6 +30,7 @@ $string['deletecontentconfirm'] = '<p>Are you sure you want to delete content <e
 $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.';
index 6d997e7..a57a95d 100644 (file)
@@ -2764,6 +2764,15 @@ $functions = array(
         '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(
index 9150a38..7af6f50 100644 (file)
@@ -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