Skip to content

Commit

Permalink
MDL-75148 mod_data: Add isplugin info to presets
Browse files Browse the repository at this point in the history
This activity currently supports two different preset types:
- Datapreset plugins, that can be installed copying them to the
mod/data/preset folder.
- Presets saved manually by users.

This commit adds an attribute to the presets to mark them, in order
to identify them later (because, for instance, the plugins can't be
removed).

Apart from that, the methods in lib.php, involved with this issue, have
been deprecated. New methods have been implemented in the manager class,
covering them with PHPUnit tests.
  • Loading branch information
sarjona committed Aug 1, 2022
1 parent abeae6a commit 9d10f7d
Show file tree
Hide file tree
Showing 9 changed files with 509 additions and 89 deletions.
10 changes: 7 additions & 3 deletions mod/data/classes/form/save_as_preset.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use moodle_exception;
use moodle_url;
use core_form\dynamic_form;
use mod_data\manager;

/**
* Save database as preset form.
Expand Down Expand Up @@ -72,9 +73,11 @@ public function validation($formdata, $files): array {

$errors = parent::validation($formdata, $files);
$context = $this->get_context_for_dynamic_submission();
$cm = get_coursemodule_from_id('', $context->instanceid, 0, false, MUST_EXIST);
$manager = manager::create_from_coursemodule($cm);

if (!empty($formdata['overwrite'])) {
$presets = data_get_available_presets($context);
$presets = $manager->get_available_presets();
$selectedpreset = new \stdClass();
foreach ($presets as $preset) {
if ($preset->name == $formdata['name']) {
Expand All @@ -87,7 +90,7 @@ public function validation($formdata, $files): array {
}
} else {
// If the preset exists now then we need to throw an error.
$sitepresets = data_get_available_site_presets($context);
$sitepresets = $manager->get_available_saved_presets();
foreach ($sitepresets as $preset) {
if ($formdata['name'] == $preset->name) {
$errors['name'] = get_string('errorpresetexists', 'data');
Expand Down Expand Up @@ -137,7 +140,8 @@ public function process_dynamic_submission(): array {

try {
if (!empty($this->get_data()->overwrite)) {
$presets = data_get_available_presets($context);
$manager = manager::create_from_coursemodule($cm);
$presets = $manager->get_available_presets();
$selectedpreset = new \stdClass();
foreach ($presets as $preset) {
if ($preset->name == $this->get_data()->name) {
Expand Down
78 changes: 78 additions & 0 deletions mod/data/classes/manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use mod_data\event\course_module_viewed;
use mod_data\event\template_viewed;
use mod_data\event\template_updated;
use core_component;
use stdClass;

/**
Expand Down Expand Up @@ -300,4 +301,81 @@ public function update_templates(stdClass $newtemplates): bool {

return true;
}

/**
* Returns an array of all the available presets.
*
* @return array A list with the datapreset plugins and the presets saved by users.
*/
public function get_available_presets(): array {
// First load the datapreset plugins that exist within the modules preset dir.
$pluginpresets = static::get_available_plugin_presets();

// Then find the presets that people have saved.
$savedpresets = static::get_available_saved_presets();

return array_merge($pluginpresets, $savedpresets);
}

/**
* Returns an array of all the presets that users have saved to the site.
*
* @return array A list with the preset saved by the users.
*/
public function get_available_saved_presets(): array {
global $USER;

$presets = [];

$fs = get_file_storage();
$files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA);
if (empty($files)) {
return $presets;
}
$canviewall = has_capability('mod/data:viewalluserpresets', $this->get_context());
foreach ($files as $file) {
$isnotdirectory = ($file->is_directory() && $file->get_filepath() == '/') || !$file->is_directory();
$userid = $file->get_userid();
$cannotviewfile = !$canviewall && $userid != $USER->id;
if ($isnotdirectory || $cannotviewfile) {
continue;
}

$preset = new stdClass();
$preset->isplugin = false;
$preset->path = $file->get_filepath();
$preset->name = trim($preset->path, '/');
$preset->shortname = $preset->name;
$preset->userid = $userid;
$preset->id = $file->get_id();
$preset->storedfile = $file;
$presets[] = $preset;
}

return $presets;
}

