From 68dcf7959ed6e135cfb0ecd81f3dc93122e075cc Mon Sep 17 00:00:00 2001 From: Jean-Michel Vedrine Date: Mon, 25 Aug 2014 09:34:57 +0200 Subject: [PATCH 01/54] First version of qcreate for Moodle 2.7 --- README.txt | 52 +- backup/moodle1/lib.php | 155 ++ .../backup_qcreate_activity_task.class.php | 90 + backup/moodle2/backup_qcreate_stepslib.php | 85 + .../restore_qcreate_activity_task.class.php | 129 ++ backup/moodle2/restore_qcreate_stepslib.php | 124 + backuplib.php | 277 --- .../course_module_instance_list_viewed.php | 39 + classes/event/course_module_viewed.php | 49 + classes/event/edit_page_viewed.php | 104 + classes/event/overview_viewed.php | 106 + classes/event/question_graded.php | 113 + classes/event/question_regraded.php | 113 + classes/task/synchronize_qaccess.php | 61 + classes/task/update_grades.php | 80 + db/access.php | 47 +- db/install.xml | 71 +- db/messages.php | 37 + db/tasks.php | 47 + db/upgrade.php | 93 +- deprecatedlib.php | 30 - edit.php | 377 +-- export_good_questions_form.php | 64 +- exportgood.php | 269 +-- index.php | 137 +- .../help/qcreate/automaticmanualgrading.html | 81 - lang/en/help/qcreate/grade.html | 3 - lang/en/help/qcreate/gradedquestiontypes.html | 17 - lang/en/help/qcreate/index.html | 11 - lang/en/help/qcreate/minimumquestions.html | 20 - lang/en/help/qcreate/mods.html | 9 - lang/en/help/qcreate/questiontype.html | 17 - .../help/qcreate/studentquestionaccess.html | 11 - lang/en/help/qcreate/timeopen.html | 5 - .../en/help/qcreate/totalquestionsgraded.html | 4 - lang/en/qcreate.php | 115 +- .../help/qcreate/automaticmanualgrading.html | 91 - lang/es/help/qcreate/grade.html | 4 - lang/es/help/qcreate/gradedquestiontypes.html | 28 - lang/es/help/qcreate/index.html | 11 - lang/es/help/qcreate/minimumquestions.html | 21 - lang/es/help/qcreate/mods.html | 23 - lang/es/help/qcreate/questiontype.html | 17 - .../help/qcreate/studentquestionaccess.html | 24 - lang/es/help/qcreate/timeopen.html | 7 - .../es/help/qcreate/totalquestionsgraded.html | 9 - lang/es/qcreate.php | 228 ++ lang/fr/qcreate.php | 187 ++ lib.php | 1493 ++++++++---- locallib.php | 2018 ++++++++++++++--- mod_form.php | 258 ++- overview.php | 90 +- renderable.php | 218 ++ renderer.php | 543 +++++ restorelib.php | 398 ---- settings.php | 44 + styles.php => styles.css | 5 + tabs.php | 45 - tests/base_test.php | 229 ++ tests/events_test.php | 111 + tests/generator/lib.php | 68 + tests/generator_test.php | 70 + tests/lib_test.php | 157 ++ tests/locallib_test.php | 247 ++ version.php | 33 +- view.php | 206 +- 66 files changed, 7267 insertions(+), 2658 deletions(-) create mode 100644 backup/moodle1/lib.php create mode 100644 backup/moodle2/backup_qcreate_activity_task.class.php create mode 100644 backup/moodle2/backup_qcreate_stepslib.php create mode 100644 backup/moodle2/restore_qcreate_activity_task.class.php create mode 100644 backup/moodle2/restore_qcreate_stepslib.php delete mode 100644 backuplib.php create mode 100644 classes/event/course_module_instance_list_viewed.php create mode 100644 classes/event/course_module_viewed.php create mode 100644 classes/event/edit_page_viewed.php create mode 100644 classes/event/overview_viewed.php create mode 100644 classes/event/question_graded.php create mode 100644 classes/event/question_regraded.php create mode 100644 classes/task/synchronize_qaccess.php create mode 100644 classes/task/update_grades.php create mode 100644 db/messages.php create mode 100644 db/tasks.php delete mode 100644 deprecatedlib.php delete mode 100644 lang/en/help/qcreate/automaticmanualgrading.html delete mode 100644 lang/en/help/qcreate/grade.html delete mode 100644 lang/en/help/qcreate/gradedquestiontypes.html delete mode 100644 lang/en/help/qcreate/index.html delete mode 100644 lang/en/help/qcreate/minimumquestions.html delete mode 100644 lang/en/help/qcreate/mods.html delete mode 100644 lang/en/help/qcreate/questiontype.html delete mode 100644 lang/en/help/qcreate/studentquestionaccess.html delete mode 100644 lang/en/help/qcreate/timeopen.html delete mode 100644 lang/en/help/qcreate/totalquestionsgraded.html delete mode 100644 lang/es/help/qcreate/automaticmanualgrading.html delete mode 100644 lang/es/help/qcreate/grade.html delete mode 100644 lang/es/help/qcreate/gradedquestiontypes.html delete mode 100644 lang/es/help/qcreate/index.html delete mode 100644 lang/es/help/qcreate/minimumquestions.html delete mode 100644 lang/es/help/qcreate/mods.html delete mode 100644 lang/es/help/qcreate/questiontype.html delete mode 100644 lang/es/help/qcreate/studentquestionaccess.html delete mode 100644 lang/es/help/qcreate/timeopen.html delete mode 100644 lang/es/help/qcreate/totalquestionsgraded.html create mode 100644 lang/fr/qcreate.php create mode 100644 renderable.php create mode 100644 renderer.php delete mode 100644 restorelib.php create mode 100644 settings.php rename styles.php => styles.css (56%) delete mode 100644 tabs.php create mode 100644 tests/base_test.php create mode 100644 tests/events_test.php create mode 100644 tests/generator/lib.php create mode 100644 tests/generator_test.php create mode 100644 tests/lib_test.php create mode 100644 tests/locallib_test.php diff --git a/README.txt b/README.txt index 28f9815..e6cc1fb 100644 --- a/README.txt +++ b/README.txt @@ -1,8 +1,12 @@ -This activity is for Moodle 2.x-versions, it will not work in Moodle 1.9 (or below) +This activity is for Moodle 2.7.x-versions, it will not work with Moodle previous versions. -This module was originally created by Jamie Pratt (e-Mail: me@jamiep.org) with funding from Future University Hakodate http://www.fun.ac.jp/e/ -The module was originally conceived and partially designed by Peter Ruthven-Stuart (http://www.ruthven-stuart.org), Future University - Hakodate. -It has been migrated to Moodle 2.x-versions by gtn gmbh (global training network ltd. - http://gtn-solutions.com, http://www.exabis.at) +This module was originally created by Jamie Pratt (e-Mail: me@jamiep.org) with funding from Future University Hakodate +http://www.fun.ac.jp/e/ +The module was originally conceived and partially designed by Peter Ruthven-Stuart (http://www.ruthven-stuart.org), +Future University - Hakodate. +It has been migrated to Moodle 2.x-versions by gtn gmbh (global training network ltd. - http://gtn-solutions.com, +http://www.exabis.at +I was upgraded to Moodle 2.7 and enhanced by Jean-Michel Vedrine (email vedrine@vedrine.net). * qcreate - Bugs, Feature Requests, and Improvements * @@ -13,21 +17,45 @@ If you have any problems installing this activity or suggestions for improvement * qcreate - Disclaimer * -As with any customization, it is recommended that you have a good backup of your Moodle site before attempting to install contributed code. -While those contributing code make every effort to provide the best code that they can, using contributed code nevertheless entails a certain degree of risk as contributed code is not as carefully reviewed and/or tested as the Moodle core code. -Hence, use this block at your own risk. +As with any customization, it is recommended that you have a good backup of your Moodle site before attempting to install +contributed code. +While those contributing code make every effort to provide the best code that they can, using contributed code nevertheless +entails a certain degree of risk as contributed code is not as carefully reviewed and/or tested as the Moodle core code. +Hence, use this plugin at your own risk. * qcreate - History * First official publishing-date: 2007/11/21 09:19:34 jamiesensei Migration to Moodle 2.4 2013/03/28 gtn gmbh +Migration to Moodle2.7 2014/08/02 Jean-Michel Vedrine -* qcreate - Installation * +QUICK INSTALL +============= -1) Save the zip file somewhere onto your local computer and extract all the files +There are two installation methods that are available. Follow one of these, then log into your Moodle site as an administrator +and visit the notifications page to complete the install. -2) Transfer the folder qcreate to the mod-directory of Moodle +==================== MOST RECOMMENDED METHOD - Git ==================== -3) Log in as 'administrator' and click on the 'Home' link (Moodle 2.x) +If you do not have git installed, please see the below link. Please note, it is not necessary to set up the SSH Keys. +This is only needed if you are going to create a repository of your own on github.com. -That's it! \ No newline at end of file +Information on installing git - http://help.github.com/set-up-git-redirect/ + +Once you have git installed, simply visit the Moodle root directory and clone git://github.com/markn86/moodle-mod_certificate.git +Remember to rename the folder to qcreate if you do not specify this in the clone command + +Eg. Linux command line would be as follow - + +git clone -b local_27 git://github.com/jmvedrine/qcreate.git mod/qcreate + +Use git pull to update this repository periodically to ensure you have the latest version. + +==================== Download the qcreate module. ==================== + +Visit https://github.com/jmvedrine/qcreate/tree/local_27 and download the zip, uncompress this zip and extract the folder. +The folder will have a name similar to qcreate-local_27, you MUST rename this to qcreate. +Place this folder in your mod folder in your Moodle directory. + +nb. The reason this is not the recommended method is due to the fact you have to over-write the contents of this folder +to apply any future updates to the qcreate module. In the above method there is a simple command to update the files. diff --git a/backup/moodle1/lib.php b/backup/moodle1/lib.php new file mode 100644 index 0000000..82bd3c3 --- /dev/null +++ b/backup/moodle1/lib.php @@ -0,0 +1,155 @@ +. + +/** + * Provides support for the conversion of moodle1 backup to the moodle2 format + * Based off of a template @ http://docs.moodle.org/dev/Backup_1.9_conversion_for_developers + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Qcreate conversion handler + */ +class moodle1_mod_qcreate_handler extends moodle1_mod_handler { + + /** @var moodle1_file_manager */ + protected $fileman = null; + + /** @var int cmid */ + protected $moduleid = null; + + /** + * Declare the paths in moodle.xml we are able to convert + * + * The method returns list of {@link convert_path} instances. + * For each path returned, the corresponding conversion method must be + * defined. + * + * Note that the path /MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE does not + * actually exist in the file. The last element with the module name was + * appended by the moodle1_converter class. + * + * @return array of {@link convert_path} instances + */ + public function get_paths() { + return array( + new convert_path( + 'qcreate', '/MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE', + array( + 'newfields' => array( + 'completionquestions' => 0, + ), + ) + ), + new convert_path('qcreate_requireds', + '/MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE/REQUIREDS'), + new convert_path('qcreate_required', + '/MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE/REQUIREDS/REQUIRED'), + new convert_path('qcreate_grades', + '/MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE/GRADES'), + new convert_path('qcreate_grade', + '/MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE/GRADE') + ); + } + + /** + * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/QCREATE + * data available + */ + public function process_qcreate($data) { + global $CFG; + + // Get the course module id and context id. + $instanceid = $data['id']; + $cminfo = $this->get_cminfo($instanceid); + $this->moduleid = $cminfo['id']; + $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $this->moduleid); + + // Get a fresh new file manager for this instance. + $this->fileman = $this->converter->get_file_manager($contextid, 'mod_qcreate'); + + // Convert course files embedded into the intro. + $this->fileman->filearea = 'intro'; + $this->fileman->itemid = 0; + $data['intro'] = moodle1_converter::migrate_referenced_files( + $data['intro'], $this->fileman); + + // Start writing qcreate.xml. + $this->open_xml_writer("activities/qcreate_{$this->moduleid}/qcreate.xml"); + $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, + 'moduleid' => $this->moduleid, 'modulename' => 'qcreate', + 'contextid' => $contextid)); + $this->xmlwriter->begin_tag('qcreate', array('id' => $instanceid)); + + foreach ($data as $field => $value) { + if ($field <> 'id') { + $this->xmlwriter->full_tag($field, $value); + } + } + + return $data; + } + + public function on_qcreate_requireds_start() { + $this->xmlwriter->begin_tag('requireds'); + } + + public function on_qcreate_requireds_end() { + $this->xmlwriter->end_tag('requireds'); + } + + public function process_qcreate_required($data) { + $this->write_xml('required', $data, array('/required/id')); + } + + public function on_qcreate_grades_start() { + $this->xmlwriter->begin_tag('grades'); + } + + public function on_qcreate_grades_end() { + $this->xmlwriter->end_tag('grades'); + } + + public function process_qcreate_grade($data) { + $this->write_xml('grade', $data, array('/grade/id')); + } + + /** + * This is executed when we reach the closing tag of our 'qcreate' path + */ + public function on_qcreate_end() { + // Finish writing qcreate.xml. + $this->xmlwriter->end_tag('qcreate'); + $this->xmlwriter->end_tag('activity'); + $this->close_xml_writer(); + + // Write inforef.xml. + $this->open_xml_writer("activities/qcreate_{$this->moduleid}/inforef.xml"); + $this->xmlwriter->begin_tag('inforef'); + $this->xmlwriter->begin_tag('fileref'); + foreach ($this->fileman->get_fileids() as $fileid) { + $this->write_xml('file', array('id' => $fileid)); + } + $this->xmlwriter->end_tag('fileref'); + $this->xmlwriter->end_tag('inforef'); + $this->close_xml_writer(); + } +} diff --git a/backup/moodle2/backup_qcreate_activity_task.class.php b/backup/moodle2/backup_qcreate_activity_task.class.php new file mode 100644 index 0000000..af4faf1 --- /dev/null +++ b/backup/moodle2/backup_qcreate_activity_task.class.php @@ -0,0 +1,90 @@ +. + +/** + * Defines backup_qcreate_activity_task class + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/qcreate/backup/moodle2/backup_qcreate_stepslib.php'); + +/** + * Provides the steps to perform one complete backup of the Quiz instance + * + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_qcreate_activity_task extends backup_activity_task { + + /** + * No specific settings for this activity + */ + protected function define_my_settings() { + } + + /** + * Defines backup steps to store the instance data and required questions + */ + protected function define_my_steps() { + // Generate the qcreate.xml file containing all the qcreate information + // and annotating used questions. + $this->add_step(new backup_qcreate_activity_structure_step('qcreate_structure', 'qcreate.xml')); + + // Note: Following steps must be present + // in all the activities using question banks. + + // Process all the annotated questions to calculate the question + // categories needing to be included in backup for this activity + // plus the categories belonging to the activity context itself. + $this->add_step(new backup_calculate_question_categories('activity_question_categories')); + + // Clean backup_temp_ids table from questions. We already + // have used them to detect question_categories and aren't + // needed anymore. + $this->add_step(new backup_delete_temp_questions('clean_temp_questions')); + } + + /** + * Encodes URLs to the index.php and view.php scripts + * + * @param string $content some HTML text that eventually contains URLs to the activity instance scripts + * @return string the content with the URLs encoded + */ + public static function encode_content_links($content) { + global $CFG; + + $base = preg_quote($CFG->wwwroot, '/'); + + // Link to the list of qcreatezes. + $search = "/(".$base."\/mod\/qcreate\/index.php\?id\=)([0-9]+)/"; + $content = preg_replace($search, '$@QCREATEINDEX*$2@$', $content); + + // Link to qcreate view by moduleid. + $search = "/(".$base."\/mod\/qcreate\/view.php\?id\=)([0-9]+)/"; + $content = preg_replace($search, '$@QCREATEVIEWBYID*$2@$', $content); + + // Link to qcreate view by qcreateid. + $search = "/(".$base."\/mod\/qcreate\/view.php\?a\=)([0-9]+)/"; + $content = preg_replace($search, '$@QCREATEVIEWBYA*$2@$', $content); + + return $content; + } +} diff --git a/backup/moodle2/backup_qcreate_stepslib.php b/backup/moodle2/backup_qcreate_stepslib.php new file mode 100644 index 0000000..6b5c699 --- /dev/null +++ b/backup/moodle2/backup_qcreate_stepslib.php @@ -0,0 +1,85 @@ +. + +/** + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Define all the backup steps that will be used by the backup_qcreate_activity_task + * + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_qcreate_activity_structure_step extends backup_questions_activity_structure_step { + + protected function define_structure() { + + // To know if we are including userinfo. + $userinfo = $this->get_setting_value('userinfo'); + + // Define each element separated. + $qcreate = new backup_nested_element('qcreate', array('id'), array( + 'name', 'intro', 'introformat', 'grade', 'graderatio', 'allowed', 'totalrequired', + 'studentqaccess', 'timesync', 'timeopen', 'timeclose', 'timecreated', + 'timemodified', 'completionquestions', 'sendgradernotifications', 'sendstudentnotifications')); + + $requireds = new backup_nested_element('requireds'); + + $required = new backup_nested_element('required', array('id'), array( + 'qtype', 'no')); + + $grades = new backup_nested_element('grades'); + + $grade = new backup_nested_element('grade', array('id'), array( + 'questionid', 'gradeval', 'gradecomment', 'teacher', 'timemarked')); + + // Build the tree. + $qcreate->add_child($requireds); + $requireds->add_child($required); + + $qcreate->add_child($grades); + $grades->add_child($grade); + + // Define sources. + $qcreate->set_source_table('qcreate', array('id' => backup::VAR_ACTIVITYID)); + + $required->set_source_table('qcreate_required', + array('qcreateid' => backup::VAR_PARENTID)); + + // All the rest of elements only happen if we are including user info. + if ($userinfo) { + $grade->set_source_table('qcreate_grades', array('qcreateid' => backup::VAR_PARENTID)); + $grade->annotate_ids('user', 'teacher'); + } + + // Define source alias. + $grade->set_source_alias('grade', 'gradeval'); + + // Define id annotations. + $grade->annotate_ids('user', 'teacher'); + + // Define file annotations. + $qcreate->annotate_files('mod_qcreate', 'intro', null); // This file area hasn't itemid. + + // Return the root element (qcreate), wrapped into standard activity structure. + return $this->prepare_activity_structure($qcreate); + } +} diff --git a/backup/moodle2/restore_qcreate_activity_task.class.php b/backup/moodle2/restore_qcreate_activity_task.class.php new file mode 100644 index 0000000..1399b5f --- /dev/null +++ b/backup/moodle2/restore_qcreate_activity_task.class.php @@ -0,0 +1,129 @@ +. + +/** + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/qcreate/backup/moodle2/restore_qcreate_stepslib.php'); + + +/** + * qcreate restore task that provides all the settings and steps to perform one + * complete restore of the activity + * + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_qcreate_activity_task extends restore_activity_task { + + /** + * Define (add) particular settings this activity can have + */ + protected function define_my_settings() { + // No particular settings for this activity. + } + + /** + * Define (add) particular steps this activity can have + */ + protected function define_my_steps() { + // Qcreate only has one structure step. + $this->add_step(new restore_qcreate_activity_structure_step('qcreate_structure', 'qcreate.xml')); + } + + /** + * Define the contents in the activity that must be + * processed by the link decoder + */ + public static function define_decode_contents() { + $contents = array(); + + $contents[] = new restore_decode_content('qcreate', array('intro'), 'qcreate'); + + return $contents; + } + + /** + * Define the decoding rules for links belonging + * to the activity to be executed by the link decoder + */ + public static function define_decode_rules() { + $rules = array(); + + $rules[] = new restore_decode_rule('QCREATEVIEWBYID', + '/mod/qcreate/view.php?id=$1', 'course_module'); + $rules[] = new restore_decode_rule('QCREATEVIEWBYA', + '/mod/qcreate/view.php?a=$1', 'qcreate'); + $rules[] = new restore_decode_rule('QCREATEINDEX', + '/mod/qcreate/index.php?id=$1', 'course'); + + return $rules; + + } + + /** + * Define the restore log rules that will be applied + * by the {@link restore_logs_processor} when restoring + * qcreate logs. It must return one array + * of {@link restore_log_rule} objects + */ + public static function define_restore_log_rules() { + $rules = array(); + + $rules[] = new restore_log_rule('qcreate', 'add', + 'view.php?id={course_module}', '{qcreate}'); + $rules[] = new restore_log_rule('qcreate', 'update', + 'view.php?id={course_module}', '{qcreate}'); + $rules[] = new restore_log_rule('qcreate', 'view', + 'view.php?id={course_module}', '{qcreate}'); + $rules[] = new restore_log_rule('qcreate', 'preview', + 'view.php?id={course_module}', '{qcreate}'); + $rules[] = new restore_log_rule('qcreate', 'report', + 'report.php?id={course_module}', '{qcreate}'); + $rules[] = new restore_log_rule('qcreate', 'editquestions', + 'view.php?id={course_module}', '{qcreate}'); + $rules[] = new restore_log_rule('qcreate', 'delete attempt', + 'report.php?id={course_module}', '[oldattempt]'); + $rules[] = new restore_log_rule('qcreate', 'manualgrading', + 'report.php?mode=grading&q={qcreate}', '{qcreate}'); + + return $rules; + } + + /** + * Define the restore log rules that will be applied + * by the {@link restore_logs_processor} when restoring + * course logs. It must return one array + * of {@link restore_log_rule} objects + * + * Note this rules are applied when restoring course logs + * by the restore final task, but are defined here at + * activity level. All them are rules not linked to any module instance (cmid = 0) + */ + public static function define_restore_log_rules_for_course() { + $rules = array(); + + $rules[] = new restore_log_rule('qcreate', 'view all', 'index.php?id={course}', null); + + return $rules; + } +} diff --git a/backup/moodle2/restore_qcreate_stepslib.php b/backup/moodle2/restore_qcreate_stepslib.php new file mode 100644 index 0000000..bbef638 --- /dev/null +++ b/backup/moodle2/restore_qcreate_stepslib.php @@ -0,0 +1,124 @@ +. + +/** + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Structure step to restore one qcreate activity + * + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_qcreate_activity_structure_step extends restore_questions_activity_structure_step { + + protected function define_structure() { + + $paths = array(); + $userinfo = $this->get_setting_value('userinfo'); + + $qcreate = new restore_path_element('qcreate', '/activity/qcreate'); + $paths[] = $qcreate; + + $paths[] = new restore_path_element('qcreate_required', + '/activity/qcreate/requireds/required'); + + if ($userinfo) { + $paths[] = new restore_path_element('qcreate_grade', '/activity/qcreate/grades/grade'); + } + + // Return the paths wrapped into standard activity structure. + return $this->prepare_activity_structure($paths); + } + + protected function process_qcreate($data) { + global $CFG, $DB; + + $data = (object)$data; + $oldid = $data->id; + $data->course = $this->get_courseid(); + + $data->timeopen = $this->apply_date_offset($data->timeopen); + $data->timeclose = $this->apply_date_offset($data->timeclose); + $data->timecreated = $this->apply_date_offset($data->timecreated); + $data->timemodified = $this->apply_date_offset($data->timemodified); + + if ($data->grade < 0) { // Scale found, get mapping. + $data->grade = -($this->get_mappingid('scale', abs($data->grade))); + } + + // Supply some items that maybe missing from previous versions. + $qcreateconfig = get_config('qcreate'); + if (!isset($data->completionquestions)) { + $data->completionquestions = 0; + } + if (!isset($data->sendgradernotifications)) { + $data->sendgradernotifications = $qcreateconfig->sendgradernotifications; + } + if (!isset($data->sendstudentnotifications)) { + $data->sendstudentnotifications = $qcreateconfig->sendstudentnotifications; + } + + // Insert the qcreate record. + $newitemid = $DB->insert_record('qcreate', $data); + // Immediately after inserting "activity" record, call this. + $this->apply_activity_instance($newitemid); + } + + protected function process_qcreate_required($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + $data->qcreateid = $this->get_new_parentid('qcreate'); + + $DB->insert_record('qcreate_required', $data); + } + + protected function process_qcreate_grade($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + $questioncreated = $this->get_mappingid('question_created', $data->questionid); + $data->qcreateid = $this->get_new_parentid('qcreate'); + $data->teacher = $this->get_mappingid('user', $data->teacher); + $data->grade = $data->gradeval; + $data->timemarked = $this->apply_date_offset($data->timemarked); + if ($questioncreated) { + // Adjust questionid. + $data->questionid = $questioncreated; + } + $DB->insert_record('qcreate_grades', $data); + } + + protected function inform_new_usage_id($newusageid) { + + } + protected function after_execute() { + parent::after_execute(); + // Add qcreate related files, no need to match by itemname (just internally handled context). + $this->add_related_files('mod_qcreate', 'intro', null); + } +} diff --git a/backuplib.php b/backuplib.php deleted file mode 100644 index f4d4134..0000000 --- a/backuplib.php +++ /dev/null @@ -1,277 +0,0 @@ -id) - // | - // | - // --------------------------------------------------- - // | | - // qcreate_grades qcreate_required - //(UL,pk->id, fk->qcreateid) (CL,pk->id, fk->qcreateid) - // - // Meaning: pk->primary key field of the table - // fk->foreign key to link with parent - // CL->course level info - // UL->user level info - // - //----------------------------------------------------------- - - //This function executes all the backup procedure about this mod - function qcreate_backup_mods($bf,$preferences) { - - global $CFG; - - $status = true; - - //Iterate over qcreate table - $qcreates = get_records("qcreate","course",$preferences->backup_course,"id"); - if ($qcreates) { - foreach ($qcreates as $qcreate) { - if (backup_mod_selected($preferences,'qcreate',$qcreate->id)) { - $status = $status && qcreate_backup_one_mod($bf,$preferences,$qcreate); - // backup files happens in backup_one_mod now too. - } - } - } - return $status; - } - - function qcreate_backup_one_mod($bf,$preferences,$qcreate) { - if (is_numeric($qcreate)) { - $qcreate = get_record('qcreate','id',$qcreate); - } - - $status = true; - - //Start mod - fwrite($bf,start_tag("MOD",3,true)); - //Print qcreate data - fwrite($bf,full_tag("ID",4,false,$qcreate->id)); - fwrite($bf,full_tag("MODTYPE",4,false, 'qcreate')); - fwrite($bf,full_tag("NAME",4,false,$qcreate->name)); - fwrite($bf,full_tag("GRADE",4,false,$qcreate->grade)); - fwrite($bf,full_tag("GRADERATIO",4,false,$qcreate->graderatio)); - fwrite($bf,full_tag("INTRO",4,false,$qcreate->intro)); - fwrite($bf,full_tag("INTROFORMAT",4,false,$qcreate->introformat)); - fwrite($bf,full_tag("ALLOWED",4,false,$qcreate->allowed)); - fwrite($bf,full_tag("TOTALREQUIRED",4,false,$qcreate->totalrequired)); - fwrite($bf,full_tag("STUDENTQACCESS",4,false,$qcreate->studentqaccess)); - fwrite($bf,full_tag("TIMEOPEN",4,false,$qcreate->timeopen)); - fwrite($bf,full_tag("TIMECLOSE",4,false,$qcreate->timeclose)); - fwrite($bf,full_tag("TIMECREATED",4,false,$qcreate->timecreated)); - fwrite($bf,full_tag("TIMEMODIFIED",4,false,$qcreate->timemodified)); - $status = $status && backup_qcreate_requireds($bf,$preferences,$qcreate->id); - //if we've selected to backup users info, then execute backup_qcreate_grades - if (backup_userdata_selected($preferences,'qcreate',$qcreate->id)) { - $status = $status && backup_qcreate_grades($bf,$preferences,$qcreate->id); - } - //End mod - $status = $status && fwrite($bf,end_tag("MOD",3,true)); - - return $status; - } - - //Backup qcreate_grades contents (executed from qcreate_backup_mods) - function backup_qcreate_grades($bf,$preferences,$qcreate) { - $status = true; - - $qcreate_grades = get_records("qcreate_grades","qcreateid",$qcreate,"id"); - //If there is grades - if ($qcreate_grades) { - //Write start tag - $status = $status && fwrite($bf,start_tag("GRADES",4,true)); - //Iterate over each grade - foreach ($qcreate_grades as $qcreate_grade) { - //Start grade - $status = $status && fwrite($bf,start_tag("GRADE",5,true)); - //Print grade contents - fwrite($bf,full_tag("ID",6,false,$qcreate_grade->id)); - fwrite($bf,full_tag("QUESTIONID",6,false,$qcreate_grade->questionid)); - fwrite($bf,full_tag("GRADE",6,false,$qcreate_grade->grade)); - fwrite($bf,full_tag("GRADECOMMENT",6,false,$qcreate_grade->gradecomment)); - fwrite($bf,full_tag("TEACHER",6,false,$qcreate_grade->teacher)); - fwrite($bf,full_tag("TIMEMARKED",6,false,$qcreate_grade->timemarked)); - //End grade - $status = $status && fwrite($bf,end_tag("GRADE",5,true)); - } - //Write end tag - $status = $status && fwrite($bf,end_tag("GRADES",4,true)); - } - return $status; - } - - //Backup qcreate_requireds contents (executed from qcreate_backup_mods) - function backup_qcreate_requireds($bf,$preferences,$qcreate) { - $status = true; - - $qcreate_requireds = get_records("qcreate_required", "qcreateid", $qcreate, "id"); - //If there is requireds - if ($qcreate_requireds) { - //Write start tag - $status = $status && fwrite($bf,start_tag("REQUIREDS",4,true)); - //Iterate over each required - foreach ($qcreate_requireds as $qcreate_required) { - //Start required - $status = $status && fwrite($bf, start_tag("REQUIRED", 5,true)); - //Print required contents - fwrite($bf, full_tag("ID", 6,false, $qcreate_required->id)); - fwrite($bf, full_tag("QTYPE", 6,false, $qcreate_required->qtype)); - fwrite($bf, full_tag("NO", 6,false, $qcreate_required->no)); - //End required - $status = $status && fwrite($bf, end_tag("REQUIRED", 5,true)); - } - //Write end tag - $status = $status && fwrite($bf, end_tag("REQUIREDS", 4,true)); - } - return $status; - } - - //Return an array of info (name, value) - function qcreate_check_backup_mods($course, $user_data=false, $backup_unique_code, $instances=null) { - if (!empty($instances) && is_array($instances) && count($instances)) { - $info = array(); - foreach ($instances as $id => $instance) { - $info += qcreate_check_backup_mods_instances($instance, $backup_unique_code); - } - return $info; - } - //First the course data - $info[0][0] = get_string("modulenameplural", "qcreate"); - if ($ids = qcreate_ids($course)) { - $info[0][1] = count($ids); - } else { - $info[0][1] = 0; - } - - //Now, if requested, the user_data - if ($user_data) { - $info[1][0] = get_string("grades"); - if ($ids = qcreate_grade_ids_by_course($course)) { - $info[1][1] = count($ids); - } else { - $info[1][1] = 0; - } - } - return $info; - } - - //Return an array of info (name, value) - function qcreate_check_backup_mods_instances($instance, $backup_unique_code) { - $info[$instance->id.'0'][0] = ''.$instance->name.''; - $info[$instance->id.'0'][1] = ''; - if (!empty($instance->userdata)) { - // in this module question categories and questions are user data. - //Categories - $info[$instance->id.'1'][0] = get_string("categories","quiz"); - if ($catids = qcreate_category_ids_by_instance ($instance->id, $backup_unique_code)) { - $info[$instance->id.'1'][1] = count($catids); - } else { - $info[$instance->id.'1'][1] = 0; - } - //Questions - $info[$instance->id.'2'][0] = get_string("questionsinclhidden","quiz"); - if ($ids = qcreate_question_ids_in_cats ($catids, $backup_unique_code)) { - $info[$instance->id.'2'][1] = count($ids); - } else { - $info[$instance->id.'2'][1] = 0; - } - $info[$instance->id.'3'][0] = get_string("grades"); - if ($ids = qcreate_grade_ids_by_instance($instance->id)) { - $info[$instance->id.'3'][1] = count($ids); - } else { - $info[$instance->id.'3'][1] = 0; - } - } - return $info; - } - - function qcreate_category_ids_by_instance ($instanceid, $backup_unique_code){ - - $cm = get_coursemodule_from_instance('qcreate', $instanceid); - $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); - $cats = get_records('question_categories', 'contextid', $modcontext->id, '', 'id, contextid'); - if ($cats){ - foreach ($cats as $cat){ - backup_putid($backup_unique_code, 'question_categories', $cat->id, 0); - } - return array_keys($cats); - } else { - return array(); - } - } - - function qcreate_question_ids_in_cats ($catids, $backup_unique_code){ - $qs = get_records_select('question', 'category IN ('.join($catids, ', ').')', '', 'id, 0'); - if ($qs){ - foreach (array_keys($qs) as $q){ - backup_putid($backup_unique_code, 'question', $q, 0); - } - return array_keys($qs); - } else { - return array(); - } - } - - //Return a content encoded to support interactivities linking. Every module - //should have its own. They are called automatically from the backup procedure. - function qcreate_encode_content_links($content, $preferences) { - - global $CFG; - - $base = preg_quote($CFG->wwwroot, "/"); - - //Link to the list of qcreates - $buscar="/(".$base."\/mod\/qcreate\/index.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar, '$@QCREATEINDEX*$2@$', $content); - - //Link to qcreate view by moduleid - $buscar="/(".$base."\/mod\/qcreate\/view.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar, '$@QCREATEVIEWBYID*$2@$', $result); - - return $result; - } - - // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE - - //Returns an array of qcreates id - function qcreate_ids ($course) { - - global $CFG; - - return get_records_sql ("SELECT qc.id, qc.course - FROM {$CFG->prefix}qcreate qc - WHERE qc.course = '$course'"); - } - - //Returns an array of qcreate_grades id - //only returns grades where question record exists. - function qcreate_grade_ids_by_course ($course) { - - global $CFG; - - return get_records_sql ("SELECT g.id , g.qcreateid - FROM {$CFG->prefix}qcreate_grades g, - {$CFG->prefix}question q, - {$CFG->prefix}qcreate qc - WHERE qc.course = '$course' AND - g.qcreateid = qc.id AND " . - "q.id = g.questionid"); - } - - //Returns an array of qcreate_grades id - //only returns grades where question record exists. - function qcreate_grade_ids_by_instance ($instanceid) { - - global $CFG; - - return get_records_sql ("SELECT g.id , g.qcreateid - FROM {$CFG->prefix}qcreate_grades g, - {$CFG->prefix}question q - WHERE g.qcreateid = $instanceid AND " . - "q.id = g.questionid"); - } -?> diff --git a/classes/event/course_module_instance_list_viewed.php b/classes/event/course_module_instance_list_viewed.php new file mode 100644 index 0000000..e1ae577 --- /dev/null +++ b/classes/event/course_module_instance_list_viewed.php @@ -0,0 +1,39 @@ +. + +/** + * The mod_qcreate instance list viewed event. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_qcreate\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The mod_qcreate instance list viewed event class. + * + * @package mod_qcreate + * @since Moodle 2.7 + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed { + // No code required here as the parent class handles it all. +} diff --git a/classes/event/course_module_viewed.php b/classes/event/course_module_viewed.php new file mode 100644 index 0000000..d46e4f0 --- /dev/null +++ b/classes/event/course_module_viewed.php @@ -0,0 +1,49 @@ +. + +/** + * The mod_qcreate course module viewed event. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_qcreate\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The mod_qcreate course module viewed event class. + * + * @package mod_qcreate + * @since Moodle 2.7 + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_module_viewed extends \core\event\course_module_viewed { + + /** + * Init method. + * + * @return void + */ + protected function init() { + $this->data['crud'] = 'r'; + $this->data['edulevel'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'qcreate'; + } +} diff --git a/classes/event/edit_page_viewed.php b/classes/event/edit_page_viewed.php new file mode 100644 index 0000000..665de26 --- /dev/null +++ b/classes/event/edit_page_viewed.php @@ -0,0 +1,104 @@ +. + +/** + * The mod_qcreate edit page viewed event. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_qcreate\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The mod_qcreate edit page viewed event class. + * + * @property-read array $other { + * Extra information about event. + * + * - int qcreateid: the id of the qcreate. + * } + * + * @package mod_qcreate + * @since Moodle 2.7 + * @copyright 2014 Jean-Michel vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class edit_page_viewed extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['crud'] = 'r'; + $this->data['edulevel'] = self::LEVEL_TEACHING; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('eventeditpageviewed', 'mod_qcreate'); + } + + /** + * Returns description of what happened. + * + * @return string + */ + public function get_description() { + return "The user with id '$this->userid' viewed the edit page for the qcreate with " . + "course module id '$this->contextinstanceid'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return new \moodle_url('/mod/qcreate/edit.php', array('cmid' => $this->contextinstanceid)); + } + + /** + * Return the legacy event log data. + * + * @return array + */ + protected function get_legacy_logdata() { + return array($this->courseid, 'qcreate', 'editquestions', 'view.php?id=' . $this->contextinstanceid, + $this->other['qcreateid'], $this->contextinstanceid); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->other['qcreateid'])) { + throw new \coding_exception('The \'qcreateid\' value must be set in other.'); + } + } +} diff --git a/classes/event/overview_viewed.php b/classes/event/overview_viewed.php new file mode 100644 index 0000000..9951593 --- /dev/null +++ b/classes/event/overview_viewed.php @@ -0,0 +1,106 @@ +. + +/** + * The mod_qcreate overview viewed event. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_qcreate\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The mod_qcreate overview viewed event class. + * + * @property-read array $other { + * Extra information about event. + * + * - int qcreateid: the id of the qcreate. + * } + * + * @package mod_qcreate + * @since Moodle 2.7 + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class overview_viewed extends \core\event\base { + + /** + * Init method. + * + * @return void + */ + protected function init() { + $this->data['crud'] = 'r'; + $this->data['edulevel'] = self::LEVEL_TEACHING; + } + + /** + * Return localised event name. + * + * @return string + */ + public static function get_name() { + return get_string('eventoverviewviewed', 'mod_qcreate'); + } + + /** + * Returns description of what happened. + * + * @return string + */ + public function get_description() { + return "The user with id '$this->userid' viewed the overview for the qcreate with " . + "course module id '$this->contextinstanceid'."; + } + + /** + * Get URL related to the action. + * + * @return \moodle_url + */ + public function get_url() { + return new \moodle_url('/mod/qcreate/overview.php', array('cmid' => $this->contextinstanceid)); + } + + /** + * Return the legacy event log data. + * + * @return array + */ + protected function get_legacy_logdata() { + return array($this->courseid, 'qcreate', 'overview', 'overview.php?cmid=' . $this->contextinstanceid, + $this->other['qcreateid'], $this->contextinstanceid); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->other['qcreateid'])) { + throw new \coding_exception('The \'qcreateid\' value must be set in other.'); + } + } +} diff --git a/classes/event/question_graded.php b/classes/event/question_graded.php new file mode 100644 index 0000000..cf59003 --- /dev/null +++ b/classes/event/question_graded.php @@ -0,0 +1,113 @@ +. + +/** + * The mod_qcreate question graded event. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace mod_qcreate\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The mod_qcreate question graded event class. + * + * @property-read array $other { + * Extra information about event. + * + * - int qcreateid: the id of the qcreate. + * } + * + * @package core + * @since Moodle 2.7 + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class question_graded extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['objecttable'] = 'qcreate_grades'; + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_TEACHING; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('eventquestiongraded', 'mod_qcreate'); + } + + /** + * Returns description of what happened. + * + * @return string + */ + public function get_description() { + return "The user with id '$this->userid' graded the question with id '" . $this->other['questionid'] . "' " . + "created by the user with id '$this->relateduserid' for the qcreate with course module id '$this->contextinstanceid'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return new \moodle_url('/grades.php', array('id' => $this->other['qcreateid'], + 'user' => $this->relateduserid)); + } + + /** + * Return the legacy event log data. + * + * @return array + */ + protected function get_legacy_logdata() { + return array($this->courseid, 'qcreate', 'manualgrade', 'comment.php?id=' . $this->other['qcreateid'] . + '&user=' . $this->relateduserid, $this->other['qcreateid'], $this->contextinstanceid); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->relateduserid)) { + throw new \coding_exception('The \'relateduserid\' must be set.'); + } + + if (!isset($this->other['qcreateid'])) { + throw new \coding_exception('The \'qcreateid\' value must be set in other.'); + } + + if (!isset($this->other['questionid'])) { + throw new \coding_exception('The \'questionid\' value must be set in other.'); + } + } +} diff --git a/classes/event/question_regraded.php b/classes/event/question_regraded.php new file mode 100644 index 0000000..8f6a515 --- /dev/null +++ b/classes/event/question_regraded.php @@ -0,0 +1,113 @@ +. + +/** + * The mod_qcreate question regraded event. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace mod_qcreate\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The mod_qcreate question regraded event class. + * + * @property-read array $other { + * Extra information about event. + * + * - int qcreateid: the id of the qcreate. + * } + * + * @package core + * @since Moodle 2.7 + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class question_regraded extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['objecttable'] = 'qcreate_grades'; + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_TEACHING; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('eventquestionregraded', 'mod_qcreate'); + } + + /** + * Returns description of what happened. + * + * @return string + */ + public function get_description() { + return "The user with id '$this->userid' regraded the question with id '" . $this->other['questionid'] . "' " . + "created by the user with id '$this->relateduserid' for the qcreate with course module id '$this->contextinstanceid'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return new \moodle_url('/grades.php', array('id' => $this->other['qcreateid'], + 'user' => $this->relateduserid)); + } + + /** + * Return the legacy event log data. + * + * @return array + */ + protected function get_legacy_logdata() { + return array($this->courseid, 'qcreate', 'manualgrade', 'comment.php?id=' . $this->other['qcreateid'] . + '&user=' . $this->relateduserid, $this->other['qcreateid'], $this->contextinstanceid); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->relateduserid)) { + throw new \coding_exception('The \'relateduserid\' must be set.'); + } + + if (!isset($this->other['qcreateid'])) { + throw new \coding_exception('The \'qcreateid\' value must be set in other.'); + } + + if (!isset($this->other['questionid'])) { + throw new \coding_exception('The \'questionid\' value must be set in other.'); + } + } +} diff --git a/classes/task/synchronize_qaccess.php b/classes/task/synchronize_qaccess.php new file mode 100644 index 0000000..01f10c9 --- /dev/null +++ b/classes/task/synchronize_qaccess.php @@ -0,0 +1,61 @@ +. + +/** + * A scheduled task for qcreate activities to synchronize student's question access capabilities. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace mod_qcreate\task; + +/** + * Simple task to run the qcreate cron. + */ +class synchronize_qaccess extends \core\task\scheduled_task { + + /** + * Get a descriptive name for this task (shown to admins). + * + * @return string + */ + public function get_name() { + return get_string('synchronizeqaccesstask', 'mod_qcreate'); + } + + /** + * Do the job. + * Throw exceptions on errors (the job will be retried). + */ + public function execute() { + global $CFG, $DB; + + require_once($CFG->dirroot . '/mod/qcreate/lib.php'); + // Find all qcreate instances. + $sql = "SELECT q.*, cm.id as cmidnumber, q.course as courseid + FROM {qcreate} q, {course_modules} cm, {modules} m + WHERE m.name='qcreate' AND m.id=cm.module AND cm.instance=q.id"; + $qcreates = $DB->get_recordset_sql($sql); + if ($qcreates) { + foreach ($qcreates as $qcreate) { + $context = \context_module::instance($qcreate->cmidnumber); + qcreate_student_q_access_sync($context, $qcreate, false); + } + } + } + +} diff --git a/classes/task/update_grades.php b/classes/task/update_grades.php new file mode 100644 index 0000000..8a3055e --- /dev/null +++ b/classes/task/update_grades.php @@ -0,0 +1,80 @@ +. + +/** + * A scheduled task for qcreate activities to upadte student's grades. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace mod_qcreate\task; + +/** + * Simple task to run the qcreate cron. + */ +class update_grades extends \core\task\scheduled_task { + + /** + * Get a descriptive name for this task (shown to admins). + * + * @return string + */ + public function get_name() { + return get_string('updategradestask', 'mod_qcreate'); + } + + /** + * Do the job. + * Throw exceptions on errors (the job will be retried). + */ + public function execute() { + global $CFG, $DB; + + require_once($CFG->dirroot . '/mod/qcreate/lib.php'); + // Find all qcreate instances. + $sql = "SELECT q.*, cm.id as cmidnumber, q.course as courseid + FROM {qcreate} q, {course_modules} cm, {modules} m + WHERE m.name='qcreate' AND m.id=cm.module AND cm.instance=q.id"; + $qcreates = $DB->get_recordset_sql($sql); + if ($qcreates) { + foreach ($qcreates as $qcreate) { + $context = \context_module::instance($qcreate->cmidnumber); + if ($users = get_users_by_capability($context, 'mod/qcreate:submit', '', '', '', '', '', '', false)) { + $users = array_keys($users); + $sql = 'SELECT q.* FROM {question_categories} qc, {question} q '. + 'LEFT JOIN {qcreate_grades} g ON q.id = g.questionid '. + 'WHERE g.timemarked IS NULL AND q.createdby IN ('.implode(',', $users).') '. + 'AND qc.id = q.category ' . + 'AND q.hidden=\'0\' AND q.parent=\'0\' ' . + 'AND qc.contextid ='.$context->id; + $questionrs = $DB->get_recordset_sql($sql); + $toupdates = array(); + foreach ($questionrs as $question) { + qcreate_process_local_grade($qcreate, $question, true, true); + $toupdates[] = $question->createdby; + } + $questionrs->close(); + $toupdates = array_unique($toupdates); + foreach ($toupdates as $toupdate) { + qcreate_update_grades($qcreate, $toupdate); + } + } + } + } + } + +} diff --git a/db/access.php b/db/access.php index 9cd81c3..13477d3 100644 --- a/db/access.php +++ b/db/access.php @@ -1,7 +1,27 @@ . + +/** + * Capability definitions for the qcreate module. + * + * For naming conventions, see lib/db/access.php. + * + * @package mod_qcreate + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late + */ defined('MOODLE_INTERNAL') || die(); @@ -9,7 +29,6 @@ 'mod/qcreate:addinstance' => array( 'riskbitmask' => RISK_XSS, - 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( @@ -20,7 +39,6 @@ ), 'mod/qcreate:view' => array( - 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => array( @@ -33,7 +51,6 @@ ), 'mod/qcreate:submit' => array( - 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => array( @@ -42,7 +59,6 @@ ), 'mod/qcreate:grade' => array( - 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => array( @@ -50,6 +66,23 @@ 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ) - ) -); + ), + + 'mod/qcreate:receivegradernotifications' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ) + ), + 'mod/qcreate:receivestudentnotification' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'student' => CAP_ALLOW + ) + ), +); diff --git a/db/install.xml b/db/install.xml index 2bf7c53..628092f 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,26 +1,29 @@ - - +
- - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -29,31 +32,31 @@
- +
- - - - + + + + - +
- +
- - - - - - - + + + + + + + - - - + + + diff --git a/db/messages.php b/db/messages.php new file mode 100644 index 0000000..7a3b275 --- /dev/null +++ b/db/messages.php @@ -0,0 +1,37 @@ +. + +/** + * Defines message providers (types of message sent) for the qcreate module. + * + * @package mod_qcreate + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$messageproviders = array( + // Notify teacher that a student has created a question. + 'gradernotification' => array( + 'capability' => 'mod/qcreate:receivegradernotifications' + ), + + // Notify student that a question was graded. + 'studentnotification' => array( + 'capability' => 'mod/qcreate:receivestudentnotifications' + ), +); diff --git a/db/tasks.php b/db/tasks.php new file mode 100644 index 0000000..77aa1d3 --- /dev/null +++ b/db/tasks.php @@ -0,0 +1,47 @@ +. + +/** + * Definition of Question creation scheduled tasks. + * + * @package mod_qcreate + * @category task + * @copyright 2014 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$tasks = array( + array( + 'classname' => 'mod_qcreate\task\update_grades', + 'blocking' => 0, + 'minute' => '*/5', + 'hour' => '*', + 'day' => '*', + 'month' => '*', + 'dayofweek' => '*' + ), + array( + 'classname' => 'mod_qcreate\task\synchronize_qaccess', + 'blocking' => 0, + 'minute' => '*/3', + 'hour' => '*', + 'day' => '*', + 'month' => '*', + 'dayofweek' => '*' + ) +); \ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php index 2b812ca..2d4bed9 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,7 +1,28 @@ -. + +/** + * This file keeps track of upgrades to the qcreate module + * + * For naming conventions, see lib/db/access.php. + * + * @package mod_qcreate + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late + */ -// This file keeps track of upgrades to -// the qcreate module // // Sometimes, changes between versions involve // alterations to database structures and other @@ -15,8 +36,70 @@ // will tell you what you need to do. // // The commands in here will all be database-neutral, -// using the functions defined in lib/ddllib.php +// using the functions defined in lib/ddllib.php. function xmldb_qcreate_upgrade($oldversion=0) { - return true; + global $CFG, $DB, $OUTPUT; + + $dbman = $DB->get_manager(); + + // Moodle v2.2.0 release upgrade line. + // Put any upgrade step following this. + + // Moodle v2.3.0 release upgrade line. + // Put any upgrade step following this. + + // Moodle v2.4.0 release upgrade line. + // Put any upgrade step following this. + + // Moodle v2.5.0 release upgrade line. + // Put any upgrade step following this. + + // Moodle v2.6.0 release upgrade line. + // Put any upgrade step following this. + + // Moodle v2.7.0 release upgrade line. + // Put any upgrade step following this. + + if ($oldversion < 2014060108) { + + // Define field completionquestions to be added to qcreate. + $table = new xmldb_table('qcreate'); + $field = new xmldb_field('completionquestions', XMLDB_TYPE_INTEGER, '10', null, + null, null, '0', 'timemodified'); + + // Conditionally launch add field completionquestions. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Qcreate savepoint reached. + upgrade_mod_savepoint(true, 2014060108, 'qcreate'); + } + + if ($oldversion < 2014082400) { + + // Define field to be added to qcreate. + $table = new xmldb_table('qcreate'); + $field = new xmldb_field('sendgradernotifications', XMLDB_TYPE_INTEGER, '2', null, + XMLDB_NOTNULL, null, '0', 'completionquestions'); + + // Conditionally launch add field. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define field to be added to qcreate. + $table = new xmldb_table('qcreate'); + $field = new xmldb_field('sendstudentnotifications', XMLDB_TYPE_INTEGER, '2', null, + XMLDB_NOTNULL, null, '0', 'sendgradernotifications'); + + // Conditionally launch add field. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + // Qcreate savepoint reached. + upgrade_mod_savepoint(true, 2014082400, 'qcreate'); + } + return true; } diff --git a/deprecatedlib.php b/deprecatedlib.php deleted file mode 100644 index 8f608e5..0000000 --- a/deprecatedlib.php +++ /dev/null @@ -1,30 +0,0 @@ - $qtype) { - $returnTypes[$name] = $qtype->local_name(); - } - - return $returnTypes; - } -} - -if (!function_exists('questionbank_navigation_tabs')) { - function questionbank_navigation_tabs(&$row, $contexts, $querystring) { - global $CFG, $QUESTION_EDITTABCAPS; - $tabs = array( - 'questions' =>array("$CFG->wwwroot/question/edit.php?$querystring", get_string('questions', 'quiz'), get_string('editquestions', 'quiz')), - 'categories' =>array("$CFG->wwwroot/question/category.php?$querystring", get_string('categories', 'quiz'), get_string('editqcats', 'quiz')), - 'import' =>array("$CFG->wwwroot/question/import.php?$querystring", get_string('import', 'quiz'), get_string('importquestions', 'quiz')), - 'export' =>array("$CFG->wwwroot/question/export.php?$querystring", get_string('export', 'quiz'), get_string('exportquestions', 'quiz'))); - foreach ($tabs as $tabname => $tabparams){ - if ($contexts->have_one_edit_tab_cap($tabname)) { - $row[] = new tabobject($tabname, $tabparams[0], $tabparams[1], $tabparams[2]); - } - } - } -} \ No newline at end of file diff --git a/edit.php b/edit.php index 15ac83f..0ce42e9 100644 --- a/edit.php +++ b/edit.php @@ -1,39 +1,52 @@ -. + /** -* Page to grade questions -* -* -* @version $Id: edit.php,v 1.16 2008/11/12 08:23:00 jamiesensei Exp $ -* @author Martin Dougiamas and many others. -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -*/ -require_once("../../config.php"); -require_once($CFG->libdir.'/gradelib.php'); -require_once($CFG->libdir.'/tablelib.php'); -require_once($CFG->dirroot.'/mod/qcreate/lib.php'); + * Page to grade created questions. + * + * @package mod_qcreate + * @copyright 2008 Jamie Pratt + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late + */ +require_once(dirname(__FILE__) . '/../../config.php'); +require_once($CFG->libdir . '/gradelib.php'); +require_once($CFG->libdir . '/tablelib.php'); +require_once($CFG->dirroot . '/mod/qcreate/lib.php'); require_once($CFG->dirroot . '/question/editlib.php'); - list($thispageurl, $contexts, $cmid, $cm, $qcreate, $pagevars) = question_edit_setup('questions', '/mod/qcreate/edit.php'); $qcreate->cmidnumber = $cm->id; -require_capability('mod/qcreate:grade', get_context_instance(CONTEXT_MODULE, $cm->id)); -if ($qcreate->graderatio == 100){ - $grading_interface = false; +require_capability('mod/qcreate:grade', context_module::instance($cm->id)); +if ($qcreate->graderatio == 100) { + $gradinginterface = false; } else { - $grading_interface = true; -} + $gradinginterface = true; +} $page = optional_param('page', 0, PARAM_INT); +$gradessubmitted = optional_param('gradessubmitted', 0, PARAM_BOOL); // Grades submitted? -$gradessubmitted = optional_param('gradessubmitted', 0, PARAM_BOOL); // grades submitted? -if ($grading_interface){ +if ($gradinginterface) { $showungraded = optional_param('showungraded', 1, PARAM_BOOL); $showgraded = optional_param('showgraded', 1, PARAM_BOOL); $showneedsregrade = optional_param('showneedsregrade', 1, PARAM_BOOL); } else { $showungraded = true; - $showgraded = true; - $showneedsregrade = true; + $showgraded = true; + $showneedsregrade = true; } @@ -41,18 +54,21 @@ /* first we check to see if the form has just been submitted * to request user_preference updates */ -if (isset($_POST['updatepref'])){ +$updatepref = optional_param('updatepref', 0, PARAM_INT); +if ($updatepref) { $perpage = optional_param('perpage', 10, PARAM_INT); - $perpage = ($perpage <= 0) ? 10 : $perpage ; + $perpage = ($perpage <= 0) ? QCREATE_PER_PAGE : $perpage; + $perpage = ($perpage > QCREATE_MAX_PER_PAGE) ? QCREATE_MAX_PER_PAGE : $perpage; set_user_preference('qcreate_perpage', $perpage); } -/// find out current groups mode + +// Find out current groups mode. $groupmode = groups_get_activity_groupmode($cm); $currentgroup = groups_get_activity_group($cm, true); -/// Get all ppl that are allowed to submit assignments -$context = get_context_instance(CONTEXT_MODULE, $cm->id); -if (!$users = get_users_by_capability($context, 'mod/qcreate:submit', '', '', '', '', $currentgroup, '', false)){ +// Get all ppl that are allowed to submit grades. +$context = context_module::instance($cm->id); +if (!$users = get_users_by_capability($context, 'mod/qcreate:submit', '', '', '', '', $currentgroup, '', false)) { $users = array(); } @@ -62,8 +78,8 @@ $users = array_intersect($users, array_keys($groupingusers)); } -// grades submitted? -if ($gradessubmitted){ +// Grades submitted? +if ($gradessubmitted) { qcreate_process_grades($qcreate, $cm, $users); } @@ -72,46 +88,52 @@ */ $perpage = get_user_preferences('qcreate_perpage', 10); -$grading_info = grade_get_grades($COURSE->id, 'mod', 'qcreate', $qcreate->id); +$gradinginfo = grade_get_grades($COURSE->id, 'mod', 'qcreate', $qcreate->id); -if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) { - $uses_outcomes = true; +if (!empty($CFG->enableoutcomes) and !empty($gradinginfo->outcomes)) { + $usesoutcomes = true; } else { - $uses_outcomes = false; + $usesoutcomes = false; } -$teacherattempts = true; /// Temporary measure -$strsaveallfeedback = get_string('saveallfeedback', 'assignment'); +$teacherattempts = true; // Temporary measure. +$strsaveallfeedback = get_string('saveallfeedback', 'qcreate'); + +$tabindex = 1; // Tabindex for quick grading tabbing; Not working for dropdowns yet. -$tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet +// Log this visit. +$params = array( + 'courseid' => $COURSE->id, + 'context' => $context, + 'other' => array( + 'qcreateid' => $qcreate->id + ) +); +$event = \mod_qcreate\event\edit_page_viewed::create($params); +$event->trigger(); -add_to_log($COURSE->id, 'qcreate', 'grade', 'grades.php?id='.$qcreate->id, $qcreate->id, $cm->id); $strqcreate = get_string('modulename', 'qcreate'); $strqcreates = get_string('modulenameplural', 'qcreate'); -$navlinks = array(); -$navlinks[] = array('name' => $strqcreates, 'link' => "index.php?id=$COURSE->id", 'type' => 'activity'); -$navlinks[] = array('name' => format_string($qcreate->name,true), - 'link' => "view.php?id={$cm->id}", - 'type' => 'activityinstance'); -$navlinks[] = array('name' => get_string('grading', 'qcreate'), 'link' => '', 'type' => 'title'); -$navigation = build_navigation($navlinks); $PAGE->set_url($thispageurl); -print_header_simple(format_string($qcreate->name,true), "", $navigation, - '', '', true, update_module_button($cm->id, $COURSE->id, $strqcreate), navmenu($COURSE, $cm)); +// Prepare header. +$title = $COURSE->shortname . ': ' . format_string($qcreate->name); +$PAGE->set_title($title); +$PAGE->set_heading($COURSE->fullname); +$PAGE->set_context($context); -$mode = 'editq'; -include('tabs.php'); +echo $OUTPUT->header(); +echo $OUTPUT->heading($qcreate->name, 2, null); -//setting this after tabs.php as these params are just for this page and should not be included in urls for tabs. $thispageurl->params(compact('showgraded', 'showneedsregrade', 'showungraded', 'page')); groups_print_activity_menu($cm, $thispageurl->out()); -if ($grading_interface){ - $tablecolumns = array('picture', 'fullname', 'qname', 'grade', 'status', 'gradecomment', 'timemodified', 'timemarked', 'finalgrade'); +if ($gradinginterface) { + $tablecolumns = array('picture', 'fullname', 'qname', 'grade', 'status', + 'gradecomment', 'timemodified', 'timemarked', 'finalgrade'); $tableheaders = array('', get_string('fullname'), get_string('question'), @@ -121,9 +143,9 @@ get_string('lastmodified'), get_string('marked', 'qcreate'), get_string('finalgrade', 'grades')); - if ($uses_outcomes) { - $tablecolumns[] = 'outcome'; // no sorting based on outcomes column - $tableheaders[] = get_string('outcome', 'grades'); + if ($usesoutcomes) { + $tablecolumns[] = 'outcomes'; // No sorting based on outcomes column. + $tableheaders[] = get_string('outcomes', 'grades'); } } else { $tablecolumns = array('picture', 'fullname', 'qname', 'gradecomment', 'timemodified', 'finalgrade'); @@ -141,7 +163,7 @@ $table->define_headers($tableheaders); $table->define_baseurl($thispageurl->out()); -$table->sortable(true, 'lastname');//sorted by lastname by default +$table->sortable(true, 'lastname');// Sorted by lastname by default. $table->collapsible(true); $table->initialbars(true); @@ -154,44 +176,42 @@ $table->column_class('gradecomment', 'comment'); $table->column_class('timemodified', 'timemodified'); $table->column_class('finalgrade', 'finalgrade'); -if ($grading_interface){ +if ($gradinginterface) { $table->column_class('grade', 'grade'); $table->column_class('timemarked', 'timemarked'); $table->column_class('status', 'status'); - if ($uses_outcomes) { - $table->column_class('outcome', 'outcome'); + if ($usesoutcomes) { + $table->column_class('outcomes', 'outcome'); } } -$table->set_attribute('cellspacing', '0'); + $table->set_attribute('id', 'attempts'); $table->set_attribute('class', 'grades'); -$table->set_attribute('width', '90%'); -//$table->set_attribute('align', 'center'); -if ($grading_interface){ +if ($gradinginterface) { $table->no_sorting('finalgrade'); - $table->no_sorting('outcome'); + $table->no_sorting('outcomes'); } -// Start working -- this is necessary as soon as the niceties are over +// Start working -- this is necessary as soon as the niceties are over. $table->setup(); -/// Construct the SQL +// Construct the SQL. -if (!empty($users) && ($showungraded || $showgraded || $showneedsregrade)){ +if (!empty($users) && ($showungraded || $showgraded || $showneedsregrade)) { if ($sort = $table->get_sql_sort()) { $sort = ' ORDER BY '.$sort; } $where = $table->get_sql_where(); - if ($where[0]) { + if ($where[0]) { $where[0] .= ' AND '; - } - - //unfortunately we cannot use status in WHERE clause - switch ($showungraded . $showneedsregrade . $showgraded){ + } + + // Unfortunately we cannot use status in WHERE clause. + switch ($showungraded . $showneedsregrade . $showgraded) { case '001': $where[0] .= '(g.timemarked IS NOT NULL) AND (g.timemarked >= q.timemodified ) AND '; break; @@ -210,7 +230,7 @@ case '110': $where[0] .= '((g.timemarked IS NULL) OR g.timemarked < q.timemodified) AND '; break; - case '111': //show everything + case '111': // Show everything. break; } if ($qcreate->allowed != 'ALL') { @@ -219,49 +239,54 @@ $where[0] .= 'q.qtype IN ('.$allowedlist.') AND '; } - $countsql = 'SELECT COUNT(*) FROM '.$CFG->prefix.'user u, '.$CFG->prefix.'question_categories c, '.$CFG->prefix.'question q '. - 'LEFT JOIN '.$CFG->prefix.'qcreate_grades g ON q.id = g.questionid '. - 'WHERE '.$where[0].'q.createdby = u.id AND u.id IN ('.implode(',',$users). + $countsql = 'SELECT COUNT(*) FROM {user} u, {question_categories} c, {question} q '. + 'LEFT JOIN {qcreate_grades} g ON q.id = g.questionid '. + 'WHERE ' . $where[0] . 'q.createdby = u.id AND u.id IN (' . implode(',', $users) . ') AND q.hidden=\'0\' AND q.parent=\'0\' AND q.category = c.id and c.contextid='.$context->id; $answercount = $DB->count_records_sql($countsql, $where[1]); - //complicated status calculation is needed for sorting on status column - $select = 'SELECT q.id AS qid, u.id, u.firstname, u.lastname, u.picture, + $ufields = user_picture::fields('u'); + // Complicated status calculation is needed for sorting on status column. + $select = "SELECT q.id AS qid, $ufields, g.id AS gradeid, g.grade, g.gradecomment, q.timemodified, g.timemarked, q.qtype, q.name AS qname, COALESCE( SIGN(SIGN(g.timemarked) + SIGN(g.timemarked - q.timemodified)) ,-1 - ) AS status '; - $sql = 'FROM '.$CFG->prefix.'user u, '.$CFG->prefix.'question_categories c, '.$CFG->prefix.'question q '. - 'LEFT JOIN '.$CFG->prefix.'qcreate_grades g ON q.id = g.questionid + ) AS status "; + $sql = 'FROM {user} u, {question_categories} c, {question} q '. + 'LEFT JOIN {qcreate_grades} g ON q.id = g.questionid AND g.qcreateid = '.$qcreate->id.' '. - 'WHERE '.$where[0].'q.createdby = u.id AND u.id IN ('.implode(',',$users). + 'WHERE ' . $where[0] . 'q.createdby = u.id AND u.id IN (' . implode(',', $users) . ') AND q.hidden=\'0\' AND q.parent=\'0\' AND q.category = c.id and c.contextid='.$context->id; } else { $answercount = 0; } -if ($grading_interface){ +if ($gradinginterface) { echo '
'; echo '
'; - // TODO: echo $thispageurl->hidden_params_out(array('showgraded', 'showneedsregrade', 'showungraded')); - //default value for checkbox when checkbox not checked. + + // Default value for checkbox when checkbox not checked. + echo ''; echo ''; echo ''; echo '
'; echo '
'; print_string('show', 'qcreate'); - $checked = $showgraded?' checked="checked"':''; - echo ''; + $checked = $showgraded ? ' checked="checked"' : ''; + echo ''; echo ''; - $checked = $showneedsregrade?' checked="checked"':''; - echo ''; + $checked = $showneedsregrade ? ' checked="checked"' : ''; + echo ' '; echo ''; - $checked = $showungraded?' checked="checked"':''; - echo ''; + $checked = $showungraded ? ' checked="checked"' : ''; + echo ' '; echo ''; echo '