From 06f192aec9603d7880effd569daef54567e6ef4e Mon Sep 17 00:00:00 2001 From: Guillermo Gomez Date: Fri, 7 May 2021 17:31:29 +1000 Subject: [PATCH] MDL-71573 qbank_exportquestion: Add plugin to core This implementation will introduce a qbank plugin "exporquestions" which will add the export feature in the question bank view by replacing the core classes. Having this plugin will give users the flexibility of enabling or disabling the export questions tab. Co-Authored-By: Guillermo Gomez Arias --- lib/classes/plugin_manager.php | 2 +- lib/questionlib.php | 4 + .../classes/exportquestions_helper.php | 58 ++++++++++ .../classes/form/export_form.php | 100 ++++++++++++++++++ .../exportquestions/classes/navigation.php | 49 +++++++++ .../classes/plugin_feature.php | 43 ++++++++ .../classes/privacy/provider.php | 37 +++++++ .../{ => bank/exportquestions}/export.php | 57 +++++----- .../lang/en/qbank_exportquestions.php | 27 +++++ question/bank/exportquestions/version.php | 31 ++++++ question/export_form.php | 5 + question/format.php | 2 +- 12 files changed, 387 insertions(+), 28 deletions(-) create mode 100644 question/bank/exportquestions/classes/exportquestions_helper.php create mode 100644 question/bank/exportquestions/classes/form/export_form.php create mode 100644 question/bank/exportquestions/classes/navigation.php create mode 100644 question/bank/exportquestions/classes/plugin_feature.php create mode 100644 question/bank/exportquestions/classes/privacy/provider.php rename question/{ => bank/exportquestions}/export.php (59%) create mode 100644 question/bank/exportquestions/lang/en/qbank_exportquestions.php create mode 100644 question/bank/exportquestions/version.php diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index 0c20d6b4159..06ccdd4cafd 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -1939,7 +1939,7 @@ class core_plugin_manager { ), 'qbank' => [ - 'deletequestion', + 'deletequestion', 'exportquestions', ], 'qbehaviour' => array( diff --git a/lib/questionlib.php b/lib/questionlib.php index 1bf8900da84..f9dcf74e3fc 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -2336,9 +2336,13 @@ function core_question_question_preview_pluginfile($previewcontext, $questionid, * @param string $withcategories * @param string $ithcontexts * @param moodle_url export file url + * @deprecated since Moodle 4.0 MDL-71573 + * @see qbank_exportquestions\exportquestions_helper */ function question_make_export_url($contextid, $categoryid, $format, $withcategories, $withcontexts, $filename) { + debugging('Function question_make_export_url() has been deprecated and moved to qbank_exportquestions plugin, + Please use qbank_exportquestions\exportquestions_helper::question_make_export_url() instead.', DEBUG_DEVELOPER); global $CFG; $urlbase = "$CFG->wwwroot/pluginfile.php"; return moodle_url::make_file_url($urlbase, diff --git a/question/bank/exportquestions/classes/exportquestions_helper.php b/question/bank/exportquestions/classes/exportquestions_helper.php new file mode 100644 index 00000000000..a9832f37098 --- /dev/null +++ b/question/bank/exportquestions/classes/exportquestions_helper.php @@ -0,0 +1,58 @@ +. + +/** + * Library functions used by qbank_exportquestions/export.php. + * + * This code is based on lib/questionlib.php by Martin Dougiamas. + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Guillermo Gomez Arias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace qbank_exportquestions; + +use moodle_url; + +/** + * Class exportquestions_helper contains all the library functions. + * + * @package qbank_exportquestions + */ +class exportquestions_helper { + + /** + * Create url for question export. + * + * @param int $contextid Current context. + * @param int $categoryid Category id. + * @param string $format Format. + * @param string $withcategories nocategories or withcategories text. + * @param string $withcontexts nocontexts or withcontexts text. + * @param string $filename File name. + * @return moodle_url Return an URL. + */ + public static function question_make_export_url($contextid, $categoryid, $format, $withcategories, + $withcontexts, $filename): moodle_url { + global $CFG; + $urlbase = "$CFG->wwwroot/pluginfile.php"; + return moodle_url::make_file_url($urlbase, + "/$contextid/question/export/{$categoryid}/{$format}/{$withcategories}" . + "/{$withcontexts}/{$filename}", true); + } +} diff --git a/question/bank/exportquestions/classes/form/export_form.php b/question/bank/exportquestions/classes/form/export_form.php new file mode 100644 index 00000000000..bd35f32645b --- /dev/null +++ b/question/bank/exportquestions/classes/form/export_form.php @@ -0,0 +1,100 @@ +. + +/** + * Defines the export questions form. + * + * @package qbank_exportquestions + * @copyright 2007 Jamie Pratt me@jamiep.org + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace qbank_exportquestions\form; + +use moodleform; + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir . '/formslib.php'); + + +/** + * Form to export questions from the question bank. + * + * @copyright 2007 Jamie Pratt me@jamiep.org + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class export_form extends moodleform { + + /** + * Build the form definition. + * + * This adds all the form fields that the export questions feature needs. + */ + protected function definition() { + global $OUTPUT; + + $mform = $this->_form; + + $defaultcategory = $this->_customdata['defaultcategory']; + $contexts = $this->_customdata['contexts']; + + // Choice of format, with help. + $mform->addElement('header', 'fileformat', get_string('fileformat', 'question')); + + $fileformatnames = get_import_export_formats('export'); + $radioarray = []; + $separators = []; + foreach ($fileformatnames as $shortname => $fileformatname) { + $radioarray[] = $mform->createElement('radio', 'format', '', $fileformatname, $shortname); + + $separator = ''; + if (get_string_manager()->string_exists('pluginname_help', 'qformat_' . $shortname)) { + $separator .= $OUTPUT->help_icon('pluginname', 'qformat_' . $shortname); + } + $separator .= '
'; + $separators[] = $separator; + } + + $radioarray[] = $mform->createElement('static', 'makelasthelpiconshowup', ''); + $mform->addGroup($radioarray, "formatchoices", '', $separators, false); + $mform->addRule("formatchoices", null, 'required', null, 'client'); + + // Export options. + $mform->addElement('header', 'general', get_string('general', 'form')); + + $mform->addElement('questioncategory', 'category', get_string('exportcategory', 'question'), + ['contexts' => $contexts, 'top' => true]); + $mform->setDefault('category', $defaultcategory); + $mform->addHelpButton('category', 'exportcategory', 'question'); + + $categorygroup = []; + $categorygroup[] = $mform->createElement('checkbox', 'cattofile', '', get_string('tofilecategory', 'question')); + $categorygroup[] = $mform->createElement('checkbox', 'contexttofile', '', get_string('tofilecontext', 'question')); + $mform->addGroup($categorygroup, 'categorygroup', '', '', false); + $mform->disabledIf('categorygroup', 'cattofile', 'notchecked'); + $mform->setDefault('cattofile', 1); + $mform->setDefault('contexttofile', 1); + + // Set a template for the format select elements. + $renderer = $mform->defaultRenderer(); + $template = "{help} {element}\n"; + $renderer->setGroupElementTemplate($template, 'format'); + + // Submit buttons. + $this->add_action_buttons(false, get_string('exportquestions', 'question')); + } +} diff --git a/question/bank/exportquestions/classes/navigation.php b/question/bank/exportquestions/classes/navigation.php new file mode 100644 index 00000000000..4d0491591ee --- /dev/null +++ b/question/bank/exportquestions/classes/navigation.php @@ -0,0 +1,49 @@ +. + +/** + * Plugin entrypoint for navigation. + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Guillermo Gomez Arias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace qbank_exportquestions; + +/** + * Class navigation. + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Guillermo Gomez Arias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class navigation extends \core_question\local\bank\navigation_node_base { + + public function get_navigation_title(): string { + return get_string('export', 'question'); + } + + public function get_navigation_key(): string { + return 'export'; + } + + public function get_navigation_url(): \moodle_url { + return new \moodle_url('/question/bank/exportquestions/export.php'); + } +} diff --git a/question/bank/exportquestions/classes/plugin_feature.php b/question/bank/exportquestions/classes/plugin_feature.php new file mode 100644 index 00000000000..e2f245dc23d --- /dev/null +++ b/question/bank/exportquestions/classes/plugin_feature.php @@ -0,0 +1,43 @@ +. + +/** + * Entry point for plugin. + * + * Every qbank plugin must extent this class. + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace qbank_exportquestions; + +/** + * Class plugin_feature. + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class plugin_feature extends \core_question\local\bank\plugin_features_base { + + public function get_navigation_node(): ?object { + return new navigation(); + } +} diff --git a/question/bank/exportquestions/classes/privacy/provider.php b/question/bank/exportquestions/classes/privacy/provider.php new file mode 100644 index 00000000000..2843e29b2e5 --- /dev/null +++ b/question/bank/exportquestions/classes/privacy/provider.php @@ -0,0 +1,37 @@ +. + +/** + * Privacy Subsystem for qbank_exportquestions implementing null_provider. + * + * @package qbank_exportquestions + * @category privacy + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Guillermo Gomez Arias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace qbank_exportquestions\privacy; + +/** + * Class provider. + */ +class provider implements \core_privacy\local\metadata\null_provider { + + public static function get_reason(): string { + return 'privacy:metadata'; + } +} diff --git a/question/export.php b/question/bank/exportquestions/export.php similarity index 59% rename from question/export.php rename to question/bank/exportquestions/export.php index 07d48dc0af1..d7f260ed4cb 100644 --- a/question/export.php +++ b/question/bank/exportquestions/export.php @@ -17,28 +17,32 @@ /** * Script for importing questions into the question bank. * - * @package moodlecore - * @subpackage questionbank + * @package qbank_exportquestions * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once(__DIR__ . '/../config.php'); +require_once(__DIR__ . '/../../../config.php'); require_once($CFG->dirroot . '/question/editlib.php'); -require_once($CFG->dirroot . '/question/export_form.php'); require_once($CFG->dirroot . '/question/format.php'); +require_once($CFG->dirroot . '/question/renderer.php'); + +use qbank_exportquestions\exportquestions_helper; +use qbank_exportquestions\form\export_form; + +require_login(); +core_question\local\bank\helper::require_plugin_enabled('qbank_exportquestions'); list($thispageurl, $contexts, $cmid, $cm, $module, $pagevars) = - question_edit_setup('export', '/question/export.php'); + question_edit_setup('export', '/question/bank/exportquestions/export.php'); -// get display strings +// Get display strings. $strexportquestions = get_string('exportquestions', 'question'); list($catid, $catcontext) = explode(',', $pagevars['cat']); -$category = $DB->get_record('question_categories', array("id" => $catid, 'contextid' => $catcontext), '*', MUST_EXIST); +$category = $DB->get_record('question_categories', ["id" => $catid, 'contextid' => $catcontext], '*', MUST_EXIST); -/// Header +// Header. $PAGE->set_url($thispageurl); $PAGE->set_title($strexportquestions); $PAGE->set_heading($COURSE->fullname); @@ -48,56 +52,57 @@ echo $OUTPUT->header(); $renderer = $PAGE->get_renderer('core_question', 'bank'); echo $renderer->extra_horizontal_navigation(); -$export_form = new question_export_form($thispageurl, - array('contexts' => $contexts->having_one_edit_tab_cap('export'), 'defaultcategory' => $pagevars['cat'])); +$exportform = new export_form($thispageurl, + ['contexts' => $contexts->having_one_edit_tab_cap('export'), 'defaultcategory' => $pagevars['cat']]); - -if ($from_form = $export_form->get_data()) { +if ($fromform = $exportform->get_data()) { $thiscontext = $contexts->lowest(); - if (!is_readable("format/{$from_form->format}/format.php")) { - print_error('unknowformat', '', '', $from_form->format); + if (!is_readable($CFG->dirroot . "/question/format/{$fromform->format}/format.php")) { + throw new moodle_exception('unknowformat', '', '', $fromform->format); } $withcategories = 'nocategories'; - if (!empty($from_form->cattofile)) { + if (!empty($fromform->cattofile)) { $withcategories = 'withcategories'; } $withcontexts = 'nocontexts'; - if (!empty($from_form->contexttofile)) { + if (!empty($fromform->contexttofile)) { $withcontexts = 'withcontexts'; } - $classname = 'qformat_' . $from_form->format; + $classname = 'qformat_' . $fromform->format; $qformat = new $classname(); $filename = question_default_export_filename($COURSE, $category) . $qformat->export_file_extension(); - $export_url = question_make_export_url($thiscontext->id, $category->id, - $from_form->format, $withcategories, $withcontexts, $filename); + $exporturl = exportquestions_helper::question_make_export_url($thiscontext->id, $category->id, + $fromform->format, $withcategories, $withcontexts, $filename); echo $OUTPUT->box_start(); - echo get_string('yourfileshoulddownload', 'question', $export_url->out()); + echo get_string('yourfileshoulddownload', 'question', $exporturl->out()); echo $OUTPUT->box_end(); // Log the export of these questions. $eventparams = [ 'contextid' => $category->contextid, - 'other' => ['format' => $from_form->format, 'categoryid' => $category->id], + 'other' => ['format' => $fromform->format, 'categoryid' => $category->id], ]; $event = \core\event\questions_exported::create($eventparams); $event->trigger(); // Don't allow force download for behat site, as pop-up can't be handled by selenium. if (!defined('BEHAT_SITE_RUNNING')) { - $PAGE->requires->js_function_call('document.location.replace', array($export_url->out(false)), false, 1); + $PAGE->requires->js_function_call('document.location.replace', [$exporturl->out(false)], false, 1); } - echo $OUTPUT->continue_button(new moodle_url('edit.php', $thispageurl->params())); + echo $OUTPUT->continue_button(new moodle_url($PAGE->settingsnav->find( + 'questionbank', + \navigation_node::TYPE_CONTAINER)->action->get_path(), $thispageurl->params())); echo $OUTPUT->footer(); exit; } -/// Display export form +// Display export form. echo $OUTPUT->heading_with_help($strexportquestions, 'exportquestions', 'question'); -$export_form->display(); +$exportform->display(); echo $OUTPUT->footer(); diff --git a/question/bank/exportquestions/lang/en/qbank_exportquestions.php b/question/bank/exportquestions/lang/en/qbank_exportquestions.php new file mode 100644 index 00000000000..1e8974ca15d --- /dev/null +++ b/question/bank/exportquestions/lang/en/qbank_exportquestions.php @@ -0,0 +1,27 @@ +. + +/** + * Strings for component 'qbank_exportquestions', language 'en' + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Guillermo Gomez Arias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['pluginname'] = 'Export question bank feature'; +$string['privacy:metadata'] = 'The Export Questions plugin does not store any personal data.'; diff --git a/question/bank/exportquestions/version.php b/question/bank/exportquestions/version.php new file mode 100644 index 00000000000..adb5946f38f --- /dev/null +++ b/question/bank/exportquestions/version.php @@ -0,0 +1,31 @@ +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package qbank_exportquestions + * @copyright 2021 Catalyst IT Australia Pty Ltd + * @author Guillermo Gomez Arias + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->component = 'qbank_exportquestions'; +$plugin->version = 2021070700; +$plugin->requires = 2021052500; +$plugin->maturity = MATURITY_STABLE; diff --git a/question/export_form.php b/question/export_form.php index 0d5ade3d4da..b23e459b227 100644 --- a/question/export_form.php +++ b/question/export_form.php @@ -34,10 +34,15 @@ require_once($CFG->libdir . '/formslib.php'); * * @copyright 2007 Jamie Pratt me@jamiep.org * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @deprecated since Moodle 4.0 MDL-71573 + * @see qbank_exportquestions\form\export_form */ class question_export_form extends moodleform { protected function definition() { + debugging('Class question_export_form in \core_question\export_form is deprecated, + please use core_question\bank\exportquestions\export_form instead.', DEBUG_DEVELOPER); + global $OUTPUT; $mform = $this->_form; diff --git a/question/format.php b/question/format.php index 0177abf03e4..878dd9500ae 100644 --- a/question/format.php +++ b/question/format.php @@ -972,7 +972,7 @@ class qformat_default { // continue path for following error checks $course = $this->course; - $continuepath = "{$CFG->wwwroot}/question/export.php?courseid={$course->id}"; + $continuepath = "{$CFG->wwwroot}/question/bank/exportquestions/export.php?courseid={$course->id}"; // did we actually process anything if ($count==0) {