From 83713d048e42888ea72b39dbf2ec42e27309cd7b Mon Sep 17 00:00:00 2001 From: Frode Petterson <frode.andre.petterson@gmail.com> Date: Fri, 9 Sep 2016 09:30:25 +0200 Subject: [PATCH] Changed context for content files Moved from course to course module. Enriches access control and backup. h5p/h5p-moodle-plugin#112 --- ajax.php | 1 + classes/file_storage.php | 43 ++++++++++++++++++++++++---------------- db/upgrade.php | 31 +++++++++++++++++++++++++++++ lib.php | 16 +++++++++++++-- library | 2 +- locallib.php | 11 ++++++++-- version.php | 2 +- view.php | 4 ++++ 8 files changed, 87 insertions(+), 23 deletions(-) diff --git a/ajax.php b/ajax.php index 2ed0637..b7c960c 100644 --- a/ajax.php +++ b/ajax.php @@ -243,6 +243,7 @@ switch($action) { // Save the valid file $file_id = $core->fs->saveFile($file, $contentid, $contextid); + // Track temporary files for later cleanup $DB->insert_record_raw('hvp_tmpfiles', array( 'id' => $file_id ), false, false, true); diff --git a/classes/file_storage.php b/classes/file_storage.php index e3947f3..dbc8336 100644 --- a/classes/file_storage.php +++ b/classes/file_storage.php @@ -69,13 +69,12 @@ class file_storage implements \H5PFileStorage { * What makes this content unique. */ public function saveContent($source, $id) { - global $COURSE; - // Remove any old content. $this->deleteContent($id); // Contents are stored in a course context. - $context = \context_course::instance($COURSE->id); + $cm = \get_coursemodule_from_instance('hvp', $id); + $context = \context_module::instance($cm->id); $options = array( 'contextid' => $context->id, 'component' => 'mod_hvp', @@ -95,9 +94,8 @@ class file_storage implements \H5PFileStorage { * Content identifier */ public function deleteContent($id) { - global $COURSE; - - $context = \context_course::instance($COURSE->id); + $cm = \get_coursemodule_from_instance('hvp', $id); + $context = \context_module::instance($cm->id); self::deleteFileTree($context->id, 'content', '/', $id); } @@ -133,9 +131,8 @@ class file_storage implements \H5PFileStorage { * Where the content folder will be saved */ public function exportContent($id, $target) { - global $COURSE; - - $context = \context_course::instance($COURSE->id); + $cm = \get_coursemodule_from_instance('hvp', $id); + $context = \context_module::instance($cm->id); self::exportFileTree($target, $context->id, 'content', '/', $id); } @@ -343,8 +340,22 @@ class file_storage implements \H5PFileStorage { * Save files uploaded through the editor. * * @param \H5peditorFile $file + * @param int $contentid + * @param \stdClass $context Course Context ID */ public function saveFile($file, $contentid, $contextid = null) { + global $COURSE; + + if ($contentid !== 0) { + // Grab cm context + $cm = \get_coursemodule_from_instance('hvp', $contentid); + $context = \context_module::instance($cm->id); + $contextid = $context->id; + } + + // Files not yet related to any activities are stored in a course context + // (These are temporary files and should not be part of backups.) + $record = array( 'contextid' => $contextid, 'component' => 'mod_hvp', @@ -374,8 +385,6 @@ class file_storage implements \H5PFileStorage { * @param int $toid Target Content ID */ public function cloneContentFile($file, $fromid, $toid) { - global $COURSE; - // Determine source file area and item id $sourcefilearea = ($fromid === 'editor' ? $fromid : 'content'); $sourceitemid = ($fromid === 'editor' ? 0 : $fromid); @@ -391,8 +400,9 @@ class file_storage implements \H5PFileStorage { return; // File exists, no need to copy } - // Grab current context - $context = \context_course::instance($COURSE->id); + // Grab context for cm + $cm = \get_coursemodule_from_instance('hvp', $toid); + $context = \context_module::instance($cm->id); // Create new file record $record = array( @@ -545,10 +555,9 @@ class file_storage implements \H5PFileStorage { * @param string $file path + name */ private function getFile($filearea, $itemid, $file) { - global $COURSE; - - // Grab current context - $context = \context_course::instance($COURSE->id); + // Grab cm context + $cm = \get_coursemodule_from_instance('hvp', $itemid); + $context = \context_module::instance($cm->id); // Load file $fs = get_file_storage(); diff --git a/db/upgrade.php b/db/upgrade.php index 2cb8137..4162891 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -149,5 +149,36 @@ function xmldb_hvp_upgrade($oldversion) { upgrade_mod_savepoint(true, 2016051000, 'hvp'); } + if ($oldversion < 2016080903) { + + // Change context of activity files from COURSE to MODULE. + + $filearea = 'content'; + $component = 'mod_hvp'; + + // Find activity ID and correct context ID + $hvpsresult = $DB->get_records_sql( + "SELECT f.id AS fileid, f.itemid, c.id, f.filepath, f.filename, f.pathnamehash + FROM {files} f + JOIN {course_modules} cm ON f.itemid = cm.instance + JOIN {modules} md ON md.id = cm.module + JOIN {context} c ON c.instanceid = cm.id + WHERE md.name = 'hvp' + AND f.filearea = 'content' + AND c.contextlevel = " . CONTEXT_MODULE + ); + + foreach ($hvpsresult as $hvp) { + // Need to re-hash pathname after changing context + $pathnamehash = file_storage::get_pathname_hash($hvp->id, $component, $filearea, $hvp->itemid, $hvp->filepath, $hvp->filename); + + // Update context ID and pathname hash for files + $DB->execute("UPDATE {files} SET contextid = {$hvp->id}, pathnamehash = '{$pathnamehash}' WHERE pathnamehash = '{$hvp->pathnamehash}'"); + } + + // Hvp savepoint reached. + upgrade_mod_savepoint(true, 2016080903, 'hvp'); + } + return true; } diff --git a/lib.php b/lib.php index 9757c2b..99734e0 100644 --- a/lib.php +++ b/lib.php @@ -259,7 +259,7 @@ function hvp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload break; case 'content': - if ($context->contextlevel != CONTEXT_COURSE) { + if ($context->contextlevel != CONTEXT_MODULE) { return false; // Invalid context. } @@ -272,13 +272,25 @@ function hvp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload break; case 'exports': + if ($context->contextlevel != CONTEXT_MODULE) { + return false; // Invalid context. + } + + // Check permissions + if (!has_capability('mod/hvp:getexport', $context)) { + return false; + } + + $itemid = 0; + break; + case 'editor': if ($context->contextlevel != CONTEXT_COURSE) { return false; // Invalid context. } // Check permissions - if (!has_capability('mod/hvp:getexport', $context)) { + if (!has_capability('mod/hvp:addinstance', $context)) { return false; } diff --git a/library b/library index d946f32..c88c049 160000 --- a/library +++ b/library @@ -1 +1 @@ -Subproject commit d946f32b8128ca53b8bf18e5d83fc1bb8459ac12 +Subproject commit c88c049438257b30e61801a940167d8805732ff0 diff --git a/locallib.php b/locallib.php index aada3e3..445640e 100644 --- a/locallib.php +++ b/locallib.php @@ -197,6 +197,13 @@ function hvp_add_editor_assets($id = null) { if ($id !== null) { $settings['editor']['nodeVersionId'] = $id; + + // Find cm context + $cm = \get_coursemodule_from_instance('hvp', $id); + $context = \context_module::instance($cm->id); + + // Override content URL + $settings['contents']['cid-'.$id]['contentUrl'] = "{$CFG->httpswwwroot}/pluginfile.php/{$context->id}/mod_hvp/content/{$id}"; } $PAGE->requires->data_for_js('H5PIntegration', $settings, true); @@ -255,8 +262,8 @@ function hvp_get_cache_buster() { function hvp_restrict_library($libraryid, $restrict) { global $DB; $DB->update_record('hvp_libraries', (object) array( - 'id' => $libraryid, - 'restricted' => $restrict ? 1 : 0 + 'id' => $libraryid, + 'restricted' => $restrict ? 1 : 0 )); } diff --git a/version.php b/version.php index 97cd757..0b28c4b 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016051306; +$plugin->version = 2016080903; $plugin->requires = 2013051403; $plugin->cron = 0; $plugin->component = 'mod_hvp'; diff --git a/view.php b/view.php index 38264c1..7b1bddc 100644 --- a/view.php +++ b/view.php @@ -93,6 +93,9 @@ if (empty($export)) { $content['disable'] |= \H5PCore::DISABLE_DOWNLOAD; } +// Find cm context +$context = \context_module::instance($cm->id); + // Add JavaScript settings for this content. $cid = 'cid-' . $content['id']; $settings['contents'][$cid] = array( @@ -103,6 +106,7 @@ $settings['contents'][$cid] = array( 'title' => $content['title'], 'disable' => $content['disable'], 'url' => "{$CFG->httpswwwroot}/mod/hvp/view.php?id={$id}", + 'contentUrl' => "{$CFG->httpswwwroot}/pluginfile.php/{$context->id}/mod_hvp/content/" . $content['id'], 'contentUserData' => array( 0 => \mod_hvp\content_user_data::load_pre_loaded_user_data($content['id']) ) -- GitLab