Merge branch 'MDL-66769-master' of git://github.com/ilyatregubov/moodle
authorSara Arjona <sara@moodle.com>
Wed, 3 Feb 2021 08:32:02 +0000 (09:32 +0100)
committerSara Arjona <sara@moodle.com>
Wed, 3 Feb 2021 08:32:30 +0000 (09:32 +0100)
lang/en/admin.php
lib/classes/task/h5p_clean_orphaned_records_task.php [new file with mode: 0644]
lib/db/tasks.php
lib/tests/h5p_clean_orphaned_records_task_test.php [new file with mode: 0644]
version.php

index 65fa702..6de019d 100644 (file)
@@ -688,6 +688,7 @@ $string['checkboxno'] = 'No';
 $string['checkboxyes'] = 'Yes';
 $string['choosefiletoedit'] = 'Choose file to edit';
 $string['h5pgetcontenttypestask'] = 'Download available H5P content types from h5p.org';
+$string['taskh5pcleanup'] = 'Unused H5P files cleanup';
 $string['iconvrequired'] = 'Installing ICONV extension is required.';
 $string['ignore'] = 'Ignore';
 $string['includemoduleuserdata'] = 'Include module user data';
diff --git a/lib/classes/task/h5p_clean_orphaned_records_task.php b/lib/classes/task/h5p_clean_orphaned_records_task.php
new file mode 100644 (file)
index 0000000..37fc605
--- /dev/null
@@ -0,0 +1,74 @@
+<?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/>.
+
+namespace core\task;
+
+/**
+ * A schedule task to clean orphaned h5p records (for example for deleted activity).
+ *
+ * @package    core_h5p
+ * @copyright  2021 Ilya Tregubov <ilya@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class h5p_clean_orphaned_records_task extends scheduled_task {
+
+    /**
+     * Get a descriptive name for this task (shown to admins).
+     *
+     * @return string
+     */
+    public function get_name() {
+        return get_string('taskh5pcleanup', 'admin');
+    }
+
+    /**
+     * Execute the task.
+     */
+    public function execute() {
+        global $DB;
+
+        $sql = "SELECT h5p.id
+                  FROM {h5p} h5p
+             LEFT JOIN {files} f
+                    ON f.pathnamehash = h5p.pathnamehash
+                 WHERE f.pathnamehash IS NULL";
+
+        $orphanedrecords = $DB->get_recordset_sql($sql);
+
+        foreach ($orphanedrecords as $orphanedrecord) {
+
+            $sql = "SELECT f.id, f.pathnamehash
+                      FROM {files} f
+                     WHERE f.itemid = :itemid
+                       AND f.filearea = :filearea
+                       AND f.component = :component";
+            $params = ['itemid' => $orphanedrecord->id, 'filearea' => 'content', 'component' => 'core_h5p'];
+            $filerecords = $DB->get_recordset_sql($sql, $params);
+
+            foreach ($filerecords as $filerecord) {
+                $fs = get_file_storage();
+                $file = $fs->get_file_by_hash($filerecord->pathnamehash);
+                if ($file) {
+                    $file->delete();
+                }
+            }
+
+            $DB->delete_records('h5p', ['id' => $orphanedrecord->id]);
+            $DB->delete_records('h5p_contents_libraries', ['h5pid' => $orphanedrecord->id]);
+        }
+
+    }
+}
index 9c473ea..9393cfc 100644 (file)
@@ -401,6 +401,15 @@ $tasks = array(
         'dayofweek' => '*',
         'month' => '*'
     ),
+    array(
+        'classname' => 'core\task\h5p_clean_orphaned_records_task',
+        'blocking' => 0,
+        'minute' => 'R',
+        'hour' => '0',
+        'day' => '*',
+        'dayofweek' => '*',
+        'month' => '*'
+    ),
     array(
         'classname' => 'core\task\antivirus_cleanup_task',
         'blocking' => 0,
diff --git a/lib/tests/h5p_clean_orphaned_records_task_test.php b/lib/tests/h5p_clean_orphaned_records_task_test.php
new file mode 100644 (file)
index 0000000..561c251
--- /dev/null
@@ -0,0 +1,85 @@
+<?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/>.
+
+/**
+ * Class containing unit tests for the task to clean orphaned h5p records.
+ *
+ * @package   core
+ * @copyright  2021 Ilya Tregubov <ilya@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ *
+ */
+class h5p_clean_orphaned_records_task_test extends advanced_testcase {
+
+    /**
+     * Test task execution
+     *
+     * return void
+     */
+    public function test_task_execution(): void {
+        global $CFG, $DB;
+
+        $this->resetAfterTest();
+        $this->setAdminUser();
+
+        // Create a course.
+        $course = $this->getDataGenerator()->create_course();
+        $params = [
+            'course' => $course->id,
+            'packagefilepath' => $CFG->dirroot.'/h5p/tests/fixtures/greeting-card-887.h5p',
+            'introformat' => 1
+        ];
+
+        // Create h5pactivity.
+        $activity = $this->getDataGenerator()->create_module('h5pactivity', $params);
+        $activity->filename = 'greeting-card-887.h5p';
+        $context = context_module::instance($activity->cmid);
+
+        // Create a fake deploy H5P file.
+        $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p');
+        $generator->create_export_file($activity->filename, $context->id,
+            'mod_h5pactivity', 'package');
+
+        // Delete activity.
+        course_delete_module($activity->cmid);
+
+        $orphanedh5psql = "SELECT h5p.id, h5p.pathnamehash
+                             FROM {h5p} h5p
+                        LEFT JOIN {files} f ON f.pathnamehash = h5p.pathnamehash
+                            WHERE f.pathnamehash IS NULL";
+        $orphanedh5p = $DB->get_records_sql($orphanedh5psql);
+        $this->assertEquals(1, count($orphanedh5p));
+
+        $h5pid = end($orphanedh5p)->id;
+        $orphanedfilessql = "SELECT id
+                               FROM {files}
+                              WHERE itemid = :h5pid
+                                AND filearea = 'content'
+                                AND component = 'core_h5p'";
+        $orphanedfiles = $DB->get_records_sql($orphanedfilessql, ['h5pid' => $h5pid]);
+        $this->assertEquals(3, count($orphanedfiles));
+
+        // Execute task.
+        $task = new \core\task\h5p_clean_orphaned_records_task();
+        $task->execute();
+
+        $orphanedh5p = $DB->get_record_sql($orphanedh5psql);
+        $this->assertFalse($orphanedh5p);
+
+        $orphanedfiles = $DB->get_record_sql($orphanedfilessql, ['h5pid' => $h5pid]);
+        $this->assertFalse($orphanedfiles);
+    }
+}
index 1fe0747..9fb0c1f 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2021052500.55;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2021052500.56;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.
 $release  = '4.0dev (Build: 20210130)'; // Human-friendly version name