/**
* Returns an array of all the available plugin presets.
*
* @return array A list with the datapreset plugins.
*/
public static function get_available_plugin_presets(): array {
$presets = [];

$dirs = core_component::get_plugin_list('datapreset');
foreach ($dirs as $dir => $fulldir) {
if (preset::is_directory_a_preset($fulldir)) {
$preset = new stdClass();
$preset->isplugin = true;
$preset->path = $fulldir;
$preset->userid = 0;
$preset->shortname = $dir;
$preset->name = preset::get_name_from_plugin($dir);
$presets[] = $preset;
}
}

return $presets;
}
}
58 changes: 58 additions & 0 deletions mod/data/classes/preset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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 mod_data;

/**
* Class preset for database activity.
*
* @package mod_data
* @copyright 2022 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class preset {

/**
* Checks if a directory contains all the required files to define a preset.
*
* @param string $directory The patch to check if it contains the preset files or not.
* @return bool True if the directory contains all the preset files; false otherwise.
*/
public static function is_directory_a_preset(string $directory): bool {
$status = true;
$directory = rtrim($directory, '/\\') . '/';
$presetfilenames = array_merge(array_values(manager::TEMPLATES_LIST), ['preset.xml']);
foreach ($presetfilenames as $filename) {
$status &= file_exists($directory.$filename);
}

return $status;
}

/**
* Returns the best name to show for a datapreset plugin.
*
* @param string $pluginname The datapreset plugin name.
* @return string The plugin preset name to display.
*/
public static function get_name_from_plugin(string $pluginname): string {
if (get_string_manager()->string_exists('modulename', 'datapreset_'.$pluginname)) {
return get_string('modulename', 'datapreset_'.$pluginname);
} else {
return $pluginname;
}
}
}
12 changes: 7 additions & 5 deletions mod/data/field.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* @package mod_data
*/

use mod_data\manager;

require_once('../../config.php');
require_once('lib.php');
require_once($CFG->dirroot.'/mod/data/preset_form.php');
Expand Down Expand Up @@ -94,7 +96,8 @@

require_login($course, true, $cm);

$context = context_module::instance($cm->id);
$manager = manager::create_from_coursemodule($cm);
$context = $manager->get_context();
require_capability('mod/data:managetemplates', $context);

