From 2a0991113b34fea3add15a42efeb4dac4b1e9954 Mon Sep 17 00:00:00 2001 From: Ferran Recio Date: Mon, 29 Aug 2022 19:23:30 +0200 Subject: [PATCH 1/3] MDL-75234 mod_data: load default templates when empty The mod_data is forcing teachers to understand how to write templates even if they want to use basic forms. With this patch the default templates will be auto updated unless the user manually define the templates. --- mod/data/amd/build/templateseditor.min.js | 4 +- mod/data/amd/build/templateseditor.min.js.map | 2 +- mod/data/amd/src/templateseditor.js | 68 ++++- mod/data/classes/manager.php | 19 ++ mod/data/classes/output/template_editor.php | 16 +- mod/data/classes/search/entry.php | 12 +- mod/data/classes/template.php | 76 +++++ mod/data/edit.php | 279 ++++++------------ mod/data/field/date/field.class.php | 5 +- mod/data/field/file/field.class.php | 48 +-- mod/data/field/picture/field.class.php | 47 +-- mod/data/lang/en/data.php | 7 +- mod/data/lang/en/deprecated.txt | 2 + mod/data/lib.php | 7 +- mod/data/locallib.php | 4 + mod/data/templates.php | 32 +- mod/data/templates/template_editor.mustache | 7 +- mod/data/tests/template_test.php | 113 +++++++ mod/data/view.php | 9 - 19 files changed, 463 insertions(+), 294 deletions(-) diff --git a/mod/data/amd/build/templateseditor.min.js b/mod/data/amd/build/templateseditor.min.js index 9da187ddee3..9491f41b9e6 100644 --- a/mod/data/amd/build/templateseditor.min.js +++ b/mod/data/amd/build/templateseditor.min.js @@ -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 * @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 \ No newline at end of file diff --git a/mod/data/amd/build/templateseditor.min.js.map b/mod/data/amd/build/templateseditor.min.js.map index 9a229818db5..b7e94269881 100644 --- a/mod/data/amd/build/templateseditor.min.js.map +++ b/mod/data/amd/build/templateseditor.min.js.map @@ -1 +1 @@ -{"version":3,"file":"templateseditor.min.js","sources":["../src/templateseditor.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 .\n\n/**\n * Javascript module to control the template editor.\n *\n * @module mod_data/templateseditor\n * @copyright 2021 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport {confirm as confirmDialogue} from 'core/notification';\nimport {relativeUrl} from 'core/url';\n\n/**\n * Template editor constants.\n */\nconst selectors = {\n toggleTemplateEditor: 'input[name=\"useeditor\"]',\n};\n\n/**\n * Register event listeners for the module.\n *\n * @param {int} d The database ID\n * @param {string} mode The template mode\n */\nconst registerEventListeners = (d, mode) => {\n const toggleTemplateEditor = document.querySelector(selectors.toggleTemplateEditor);\n\n if (!toggleTemplateEditor) {\n return;\n }\n\n toggleTemplateEditor.addEventListener('click', async(event) => {\n event.preventDefault();\n // Whether the event action attempts to enable or disable the template editor.\n const enableTemplateEditor = event.target.checked;\n\n if (enableTemplateEditor) {\n // Display a confirmation dialog before enabling the template editor.\n confirmDialogue(\n getString('confirmation', 'admin'),\n getString('enabletemplateeditorcheck', 'mod_data'),\n getString('yes', 'core'),\n getString('no', 'core'),\n () => {\n window.location = relativeUrl('/mod/data/templates.php', {d: d, mode: mode, useeditor: true});\n }\n );\n } else {\n window.location = relativeUrl('/mod/data/templates.php', {d: d, mode: mode, useeditor: false});\n }\n });\n};\n\n/**\n * Initialize the module.\n *\n * @param {int} d The database ID\n * @param {string} mode The template mode\n */\nexport const init = (d, mode) => {\n registerEventListeners(d, mode);\n};\n"],"names":["selectors","d","mode","toggleTemplateEditor","document","querySelector","addEventListener","async","event","preventDefault","target","checked","window","location","useeditor","registerEventListeners"],"mappings":";;;;;;;;MA8BMA,+BACoB,wCA4CN,CAACC,EAAGC,QAnCO,EAACD,EAAGC,cACzBC,qBAAuBC,SAASC,cAAcL,gCAE/CG,sBAILA,qBAAqBG,iBAAiB,SAASC,MAAAA,QAC3CC,MAAMC,iBAEuBD,MAAME,OAAOC,mCAKlC,mBAAU,eAAgB,UAC1B,mBAAU,4BAA6B,aACvC,mBAAU,MAAO,SACjB,mBAAU,KAAM,SAChB,KACIC,OAAOC,UAAW,oBAAY,0BAA2B,CAACZ,EAAGA,EAAGC,KAAMA,KAAMY,WAAW,OAI/FF,OAAOC,UAAW,oBAAY,0BAA2B,CAACZ,EAAGA,EAAGC,KAAMA,KAAMY,WAAW,QAY/FC,CAAuBd,EAAGC"} \ No newline at end of file +{"version":3,"file":"templateseditor.min.js","sources":["../src/templateseditor.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 .\n\n/**\n * Javascript module to control the template editor.\n *\n * @module mod_data/templateseditor\n * @copyright 2021 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\nimport {relativeUrl} from 'core/url';\nimport {saveCancel} from 'core/notification';\n\nprefetchStrings('admin', ['confirmation']);\nprefetchStrings('mod_data', [\n 'resettemplateconfirmtitle',\n 'resettemplateconfirm',\n 'resettemplate',\n 'enabletemplateeditorcheck',\n 'editorenable'\n]);\n\n/**\n * Template editor constants.\n */\nconst selectors = {\n toggleTemplateEditor: 'input[name=\"useeditor\"]',\n resetTemplate: 'input[name=\"defaultform\"]',\n resetButton: 'input[name=\"resetbutton\"]',\n editForm: '#edittemplateform',\n};\n\n/**\n * Register event listeners for the module.\n *\n * @param {int} instanceId The database ID\n * @param {string} mode The template mode\n */\nconst registerEventListeners = (instanceId, mode) => {\n registerResetButton();\n registerEditorToggler(instanceId, mode);\n};\n\nconst registerResetButton = () => {\n const editForm = document.querySelector(selectors.editForm);\n const resetButton = document.querySelector(selectors.resetButton);\n const resetTemplate = document.querySelector(selectors.resetTemplate);\n\n if (!resetButton || !resetTemplate || !editForm) {\n return;\n }\n\n resetButton.addEventListener('click', async(event) => {\n event.preventDefault();\n saveCancel(\n getString('resettemplateconfirmtitle', 'mod_data'),\n getString('resettemplateconfirm', 'mod_data'),\n getString('resettemplate', 'mod_data'),\n () => {\n resetTemplate.value = \"true\";\n editForm.submit();\n },\n null,\n {triggerElement: event.target}\n );\n });\n};\n\nconst registerEditorToggler = (instanceId, mode) => {\n const toggleTemplateEditor = document.querySelector(selectors.toggleTemplateEditor);\n\n if (!toggleTemplateEditor) {\n return;\n }\n\n toggleTemplateEditor.addEventListener('click', async(event) => {\n event.preventDefault();\n // Whether the event action attempts to enable or disable the template editor.\n const enableTemplateEditor = event.target.checked;\n\n if (enableTemplateEditor) {\n // Display a confirmation dialog before enabling the template editor.\n saveCancel(\n getString('confirmation', 'admin'),\n getString('enabletemplateeditorcheck', 'mod_data'),\n getString('editorenable', 'mod_data'),\n () => {\n window.location = relativeUrl('/mod/data/templates.php', {d: instanceId, mode: mode, useeditor: true});\n },\n null,\n {triggerElement: event.target}\n );\n } else {\n window.location = relativeUrl('/mod/data/templates.php', {d: instanceId, mode: mode, useeditor: false});\n }\n });\n};\n\n/**\n * Initialize the module.\n *\n * @param {int} instanceId The database ID\n * @param {string} mode The template mode\n */\nexport const init = (instanceId, mode) => {\n registerEventListeners(instanceId, mode);\n};\n"],"names":["selectors","registerResetButton","editForm","document","querySelector","resetButton","resetTemplate","addEventListener","async","event","preventDefault","value","submit","triggerElement","target","registerEditorToggler","instanceId","mode","toggleTemplateEditor","checked","window","location","d","useeditor","registerEventListeners"],"mappings":";;;;;;;;8BA4BgB,QAAS,CAAC,+CACV,WAAY,CACxB,4BACA,uBACA,gBACA,4BACA,uBAMEA,+BACoB,0BADpBA,wBAEa,4BAFbA,sBAGW,4BAHXA,mBAIQ,oBAcRC,oBAAsB,WAClBC,SAAWC,SAASC,cAAcJ,oBAClCK,YAAcF,SAASC,cAAcJ,uBACrCM,cAAgBH,SAASC,cAAcJ,yBAExCK,aAAgBC,eAAkBJ,UAIvCG,YAAYE,iBAAiB,SAASC,MAAAA,QAClCC,MAAMC,+CAEF,mBAAU,4BAA6B,aACvC,mBAAU,uBAAwB,aAClC,mBAAU,gBAAiB,aAC3B,KACIJ,cAAcK,MAAQ,OACtBT,SAASU,WAEb,KACA,CAACC,eAAgBJ,MAAMK,aAK7BC,sBAAwB,CAACC,WAAYC,cACjCC,qBAAuBf,SAASC,cAAcJ,gCAE/CkB,sBAILA,qBAAqBX,iBAAiB,SAASC,MAAAA,QAC3CC,MAAMC,iBAEuBD,MAAMK,OAAOK,sCAKlC,mBAAU,eAAgB,UAC1B,mBAAU,4BAA6B,aACvC,mBAAU,eAAgB,aAC1B,KACIC,OAAOC,UAAW,oBAAY,0BAA2B,CAACC,EAAGN,WAAYC,KAAMA,KAAMM,WAAW,MAEpG,KACA,CAACV,eAAgBJ,MAAMK,SAG3BM,OAAOC,UAAW,oBAAY,0BAA2B,CAACC,EAAGN,WAAYC,KAAMA,KAAMM,WAAW,sBAWxF,CAACP,WAAYC,QAlEF,EAACD,WAAYC,QACxChB,sBACAc,sBAAsBC,WAAYC,OAiElCO,CAAuBR,WAAYC"} \ No newline at end of file diff --git a/mod/data/amd/src/templateseditor.js b/mod/data/amd/src/templateseditor.js index 2675eda9563..5dc45eba7b6 100644 --- a/mod/data/amd/src/templateseditor.js +++ b/mod/data/amd/src/templateseditor.js @@ -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); }; diff --git a/mod/data/classes/manager.php b/mod/data/classes/manager.php index c501d669fd9..1c45a64fc78 100644 --- a/mod/data/classes/manager.php +++ b/mod/data/classes/manager.php @@ -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 stdClass; @@ -155,6 +157,18 @@ class manager { return $this->cm; } + /** + * Return the current module renderer. + * + * @param moodle_page|null $page the current page + * @return mod_data_renderer the module renderer + */ + public function get_renderer(?moodle_page $page = null): mod_data_renderer { + global $PAGE; + $page = $page ?? $PAGE; + return $page->get_renderer(self::PLUGINNAME); + } + /** * Trigger module viewed event and set the module viewed for completion. * @@ -262,6 +276,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 diff --git a/mod/data/classes/output/template_editor.php b/mod/data/classes/output/template_editor.php index dcfebc16d7d..6da2e9a7832 100644 --- a/mod/data/classes/output/template_editor.php +++ b/mod/data/classes/output/template_editor.php @@ -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() ); } diff --git a/mod/data/classes/search/entry.php b/mod/data/classes/search/entry.php index b1a6fd9fd61..dc65a5751e7 100644 --- a/mod/data/classes/search/entry.php +++ b/mod/data/classes/search/entry.php @@ -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) { diff --git a/mod/data/classes/template.php b/mod/data/classes/template.php index 369aba2c315..f4ed647bd0a 100644 --- a/mod/data/classes/template.php +++ b/mod/data/classes/template.php @@ -168,6 +168,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. * @@ -736,4 +745,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; + } } diff --git a/mod/data/edit.php b/mod/data/edit.php index dbaad1e54ca..c6adcfe73fa 100644 --- a/mod/data/edit.php +++ b/mod/data/edit.php @@ -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 '
'; echo '
'; echo ''; @@ -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 '
'; - -/// 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(); diff --git a/mod/data/field/date/field.class.php b/mod/data/field/date/field.class.php index 758f307a53b..861c241aa99 100644 --- a/mod/data/field/date/field.class.php +++ b/mod/data/field/date/field.class.php @@ -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']); diff --git a/mod/data/field/file/field.class.php b/mod/data/field/file/field.class.php index 19f372cc51d..16fe7ce15d8 100644 --- a/mod/data/field/file/field.class.php +++ b/mod/data/field/file/field.class.php @@ -1,27 +1,26 @@ . +/** + * 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; diff --git a/mod/data/field/picture/field.class.php b/mod/data/field/picture/field.class.php index 2a432d8fec4..afd8749cae3 100644 --- a/mod/data/field/picture/field.class.php +++ b/mod/data/field/picture/field.class.php @@ -1,26 +1,26 @@ . + +/** + * 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 = ''; diff --git a/mod/data/lang/en/data.php b/mod/data/lang/en/data.php index 60aebc1ea88..a02f76074f8 100644 --- a/mod/data/lang/en/data.php +++ b/mod/data/lang/en/data.php @@ -294,12 +294,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}'; @@ -370,6 +368,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.'; @@ -407,6 +407,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'; @@ -446,3 +447,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'; diff --git a/mod/data/lang/en/deprecated.txt b/mod/data/lang/en/deprecated.txt index 3faf76f565d..e3ff3c52742 100644 --- a/mod/data/lang/en/deprecated.txt +++ b/mod/data/lang/en/deprecated.txt @@ -1,2 +1,4 @@ unsupportedexport,mod_data buttons,mod_data +nosingletemplate,mod_data +nolisttemplate,mod_data diff --git a/mod/data/lib.php b/mod/data/lib.php index de9e52ef913..2f4c1a6186e 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -1784,8 +1784,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(); @@ -1841,7 +1842,7 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order=' $options->para=false; $options->noclean=true; echo ''; - echo preg_replace($patterns, $replacement, format_text($data->asearchtemplate, FORMAT_HTML, $options)); + echo preg_replace($patterns, $replacement, format_text($asearchtemplate, FORMAT_HTML, $options)); echo ''; echo '
' . diff --git a/mod/data/locallib.php b/mod/data/locallib.php index 2cb5020de80..37cf3e805ec 100644 --- a/mod/data/locallib.php +++ b/mod/data/locallib.php @@ -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 = []; diff --git a/mod/data/templates.php b/mod/data/templates.php index 9613d9e8575..392b88c0308 100644 --- a/mod/data/templates.php +++ b/mod/data/templates.php @@ -84,30 +84,24 @@ 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'); diff --git a/mod/data/templates/template_editor.mustache b/mod/data/templates/template_editor.mustache index e4e4461f8f2..0ab2241ec45 100644 --- a/mod/data/templates/template_editor.mustache +++ b/mod/data/templates/template_editor.mustache @@ -66,8 +66,9 @@ } }}
{{title}}
-
+ +
{{#toolbar}} {{> mod_data/template_editor_tools }} @@ -96,8 +97,8 @@
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, + ], + ]; + } } diff --git a/mod/data/view.php b/mod/data/view.php index f4aa3d21190..46278584d5b 100644 --- a/mod/data/view.php +++ b/mod/data/view.php @@ -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, From 64c07858b048dd133f7e8e260f6f3991f138a334 Mon Sep 17 00:00:00 2001 From: Ferran Recio Date: Mon, 29 Aug 2022 19:22:55 +0200 Subject: [PATCH 2/3] MDL-75234 mod_data: add default templates behats Most behats access the templates page just to autocreate the default templates. This is not needed anymore and most behats can be optimized. --- mod/data/tests/behat/add_entries.feature | 29 +--- .../behat/data_activity_completion.feature | 2 - ...ata_activity_completion_pass_grade.feature | 2 - .../tests/behat/default_templates.feature | 158 ++++++++++++++++++ mod/data/tests/behat/edit_templates.feature | 31 +++- mod/data/tests/behat/manageapproved.feature | 4 - mod/data/tests/behat/required_entries.feature | 126 +++----------- mod/data/tests/behat/view_entries.feature | 7 - mod/data/tests/generator/lib.php | 7 +- 9 files changed, 219 insertions(+), 147 deletions(-) create mode 100644 mod/data/tests/behat/default_templates.feature diff --git a/mod/data/tests/behat/add_entries.feature b/mod/data/tests/behat/add_entries.feature index 782f2df0f96..75e658f7391 100644 --- a/mod/data/tests/behat/add_entries.feature +++ b/mod/data/tests/behat/add_entries.feature @@ -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 | @@ -96,8 +89,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" @@ -133,14 +124,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 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 - 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 + And I should see "Add entry" Examples: | user | diff --git a/mod/data/tests/behat/data_activity_completion.feature b/mod/data/tests/behat/data_activity_completion.feature index 2095ef23fc4..09c6a7efa91 100644 --- a/mod/data/tests/behat/data_activity_completion.feature +++ b/mod/data/tests/behat/data_activity_completion.feature @@ -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 diff --git a/mod/data/tests/behat/data_activity_completion_pass_grade.feature b/mod/data/tests/behat/data_activity_completion_pass_grade.feature index f7f7fc942d0..17994603d2b 100644 --- a/mod/data/tests/behat/data_activity_completion_pass_grade.feature +++ b/mod/data/tests/behat/data_activity_completion_pass_grade.feature @@ -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 diff --git a/mod/data/tests/behat/default_templates.feature b/mod/data/tests/behat/default_templates.feature new file mode 100644 index 00000000000..ec63a4bd083 --- /dev/null +++ b/mod/data/tests/behat/default_templates.feature @@ -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" diff --git a/mod/data/tests/behat/edit_templates.feature b/mod/data/tests/behat/edit_templates.feature index 32757d1d62e..bf263616583 100644 --- a/mod/data/tests/behat/edit_templates.feature +++ b/mod/data/tests/behat/edit_templates.feature @@ -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" diff --git a/mod/data/tests/behat/manageapproved.feature b/mod/data/tests/behat/manageapproved.feature index 4f86ecba5a7..2fa3ea98746 100644 --- a/mod/data/tests/behat/manageapproved.feature +++ b/mod/data/tests/behat/manageapproved.feature @@ -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 @@ -62,8 +60,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 diff --git a/mod/data/tests/behat/required_entries.feature b/mod/data/tests/behat/required_entries.feature index 1123a1602a0..2ee271766a0 100644 --- a/mod/data/tests/behat/required_entries.feature +++ b/mod/data/tests/behat/required_entries.feature @@ -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" diff --git a/mod/data/tests/behat/view_entries.feature b/mod/data/tests/behat/view_entries.feature index 79be35b744d..15af3773958 100644 --- a/mod/data/tests/behat/view_entries.feature +++ b/mod/data/tests/behat/view_entries.feature @@ -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 diff --git a/mod/data/tests/generator/lib.php b/mod/data/tests/generator/lib.php index 94a18dd2ec8..1f5d28a7e86 100644 --- a/mod/data/tests/generator/lib.php +++ b/mod/data/tests/generator/lib.php @@ -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; } From 37b9bd48b63b23bf313b1fd5dd6d943c02c49426 Mon Sep 17 00:00:00 2001 From: Ferran Recio Date: Fri, 16 Sep 2022 15:47:11 +0200 Subject: [PATCH 3/3] MDL-75234 mod_data: introduce manager get_renderer --- mod/data/field.php | 2 +- mod/data/preset.php | 2 +- mod/data/templates.php | 2 +- mod/data/view.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mod/data/field.php b/mod/data/field.php index de20d658f86..65dbc07c912 100644 --- a/mod/data/field.php +++ b/mod/data/field.php @@ -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])); diff --git a/mod/data/preset.php b/mod/data/preset.php index 2cc88ebfd3e..b97b84570cf 100644 --- a/mod/data/preset.php +++ b/mod/data/preset.php @@ -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') { diff --git a/mod/data/templates.php b/mod/data/templates.php index 392b88c0308..e22faab327c 100644 --- a/mod/data/templates.php +++ b/mod/data/templates.php @@ -104,7 +104,7 @@ if (($formdata = data_submitted()) && confirm_sesskey()) { } } -$renderer = $PAGE->get_renderer('mod_data'); +$renderer = $manager->get_renderer(); $templateeditor = new \mod_data\output\template_editor($manager, $mode); echo $renderer->render($templateeditor); diff --git a/mod/data/view.php b/mod/data/view.php index 46278584d5b..4a93fbc062c 100644 --- a/mod/data/view.php +++ b/mod/data/view.php @@ -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.