Merge branch 'MDL-75148-master' of https://github.com/sarjona/moodle
This commit is contained in:
+3
-2
@@ -1,10 +1,11 @@
|
||||
define("mod_data/selectpreset",["exports","core/notification","core/str"],(function(_exports,_notification,_str){var obj;
|
||||
define("mod_data/selectpreset",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;
|
||||
/**
|
||||
* Javascript module to control the form responsible for selecting a preset.
|
||||
*
|
||||
* @module mod_data/selectpreset
|
||||
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};const selectors_selectPresetButton='input[name="selectpreset"]',selectors_selectedPresetRadioButton='input[name="fullname"]:checked';_exports.init=()=>{document.querySelector(selectors_selectPresetButton).addEventListener("click",(event=>{if(event.preventDefault(),document.querySelectorAll(selectors_selectedPresetRadioButton).length>0){event.target.closest("form").submit()}else(0,_str.get_string)("presetnotselected","mod_data").then((str=>_notification.default.addNotification({type:"error",message:str}))).catch(_notification.default.exception)}))}}));
|
||||
*/
|
||||
const selectors_presetRadioButton='input[name="fullname"]',selectors_selectPresetButton='input[name="selectpreset"]',selectors_selectedPresetRadioButton='input[name="fullname"]:checked';_exports.init=()=>{const radioButton=document.querySelectorAll(selectors_presetRadioButton);disableUsePresetButton(),radioButton.forEach((elem=>{elem.addEventListener("change",(function(event){event.preventDefault(),disableUsePresetButton()}))}))};const disableUsePresetButton=()=>{let selectPresetButton=document.querySelector(selectors_selectPresetButton);document.querySelectorAll(selectors_selectedPresetRadioButton).length>0?(selectPresetButton.removeAttribute("disabled"),selectPresetButton.classList.remove("btn-secondary"),selectPresetButton.classList.add("btn-primary")):(selectPresetButton.setAttribute("disabled",!0),selectPresetButton.classList.remove("btn-primary"),selectPresetButton.classList.add("btn-secondary"))}}));
|
||||
|
||||
//# sourceMappingURL=selectpreset.min.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"selectpreset.min.js","sources":["../src/selectpreset.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript module to control the form responsible for selecting a preset.\n *\n * @module mod_data/selectpreset\n * @copyright 2021 Mihail Geshoski <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\n\nconst selectors = {\n selectPresetButton: 'input[name=\"selectpreset\"]',\n selectedPresetRadioButton: 'input[name=\"fullname\"]:checked',\n};\n\n/**\n * Initialize module.\n */\nexport const init = () => {\n const selectPresetButton = document.querySelector(selectors.selectPresetButton);\n\n selectPresetButton.addEventListener('click', event => {\n event.preventDefault();\n // Validate whether there is a selected preset before submitting the form.\n if (document.querySelectorAll(selectors.selectedPresetRadioButton).length > 0) {\n const presetsForm = event.target.closest('form');\n presetsForm.submit();\n } else {\n // No selected presets. Display an error message to user.\n getString('presetnotselected', 'mod_data').then((str) => {\n return Notification.addNotification({\n type: 'error',\n message: str\n });\n }).catch(Notification.exception);\n }\n });\n};\n"],"names":["selectors","document","querySelector","addEventListener","event","preventDefault","querySelectorAll","length","target","closest","submit","then","str","Notification","addNotification","type","message","catch","exception"],"mappings":";;;;;;;4JA0BMA,6BACkB,6BADlBA,oCAEyB,+CAMX,KACWC,SAASC,cAAcF,8BAE/BG,iBAAiB,SAASC,WACzCA,MAAMC,iBAEFJ,SAASK,iBAAiBN,qCAAqCO,OAAS,EAAG,CACvDH,MAAMI,OAAOC,QAAQ,QAC7BC,iCAGF,oBAAqB,YAAYC,MAAMC,KACtCC,sBAAaC,gBAAgB,CAChCC,KAAM,QACNC,QAASJ,QAEdK,MAAMJ,sBAAaK"}
|
||||
{"version":3,"file":"selectpreset.min.js","sources":["../src/selectpreset.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript module to control the form responsible for selecting a preset.\n *\n * @module mod_data/selectpreset\n * @copyright 2021 Mihail Geshoski <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst selectors = {\n presetRadioButton: 'input[name=\"fullname\"]',\n selectPresetButton: 'input[name=\"selectpreset\"]',\n selectedPresetRadioButton: 'input[name=\"fullname\"]:checked',\n};\n\n/**\n * Initialize module.\n */\nexport const init = () => {\n const radioButton = document.querySelectorAll(selectors.presetRadioButton);\n\n // Initialize the \"Use preset\" button properly.\n disableUsePresetButton();\n\n radioButton.forEach((elem) => {\n elem.addEventListener('change', function(event) {\n event.preventDefault();\n // Enable the \"Use preset\" button when any of the radio buttons in the presets list is checked.\n disableUsePresetButton();\n });\n });\n\n};\n\n/**\n * Decide whether to disable or not the \"Use preset\" button.\n * When there is no preset selected, the button should be displayed disabled; otherwise, it will appear enabled as a primary button.\n *\n * @method\n * @private\n */\nconst disableUsePresetButton = () => {\n let selectPresetButton = document.querySelector(selectors.selectPresetButton);\n const selectedRadioButton = document.querySelectorAll(selectors.selectedPresetRadioButton);\n\n if (selectedRadioButton.length > 0) {\n // There is one preset selected, so the button should be enabled.\n selectPresetButton.removeAttribute('disabled');\n selectPresetButton.classList.remove('btn-secondary');\n selectPresetButton.classList.add('btn-primary');\n } else {\n // There is no any preset selected, so the button should be disabled.\n selectPresetButton.setAttribute('disabled', true);\n selectPresetButton.classList.remove('btn-primary');\n selectPresetButton.classList.add('btn-secondary');\n }\n};\n"],"names":["selectors","radioButton","document","querySelectorAll","disableUsePresetButton","forEach","elem","addEventListener","event","preventDefault","selectPresetButton","querySelector","length","removeAttribute","classList","remove","add","setAttribute"],"mappings":";;;;;;;;MAuBMA,4BACiB,yBADjBA,6BAEkB,6BAFlBA,oCAGyB,+CAMX,WACVC,YAAcC,SAASC,iBAAiBH,6BAG9CI,yBAEAH,YAAYI,SAASC,OACjBA,KAAKC,iBAAiB,UAAU,SAASC,OACrCA,MAAMC,iBAENL,sCAaNA,uBAAyB,SACvBM,mBAAqBR,SAASS,cAAcX,8BACpBE,SAASC,iBAAiBH,qCAE9BY,OAAS,GAE7BF,mBAAmBG,gBAAgB,YACnCH,mBAAmBI,UAAUC,OAAO,iBACpCL,mBAAmBI,UAAUE,IAAI,iBAGjCN,mBAAmBO,aAAa,YAAY,GAC5CP,mBAAmBI,UAAUC,OAAO,eACpCL,mBAAmBI,UAAUE,IAAI"}
|
||||
@@ -21,10 +21,8 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import Notification from 'core/notification';
|
||||
import {get_string as getString} from 'core/str';
|
||||
|
||||
const selectors = {
|
||||
presetRadioButton: 'input[name="fullname"]',
|
||||
selectPresetButton: 'input[name="selectpreset"]',
|
||||
selectedPresetRadioButton: 'input[name="fullname"]:checked',
|
||||
};
|
||||
@@ -33,22 +31,41 @@ const selectors = {
|
||||
* Initialize module.
|
||||
*/
|
||||
export const init = () => {
|
||||
const selectPresetButton = document.querySelector(selectors.selectPresetButton);
|
||||
const radioButton = document.querySelectorAll(selectors.presetRadioButton);
|
||||
|
||||
selectPresetButton.addEventListener('click', event => {
|
||||
event.preventDefault();
|
||||
// Validate whether there is a selected preset before submitting the form.
|
||||
if (document.querySelectorAll(selectors.selectedPresetRadioButton).length > 0) {
|
||||
const presetsForm = event.target.closest('form');
|
||||
presetsForm.submit();
|
||||
} else {
|
||||
// No selected presets. Display an error message to user.
|
||||
getString('presetnotselected', 'mod_data').then((str) => {
|
||||
return Notification.addNotification({
|
||||
type: 'error',
|
||||
message: str
|
||||
});
|
||||
}).catch(Notification.exception);
|
||||
}
|
||||
// Initialize the "Use preset" button properly.
|
||||
disableUsePresetButton();
|
||||
|
||||
radioButton.forEach((elem) => {
|
||||
elem.addEventListener('change', function(event) {
|
||||
event.preventDefault();
|
||||
// Enable the "Use preset" button when any of the radio buttons in the presets list is checked.
|
||||
disableUsePresetButton();
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Decide whether to disable or not the "Use preset" button.
|
||||
* When there is no preset selected, the button should be displayed disabled; otherwise, it will appear enabled as a primary button.
|
||||
*
|
||||
* @method
|
||||
* @private
|
||||
*/
|
||||
const disableUsePresetButton = () => {
|
||||
let selectPresetButton = document.querySelector(selectors.selectPresetButton);
|
||||
const selectedRadioButton = document.querySelectorAll(selectors.selectedPresetRadioButton);
|
||||
|
||||
if (selectedRadioButton.length > 0) {
|
||||
// There is one preset selected, so the button should be enabled.
|
||||
selectPresetButton.removeAttribute('disabled');
|
||||
selectPresetButton.classList.remove('btn-secondary');
|
||||
selectPresetButton.classList.add('btn-primary');
|
||||
} else {
|
||||
// There is no any preset selected, so the button should be disabled.
|
||||
selectPresetButton.setAttribute('disabled', true);
|
||||
selectPresetButton.classList.remove('btn-primary');
|
||||
selectPresetButton.classList.add('btn-secondary');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ use context;
|
||||
use moodle_exception;
|
||||
use moodle_url;
|
||||
use core_form\dynamic_form;
|
||||
use mod_data\manager;
|
||||
|
||||
/**
|
||||
* Save database as preset form.
|
||||
@@ -72,9 +73,11 @@ class save_as_preset extends dynamic_form {
|
||||
|
||||
$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']) {
|
||||
@@ -87,7 +90,7 @@ class save_as_preset extends dynamic_form {
|
||||
}
|
||||
} 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');
|
||||
@@ -137,7 +140,8 @@ class save_as_preset extends dynamic_form {
|
||||
|
||||
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) {
|
||||
|
||||
@@ -23,6 +23,7 @@ use data_field_base;
|
||||
use mod_data\event\course_module_viewed;
|
||||
use mod_data\event\template_viewed;
|
||||
use mod_data\event\template_updated;
|
||||
use core_component;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
@@ -300,4 +301,81 @@ class manager {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
namespace mod_data\output;
|
||||
|
||||
use action_menu;
|
||||
use action_menu_link_secondary;
|
||||
use moodle_url;
|
||||
use templatable;
|
||||
use renderable;
|
||||
@@ -64,54 +66,69 @@ class presets implements templatable, renderable {
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output): array {
|
||||
|
||||
$presets = $this->get_presets();
|
||||
return [
|
||||
'd' => $this->id,
|
||||
'formactionul' => $this->formactionurl->out(),
|
||||
'presetstable' => $this->get_presets_table(),
|
||||
'showmanage' => $this->manage,
|
||||
'presets' => $presets,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and returns the HTML for the presets table.
|
||||
* Returns the presets list with the information required to display them.
|
||||
*
|
||||
* @return string
|
||||
* @return array Presets list.
|
||||
*/
|
||||
private function get_presets_table(): string {
|
||||
global $OUTPUT, $PAGE, $DB;
|
||||
|
||||
$presetstable = new \html_table();
|
||||
$presetstable->align = ['center', 'left', 'left'];
|
||||
$presetstable->size = ['1%', '90%', '1%'];
|
||||
private function get_presets(): array {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
$presets = [];
|
||||
foreach ($this->presets as $preset) {
|
||||
$presetname = $preset->name;
|
||||
if (!empty($preset->userid)) {
|
||||
// If the preset has the userid field, the full name of creator it will be added to the end of the name.
|
||||
$userfieldsapi = \core_user\fields::for_name();
|
||||
$namefields = $userfieldsapi->get_sql('', false, '', '', false)->selects;
|
||||
$presetuser = $DB->get_record('user', array('id' => $preset->userid), 'id, ' . $namefields, MUST_EXIST);
|
||||
$fields = 'id, ' . $namefields;
|
||||
$presetuser = \core_user::get_user($preset->userid, $fields, MUST_EXIST);
|
||||
$username = fullname($presetuser, true);
|
||||
$presetname = "{$presetname} ({$username})";
|
||||
}
|
||||
|
||||
$deleteaction = '';
|
||||
$actions = [];
|
||||
if ($this->manage) {
|
||||
if (data_user_can_delete_preset($PAGE->context, $preset) && $preset->name != 'Image gallery') {
|
||||
// Only presets saved by users can be removed (so the datapreset plugins shouldn't display the delete button).
|
||||
if (!$preset->isplugin && data_user_can_delete_preset($PAGE->context, $preset)) {
|
||||
$deleteactionurl = new moodle_url('/mod/data/preset.php',
|
||||
['d' => $this->id, 'fullname' => "{$preset->userid}/{$preset->shortname}",
|
||||
'action' => 'confirmdelete']);
|
||||
$deleteaction = $OUTPUT->action_icon($deleteactionurl,
|
||||
new \pix_icon('t/delete', get_string('delete')));
|
||||
|
||||
$actionmenu = new action_menu();
|
||||
$icon = $OUTPUT->pix_icon('i/menu', get_string('actions'));
|
||||
$actionmenu->set_menu_trigger($icon, 'btn btn-icon d-flex align-items-center justify-content-center');
|
||||
$actionmenu->set_action_label(get_string('actions'));
|
||||
$actionmenu->attributes['class'] .= ' presets-actions';
|
||||
|
||||
$actionmenu->add(new action_menu_link_secondary(
|
||||
$deleteactionurl,
|
||||
null,
|
||||
get_string('delete'),
|
||||
));
|
||||
$actions = $actionmenu->export_for_template($OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
$presetstable->data[] = [
|
||||
\html_writer::tag('input', '', array('type' => 'radio', 'name' => 'fullname',
|
||||
'value' => "{$preset->userid}/{$preset->shortname}")),
|
||||
$presetname,
|
||||
$deleteaction,
|
||||
$presets[] = [
|
||||
'id' => $this->id,
|
||||
'name' => $preset->name,
|
||||
'shortname' => $preset->shortname,
|
||||
'fullname' => $presetname,
|
||||
'userid' => $preset->userid,
|
||||
'actions' => $actions,
|
||||
];
|
||||
}
|
||||
|
||||
return \html_writer::table($presetstable);
|
||||
return $presets;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -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');
|
||||
@@ -94,7 +96,8 @@ if ($id) {
|
||||
|
||||
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();
|
||||
@@ -315,10 +318,10 @@ switch ($mode) {
|
||||
}
|
||||
} 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;
|
||||
@@ -463,4 +466,3 @@ if (($mode == 'new') && (!empty($newtype))) { // Adding a new field.
|
||||
|
||||
/// Finish the page
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
@@ -320,6 +320,7 @@ $string['portfolionotfile'] = 'Export to a portfolio rather than a file (csv and
|
||||
$string['presetinfo'] = 'Saving as a preset will publish this template. Other users may be able to use it in their databases.';
|
||||
$string['presetnotselected'] = 'No preset has been selected.';
|
||||
$string['presets'] = 'Presets';
|
||||
$string['presetshelp'] = 'Choose a preset to use as a starting point.';
|
||||
$string['privacy:metadata:commentpurpose'] = 'Comments on database records';
|
||||
$string['privacy:metadata:data_content'] = 'Represents one answer to one field in database activity module';
|
||||
$string['privacy:metadata:data_content:fieldid'] = 'Field definition ID';
|
||||
|
||||
+35
-70
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
use mod_data\manager;
|
||||
use mod_data\preset;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@@ -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;
|
||||
debugging('data_get_available_presets() is deprecated. Please use manager::get_available_presets() instead.', DEBUG_DEVELOPER);
|
||||
|
||||
$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;
|
||||
$cm = get_coursemodule_from_id('', $context->instanceid, 0, false, MUST_EXIST);
|
||||
$manager = manager::create_from_coursemodule($cm);
|
||||
return $manager->get_available_presets();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2350,7 +2315,7 @@ abstract class data_preset_importer {
|
||||
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();
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
+17
-10
@@ -28,21 +28,27 @@
|
||||
* @package mod_data
|
||||
*/
|
||||
|
||||
use mod_data\manager;
|
||||
|
||||
require_once('../../config.php');
|
||||
require_once($CFG->dirroot.'/mod/data/lib.php');
|
||||
require_once($CFG->dirroot.'/mod/data/preset_form.php');
|
||||
|
||||
$id = optional_param('id', 0, PARAM_INT); // The course module id.
|
||||
// The course module id.
|
||||
$id = optional_param('id', 0, PARAM_INT);
|
||||
|
||||
$manager = null;
|
||||
if ($id) {
|
||||
$cm = get_coursemodule_from_id('data', $id, null, null, MUST_EXIST);
|
||||
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
|
||||
$data = $DB->get_record('data', array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
list($course, $cm) = get_course_and_cm_from_cmid($id, manager::MODULE);
|
||||
$manager = manager::create_from_coursemodule($cm);
|
||||
$data = $manager->get_instance();
|
||||
} else {
|
||||
$d = required_param('d', PARAM_INT); // database activity id
|
||||
$data = $DB->get_record('data', array('id' => $d), '*', MUST_EXIST);
|
||||
$course = $DB->get_record('course', array('id' => $data->course), '*', MUST_EXIST);
|
||||
$cm = get_coursemodule_from_instance('data', $data->id, $course->id, null, MUST_EXIST);
|
||||
// We must have the database activity id.
|
||||
$d = required_param('d', PARAM_INT);
|
||||
$data = $DB->get_record('data', ['id' => $d], '*', MUST_EXIST);
|
||||
$manager = manager::create_from_instance($data);
|
||||
$cm = $manager->get_coursemodule();
|
||||
$course = get_course($cm->course);
|
||||
}
|
||||
|
||||
$action = optional_param('action', 'view', PARAM_ALPHA); // The page action.
|
||||
@@ -52,7 +58,8 @@ if (!in_array($action, $allowedactions)) {
|
||||
throw new moodle_exception('invalidaccess');
|
||||
}
|
||||
|
||||
$context = context_module::instance($cm->id, MUST_EXIST);
|
||||
$context = $manager->get_context();
|
||||
|
||||
require_login($course, false, $cm);
|
||||
require_capability('mod/data:managetemplates', $context);
|
||||
|
||||
@@ -70,7 +77,7 @@ $data->cmidnumber = $cm->idnumber;
|
||||
$data->instance = $cm->instance;
|
||||
|
||||
$renderer = $PAGE->get_renderer('mod_data');
|
||||
$presets = data_get_available_presets($context);
|
||||
$presets = $manager->get_available_presets();
|
||||
|
||||
if ($action === 'export') {
|
||||
if (headers_sent()) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<div class="defaulttemplate"><table class="mod-data-default-template">
|
||||
<tbody><tr class="r0">
|
||||
<td class="template-field cell c0">Title: </td>
|
||||
<td class="template-token cell c1 lastcol">[[title]]</td>
|
||||
</tr>
|
||||
<tr class="r1">
|
||||
<td class="template-field cell c0">Caption: </td>
|
||||
<td class="template-token cell c1 lastcol">[[caption]]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -148,3 +148,7 @@
|
||||
#page-mod-data-edit .datatagcontrol {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.preset_action_menu .dropdown-toggle::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -19,22 +19,69 @@
|
||||
Context variables required for this template:
|
||||
* formactionul - The form action url.
|
||||
* d - The database id.
|
||||
* presetstable - The HTML output of the table with presets
|
||||
* presets - List of presets containing id, name, fullname, shortname and actions.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"formactionul": "http://www.example.com",
|
||||
"d": 1,
|
||||
"presetstable": "<table></table>"
|
||||
"presets": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Image gallery",
|
||||
"shortname": "imagegallery",
|
||||
"fullname": "Image gallery",
|
||||
"userid": 0,
|
||||
"actions": []
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Preset saved manually",
|
||||
"shortname": "Preset saved manually",
|
||||
"fullname": "Preset saved manually (admin)",
|
||||
"userid": 2,
|
||||
"actions": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
{{#str}}presetshelp, mod_data{{/str}}
|
||||
|
||||
<form method="post" action="{{formactionul}}" class="mt-4">
|
||||
<input type="hidden" name="d" value="{{d}}">
|
||||
<input type="hidden" name="mode" value="usepreset">
|
||||
<input type="hidden" name="action" value="select">
|
||||
{{{presetstable}}}
|
||||
<input type="submit" name="selectpreset" value="{{#str}}usepreset, mod_data{{/str}}" class="btn btn-primary mt-2">
|
||||
|
||||
<table id="presets-list" class="generaltable fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="pl-4 border-top-0" scope="col" style="width: 3%"></th>
|
||||
<th class="pl-4 border-top-0" scope="col">{{#str}} name {{/str}}</th>
|
||||
<th class="pl-4 border-top-0" scope="col" style="width: 3%">{{#showmanage}}{{#str}} action {{/str}}{{/showmanage}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#presets}}
|
||||
<tr>
|
||||
<td class="p-4 border-right">
|
||||
<input type="radio" name="fullname" value="{{userid}}/{{shortname}}" />
|
||||
</td>
|
||||
<td class="p-4">{{fullname}}</td>
|
||||
<td class="p-4 preset_action_menu">
|
||||
{{#actions}}
|
||||
<div class="float-right">
|
||||
{{>core/action_menu}}
|
||||
</div>
|
||||
{{/actions}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/presets}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<input type="submit" name="selectpreset" value="{{#str}}usepreset, mod_data{{/str}}" class="btn btn-secondary mt-2 float-right" disabled>
|
||||
</form>
|
||||
|
||||
{{#js}}
|
||||
require(['mod_data/selectpreset'], function(selectPreset) {
|
||||
selectPreset.init();
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
}}
|
||||
<div class="container-fluid tertiary-navigation">
|
||||
<div class="row">
|
||||
<div class="row float-right">
|
||||
<div class="navitem">
|
||||
<a href="{{importpreseturl}}" class="btn btn-secondary">{{#str}}import, core{{/str}}</a>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
@mod @mod_data
|
||||
Feature: Users can view and manage data presets
|
||||
In order to use presets
|
||||
As a user
|
||||
I need to view, manage and use presets
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| data | Mountain landscapes | n | C1 | data1 |
|
||||
And the following "mod_data > presets" exist:
|
||||
| database | name |
|
||||
| data1 | Saved preset 1 |
|
||||
| data1 | Saved preset 2 |
|
||||
|
||||
@javascript
|
||||
Scenario: Admins can delete saved presets
|
||||
Given I am on the "Mountain landscapes" "data activity" page logged in as admin
|
||||
When I follow "Presets"
|
||||
Then I should see "Choose a preset to use as a starting point."
|
||||
And I should see "Image gallery"
|
||||
And I should see "Saved preset 1"
|
||||
And I should see "Saved preset 2"
|
||||
# Plugin presets can't be removed.
|
||||
And I should not see "Actions" in the "Image gallery" "table_row"
|
||||
# The admin should be able to delete saved presets.
|
||||
But I open the action menu in "Saved preset 1" "table_row"
|
||||
And I should see "Delete"
|
||||
And I open the action menu in "Saved preset 2" "table_row"
|
||||
And I should see "Delete"
|
||||
|
||||
@javascript
|
||||
Scenario: Teachers can see and use presets
|
||||
Given the following "mod_data > fields" exist:
|
||||
| database | type | name | description |
|
||||
| data1 | text | Test field name | Test field description |
|
||||
And I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Templates"
|
||||
And I click on "Save as preset" "button"
|
||||
And I set the field "Name" to "Saved preset by teacher1"
|
||||
And I click on "Save" "button" in the "Save all fields and templates as preset" "dialogue"
|
||||
When I follow "Presets"
|
||||
Then I should see "Choose a preset to use as a starting point."
|
||||
And I should see "Image gallery"
|
||||
And I should see "Saved preset 1"
|
||||
And I should see "Saved preset 2"
|
||||
And I should see "Saved preset by teacher1"
|
||||
# Plugin presets can't be removed.
|
||||
And I should not see "Actions" in the "Image gallery" "table_row"
|
||||
# Teachers should be able to delete their saved presets.
|
||||
And I open the action menu in "Saved preset by teacher1" "table_row"
|
||||
And I should see "Delete"
|
||||
# Teachers can't delete the presets they haven't created.
|
||||
And I should not see "Actions" in the "Saved preset 1" "table_row"
|
||||
# The "Use preset" button should be enabled only when a preset is selected.
|
||||
And the "Use preset" "button" should be disabled
|
||||
And I click on "fullname" "radio" in the "Image gallery" "table_row"
|
||||
And the "Use preset" "button" should be enabled
|
||||
|
||||
@javascript
|
||||
Scenario: Only users with the viewalluserpresets capability can see presets created by other users
|
||||
Given the following "permission override" exists:
|
||||
| role | editingteacher |
|
||||
| capability | mod/data:viewalluserpresets |
|
||||
| permission | Prohibit |
|
||||
| contextlevel | System |
|
||||
| reference | |
|
||||
When I am on the "Mountain landscapes" "data activity" page logged in as teacher1
|
||||
And I follow "Presets"
|
||||
Then I should see "Image gallery"
|
||||
And I should not see "Saved preset 1"
|
||||
And I should not see "Saved preset 2"
|
||||
@@ -49,6 +49,12 @@ class behat_mod_data_generator extends behat_generator_base {
|
||||
'required' => ['database', 'name'],
|
||||
'switchids' => ['database' => 'databaseid'],
|
||||
],
|
||||
'presets' => [
|
||||
'singular' => 'preset',
|
||||
'datagenerator' => 'preset',
|
||||
'required' => ['database', 'name'],
|
||||
'switchids' => ['database' => 'databaseid'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -124,6 +130,19 @@ class behat_mod_data_generator extends behat_generator_base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a preset.
|
||||
*
|
||||
* @param array $data Preset data.
|
||||
*/
|
||||
protected function process_preset(array $data): void {
|
||||
global $DB;
|
||||
|
||||
$instance = $DB->get_record('data', ['id' => $data['databaseid']], '*', MUST_EXIST);
|
||||
|
||||
$this->get_data_generator()->create_preset($instance, (object) $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the module data generator.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use mod_data\manager;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
@@ -361,4 +363,28 @@ class mod_data_generator extends testing_module_generator {
|
||||
|
||||
return $recordid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a preset from a mod_data instance.
|
||||
*
|
||||
* @param stdClass $instance The mod_data instance.
|
||||
* @param stdClass|null $record The preset information, like 'name'.
|
||||
* @return bool Whether the preset has been created or not.
|
||||
*/
|
||||
public function create_preset(stdClass $instance, stdClass $record = null): bool {
|
||||
global $DB;
|
||||
|
||||
if (is_null($record)) {
|
||||
$record = new stdClass();
|
||||
}
|
||||
|
||||
// Fill in optional values if not specified.
|
||||
if (!isset($record->name)) {
|
||||
$record->name = 'New preset ' . microtime();
|
||||
}
|
||||
|
||||
$course = $DB->get_record('course', ['id' => $instance->course], '*', MUST_EXIST);
|
||||
$cm = get_coursemodule_from_instance(manager::MODULE, $instance->id, $course->id, null, MUST_EXIST);
|
||||
return data_presets_save($course, $cm, $instance, $record->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace mod_data;
|
||||
* @category phpunit
|
||||
* @copyright 2012 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \mod_data_generator
|
||||
*/
|
||||
class generator_test extends \advanced_testcase {
|
||||
public function test_generator() {
|
||||
@@ -229,4 +230,46 @@ class generator_test extends \advanced_testcase {
|
||||
$this->assertEquals(array('Cats', 'mice'),
|
||||
array_values(\core_tag_tag::get_item_tags_array('mod_data', 'data_records', $datarecordid)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for create_preset().
|
||||
*
|
||||
* @covers ::create_preset
|
||||
*/
|
||||
public function test_create_preset() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
$cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
|
||||
|
||||
// Check initially there are no saved presets.
|
||||
$manager = manager::create_from_coursemodule($cm);
|
||||
$savedpresets = $manager->get_available_saved_presets();
|
||||
$this->assertEmpty($savedpresets);
|
||||
|
||||
// Create one preset with the default configuration.
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$result = $plugingenerator->create_preset($activity);
|
||||
$this->assertTrue($result);
|
||||
$savedpresets = $manager->get_available_saved_presets();
|
||||
$this->assertCount(1, $savedpresets);
|
||||
$preset = reset($savedpresets);
|
||||
$this->assertStringStartsWith('New preset', $preset->name);
|
||||
|
||||
// Create another preset with a specific name.
|
||||
$record = (object) [
|
||||
'name' => 'World recipes preset',
|
||||
];
|
||||
$result = $plugingenerator->create_preset($activity, $record);
|
||||
$this->assertTrue($result);
|
||||
$savedpresets = $manager->get_available_saved_presets();
|
||||
$this->assertCount(2, $savedpresets);
|
||||
foreach ($savedpresets as $preset) {
|
||||
if (!str_starts_with($preset->name, 'New preset')) {
|
||||
$this->assertEquals('World recipes preset', $preset->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace mod_data;
|
||||
|
||||
use context_module;
|
||||
use moodle_url;
|
||||
use core_component;
|
||||
|
||||
/**
|
||||
* Manager tests class for mod_data.
|
||||
@@ -161,4 +162,215 @@ class manager_test extends \advanced_testcase {
|
||||
$this->assertEventContextNotUsed($event);
|
||||
$this->assertNotEmpty($event->get_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for get_available_presets().
|
||||
*
|
||||
* @covers ::get_available_presets
|
||||
*/
|
||||
public function test_get_available_presets() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
|
||||
$this->setUser($user);
|
||||
|
||||
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
$cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
|
||||
|
||||
// Check available presets meet the datapreset plugins when there are no any preset saved by users.
|
||||
$datapresetplugins = core_component::get_plugin_list('datapreset');
|
||||
$manager = manager::create_from_coursemodule($cm);
|
||||
$presets = $manager->get_available_presets();
|
||||
$this->assertCount(count($datapresetplugins), $presets);
|
||||
// Confirm that, at least, the "Image gallery" is one of them.
|
||||
$namepresets = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $presets);
|
||||
$this->assertContains('Image gallery', $namepresets);
|
||||
|
||||
// Login as admin and create some presets saved manually by users.
|
||||
$this->setAdminUser();
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$savedpresets = [];
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
$preset = (object) [
|
||||
'name' => 'Preset name ' . $i,
|
||||
];
|
||||
$plugingenerator->create_preset($activity, $preset);
|
||||
$savedpresets[] = $preset;
|
||||
}
|
||||
$savedpresetsnames = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $savedpresets);
|
||||
$this->setUser($user);
|
||||
|
||||
// Check available presets meet the datapreset plugins + presets saved manually by users.
|
||||
$presets = $manager->get_available_presets();
|
||||
$this->assertCount(count($datapresetplugins) + count($savedpresets), $presets);
|
||||
// Confirm that, apart from the "Image gallery" preset, the ones created manually have been also returned.
|
||||
$namepresets = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $presets);
|
||||
$this->assertContains('Image gallery', $namepresets);
|
||||
foreach ($savedpresets as $savedpreset) {
|
||||
$this->assertContains($savedpreset->name, $namepresets);
|
||||
}
|
||||
// Check all the presets have the proper value for the isplugin attribute.
|
||||
foreach ($presets as $preset) {
|
||||
if (in_array($preset->name, $savedpresetsnames)) {
|
||||
$this->assertFalse($preset->isplugin);
|
||||
} else {
|
||||
$this->assertTrue($preset->isplugin);
|
||||
}
|
||||
}
|
||||
|
||||
// Unassign the capability to the teacher role and check that only plugin presets are returned (because the saved presets
|
||||
// have been created by admin).
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
|
||||
unassign_capability('mod/data:viewalluserpresets', $teacherrole->id);
|
||||
$presets = $manager->get_available_presets();
|
||||
$this->assertCount(count($datapresetplugins), $presets);
|
||||
// Confirm that, at least, the "Image gallery" is one of them.
|
||||
$namepresets = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $presets);
|
||||
$this->assertContains('Image gallery', $namepresets);
|
||||
foreach ($savedpresets as $savedpreset) {
|
||||
$this->assertNotContains($savedpreset->name, $namepresets);
|
||||
}
|
||||
|
||||
// Create a preset with the current user and check that, although the viewalluserpresets is not assigned to the teacher
|
||||
// role, the preset is returned because the teacher is the owner.
|
||||
$savedpreset = (object) [
|
||||
'name' => 'Preset created by teacher',
|
||||
];
|
||||
$plugingenerator->create_preset($activity, $savedpreset);
|
||||
$presets = $manager->get_available_presets();
|
||||
// The presets total is all the plugin presets plus the preset created by the teacher.
|
||||
$this->assertCount(count($datapresetplugins) + 1, $presets);
|
||||
// Confirm that, at least, the "Image gallery" is one of them.
|
||||
$namepresets = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $presets);
|
||||
$this->assertContains('Image gallery', $namepresets);
|
||||
// Confirm that savedpresets are still not returned.
|
||||
foreach ($savedpresets as $savedpreset) {
|
||||
$this->assertNotContains($savedpreset->name, $namepresets);
|
||||
}
|
||||
// Confirm the new preset created by the teacher is returned too.
|
||||
$this->assertContains('Preset created by teacher', $namepresets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for get_available_plugin_presets().
|
||||
*
|
||||
* @covers ::get_available_plugin_presets
|
||||
*/
|
||||
public function test_get_available_plugin_presets() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
|
||||
// Check available plugin presets meet the datapreset plugins.
|
||||
$datapresetplugins = core_component::get_plugin_list('datapreset');
|
||||
$manager = manager::create_from_instance($activity);
|
||||
$presets = $manager->get_available_plugin_presets();
|
||||
$this->assertCount(count($datapresetplugins), $presets);
|
||||
// Confirm that, at least, the "Image gallery" is one of them.
|
||||
$namepresets = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $presets);
|
||||
$this->assertContains('Image gallery', $namepresets);
|
||||
|
||||
// Create a preset saved manually by users.
|
||||
$savedpreset = (object) [
|
||||
'name' => 'Preset name 1',
|
||||
];
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$plugingenerator->create_preset($activity, $savedpreset);
|
||||
|
||||
// Check available plugin presets don't contain the preset saved manually.
|
||||
$presets = $manager->get_available_plugin_presets();
|
||||
$this->assertCount(count($datapresetplugins), $presets);
|
||||
// Confirm that, at least, the "Image gallery" is one of them.
|
||||
$namepresets = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $presets);
|
||||
$this->assertContains('Image gallery', $namepresets);
|
||||
// Confirm that the preset saved manually hasn't been returned.
|
||||
$this->assertNotContains($savedpreset->name, $namepresets);
|
||||
// Check all the presets have the proper value for the isplugin attribute.
|
||||
foreach ($presets as $preset) {
|
||||
$this->assertTrue($preset->isplugin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for get_available_saved_presets().
|
||||
*
|
||||
* @covers ::get_available_saved_presets
|
||||
*/
|
||||
public function test_get_available_saved_presets() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
|
||||
$this->setUser($user);
|
||||
|
||||
$activity = $this->getDataGenerator()->create_module(manager::MODULE, ['course' => $course]);
|
||||
$cm = get_coursemodule_from_id(manager::MODULE, $activity->cmid, 0, false, MUST_EXIST);
|
||||
|
||||
// Check available saved presets is empty (because, for now, no user preset has been created).
|
||||
$manager = manager::create_from_coursemodule($cm);
|
||||
$presets = $manager->get_available_saved_presets();
|
||||
$this->assertCount(0, $presets);
|
||||
|
||||
// Create some presets saved manually by the admin user.
|
||||
$this->setAdminUser();
|
||||
$plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
|
||||
$savedpresets = [];
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
$preset = (object) [
|
||||
'name' => 'Preset name ' . $i,
|
||||
];
|
||||
$plugingenerator->create_preset($activity, $preset);
|
||||
$savedpresets[] = $preset;
|
||||
}
|
||||
// Create one more preset saved manually by the teacher user.
|
||||
$this->setUser($user);
|
||||
$teacherpreset = (object) [
|
||||
'name' => 'Preset created by teacher',
|
||||
];
|
||||
$plugingenerator->create_preset($activity, $teacherpreset);
|
||||
$savedpresets[] = $teacherpreset;
|
||||
|
||||
$savedpresetsnames = array_map(function($preset) {
|
||||
return $preset->name;
|
||||
}, $savedpresets);
|
||||
|
||||
// Check available saved presets only contain presets saved manually by users.
|
||||
$presets = $manager->get_available_saved_presets();
|
||||
$this->assertCount(count($savedpresets), $presets);
|
||||
// Confirm that it contains only the presets created manually.
|
||||
foreach ($presets as $preset) {
|
||||
$this->assertContains($preset->name, $savedpresetsnames);
|
||||
$this->assertFalse($preset->isplugin);
|
||||
}
|
||||
|
||||
// Unassign the mod/data:viewalluserpresets capability to the teacher role and check that saved presets are not returned.
|
||||
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
|
||||
unassign_capability('mod/data:viewalluserpresets', $teacherrole->id);
|
||||
|
||||
$presets = $manager->get_available_saved_presets();
|
||||
$this->assertCount(1, $presets);
|
||||
$preset = reset($presets);
|
||||
$this->assertEquals($teacherpreset->name, $preset->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Preset tests class for mod_data.
|
||||
*
|
||||
* @package mod_data
|
||||
* @category test
|
||||
* @copyright 2022 Sara Arjona <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \mod_data\preset
|
||||
*/
|
||||
class preset_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test for is_directory_a_preset().
|
||||
*
|
||||
* @dataProvider is_directory_a_preset_provider
|
||||
* @covers ::is_directory_a_preset
|
||||
* @param string $directory
|
||||
* @param bool $expected
|
||||
*/
|
||||
public function test_is_directory_a_preset(string $directory, bool $expected): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$result = preset::is_directory_a_preset($directory);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_is_directory_a_preset().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_directory_a_preset_provider(): array {
|
||||
global $CFG;
|
||||
|
||||
return [
|
||||
'Valid preset directory' => [
|
||||
'directory' => $CFG->dirroot . '/mod/data/preset/imagegallery',
|
||||
'expected' => true,
|
||||
],
|
||||
'Invalid preset directory' => [
|
||||
'directory' => $CFG->dirroot . '/mod/data/field/checkbox',
|
||||
'expected' => false,
|
||||
],
|
||||
'Unexisting preset directory' => [
|
||||
'directory' => $CFG->dirroot . 'unexistingdirectory',
|
||||
'expected' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for get_name_from_plugin().
|
||||
*
|
||||
* @covers ::get_name_from_plugin
|
||||
*/
|
||||
public function test_get_name_from_plugin() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
// The expected name for plugins with modulename in lang is this value.
|
||||
$name = preset::get_name_from_plugin('imagegallery');
|
||||
$this->assertEquals('Image gallery', $name);
|
||||
|
||||
// However, if the plugin doesn't exist or the modulename is not defined, the preset shortname will be returned.
|
||||
$presetshortname = 'nonexistingpreset';
|
||||
$name = preset::get_name_from_plugin($presetshortname);
|
||||
$this->assertEquals($presetshortname, $name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,11 @@ information provided here is intended especially for developers.
|
||||
* The method data_view is now deprecated. Use $maganer->set_module_viewed instead.
|
||||
* The data_print_template function is now deprecated and replaced by mod_data\template class.
|
||||
* The data_print_ratings function now has an extra $print to get the ratings output instead of printing it directly.
|
||||
* The following functions have been deprecated because they have been moved to the manager class:
|
||||
- data_get_available_presets
|
||||
- data_get_available_site_presets
|
||||
- data_preset_name
|
||||
- is_directory_a_preset
|
||||
|
||||
=== 3.7 ===
|
||||
* External functions get_entries, get_entry and search_entries now return an additional field "tags" containing the entry tags.
|
||||
|
||||
Reference in New Issue
Block a user