$formimportzip = new data_import_preset_zip_form();
Expand Down Expand Up @@ -315,10 +318,10 @@
}
} else {
echo $OUTPUT->heading(get_string('presets', 'data'), 2, 'mb-4');
$presets = data_get_available_presets($context);
$presetstable = new \mod_data\output\presets($data->id, $presets,
$presets = $manager->get_available_presets();
$presetsdata = new \mod_data\output\presets($data->id, $presets,
new \moodle_url('/mod/data/field.php'));
echo $renderer->render_presets($presetstable, false);
echo $renderer->render_presets($presetsdata);
}
echo $OUTPUT->footer();
exit;
Expand Down Expand Up @@ -463,4 +466,3 @@

/// Finish the page
echo $OUTPUT->footer();

107 changes: 36 additions & 71 deletions mod/data/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/

use mod_data\manager;
use mod_data\preset;

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

Expand Down Expand Up @@ -2030,52 +2031,30 @@ function data_convert_to_roles($data, $teacherroles=array(), $studentroles=array
* @param string $shortname
* @param string $path
* @return string
* @deprecated since Moodle 4.1 MDL-75148 - please, use the preset::get_name_from_plugin() function instead.
* @todo MDL-75189 This will be deleted in Moodle 4.5.
* @see preset::get_name_from_plugin()
*/
function data_preset_name($shortname, $path) {
debugging('data_preset_name() is deprecated. Please use preset::get_name_from_plugin() instead.', DEBUG_DEVELOPER);

// We are looking inside the preset itself as a first choice, but also in normal data directory
$string = get_string('modulename', 'datapreset_'.$shortname);

if (substr($string, 0, 1) == '[') {
return $shortname;
} else {
return $string;
}
return preset::get_name_from_plugin($shortname);
}

/**
* Returns an array of all the available presets.
*
* @return array
* @deprecated since Moodle 4.1 MDL-75148 - please, use the manager::get_available_presets() function instead.
* @todo MDL-75189 This will be deleted in Moodle 4.5.
* @see manager::get_available_presets()
*/
function data_get_available_presets($context) {
global $CFG, $USER;

$presets = array();

// First load the ratings sub plugins that exist within the modules preset dir
if ($dirs = core_component::get_plugin_list('datapreset')) {
foreach ($dirs as $dir=>$fulldir) {
if (is_directory_a_preset($fulldir)) {
$preset = new stdClass();
$preset->path = $fulldir;
$preset->userid = 0;
$preset->shortname = $dir;
$preset->name = data_preset_name($dir, $fulldir);
if (file_exists($fulldir.'/screenshot.jpg')) {
$preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
} else if (file_exists($fulldir.'/screenshot.png')) {
$preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png';
} else if (file_exists($fulldir.'/screenshot.gif')) {
$preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif';
}
$presets[] = $preset;
}
}
}
// Now add to that the site presets that people have saved
$presets = data_get_available_site_presets($context, $presets);
return $presets;
debugging('data_get_available_presets() is deprecated. Please use manager::get_available_presets() instead.', DEBUG_DEVELOPER);

$cm = get_coursemodule_from_id('', $context->instanceid, 0, false, MUST_EXIST);
$manager = manager::create_from_coursemodule($cm);
return $manager->get_available_presets();
}

/**
Expand All @@ -2084,30 +2063,20 @@ function data_get_available_presets($context) {
* @param stdClass $context The context that we are looking from.
* @param array $presets
* @return array An array of presets
* @deprecated since Moodle 4.1 MDL-75148 - please, use the manager::get_available_saved_presets() function instead.
* @todo MDL-75189 This will be deleted in Moodle 4.5.
* @see manager::get_available_saved_presets()
*/
function data_get_available_site_presets($context, array $presets=array()) {
global $USER;
debugging(
'data_get_available_site_presets() is deprecated. Please use manager::get_available_saved_presets() instead.',
DEBUG_DEVELOPER
);

$fs = get_file_storage();
$files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA);
$canviewall = has_capability('mod/data:viewalluserpresets', $context);
if (empty($files)) {
return $presets;
}
foreach ($files as $file) {
if (($file->is_directory() && $file->get_filepath()=='/') || !$file->is_directory() || (!$canviewall && $file->get_userid() != $USER->id)) {
continue;
}
$preset = new stdClass;
$preset->path = $file->get_filepath();
$preset->name = trim($preset->path, '/');
$preset->shortname = $preset->name;
$preset->userid = $file->get_userid();
$preset->id = $file->get_id();
$preset->storedfile = $file;
$presets[] = $preset;
}
return $presets;
$cm = get_coursemodule_from_id('', $context->instanceid, 0, false, MUST_EXIST);
$manager = manager::create_from_coursemodule($cm);
$savedpresets = $manager->get_available_saved_presets();
return array_merge($presets, $savedpresets);
}

/**
Expand Down Expand Up @@ -2261,22 +2230,18 @@ function data_in_readonly_period($data) {
}

/**
* @return bool
* Check if the files in a directory are the expected for a preset.
*
* @return bool Wheter the defined $directory has or not all the expected preset files.
*
* @deprecated since Moodle 4.1 MDL-75148 - please, use the preset::is_directory_a_preset() function instead.
* @todo MDL-75189 This will be deleted in Moodle 4.5.
* @see manager::is_directory_a_preset()
*/
function is_directory_a_preset($directory) {
$directory = rtrim($directory, '/\\') . '/';
$status = file_exists($directory.'singletemplate.html') &&
file_exists($directory.'listtemplate.html') &&
file_exists($directory.'listtemplateheader.html') &&
file_exists($directory.'listtemplatefooter.html') &&
file_exists($directory.'addtemplate.html') &&
file_exists($directory.'rsstemplate.html') &&
file_exists($directory.'rsstitletemplate.html') &&
file_exists($directory.'csstemplate.css') &&
file_exists($directory.'jstemplate.js') &&
file_exists($directory.'preset.xml');
debugging('is_directory_a_preset() is deprecated. Please use preset::is_directory_a_preset() instead.', DEBUG_DEVELOPER);

return $status;
return preset::is_directory_a_preset($directory);
}

/**
Expand Down Expand Up @@ -2350,7 +2315,7 @@ public function get_preset_settings() {
require_once($CFG->libdir.'/xmlize.php');

$fs = $fileobj = null;
if (!is_directory_a_preset($this->directory)) {
if (!preset::is_directory_a_preset($this->directory)) {
//maybe the user requested a preset stored in the Moodle file storage

$fs = get_file_storage();
Expand Down Expand Up @@ -3650,7 +3615,7 @@ function data_presets_export($course, $cm, $data, $tostorage=false) {
fclose($asearchtemplate);

// Check if all files have been generated
if (! is_directory_a_preset($exportdir)) {
if (! preset::is_directory_a_preset($exportdir)) {
throw new \moodle_exception('generateerror', 'data');
}

Expand Down
Loading

0 comments on commit 9d10f7d

Please sign in to comment.