Merge branch 'MDL-75234-master' of https://github.com/ferranrecio/moodle

This commit is contained in:
Jun Pataleta
2022-10-04 11:59:57 +08:00
30 changed files with 675 additions and 446 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
define("mod_data/templateseditor",["exports","core/str","core/notification","core/url"],(function(_exports,_str,_notification,_url){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;
define("mod_data/templateseditor",["exports","core/str","core/prefetch","core/url","core/notification"],(function(_exports,_str,_prefetch,_url,_notification){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,
/**
* Javascript module to control the template editor.
*
@@ -6,6 +6,6 @@ define("mod_data/templateseditor",["exports","core/str","core/notification","cor
* @copyright 2021 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const selectors_toggleTemplateEditor='input[name="useeditor"]';_exports.init=(d,mode)=>{((d,mode)=>{const toggleTemplateEditor=document.querySelector(selectors_toggleTemplateEditor);toggleTemplateEditor&&toggleTemplateEditor.addEventListener("click",(async event=>{event.preventDefault(),event.target.checked?(0,_notification.confirm)((0,_str.get_string)("confirmation","admin"),(0,_str.get_string)("enabletemplateeditorcheck","mod_data"),(0,_str.get_string)("yes","core"),(0,_str.get_string)("no","core"),(()=>{window.location=(0,_url.relativeUrl)("/mod/data/templates.php",{d:d,mode:mode,useeditor:!0})})):window.location=(0,_url.relativeUrl)("/mod/data/templates.php",{d:d,mode:mode,useeditor:!1})}))})(d,mode)}}));
(0,_prefetch.prefetchStrings)("admin",["confirmation"]),(0,_prefetch.prefetchStrings)("mod_data",["resettemplateconfirmtitle","resettemplateconfirm","resettemplate","enabletemplateeditorcheck","editorenable"]);const selectors_toggleTemplateEditor='input[name="useeditor"]',selectors_resetTemplate='input[name="defaultform"]',selectors_resetButton='input[name="resetbutton"]',selectors_editForm="#edittemplateform",registerResetButton=()=>{const editForm=document.querySelector(selectors_editForm),resetButton=document.querySelector(selectors_resetButton),resetTemplate=document.querySelector(selectors_resetTemplate);resetButton&&resetTemplate&&editForm&&resetButton.addEventListener("click",(async event=>{event.preventDefault(),(0,_notification.saveCancel)((0,_str.get_string)("resettemplateconfirmtitle","mod_data"),(0,_str.get_string)("resettemplateconfirm","mod_data"),(0,_str.get_string)("resettemplate","mod_data"),(()=>{resetTemplate.value="true",editForm.submit()}),null,{triggerElement:event.target})}))},registerEditorToggler=(instanceId,mode)=>{const toggleTemplateEditor=document.querySelector(selectors_toggleTemplateEditor);toggleTemplateEditor&&toggleTemplateEditor.addEventListener("click",(async event=>{event.preventDefault();event.target.checked?(0,_notification.saveCancel)((0,_str.get_string)("confirmation","admin"),(0,_str.get_string)("enabletemplateeditorcheck","mod_data"),(0,_str.get_string)("editorenable","mod_data"),(()=>{window.location=(0,_url.relativeUrl)("/mod/data/templates.php",{d:instanceId,mode:mode,useeditor:!0})}),null,{triggerElement:event.target}):window.location=(0,_url.relativeUrl)("/mod/data/templates.php",{d:instanceId,mode:mode,useeditor:!1})}))};_exports.init=(instanceId,mode)=>{((instanceId,mode)=>{registerResetButton(),registerEditorToggler(instanceId,mode)})(instanceId,mode)}}));
//# sourceMappingURL=templateseditor.min.js.map
File diff suppressed because one or more lines are too long
+56 -12
View File
@@ -22,23 +22,66 @@
*/
import {get_string as getString} from 'core/str';
import {confirm as confirmDialogue} from 'core/notification';
import {prefetchStrings} from 'core/prefetch';
import {relativeUrl} from 'core/url';
import {saveCancel} from 'core/notification';
prefetchStrings('admin', ['confirmation']);
prefetchStrings('mod_data', [
'resettemplateconfirmtitle',
'resettemplateconfirm',
'resettemplate',
'enabletemplateeditorcheck',
'editorenable'
]);
/**
* Template editor constants.
*/
const selectors = {
toggleTemplateEditor: 'input[name="useeditor"]',
resetTemplate: 'input[name="defaultform"]',
resetButton: 'input[name="resetbutton"]',
editForm: '#edittemplateform',
};
/**
* Register event listeners for the module.
*
* @param {int} d The database ID
* @param {int} instanceId The database ID
* @param {string} mode The template mode
*/
const registerEventListeners = (d, mode) => {
const registerEventListeners = (instanceId, mode) => {
registerResetButton();
registerEditorToggler(instanceId, mode);
};
const registerResetButton = () => {
const editForm = document.querySelector(selectors.editForm);
const resetButton = document.querySelector(selectors.resetButton);
const resetTemplate = document.querySelector(selectors.resetTemplate);
if (!resetButton || !resetTemplate || !editForm) {
return;
}
resetButton.addEventListener('click', async(event) => {
event.preventDefault();
saveCancel(
getString('resettemplateconfirmtitle', 'mod_data'),
getString('resettemplateconfirm', 'mod_data'),
getString('resettemplate', 'mod_data'),
() => {
resetTemplate.value = "true";
editForm.submit();
},
null,
{triggerElement: event.target}
);
});
};
const registerEditorToggler = (instanceId, mode) => {
const toggleTemplateEditor = document.querySelector(selectors.toggleTemplateEditor);
if (!toggleTemplateEditor) {
@@ -52,17 +95,18 @@ const registerEventListeners = (d, mode) => {
if (enableTemplateEditor) {
// Display a confirmation dialog before enabling the template editor.
confirmDialogue(
saveCancel(
getString('confirmation', 'admin'),
getString('enabletemplateeditorcheck', 'mod_data'),
getString('yes', 'core'),
getString('no', 'core'),
getString('editorenable', 'mod_data'),
() => {
window.location = relativeUrl('/mod/data/templates.php', {d: d, mode: mode, useeditor: true});
}
window.location = relativeUrl('/mod/data/templates.php', {d: instanceId, mode: mode, useeditor: true});
},
null,
{triggerElement: event.target}
);
} else {
window.location = relativeUrl('/mod/data/templates.php', {d: d, mode: mode, useeditor: false});
window.location = relativeUrl('/mod/data/templates.php', {d: instanceId, mode: mode, useeditor: false});
}
});
};
@@ -70,9 +114,9 @@ const registerEventListeners = (d, mode) => {
/**
* Initialize the module.
*
* @param {int} d The database ID
* @param {int} instanceId The database ID
* @param {string} mode The template mode
*/
export const init = (d, mode) => {
registerEventListeners(d, mode);
export const init = (instanceId, mode) => {
registerEventListeners(instanceId, mode);
};
+7
View File
@@ -20,9 +20,11 @@ use cm_info;
use context_module;
use completion_info;
use data_field_base;
use mod_data_renderer;
use mod_data\event\course_module_viewed;
use mod_data\event\template_viewed;
use mod_data\event\template_updated;
use moodle_page;
use core_component;
use mod_data_renderer;
use moodle_page;
@@ -276,6 +278,11 @@ class manager {
* NOTE: this method returns a default template if the module template is empty.
* However, it won't update the template database field.
*
* Some possible options:
* - search: string with the current searching text.
* - page: integer repesenting the current pagination page numbre (if any)
* - baseurl: a moodle_url object to the current page.
*
* @param string $templatename
* @param array $options extra display options array
* @return template the template instance
+10 -6
View File
@@ -93,7 +93,8 @@ class template_editor implements templatable, renderable {
global $PAGE;
$result = [];
$instance = $this->manager->get_instance();
$manager = $this->manager;
$instance = $manager->get_instance();
// Setup editor.
editors_head_setup();
@@ -112,40 +113,43 @@ class template_editor implements templatable, renderable {
// Add editors.
if ($this->templatename === 'listtemplate') {
$template = $manager->get_template('listtemplateheader');
$result[] = $this->generate_editor_data(
$editor,
'header',
'listtemplateheader',
$instance->listtemplateheader
$template->get_template_content()
);
$maineditorname = 'multientry';
} else {
$maineditorname = $this->templatename;
}
$value = $instance->{$this->templatename} ?? '';
$template = $manager->get_template($this->templatename);
$result[] = $this->generate_editor_data(
$editor,
$maineditorname,
$this->templatename,
$value
$template->get_template_content()
);
if ($this->templatename === 'listtemplate') {
$template = $manager->get_template('listtemplatefooter');
$result[] = $this->generate_editor_data(
$editor,
'footer',
'listtemplatefooter',
$instance->listtemplatefooter
$template->get_template_content()
);
}
if ($this->templatename === 'rsstemplate') {
$template = $manager->get_template('rsstitletemplate');
$result[] = $this->generate_editor_data(
$editor,
'rsstitletemplate',
'rsstitletemplate',
$instance->rsstitletemplate
$template->get_template_content()
);
}
+8 -4
View File
@@ -24,6 +24,8 @@
namespace mod_data\search;
use mod_data\manager;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/data/lib.php');
@@ -280,11 +282,13 @@ class entry extends \core_search\base_mod {
WHERE dc.fieldid = df.id
AND dc.recordid = :recordid";
$contents = $DB->get_records_sql($sql, array('recordid' => $entry->id));
$filteredcontents = array();
$contents = $DB->get_records_sql($sql, ['recordid' => $entry->id]);
$filteredcontents = [];
$template = $DB->get_record_sql('SELECT addtemplate FROM {data} WHERE id = ?', array($entry->dataid));
$template = $template->addtemplate;
$data = $DB->get_record('data', ['id' => $entry->dataid]);
$manager = manager::create_from_instance($data);
$template = $manager->get_template('addtemplate');
$template = $template->get_template_content();
// Filtering out the data_content records having invalid fieldtypes.
foreach ($contents as $content) {
+76
View File
@@ -231,6 +231,15 @@ class template {
];
}
/**
* Return the raw template content.
*
* @return string the template content before parsing
*/
public function get_template_content(): string {
return $this->templatecontent;
}
/**
* Return the parsed entry using a template.
*
@@ -799,4 +808,71 @@ class template {
return $OUTPUT->render($actionmenu);
}
/**
* Parse the template as if it was for add entry.
*
* This method is similar to the parse_entry but it uses the display_add_field method
* instead of the display_browse_field.
*
* @param stdClass|null $processeddata the previous process data information.
* @param int|null $entryid the possible entry id
* @param stdClass|null $entrydata the entry data from a previous form or from a real entry
* @return string the add entry HTML content
*/
public function parse_add_entry(
?stdClass $processeddata = null,
?int $entryid = null,
?stdClass $entrydata = null
): string {
$manager = $this->manager;
$renderer = $manager->get_renderer();
$templatecontent = $this->templatecontent;
if (!$processeddata) {
$processeddata = (object)[
'generalnotifications' => [],
'fieldnotifications' => [],
];
}
$result = '';
foreach ($processeddata->generalnotifications as $notification) {
$result .= $renderer->notification($notification);
}
$possiblefields = $manager->get_fields();
$patterns = [];
$replacements = [];
// Then we generate strings to replace.
foreach ($possiblefields as $field) {
// To skip unnecessary calls to display_add_field().
if (strpos($templatecontent, "[[" . $field->field->name . "]]") !== false) {
// Replace the field tag.
$patterns[] = "[[" . $field->field->name . "]]";
$errors = '';
$fieldnotifications = $processeddata->fieldnotifications[$field->field->name] ?? [];
if (!empty($fieldnotifications)) {
foreach ($fieldnotifications as $notification) {
$errors .= $renderer->notification($notification);
}
}
$replacements[] = $errors . $field->display_add_field($entryid, $entrydata);
}
// Replace the field id tag.
$patterns[] = "[[" . $field->field->name . "#id]]";
$replacements[] = 'field_' . $field->field->id;
}
if (core_tag_tag::is_enabled('mod_data', 'data_records')) {
$patterns[] = "##tags##";
$replacements[] = data_generate_tag_form($entryid);
}
$result .= str_ireplace($patterns, $replacements, $templatecontent);
return $result;
}
}
+92 -187
View File
@@ -23,103 +23,85 @@
* @package mod_data
*/
use mod_data\manager;
require_once('../../config.php');
require_once('locallib.php');
require_once("$CFG->libdir/rsslib.php");
require_once("$CFG->libdir/form/filemanager.php");
$id = optional_param('id', 0, PARAM_INT); // course module id
$d = optional_param('d', 0, PARAM_INT); // database id
$rid = optional_param('rid', 0, PARAM_INT); //record id
$mode ='addtemplate'; //define the mode for this page, only 1 mode available
$id = optional_param('id', 0, PARAM_INT); // Course module id.
$d = optional_param('d', 0, PARAM_INT); // Database id.
$rid = optional_param('rid', 0, PARAM_INT); // Record id.
$mode = 'addtemplate'; // Define the mode for this page, only 1 mode available.
$tags = optional_param_array('tags', [], PARAM_TAGLIST);
$redirectbackto = optional_param('backto', '', PARAM_LOCALURL); // The location to redirect back.
$url = new moodle_url('/mod/data/edit.php');
$record = null;
if ($id) {
list($course, $cm) = get_course_and_cm_from_cmid($id, manager::MODULE);
$manager = manager::create_from_coursemodule($cm);
} else { // We must have $d.
$data = $DB->get_record('data', ['id' => $d], '*', MUST_EXIST);
$manager = manager::create_from_instance($data);
$cm = $manager->get_coursemodule();
$course = get_course($cm->course);
}
$data = $manager->get_instance();
$context = $manager->get_context();
$url->param('id', $cm->id);
if ($rid !== 0) {
$record = $DB->get_record('data_records', array(
'id' => $rid,
'dataid' => $d,
), '*', MUST_EXIST);
$record = $DB->get_record(
'data_records',
['id' => $rid, 'dataid' => $data->id],
'*',
MUST_EXIST
);
$url->param('rid', $rid);
}
if ($id) {
$url->param('id', $id);
$PAGE->set_url($url);
if (! $cm = get_coursemodule_from_id('data', $id)) {
throw new \moodle_exception('invalidcoursemodule');
}
if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
throw new \moodle_exception('coursemisconf');
}
if (! $data = $DB->get_record('data', array('id'=>$cm->instance))) {
throw new \moodle_exception('invalidcoursemodule');
}
} else {
$url->param('d', $d);
$PAGE->set_url($url);
if (! $data = $DB->get_record('data', array('id'=>$d))) {
throw new \moodle_exception('invalidid', 'data');
}
if (! $course = $DB->get_record('course', array('id'=>$data->course))) {
throw new \moodle_exception('coursemisconf');
}
if (! $cm = get_coursemodule_from_instance('data', $data->id, $course->id)) {
throw new \moodle_exception('invalidcoursemodule');
}
}
$PAGE->set_url($url);
require_login($course, false, $cm);
$url->param('backto', $redirectbackto);
require_login($course, false, $cm);
if (isguestuser()) {
redirect('view.php?d='.$data->id);
}
$context = context_module::instance($cm->id);
/// If it's hidden then it doesn't show anything. :)
if (empty($cm->visible) and !has_capability('moodle/course:viewhiddenactivities', $context)) {
$strdatabases = get_string("modulenameplural", "data");
$PAGE->set_title($data->name);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
notice(get_string("activityiscurrentlyhidden"));
}
/// Can't use this if there are no fields
if (has_capability('mod/data:managetemplates', $context)) {
if (!$DB->record_exists('data_fields', array('dataid'=>$data->id))) { // Brand new database!
redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id); // Redirect to field entry
if (!$manager->has_fields()) {
redirect($CFG->wwwroot.'/mod/data/field.php?d='.$data->id); // Redirect to field entry.
}
}
if ($rid) {
// When editing an existing record, we require the session key
// When editing an existing record, we require the session key.
require_sesskey();
}
// Get Group information for permission testing and record creation
// Get Group information for permission testing and record creation.
$currentgroup = groups_get_activity_group($cm);
$groupmode = groups_get_activity_groupmode($cm);
if (!has_capability('mod/data:manageentries', $context)) {
if ($rid) {
// User is editing an existing record
// User is editing an existing record.
if (!data_user_can_manage_entry($record, $data, $context)) {
throw new \moodle_exception('noaccess', 'data');
}
} else if (!data_user_can_add_entry($data, $currentgroup, $groupmode, $context)) {
// User is trying to create a new record
// User is trying to create a new record.
throw new \moodle_exception('noaccess', 'data');
}
}
/// RSS and CSS and JS meta
// RSS and CSS and JS meta.
if (!empty($CFG->enablerssfeeds) && !empty($CFG->data_enablerssfeeds) && $data->rssarticles > 0) {
$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
$rsstitle = $courseshortname . ': ' . format_string($data->name);
@@ -132,16 +114,7 @@ if ($data->jstemplate) {
$PAGE->requires->js('/mod/data/js.php?d='.$data->id, true);
}
$possiblefields = $DB->get_records('data_fields', array('dataid'=>$data->id), 'id');
foreach ($possiblefields as $field) {
if ($field->type == 'file' || $field->type == 'picture') {
require_once($CFG->dirroot.'/repository/lib.php');
break;
}
}
/// Define page variables
// Define page variables.
$strdata = get_string('modulenameplural','data');
if ($rid) {
@@ -156,86 +129,53 @@ $PAGE->activityheader->disable();
// Process incoming data for adding/updating records.
// Keep track of any notifications.
$generalnotifications = array();
$fieldnotifications = array();
// Keep track of any notifications ad submitted data.
$processeddata = null;
$datarecord = data_submitted() ?: null;
// Process the submitted form.
if ($datarecord = data_submitted() and confirm_sesskey()) {
if ($rid) {
// Updating an existing record.
if ($datarecord && confirm_sesskey()) {
// Validate the form to ensure that enough data was submitted.
$fields = $manager->get_field_records();
$processeddata = data_process_submission($data, $fields, $datarecord);
// Retrieve the format for the fields.
$fields = $DB->get_records('data_fields', array('dataid' => $datarecord->d));
// Validate the form to ensure that enough data was submitted.
$processeddata = data_process_submission($data, $fields, $datarecord);
// Add the new notification data.
$generalnotifications = array_merge($generalnotifications, $processeddata->generalnotifications);
$fieldnotifications = array_merge($fieldnotifications, $processeddata->fieldnotifications);
if ($processeddata->validated) {
// Enough data to update the record.
if ($processeddata->validated) {
if ($rid) {
$recordid = $rid;
// Updating an existing record.
data_update_record_fields_contents($data, $record, $context, $datarecord, $processeddata);
core_tag_tag::set_item_tags('mod_data', 'data_records', $rid, $context, $tags);
$viewurl = new moodle_url('/mod/data/view.php', array(
'd' => $data->id,
'rid' => $rid,
));
redirect($viewurl);
} else {
// Add instance to data_record.
$recordid = data_add_record($data, $currentgroup);
if ($recordid) {
// Now populate the fields contents of the new record.
data_add_fields_contents_to_new_record($data, $context, $recordid, $fields, $datarecord, $processeddata);
}
}
} else {
// No recordid was specified - creating a new entry.
// Retrieve the format for the fields.
$fields = $DB->get_records('data_fields', array('dataid' => $datarecord->d));
// Validate the form to ensure that enough data was submitted.
$processeddata = data_process_submission($data, $fields, $datarecord);
// Add the new notification data.
$generalnotifications = array_merge($generalnotifications, $processeddata->generalnotifications);
$fieldnotifications = array_merge($fieldnotifications, $processeddata->fieldnotifications);
// Add instance to data_record.
if ($processeddata->validated && $recordid = data_add_record($data, $currentgroup)) {
// Now populate the fields contents of the new record.
data_add_fields_contents_to_new_record($data, $context, $recordid, $fields, $datarecord, $processeddata);
if ($recordid) {
core_tag_tag::set_item_tags('mod_data', 'data_records', $recordid, $context, $tags);
if (!empty($datarecord->saveandview)) {
$viewurl = new moodle_url('/mod/data/view.php', array(
'd' => $data->id,
'rid' => $recordid,
));
redirect($viewurl);
} else if (!empty($datarecord->saveandadd)) {
if (!empty($datarecord->saveandadd)) {
// User has clicked "Save and add another". Reset all of the fields.
$datarecord = null;
} else {
$viewurl = new moodle_url('/mod/data/view.php', [
'd' => $data->id,
'rid' => $recordid,
]);
redirect($viewurl);
}
}
}
}
// End of form processing.
/// Print the page header
echo $OUTPUT->header();
groups_print_activity_menu($cm, $CFG->wwwroot.'/mod/data/edit.php?d='.$data->id);
/// Print the browsing interface
$patterns = array(); //tags to replace
$replacement = array(); //html to replace those yucky tags
//form goes here first in case add template is empty
// Form goes here first in case add template is empty.
echo '<form enctype="multipart/form-data" action="edit.php" method="post">';
echo '<div>';
echo '<input name="d" value="'.$data->id.'" type="hidden" />';
@@ -249,80 +189,45 @@ if (!$rid){
echo $OUTPUT->heading(get_string('editentry','data'));
}
/******************************************
* Regular expression replacement section *
******************************************/
if ($data->addtemplate){
$possiblefields = $DB->get_records('data_fields', array('dataid'=>$data->id), 'id');
$patterns = array();
$replacements = array();
$template = $manager->get_template($mode);
echo $template->parse_add_entry($processeddata, $rid, $datarecord);
///then we generate strings to replace
foreach ($possiblefields as $eachfield){
$field = data_get_field($eachfield, $data);
// To skip unnecessary calls to display_add_field().
if (strpos($data->addtemplate, "[[".$field->field->name."]]") !== false) {
// Replace the field tag.
$patterns[] = "[[".$field->field->name."]]";
$errors = '';
if (!empty($fieldnotifications[$field->field->name])) {
foreach ($fieldnotifications[$field->field->name] as $notification) {
$errors .= $OUTPUT->notification($notification);
}
}
$replacements[] = $errors . $field->display_add_field($rid, $datarecord);
}
// Replace the field id tag.
$patterns[] = "[[".$field->field->name."#id]]";
$replacements[] = 'field_'.$field->field->id;
}
if (core_tag_tag::is_enabled('mod_data', 'data_records')) {
$patterns[] = "##tags##";
$replacements[] = data_generate_tag_form($rid);
}
$newtext = str_ireplace($patterns, $replacements, $data->{$mode});
} else { //if the add template is not yet defined, print the default form!
echo data_generate_default_template($data, 'addtemplate', $rid, true, false);
$newtext = '';
if (empty($redirectbackto)) {
$redirectbackto = new \moodle_url('/mod/data/view.php', ['id' => $cm->id]);
}
foreach ($generalnotifications as $notification) {
echo $OUTPUT->notification($notification);
}
echo $newtext;
$redirectbackto = !empty($redirectbackto) ? $redirectbackto :
new \moodle_url('/mod/data/view.php', ['d' => $data->id]);
$actionbuttons = html_writer::link($redirectbackto, get_string('cancel'), ['class' => 'btn btn-secondary']);
$actionbuttons .= html_writer::empty_tag('input', ['type' => 'submit', 'name' => 'saveandview',
'value' => get_string('save'), 'class' => 'btn btn-primary ml-2']);
$actionbuttons = html_writer::link(
$redirectbackto,
get_string('cancel'),
['class' => 'btn btn-secondary', 'role' => 'button']
);
$actionbuttons .= html_writer::empty_tag('input', [
'type' => 'submit',
'name' => 'saveandview',
'value' => get_string('save'),
'class' => 'btn btn-primary ml-2'
]);
if (!$rid && ((!$data->maxentries) ||
has_capability('mod/data:manageentries', $context) ||
(data_numentries($data) < ($data->maxentries - 1)))) {
$actionbuttons .= html_writer::empty_tag('input', ['type' => 'submit', 'name' => 'saveandadd',
'value' => get_string('saveandadd', 'data'), 'class' => 'btn btn-primary ml-2']);
has_capability('mod/data:manageentries', $context) ||
(data_numentries($data) < ($data->maxentries - 1)))) {
$actionbuttons .= html_writer::empty_tag('input', [
'type' => 'submit', 'name' => 'saveandadd',
'value' => get_string('saveandadd', 'data'), 'class' => 'btn btn-primary ml-2'
]);
}
echo html_writer::div($actionbuttons, 'mdl-align mt-2');
echo $OUTPUT->box_end();
echo '</div></form>';
/// Finish the page
// Print the stuff that need to come after the form fields.
if (!$fields = $DB->get_records('data_fields', array('dataid'=>$data->id))) {
throw new \moodle_exception('nofieldindatabase', 'data');
}
foreach ($fields as $eachfield) {
$field = data_get_field($eachfield, $data);
$possiblefields = $manager->get_fields();
foreach ($possiblefields as $field) {
$field->print_after_form();
}
// Finish the page.
if (empty($possiblefields)) {
throw new \moodle_exception('nofieldindatabase', 'data');
}
echo $OUTPUT->footer();
+1 -1
View File
@@ -117,7 +117,7 @@ $data->instance = $cm->instance;
/************************************
* Data Processing *
***********************************/
$renderer = $PAGE->get_renderer('mod_data');
$renderer = $manager->get_renderer();
if ($formimportzip->is_cancelled()) {
redirect(new moodle_url('/mod/data/field.php', ['d' => $data->id]));
+4 -1
View File
@@ -90,7 +90,10 @@ class data_field_date extends data_field_base {
}
//Enable the following three functions once core API issues have been addressed.
function display_search_field($value=0) {
function display_search_field($value = null) {
if (empty($value)) {
$value = ['timestamp' => 0, 'usedate' => false];
}
$selectors = html_writer::select_time('days', 'f_'.$this->field->id.'_d', $value['timestamp'])
. html_writer::select_time('months', 'f_'.$this->field->id.'_m', $value['timestamp'])
. html_writer::select_time('years', 'f_'.$this->field->id.'_y', $value['timestamp']);
+25 -23
View File
@@ -1,27 +1,26 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999-onwards Moodle Pty Ltd http://moodle.com //
// //
// This program 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 2 of the License, or //
// (at your option) any later version. //
// //
// This program 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: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
// 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 file field for database activity
*
* @package datafield_file
* @copyright 2005 Martin Dougiamas
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class data_field_file extends data_field_base {
var $type = 'file';
@@ -43,7 +42,10 @@ class data_field_file extends data_field_base {
}
function display_add_field($recordid = 0, $formdata = null) {
global $DB, $OUTPUT, $PAGE;
global $CFG, $DB, $OUTPUT, $PAGE;
// Necessary for the constants used in args.
require_once($CFG->dirroot . '/repository/lib.php');
$itemid = null;
+25 -22
View File
@@ -1,26 +1,26 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999-onwards Moodle Pty Ltd http://moodle.com //
// //
// This program 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 2 of the License, or //
// (at your option) any later version. //
// //
// This program 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: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
// 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 picture field for database activity
*
* @package datafield_picture
* @copyright 2005 Martin Dougiamas
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class data_field_picture extends data_field_base {
var $type = 'picture';
@@ -47,6 +47,9 @@ class data_field_picture extends data_field_base {
function display_add_field($recordid = 0, $formdata = null) {
global $CFG, $DB, $OUTPUT, $USER, $PAGE;
// Necessary for the constants used in args.
require_once($CFG->dirroot . '/repository/lib.php');
$file = false;
$content = false;
$alttext = '';
+5 -2
View File
@@ -297,12 +297,10 @@ $string['noaccess'] = 'You do not have access to this page';
$string['nodefinedfields'] = 'New preset has no defined fields!';
$string['nofieldcontent'] = 'Field content not found';
$string['nofieldindatabase'] = 'There are no fields defined for this database.';
$string['nolisttemplate'] = 'List template is not yet defined';
$string['nomatch'] = 'No matching entries found!';
$string['nomaximum'] = 'No maximum';
$string['nopreviewavailable'] = 'No preview available for {$a}';
$string['norecords'] = 'No entries yet';
$string['nosingletemplate'] = 'Single template is not yet defined';
$string['notapproved'] = 'Entry is not approved yet.';
$string['notinjectivemap'] = 'Not an injective map';
$string['notopenyet'] = 'Sorry, this activity is not available until {$a}';
@@ -373,6 +371,8 @@ Note: If entries are required before viewing, the database auto-linking filter s
$string['requiredfield'] = 'Required field';
$string['resetsettings'] = 'Reset filters';
$string['resettemplate'] = 'Reset template';
$string['resettemplateconfirmtitle'] = 'Reset template?';
$string['resettemplateconfirm'] = 'Resetting a template removes the existing preset and any customisations you have done to the template. You can\'t undo this action.';
$string['resizingimages'] = 'Resizing image thumbnails...';
$string['rows'] = 'rows';
$string['rssglobaldisabled'] = 'Disabled. See site configuration variables.';
@@ -410,6 +410,7 @@ $string['tags'] = 'Tags';
$string['tagsdeleted'] = 'Database tags have been deleted';
$string['teachersandstudents'] = '{$a->teachers} and {$a->students}';
$string['templates'] = 'Templates';
$string['templatereset'] = 'Template reset';
$string['templatesnavigation'] = 'Templates tertiary navigation';
$string['templatesaved'] = 'Template saved';
$string['text'] = 'Text';
@@ -449,3 +450,5 @@ $string['unsupportedexport'] = '({$a->fieldtype}) cannot be exported.';
// Deprecated since Moodle 4.1.
$string['buttons'] = 'Actions';
$string['nolisttemplate'] = 'List template is not yet defined';
$string['nosingletemplate'] = 'Single template is not yet defined';
+2
View File
@@ -1,2 +1,4 @@
unsupportedexport,mod_data
buttons,mod_data
nosingletemplate,mod_data
nolisttemplate,mod_data
+4 -3
View File
@@ -1731,8 +1731,9 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
// Determine if we are printing all fields for advanced search, or the template for advanced search
// If a template is not defined, use the deafault template and display all fields.
if(empty($data->asearchtemplate)) {
data_generate_default_template($data, 'asearchtemplate');
$asearchtemplate = $data->asearchtemplate;
if (empty($asearchtemplate)) {
$asearchtemplate = data_generate_default_template($data, 'asearchtemplate', 0, false, false);
}
static $fields = array();
@@ -1788,7 +1789,7 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
$options->para=false;
$options->noclean=true;
echo '<tr><td>';
echo preg_replace($patterns, $replacement, format_text($data->asearchtemplate, FORMAT_HTML, $options));
echo preg_replace($patterns, $replacement, format_text($asearchtemplate, FORMAT_HTML, $options));
echo '</td></tr>';
echo '<tr><td colspan="4"><br/>' .
+4
View File
@@ -959,6 +959,10 @@ function data_get_tag_title_field($dataid) {
$validfieldtypes = array('text', 'textarea', 'menu', 'radiobutton', 'checkbox', 'multimenu', 'url');
$fields = $DB->get_records('data_fields', ['dataid' => $dataid]);
$template = $DB->get_field('data', 'addtemplate', ['id' => $dataid]);
if (empty($template)) {
$data = $DB->get_record('data', ['id' => $dataid]);
$template = data_generate_default_template($data, 'addtemplate', 0, false, false);
}
$filteredfields = [];
+1 -1
View File
@@ -80,7 +80,7 @@ $data->course = $cm->course;
$data->cmidnumber = $cm->idnumber;
$data->instance = $cm->instance;
$renderer = $PAGE->get_renderer('mod_data');
$renderer = $manager->get_renderer();
$presets = $manager->get_available_presets();
if ($action === 'export') {
+14 -20
View File
@@ -84,33 +84,27 @@ echo $actionbar->get_templates_action_bar();
echo $OUTPUT->heading(get_string($mode, 'data'), 2, 'mb-4');
if (($formdata = data_submitted()) && confirm_sesskey()) {
$notificationstr = get_string('templatesaved', 'data');
if (!empty($formdata->defaultform)) {
// Reset the template to default, but don't save yet.
$instance->{$mode} = data_generate_default_template($instance, $mode, 0, false, false);
// Reset the template to default.
$formdata->{$mode} = '';
if ($mode == 'listtemplate') {
$instance->listtemplateheader = '';
$instance->listtemplatefooter = '';
$formdata->listtemplateheader = '';
$formdata->listtemplatefooter = '';
}
} else {
if ($manager->update_templates($formdata)) {
// Reload instance.
$instance = $manager->get_instance();
echo $OUTPUT->notification(get_string('templatesaved', 'data'), 'notifysuccess');
if ($mode == 'rsstemplate') {
$formdata->rsstitletemplate = '';
}
$notificationstr = get_string('templatereset', 'data');
}
if ($manager->update_templates($formdata)) {
// Reload instance.
$instance = $manager->get_instance();
echo $OUTPUT->notification($notificationstr, 'notifysuccess');
}
}
/// If everything is empty then generate some defaults
if (empty($instance->addtemplate) && empty($instance->singletemplate) &&
empty($instance->listtemplate) && empty($instance->rsstemplate)) {
data_generate_default_template($instance, 'singletemplate');
data_generate_default_template($instance, 'listtemplate');
data_generate_default_template($instance, 'addtemplate');
data_generate_default_template($instance, 'asearchtemplate');
data_generate_default_template($instance, 'rsstemplate');
}
$renderer = $PAGE->get_renderer('mod_data');
$renderer = $manager->get_renderer();
$templateeditor = new \mod_data\output\template_editor($manager, $mode);
echo $renderer->render($templateeditor);
+4 -3
View File
@@ -66,8 +66,9 @@
}
}}
<div>{{title}}</div>
<form id="tempform" action="{{{url}}}" method="post">
<form id="edittemplateform" action="{{{url}}}" method="post">
<input name="sesskey" value="{{sesskey}}" type="hidden" />
<input name="defaultform" type="hidden" value=""/>
<div class="d-flex flex-row align-items-center">
{{#toolbar}}
{{> mod_data/template_editor_tools }}
@@ -96,8 +97,8 @@
<div>
<input
class="btn btn-secondary"
type="submit"
name="defaultform"
type="button"
name="resetbutton"
value="{{#str}} resettemplate, data {{/str}}"
/>
<input
+9 -20
View File
@@ -22,17 +22,10 @@ Feature: Users can add entries to database activities
@javascript
Scenario: Students can add entries to a database
Given I am on the "Course 1" course page logged in as teacher1
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Test field name |
| Field description | Test field description |
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Test field 2 name |
| Field description | Test field 2 description |
# To generate the default templates.
And I navigate to "Templates" in current page administration
And I wait until the page is ready
And I log out
Given the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | Test field name | Test field description |
| data1 | text | Test field 2 name | Test field 2 description |
When I am on the "Course 1" course page logged in as student1
And I add an entry to "Test database name" database with:
| Test field name | Student original entry |
@@ -92,8 +85,6 @@ Feature: Users can add entries to database activities
And I press "Save and display"
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Test1 |
And I navigate to "Templates" in current page administration
And I press "Save template"
And I log out
And I am on the "Test database name" "data activity" page logged in as student1
And I press "Add entry"
@@ -129,14 +120,12 @@ Feature: Users can add entries to database activities
Scenario Outline: Users see the Add entry button in the view page when some field has been created only.
Given I am on the "Test database name" "data activity" page logged in as <user>
And I should not see "Add entry"
When I log out
And I am on the "Test database name" "data activity" page logged in as teacher1
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Test field name |
| Field description | Test field description |
And I log out
And I am on the "Test database name" "data activity" page logged in as <user>
Then I should see "Add entry"
When the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | Test field name | Test field description |
Then I am on the "Test database name" "data activity" page logged in as <user>
And I should see "Add entry"
Examples:
| user |
@@ -36,8 +36,6 @@ Feature: View activity completion in the database activity
And I press "Save and display"
And I add a "Short text" field to "Music history" database and I fill the form with:
| Field name | Instrument types |
And I navigate to "Templates" in current page administration
And I press "Save template"
And I log out
Scenario: View automatic completion items as a teacher
@@ -50,8 +50,6 @@ Feature: Completion pass grade
And I press "Save and display"
And I add a "Short text" field to "Music history" database and I fill the form with:
| Field name | Instrument types |
And I navigate to "Templates" in current page administration
And I press "Save template"
And I log out
Scenario: View automatic completion items as a teacher
@@ -0,0 +1,158 @@
@mod @mod_data
Feature: Users can use mod_data without editing the templates
In order to use the database module
As a teacher
I need to manage fields and entries using always the default templates.
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 | Test database name | Database intro | C1 | data1 |
And the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | field1 | Test field description |
| data1 | text | field2 | Test field 2 description |
And the following "mod_data > entries" exist:
| database | field1 | field2 |
| data1 | Student entry 1 | Some content 1 |
| data1 | Student entry 2 | Some content 2 |
And I am on the "Test database name" "data activity" page logged in as teacher1
@javascript
Scenario: The default view templates should be updated when a field is added.
Given I navigate to "Database" in current page administration
And I should see "field1"
And I should see "field2"
And I should see "Student entry 1"
And I should see "Some content 1"
And I should see "Student entry 2"
And I should see "Some content 2"
And I set the field "View mode tertiary navigation" to "Single view"
And I should see "field1"
And I should see "field2"
And I should see "Student entry 1"
And I should see "Some content 1"
And I should not see "Student entry 2"
And I should not see "Some content 2"
When the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | field3 | Test field 3 description |
Then I navigate to "Database" in current page administration
And I should see "field1"
And I should see "field2"
And I should see "field3"
And I should see "Student entry 1"
And I should see "Some content 1"
And I should see "Student entry 2"
And I should see "Some content 2"
And I set the field "View mode tertiary navigation" to "Single view"
And I should see "field1"
And I should see "field2"
And I should see "field3"
And I should see "Student entry 1"
And I should see "Some content 1"
And I should not see "Student entry 2"
And I should not see "Some content 2"
Scenario: The default add templates should be updated when a field is added.
Given I navigate to "Database" in current page administration
And I click on "Add entry" "button"
And I should see "field1"
And I should see "field2"
When the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | field3 | Test field 3 description |
Then I navigate to "Database" in current page administration
And I click on "Add entry" "button"
And I should see "field1"
And I should see "field2"
And I should see "field3"
@javascript
Scenario: The default view templates should be updated when a field is deleted.
Given I navigate to "Database" in current page administration
And I should see "field1"
And I should see "field2"
And I should see "Student entry 1"
And I should see "Some content 1"
And I should see "Student entry 2"
And I should see "Some content 2"
And I set the field "View mode tertiary navigation" to "Single view"
And I should see "field1"
And I should see "field2"
And I should see "Student entry 1"
And I should see "Some content 1"
And I should not see "Student entry 2"
And I should not see "Some content 2"
When I navigate to "Fields" in current page administration
And I click on "Delete" "link" in the "field2" "table_row"
And I click on "Continue" "button"
Then I navigate to "Database" in current page administration
And I should see "field1"
And I should not see "field2"
And I should see "Student entry 1"
And I should not see "Some content 1"
And I should see "Student entry 2"
And I should not see "Some content 2"
And I set the field "View mode tertiary navigation" to "Single view"
And I should see "field1"
And I should not see "field2"
And I should see "Student entry 1"
And I should not see "Some content 1"
And I should not see "Student entry 2"
And I should not see "Some content 2"
Scenario: The default add templates should be updated when a field is deleted.
Given I navigate to "Database" in current page administration
And I click on "Add entry" "button"
And I should see "field1"
And I should see "field2"
When I navigate to "Fields" in current page administration
And I click on "Delete" "link" in the "field2" "table_row"
And I click on "Continue" "button"
Then I navigate to "Database" in current page administration
And I click on "Add entry" "button"
And I should see "field1"
And I should not see "field2"
@javascript
Scenario: The dynamic default templates can be reset after a manual edition.
Given I navigate to "Templates" in current page administration
And I set the following fields to these values:
| Header | New header! |
| Repeated entry | This is the template content |
| Footer | New footer! |
And I click on "Save template" "button"
And I navigate to "Database" in current page administration
And I should see "New header!"
And I should see "This is the template content"
And I should see "New footer!"
And I should not see "Student entry 1"
And I should not see "Some content 1"
When I navigate to "Templates" in current page administration
And I click on "Reset template" "button"
And I click on "Reset template" "button" in the "Reset template?" "dialogue"
And I should see "Template reset"
And I navigate to "Database" in current page administration
And I should not see "New header!"
And I should not see "This is the template content"
And I should not see "New footer!"
And I should see "Student entry 1"
And I should see "Some content 1"
Then the following "mod_data > fields" exist:
| database | type | name | description |
| data1 | text | field3 | Test field 3 description |
And I navigate to "Database" in current page administration
And I click on "Add entry" "button"
And I should see "field1"
And I should see "field2"
And I should see "field3"
+24 -7
View File
@@ -21,13 +21,6 @@ Feature: Users can edit the database templates
| database | type | name | description |
| data1 | text | field1 | Test field description |
| data1 | text | field2 | Test field 2 description |
And the following "mod_data > templates" exist:
| database | name |
| data1 | singletemplate |
| data1 | listtemplate |
| data1 | addtemplate |
| data1 | asearchtemplate |
| data1 | rsstemplate |
And the following "mod_data > entries" exist:
| database | field1 | field2 |
| data1 | Student entry 1 | Some content 1 |
@@ -113,3 +106,27 @@ Feature: Users can edit the database templates
When I navigate to "Database" in current page administration
Then I should not see "Nope"
And I should see "Yep!"
@javascript
Scenario: Reset database activity template
Given I set the following fields to these values:
| Header | New header! |
| Repeated entry | This is the template content |
| Footer | New footer! |
And I click on "Save template" "button"
And I navigate to "Database" in current page administration
And I should see "New header!"
And I should see "This is the template content"
And I should see "New footer!"
And I should not see "Student entry 1"
And I should not see "Some content 1"
When I navigate to "Templates" in current page administration
And I click on "Reset template" "button"
And I click on "Reset template" "button" in the "Reset template?" "dialogue"
Then I should see "Template reset"
And I navigate to "Database" in current page administration
And I should not see "New header!"
And I should not see "This is the template content"
And I should not see "New footer!"
And I should see "Student entry 1"
And I should see "Some content 1"
@@ -30,8 +30,6 @@ Feature: Users can edit approved entries in database activities
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Test field name |
| Field description | Test field description |
# To generate the default templates.
And I navigate to "Templates" in current page administration
And I log out
# Add an entry as a student.
And I am on the "Test database name" "data activity" page logged in as student1
@@ -63,8 +61,6 @@ Feature: Users can edit approved entries in database activities
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Test field name |
| Field description | Test field description |
# To generate the default templates.
And I navigate to "Templates" in current page administration
And I log out
# Add an entry as a student.
And I am on the "Test database name" "data activity" page logged in as student1
+23 -103
View File
@@ -19,109 +19,29 @@ Feature: Users can be required to specify certain fields when adding entries to
And the following "activities" exist:
| activity | name | intro | course | idnumber |
| data | Test database name | n | C1 | data1 |
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Base Text input |
| Required | yes |
| Field description | Base Text input |
And I add a "Checkbox" field to "Test database name" database and I fill the form with:
| Field name | Required Checkbox |
| Field description | Required Checkbox |
| Required | yes |
| Options | Required Checkbox Option 1 |
And I follow "Fields"
And I select "Checkbox" from the "newtype" singleselect
And I set the following fields to these values:
| Field name | Required Two-Option Checkbox |
| Field description | Required Two-Option Checkbox |
| Required | yes |
And I set the field "Options" to multiline:
"""
RTOC Option 1
RTOC Option 2
"""
And I press "Add"
And I add a "Coordinates" field to "Test database name" database and I fill the form with:
| Field name | Required Coordinates |
| Field description | Required Coordinates |
| Required | yes |
And I add a "Dropdown list" field to "Test database name" database and I fill the form with:
| Field name | Required Menu |
| Field description | Required Menu |
| Required | yes |
| Options | Option 1 |
And I add a "Number" field to "Test database name" database and I fill the form with:
| Field name | Required Number |
| Field description | Required Number |
| Required | yes |
And I add a "Radio button" field to "Test database name" database and I fill the form with:
| Field name | Required Radio |
| Field description | Required Radio |
| Required | yes |
| Options | Required Radio Option 1 |
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Required Text input |
| Field description | Required Text input |
| Required | yes |
And I add a "Text area" field to "Test database name" database and I fill the form with:
| Field name | Required Text area |
| Field description | Required Text area |
| Required | yes |
And I add a "URL" field to "Test database name" database and I fill the form with:
| Field name | Required URL |
| Field description | Required URL |
| Required | yes |
And I add a "Multi-select list" field to "Test database name" database and I fill the form with:
| Field name | Required Multimenu |
| Field description | Required Multimenu |
| Required | yes |
| Options | Option 1 |
And I follow "Fields"
And I select "Multi-select list" from the "newtype" singleselect
And I set the following fields to these values:
| Field name | Required Two-Option Multimenu |
| Field description | Required Two-Option Multimenu |
| Required | yes |
And I set the field "Options" to multiline:
"""
Option 1
Option 2
"""
And I press "Add"
And I add a "Checkbox" field to "Test database name" database and I fill the form with:
| Field name | Not required Checkbox |
| Field description | Not required Checkbox |
| Options | Not required Checkbox Option 1 |
And I add a "Coordinates" field to "Test database name" database and I fill the form with:
| Field name | Not required Coordinates |
| Field description | Not required Coordinates |
And I add a "Dropdown list" field to "Test database name" database and I fill the form with:
| Field name | Not required Menu |
| Field description | Not required Menu |
| Options | Option 1 |
And I add a "Number" field to "Test database name" database and I fill the form with:
| Field name | Not required Number |
| Field description | Not required Number |
And I add a "Radio button" field to "Test database name" database and I fill the form with:
| Field name | Not required Radio |
| Field description | Not required Radio |
| Options | Not required Radio Option 1 |
And I add a "Short text" field to "Test database name" database and I fill the form with:
| Field name | Not required Text input |
| Field description | Not required Text input |
And I add a "Text area" field to "Test database name" database and I fill the form with:
| Field name | Not required Text area |
| Field description | Not required Text area |
And I add a "URL" field to "Test database name" database and I fill the form with:
| Field name | Not required URL |
| Field description | Not required URL |
And I add a "Multi-select list" field to "Test database name" database and I fill the form with:
| Field name | Not required Multimenu |
| Field description | Not required Multimenu |
| Options | Option 1 |
And I navigate to "Templates" in current page administration
And I log out
And the following "mod_data > fields" exist:
| database | type | name | required | description | param1 |
| data1 | text | Base Text input | 1 | Base Text input | |
| data1 | checkbox | Required Checkbox | 1 | Base Text input | Required Checkbox Option 1 |
| data1 | checkbox | Required Two-Option Checkbox | 1 | Required Two-Option Checkbox | RTOC Option 1\nRTOC Option 2 |
| data1 | latlong | Required Coordinates | 1 | Required Coordinates | |
| data1 | menu | Required Menu | 1 | Required Menu | Option 1 |
| data1 | number | Required Number | 1 | Required Number | |
| data1 | radiobutton | Required Radio | 1 | Required Radio | Required Radio Option 1 |
| data1 | text | Required Text input | 1 | Required Text input | |
| data1 | textarea | Required Text area | 1 | Required Text area | |
| data1 | url | Required URL | 1 | Required URL | |
| data1 | multimenu | Required Multimenu | 1 | Required Multimenu | Option 1 |
| data1 | multimenu | Required Two-Option Multimenu | 1 | Required Two-Option Multimenu | Option 1\nOption 2 |
| data1 | checkbox | Not required Checkbox | 0 | Not required Checkbox | Not required Checkbox Option 1 |
| data1 | latlong | Not required Coordinates | 0 | Not required Coordinates | |
| data1 | menu | Not required Menu | 0 | Not required Menu | Option 1 |
| data1 | number | Not required Number | 0 | Not required Number | |
| data1 | radiobutton | Not required Radio | 0 | Not required Radio | Not required Radio Option 1 |
| data1 | text | Not required Text input | 0 | Not required Text input | |
| data1 | textarea | Not required Text area | 0 | Not required Text area | |
| data1 | url | Not required URL | 0 | Not required URL | |
| data1 | multimenu | Not required Multimenu | 0 | Not required Multimenu | Option 1 |
Scenario: Students receive errors for empty required fields but not for optional fields
When I log in as "student1"
@@ -29,13 +29,6 @@ Feature: Users can view and search database entries
| data1 | text | Test field name | Test field description |
| data1 | text | Test field 2 name | Test field 2 description |
| data1 | url | Test field 3 name | Test field 3 description |
And the following "mod_data > templates" exist:
| database | name |
| data1 | singletemplate |
| data1 | listtemplate |
| data1 | addtemplate |
| data1 | asearchtemplate |
| data1 | rsstemplate |
@javascript
Scenario: Students can view, list and search entries
+5 -2
View File
@@ -120,6 +120,11 @@ class mod_data_generator extends testing_module_generator {
$record['description'] = " This is testField - " . $this->databasefieldcount;
}
if (isset($record['param1']) && !empty($record['param1'])) {
// Some fields have multiline entries.
$record['param1'] = str_replace('\n', "\n", $record['param1']);
}
if (!isset($record['param1'])) {
if ($record['type'] == 'checkbox') {
$record['param1'] = implode("\n", array('opt1', 'opt2', 'opt3', 'opt4'));
@@ -178,8 +183,6 @@ class mod_data_generator extends testing_module_generator {
$field = data_get_field($record, $data);
$field->insert_field();
data_generate_default_template($data, 'addtemplate', 0, false, true);
return $field;
}
+113
View File
@@ -794,4 +794,117 @@ class template_test extends \advanced_testcase {
$rm = new rating_manager();
return $rm->get_ratings($ratingoptions);
}
/**
* Test parse add entry template parsing.
*
* @covers ::parse_add_entry
* @dataProvider parse_add_entry_provider
* @param string $templatecontent the template string
* @param string $expected expected output
* @param bool $newentry if it is a new entry or editing and existing one
*/
public function test_parse_add_entry(
string $templatecontent,
string $expected,
bool $newentry = false
) {
global $DB, $PAGE;
// Comments, tags, approval, user role.
$this->resetAfterTest();
$params = ['approval' => true];
$course = $this->getDataGenerator()->create_course();
$params['course'] = $course;
$activity = $this->getDataGenerator()->create_module('data', $params);
$author = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
// Generate an entry.
$generator = $this->getDataGenerator()->get_plugin_generator('mod_data');
$fieldrecord = (object)[
'name' => 'myfield',
'type' => 'text',
];
$field = $generator->create_field($fieldrecord, $activity);
if ($newentry) {
$entryid = null;
$entry = null;
} else {
$entryid = $generator->create_entry(
$activity,
[$field->field->id => 'Example entry'],
0,
['Cats', 'Dogs']
);
$entry = (object)[
'd' => $activity->id,
'rid' => $entryid,
"field_{$field->field->id}" => "New value",
];
}
$manager = manager::create_from_instance($activity);
// Some cooked variables for the regular expression.
$replace = [
'{fieldid}' => $field->field->id,
];
$processdata = (object)[
'generalnotifications' => ['GENERAL'],
'fieldnotifications' => [$field->field->name => ['FIELD']],
];
$parser = new template($manager, $templatecontent);
$result = $parser->parse_add_entry($processdata, $entryid, $entry);
// We don't want line breaks for the validations.
$result = str_replace("\n", '', $result);
$regexp = str_replace(array_keys($replace), array_values($replace), $expected);
$this->assertMatchesRegularExpression($regexp, $result);
}
/**
* Data provider for test_parse_add_entry().
*
* @return array of scenarios
*/
public function parse_add_entry_provider(): array {
return [
// Editing an entry.
'Teacher editing entry tags tag' => [
'templatecontent' => 'Some ##tags## tag',
'expected' => '|GENERAL.*Some .*select .*tags.*Cats.* tag|',
'newentry' => false,
],
'Teacher editing entry field name tag' => [
'templatecontent' => 'Some [[myfield]] tag',
'expected' => '|GENERAL.*Some .*FIELD.*field_{fieldid}.*input.*New value.* tag|',
'newentry' => false,
],
'Teacher editing entry field#id tag' => [
'templatecontent' => 'Some [[myfield#id]] tag',
'expected' => '|GENERAL.*Some field_{fieldid} tag|',
'newentry' => false,
],
// New entry.
'Teacher new entry tags tag' => [
'templatecontent' => 'Some ##tags## tag',
'expected' => '|GENERAL.*Some .*select .*tags\[\].* tag|',
'newentry' => true,
],
'Teacher new entry field name tag' => [
'templatecontent' => 'Some [[myfield]] tag',
'expected' => '|GENERAL.*Some .*FIELD.*field_{fieldid}.*input.*value="".* tag|',
'newentry' => true,
],
'Teacher new entry field#id name tag' => [
'templatecontent' => 'Some [[myfield#id]] tag',
'expected' => '|GENERAL.*Some field_{fieldid} tag|',
'newentry' => true,
],
];
}
}
+2 -11
View File
@@ -241,7 +241,7 @@ echo $OUTPUT->header();
if (!$manager->has_fields()) {
// It's a brand-new database. There are no fields.
$renderer = $PAGE->get_renderer('mod_data');
$renderer = $manager->get_renderer();
echo $renderer->render_zero_state($manager);
echo $OUTPUT->footer();
// Don't check the rest of the options. There is no field, there is nothing else to work with.
@@ -387,7 +387,7 @@ if ($showactivity) {
$hasrecords = !empty($records);
if ($maxcount == 0) {
$renderer = $PAGE->get_renderer('mod_data');
$renderer = $manager->get_renderer();
echo $renderer->render_empty_database($manager);
echo $OUTPUT->footer();
// There is no entry, so makes no sense to check different views, pagination, etc.
@@ -449,11 +449,6 @@ if ($showactivity) {
$baseurl = new moodle_url($baseurl, $baseurlparams);
echo $OUTPUT->paging_bar($totalcount, $page, $nowperpage, $baseurl);
if (empty($data->singletemplate)){
echo $OUTPUT->notification(get_string('nosingletemplate','data'));
data_generate_default_template($data, 'singletemplate', 0, false, false);
}
require_once($CFG->dirroot.'/rating/lib.php');
if ($data->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions = new stdClass;
@@ -492,10 +487,6 @@ if ($showactivity) {
echo $OUTPUT->paging_bar($totalcount, $page, $nowperpage, $baseurl);
if (empty($data->listtemplate)){
echo $OUTPUT->notification(get_string('nolisttemplate','data'));
data_generate_default_template($data, 'listtemplate', 0, false, false);
}
echo $data->listtemplateheader;
$options = [
'search' => $search,