From 9d94ea58b662dec093c070bb5ab3fa094d5b06c8 Mon Sep 17 00:00:00 2001 From: Laurent David Date: Thu, 31 Oct 2024 10:43:25 +0100 Subject: [PATCH 1/8] MDL-82457 mod_survey: Remove mod survey from Moodle 5.0 --- .upgradenotes/MDL-82457-2024103109431645.yml | 5 + lib/db/upgrade.php | 9 + mod/survey/amd/build/validation.min.js | 11 - mod/survey/amd/build/validation.min.js.map | 1 - mod/survey/amd/src/validation.js | 46 - mod/survey/backup/moodle1/lib.php | 127 -- .../backup_survey_activity_task.class.php | 70 - .../backup/moodle2/backup_survey_stepslib.php | 79 -- .../restore_survey_activity_task.class.php | 114 -- .../moodle2/restore_survey_stepslib.php | 95 -- .../analytics/indicator/activity_base.php | 46 - .../analytics/indicator/cognitive_depth.php | 56 - .../analytics/indicator/social_breadth.php | 56 - .../classes/completion/custom_completion.php | 82 -- .../course_module_instance_list_viewed.php | 39 - .../classes/event/course_module_viewed.php | 75 -- .../classes/event/report_downloaded.php | 109 -- mod/survey/classes/event/report_viewed.php | 97 -- .../classes/event/response_submitted.php | 99 -- mod/survey/classes/external.php | 394 ------ mod/survey/classes/output/actionbar.php | 128 -- mod/survey/classes/privacy/provider.php | 414 ------ mod/survey/classes/search/activity.php | 70 - mod/survey/db/access.php | 77 -- mod/survey/db/install.php | 125 -- mod/survey/db/install.xml | 77 -- mod/survey/db/log.php | 37 - mod/survey/db/services.php | 68 - mod/survey/db/upgrade.php | 56 - mod/survey/deprecatedlib.php | 31 - mod/survey/download.php | 365 ----- mod/survey/graph.php | 753 ----------- mod/survey/index.php | 91 -- mod/survey/lang/en/survey.php | 283 ---- mod/survey/lib.php | 1193 ----------------- mod/survey/mod_form.php | 93 -- mod/survey/pix/monologo.svg | 3 - mod/survey/renderer.php | 39 - mod/survey/report.php | 526 -------- mod/survey/save.php | 78 -- mod/survey/styles.css | 42 - .../templates/response_action_bar.mustache | 72 - mod/survey/tests/backup/restore_date_test.php | 73 - .../tests/behat/survey_completion.feature | 65 - .../behat/survey_critical_incidents.feature | 47 - .../tests/behat/survey_description.feature | 31 - mod/survey/tests/behat/survey_groups.feature | 86 -- mod/survey/tests/behat/survey_types.feature | 48 - .../tests/behat/survey_validation.feature | 25 - mod/survey/tests/custom_completion_test.php | 217 --- mod/survey/tests/event/events_test.php | 139 -- mod/survey/tests/externallib_test.php | 414 ------ mod/survey/tests/generator/lib.php | 75 -- mod/survey/tests/generator_test.php | 98 -- mod/survey/tests/lib_test.php | 404 ------ mod/survey/tests/privacy/provider_test.php | 534 -------- mod/survey/tests/search/search_test.php | 85 -- mod/survey/version.php | 30 - mod/survey/view.php | 184 --- version.php | 2 +- 60 files changed, 15 insertions(+), 8773 deletions(-) create mode 100644 .upgradenotes/MDL-82457-2024103109431645.yml delete mode 100644 mod/survey/amd/build/validation.min.js delete mode 100644 mod/survey/amd/build/validation.min.js.map delete mode 100644 mod/survey/amd/src/validation.js delete mode 100644 mod/survey/backup/moodle1/lib.php delete mode 100644 mod/survey/backup/moodle2/backup_survey_activity_task.class.php delete mode 100644 mod/survey/backup/moodle2/backup_survey_stepslib.php delete mode 100644 mod/survey/backup/moodle2/restore_survey_activity_task.class.php delete mode 100644 mod/survey/backup/moodle2/restore_survey_stepslib.php delete mode 100644 mod/survey/classes/analytics/indicator/activity_base.php delete mode 100644 mod/survey/classes/analytics/indicator/cognitive_depth.php delete mode 100644 mod/survey/classes/analytics/indicator/social_breadth.php delete mode 100644 mod/survey/classes/completion/custom_completion.php delete mode 100644 mod/survey/classes/event/course_module_instance_list_viewed.php delete mode 100644 mod/survey/classes/event/course_module_viewed.php delete mode 100644 mod/survey/classes/event/report_downloaded.php delete mode 100644 mod/survey/classes/event/report_viewed.php delete mode 100644 mod/survey/classes/event/response_submitted.php delete mode 100644 mod/survey/classes/external.php delete mode 100644 mod/survey/classes/output/actionbar.php delete mode 100644 mod/survey/classes/privacy/provider.php delete mode 100644 mod/survey/classes/search/activity.php delete mode 100644 mod/survey/db/access.php delete mode 100644 mod/survey/db/install.php delete mode 100644 mod/survey/db/install.xml delete mode 100644 mod/survey/db/log.php delete mode 100644 mod/survey/db/services.php delete mode 100644 mod/survey/db/upgrade.php delete mode 100644 mod/survey/deprecatedlib.php delete mode 100644 mod/survey/download.php delete mode 100644 mod/survey/graph.php delete mode 100644 mod/survey/index.php delete mode 100644 mod/survey/lang/en/survey.php delete mode 100644 mod/survey/lib.php delete mode 100644 mod/survey/mod_form.php delete mode 100644 mod/survey/pix/monologo.svg delete mode 100644 mod/survey/renderer.php delete mode 100644 mod/survey/report.php delete mode 100644 mod/survey/save.php delete mode 100644 mod/survey/styles.css delete mode 100644 mod/survey/templates/response_action_bar.mustache delete mode 100644 mod/survey/tests/backup/restore_date_test.php delete mode 100644 mod/survey/tests/behat/survey_completion.feature delete mode 100644 mod/survey/tests/behat/survey_critical_incidents.feature delete mode 100644 mod/survey/tests/behat/survey_description.feature delete mode 100644 mod/survey/tests/behat/survey_groups.feature delete mode 100644 mod/survey/tests/behat/survey_types.feature delete mode 100644 mod/survey/tests/behat/survey_validation.feature delete mode 100644 mod/survey/tests/custom_completion_test.php delete mode 100644 mod/survey/tests/event/events_test.php delete mode 100644 mod/survey/tests/externallib_test.php delete mode 100644 mod/survey/tests/generator/lib.php delete mode 100644 mod/survey/tests/generator_test.php delete mode 100644 mod/survey/tests/lib_test.php delete mode 100644 mod/survey/tests/privacy/provider_test.php delete mode 100644 mod/survey/tests/search/search_test.php delete mode 100644 mod/survey/version.php delete mode 100644 mod/survey/view.php diff --git a/.upgradenotes/MDL-82457-2024103109431645.yml b/.upgradenotes/MDL-82457-2024103109431645.yml new file mode 100644 index 00000000000..ff346884ece --- /dev/null +++ b/.upgradenotes/MDL-82457-2024103109431645.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-82457 +notes: + mod: + - message: Remove mod_survey for Moodle 5.0 + type: removed diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index ea4729ca06f..c9032d23690 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1303,5 +1303,14 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2024112900.02); } + // Moodle 5.0 Upgrade. + // Remove survey. + if ($oldversion < 2024120500.01) { + if (!file_exists($CFG->dirroot . "/mod/survey/version.php")) { + uninstall_plugin('mod', 'survey'); + } + // Main savepoint reached. + upgrade_main_savepoint(true, 2024120500.01); + } return true; } diff --git a/mod/survey/amd/build/validation.min.js b/mod/survey/amd/build/validation.min.js deleted file mode 100644 index b3f85da8360..00000000000 --- a/mod/survey/amd/build/validation.min.js +++ /dev/null @@ -1,11 +0,0 @@ -define("mod_survey/validation",["exports","core/str","core/notification"],(function(_exports,_str,_notification){var obj; -/** - * Javascript to handle survey validation. - * - * @module mod_survey/validation - * @copyright 2017 Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 3.3 - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.ensureRadiosChosen=void 0,_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};_exports.ensureRadiosChosen=formid=>{const form=document.getElementById(formid);form.addEventListener("submit",(e=>{0!==form.querySelectorAll('input[type="radio"][data-survey-default="true"]:checked').length&&(_notification.default.alert((0,_str.get_string)("error"),(0,_str.get_string)("questionsnotanswered","survey"),(0,_str.get_string)("ok")),e.preventDefault())}))}})); - -//# sourceMappingURL=validation.min.js.map \ No newline at end of file diff --git a/mod/survey/amd/build/validation.min.js.map b/mod/survey/amd/build/validation.min.js.map deleted file mode 100644 index b2004df7b11..00000000000 --- a/mod/survey/amd/build/validation.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"validation.min.js","sources":["../src/validation.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 to handle survey validation.\n *\n * @module mod_survey/validation\n * @copyright 2017 Dan Poltawski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.3\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\n\n/**\n * Prevents form submission until all radio buttons are chosen, displays\n * modal error if any choices are missing.\n *\n * @param {String} formid HTML id of form\n */\nexport const ensureRadiosChosen = (formid) => {\n const form = document.getElementById(formid);\n form.addEventListener('submit', (e) => {\n const optionsToSet = form.querySelectorAll('input[type=\"radio\"][data-survey-default=\"true\"]:checked');\n if (optionsToSet.length !== 0) {\n Notification.alert(\n getString('error'),\n getString('questionsnotanswered', 'survey'),\n getString('ok'),\n );\n e.preventDefault();\n }\n });\n};\n"],"names":["formid","form","document","getElementById","addEventListener","e","querySelectorAll","length","alert","preventDefault"],"mappings":";;;;;;;;gMAgCmCA,eACzBC,KAAOC,SAASC,eAAeH,QACrCC,KAAKG,iBAAiB,UAAWC,IAED,IADPJ,KAAKK,iBAAiB,2DAC1BC,+BACAC,OACT,mBAAU,UACV,mBAAU,uBAAwB,WAClC,mBAAU,OAEdH,EAAEI"} \ No newline at end of file diff --git a/mod/survey/amd/src/validation.js b/mod/survey/amd/src/validation.js deleted file mode 100644 index a4eb9b89bae..00000000000 --- a/mod/survey/amd/src/validation.js +++ /dev/null @@ -1,46 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// Moodle is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Moodle is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Moodle. If not, see . - -/** - * Javascript to handle survey validation. - * - * @module mod_survey/validation - * @copyright 2017 Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 3.3 - */ -import {get_string as getString} from 'core/str'; -import Notification from 'core/notification'; - -/** - * Prevents form submission until all radio buttons are chosen, displays - * modal error if any choices are missing. - * - * @param {String} formid HTML id of form - */ -export const ensureRadiosChosen = (formid) => { - const form = document.getElementById(formid); - form.addEventListener('submit', (e) => { - const optionsToSet = form.querySelectorAll('input[type="radio"][data-survey-default="true"]:checked'); - if (optionsToSet.length !== 0) { - Notification.alert( - getString('error'), - getString('questionsnotanswered', 'survey'), - getString('ok'), - ); - e.preventDefault(); - } - }); -}; diff --git a/mod/survey/backup/moodle1/lib.php b/mod/survey/backup/moodle1/lib.php deleted file mode 100644 index 7b5f79bab0d..00000000000 --- a/mod/survey/backup/moodle1/lib.php +++ /dev/null @@ -1,127 +0,0 @@ -. - -/** - * Provides support for the conversion of moodle1 backup to the moodle2 format - * - * @package mod_survey - * @copyright 2011 Rossiani Wijaya - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Survey conversion handler - */ -class moodle1_mod_survey_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/SURVEY 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( - 'survey', '/MOODLE_BACKUP/COURSE/MODULES/MOD/SURVEY', - array( - 'newfields' => array( - 'introformat' => 0, - ), - ) - ), - ); - } - - /** - * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/SURVEY - * data available - */ - public function process_survey($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); - - // replay upgrade step 2009042002 - if ($CFG->texteditors !== 'textarea') { - $data['intro'] = text_to_html($data['intro'], false, false, true); - $data['introformat'] = FORMAT_HTML; - } - - // get a fresh new file manager for this instance - $this->fileman = $this->converter->get_file_manager($contextid, 'mod_survey'); - - // 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); - - // write survey.xml - $this->open_xml_writer("activities/survey_{$this->moduleid}/survey.xml"); - $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $this->moduleid, - 'modulename' => 'survey', 'contextid' => $contextid)); - $this->xmlwriter->begin_tag('survey', array('id' => $instanceid)); - - foreach ($data as $field => $value) { - if ($field <> 'id') { - $this->xmlwriter->full_tag($field, $value); - } - } - - return $data; - } - - /** - * This is executed when we reach the closing tag of our 'survey' path - */ - public function on_survey_end() { - // finish survey.xml - $this->xmlwriter->end_tag('survey'); - $this->xmlwriter->end_tag('activity'); - $this->close_xml_writer(); - - // write inforef.xml - $this->open_xml_writer("activities/survey_{$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/mod/survey/backup/moodle2/backup_survey_activity_task.class.php b/mod/survey/backup/moodle2/backup_survey_activity_task.class.php deleted file mode 100644 index 8dff68befe3..00000000000 --- a/mod/survey/backup/moodle2/backup_survey_activity_task.class.php +++ /dev/null @@ -1,70 +0,0 @@ -. - -/** - * Defines backup_survey_activity_task class - * - * @package mod_survey - * @category backup - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/mod/survey/backup/moodle2/backup_survey_stepslib.php'); - -/** - * Provides all the settings and steps to perform one complete backup of the activity - */ -class backup_survey_activity_task extends backup_activity_task { - - /** - * No specific settings for this activity - */ - protected function define_my_settings() { - } - - /** - * Defines a backup step to store the instance data in the survey.xml file - */ - protected function define_my_steps() { - $this->add_step(new backup_survey_activity_structure_step('survey_structure', 'survey.xml')); - } - - /** - * 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 surveys - $search="/(".$base."\/mod\/survey\/index.php\?id\=)([0-9]+)/"; - $content= preg_replace($search, '$@SURVEYINDEX*$2@$', $content); - - // Link to survey view by moduleid - $search="/(".$base."\/mod\/survey\/view.php\?id\=)([0-9]+)/"; - $content= preg_replace($search, '$@SURVEYVIEWBYID*$2@$', $content); - - return $content; - } -} diff --git a/mod/survey/backup/moodle2/backup_survey_stepslib.php b/mod/survey/backup/moodle2/backup_survey_stepslib.php deleted file mode 100644 index 5bd3b08c380..00000000000 --- a/mod/survey/backup/moodle2/backup_survey_stepslib.php +++ /dev/null @@ -1,79 +0,0 @@ -. - -/** - * @package mod_survey - * @subpackage backup-moodle2 - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Define all the backup steps that will be used by the backup_survey_activity_task - */ - -/** - * Define the complete survey structure for backup, with file and id annotations - */ -class backup_survey_activity_structure_step extends backup_activity_structure_step { - - protected function define_structure() { - - // To know if we are including userinfo - $userinfo = $this->get_setting_value('userinfo'); - - // Define each element separated - $survey = new backup_nested_element('survey', array('id'), array( - 'name', 'intro', 'introformat', 'template', - 'questions', 'days', 'timecreated', 'timemodified', 'completionsubmit')); - - $answers = new backup_nested_element('answers'); - - $answer = new backup_nested_element('answer', array('id'), array( - 'userid', 'question', 'time', 'answer1', - 'answer2')); - - $analysis = new backup_nested_element('analysis'); - - $analys = new backup_nested_element('analys', array('id'), array( - 'userid', 'notes')); - - // Build the tree - $survey->add_child($answers); - $answers->add_child($answer); - - $survey->add_child($analysis); - $analysis->add_child($analys); - - // Define sources - $survey->set_source_table('survey', array('id' => backup::VAR_ACTIVITYID)); - - $answer->set_source_table('survey_answers', array('survey' => backup::VAR_PARENTID)); - - $analys->set_source_table('survey_analysis', array('survey' => backup::VAR_PARENTID)); - - // Define id annotations - $answer->annotate_ids('user', 'userid'); - $analys->annotate_ids('user', 'userid'); - - // Define file annotations - $survey->annotate_files('mod_survey', 'intro', null); // This file area hasn't itemid - - // Return the root element (survey), wrapped into standard activity structure - return $this->prepare_activity_structure($survey); - } -} diff --git a/mod/survey/backup/moodle2/restore_survey_activity_task.class.php b/mod/survey/backup/moodle2/restore_survey_activity_task.class.php deleted file mode 100644 index c90ae6d45f3..00000000000 --- a/mod/survey/backup/moodle2/restore_survey_activity_task.class.php +++ /dev/null @@ -1,114 +0,0 @@ -. - -/** - * @package mod_survey - * @subpackage backup-moodle2 - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/mod/survey/backup/moodle2/restore_survey_stepslib.php'); // Because it exists (must) - -/** - * survey restore task that provides all the settings and steps to perform one - * complete restore of the activity - */ -class restore_survey_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() { - // survey only has one structure step - $this->add_step(new restore_survey_activity_structure_step('survey_structure', 'survey.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('survey', array('intro'), 'survey'); - - 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('SURVEYVIEWBYID', '/mod/survey/view.php?id=$1', 'course_module'); - $rules[] = new restore_decode_rule('SURVEYINDEX', '/mod/survey/index.php?id=$1', 'course'); - - return $rules; - - } - - /** - * Define the restore log rules that will be applied - * by the {@link restore_logs_processor} when restoring - * survey 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('survey', 'add', 'view.php?id={course_module}', '{survey}'); - $rules[] = new restore_log_rule('survey', 'update', 'view.php?id={course_module}', '{survey}'); - $rules[] = new restore_log_rule('survey', 'view', 'view.php?id={course_module}', '{survey}'); - $rules[] = new restore_log_rule('survey', 'download', 'download.php?id={course_module}&type=[type]&group=[group]', '{survey}'); - $rules[] = new restore_log_rule('survey', 'view report', 'report.php?id={course_module}', '{survey}'); - $rules[] = new restore_log_rule('survey', 'submit', 'view.php?id={course_module}', '{survey}'); - $rules[] = new restore_log_rule('survey', 'view graph', 'view.php?id={course_module}', '{survey}'); - $rules[] = new restore_log_rule('survey', 'view form', 'view.php?id={course_module}', '{survey}'); - - 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('survey', 'view all', 'index.php?id={course}', null); - - return $rules; - } -} diff --git a/mod/survey/backup/moodle2/restore_survey_stepslib.php b/mod/survey/backup/moodle2/restore_survey_stepslib.php deleted file mode 100644 index a4de735990c..00000000000 --- a/mod/survey/backup/moodle2/restore_survey_stepslib.php +++ /dev/null @@ -1,95 +0,0 @@ -. - -/** - * @package mod_survey - * @subpackage backup-moodle2 - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Define all the restore steps that will be used by the restore_survey_activity_task - */ - -/** - * Structure step to restore one survey activity - */ -class restore_survey_activity_structure_step extends restore_activity_structure_step { - - protected function define_structure() { - - $paths = array(); - $userinfo = $this->get_setting_value('userinfo'); - - $paths[] = new restore_path_element('survey', '/activity/survey'); - if ($userinfo) { - $paths[] = new restore_path_element('survey_answer', '/activity/survey/answers/answer'); - $paths[] = new restore_path_element('survey_analys', '/activity/survey/analysis/analys'); - } - - // Return the paths wrapped into standard activity structure - return $this->prepare_activity_structure($paths); - } - - protected function process_survey($data) { - global $DB; - - $data = (object)$data; - $oldid = $data->id; - $data->course = $this->get_courseid(); - - // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. - // See MDL-9367. - - // insert the survey record - $newitemid = $DB->insert_record('survey', $data); - // immediately after inserting "activity" record, call this - $this->apply_activity_instance($newitemid); - } - - protected function process_survey_analys($data) { - global $DB; - - $data = (object)$data; - $oldid = $data->id; - $data->survey = $this->get_new_parentid('survey'); - $data->userid = $this->get_mappingid('user', $data->userid); - - $newitemid = $DB->insert_record('survey_analysis', $data); - // No need to save this mapping as far as nothing depend on it - // (child paths, file areas nor links decoder) - } - - protected function process_survey_answer($data) { - global $DB; - - $data = (object)$data; - $oldid = $data->id; - $data->survey = $this->get_new_parentid('survey'); - $data->userid = $this->get_mappingid('user', $data->userid); - - $newitemid = $DB->insert_record('survey_answers', $data); - // No need to save this mapping as far as nothing depend on it - // (child paths, file areas nor links decoder) - } - - protected function after_execute() { - // Add survey related files, no need to match by itemname (just internally handled context) - $this->add_related_files('mod_survey', 'intro', null); - } -} diff --git a/mod/survey/classes/analytics/indicator/activity_base.php b/mod/survey/classes/analytics/indicator/activity_base.php deleted file mode 100644 index 80c8f38c1e4..00000000000 --- a/mod/survey/classes/analytics/indicator/activity_base.php +++ /dev/null @@ -1,46 +0,0 @@ -. - -/** - * Activity base class. - * - * @package mod_survey - * @copyright 2017 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\analytics\indicator; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Activity base class. - * - * @package mod_survey - * @copyright 2017 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity { - - /** - * No need to fetch grades. - * - * @param \core_analytics\course $course - * @return void - */ - public function fetch_student_grades(\core_analytics\course $course) { - } -} diff --git a/mod/survey/classes/analytics/indicator/cognitive_depth.php b/mod/survey/classes/analytics/indicator/cognitive_depth.php deleted file mode 100644 index 5d0e60af2fe..00000000000 --- a/mod/survey/classes/analytics/indicator/cognitive_depth.php +++ /dev/null @@ -1,56 +0,0 @@ -. - -/** - * Cognitive depth indicator - survey. - * - * @package mod_survey - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\analytics\indicator; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Cognitive depth indicator - survey. - * - * @package mod_survey - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class cognitive_depth extends activity_base { - - /** - * Returns the name. - * - * If there is a corresponding '_help' string this will be shown as well. - * - * @return \lang_string - */ - public static function get_name(): \lang_string { - return new \lang_string('indicator:cognitivedepth', 'mod_survey'); - } - - public function get_indicator_type() { - return self::INDICATOR_COGNITIVE; - } - - public function get_cognitive_depth_level(\cm_info $cm) { - return self::COGNITIVE_LEVEL_2; - } -} diff --git a/mod/survey/classes/analytics/indicator/social_breadth.php b/mod/survey/classes/analytics/indicator/social_breadth.php deleted file mode 100644 index 1f4e78734e6..00000000000 --- a/mod/survey/classes/analytics/indicator/social_breadth.php +++ /dev/null @@ -1,56 +0,0 @@ -. - -/** - * Social breadth indicator - survey. - * - * @package mod_survey - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\analytics\indicator; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Social breadth indicator - survey. - * - * @package mod_survey - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class social_breadth extends activity_base { - - /** - * Returns the name. - * - * If there is a corresponding '_help' string this will be shown as well. - * - * @return \lang_string - */ - public static function get_name(): \lang_string { - return new \lang_string('indicator:socialbreadth', 'mod_survey'); - } - - public function get_indicator_type() { - return self::INDICATOR_SOCIAL; - } - - public function get_social_breadth_level(\cm_info $cm) { - return self::SOCIAL_LEVEL_1; - } -} diff --git a/mod/survey/classes/completion/custom_completion.php b/mod/survey/classes/completion/custom_completion.php deleted file mode 100644 index 8b53b19aed3..00000000000 --- a/mod/survey/classes/completion/custom_completion.php +++ /dev/null @@ -1,82 +0,0 @@ -. - -declare(strict_types=1); - -namespace mod_survey\completion; - -use core_completion\activity_custom_completion; - -/** - * Activity custom completion subclass for the survey activity. - * - * Class for defining mod_survey's custom completion rules and fetching the completion statuses - * of the custom completion rules for a given survey instance and a user. - * - * @package mod_survey - * @copyright Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class custom_completion extends activity_custom_completion { - - /** - * Fetches the completion state for a given completion rule. - * - * @param string $rule The completion rule. - * @return int The completion state. - */ - public function get_state(string $rule): int { - global $DB; - - $this->validate_rule($rule); - - // Survey only supports completionsubmit as a custom rule. - $status = $DB->record_exists('survey_answers', ['survey' => $this->cm->instance, 'userid' => $this->userid]); - return $status ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE; - } - - /** - * Fetch the list of custom completion rules that this module defines. - * - * @return array - */ - public static function get_defined_custom_rules(): array { - return ['completionsubmit']; - } - - /** - * Returns an associative array of the descriptions of custom completion rules. - * - * @return array - */ - public function get_custom_rule_descriptions(): array { - return [ - 'completionsubmit' => get_string('completiondetail:submit', 'survey') - ]; - } - - /** - * Returns an array of all completion rules, in the order they should be displayed to users. - * - * @return array - */ - public function get_sort_order(): array { - return [ - 'completionview', - 'completionsubmit', - ]; - } -} diff --git a/mod/survey/classes/event/course_module_instance_list_viewed.php b/mod/survey/classes/event/course_module_instance_list_viewed.php deleted file mode 100644 index e3a3fe88fd1..00000000000 --- a/mod/survey/classes/event/course_module_instance_list_viewed.php +++ /dev/null @@ -1,39 +0,0 @@ -. - -/** - * The mod_survey instance list viewed event. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_survey instance list viewed event class. - * - * @package mod_survey - * @since Moodle 2.7 - * @copyright 2014 Rajesh Taneja - * @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/mod/survey/classes/event/course_module_viewed.php b/mod/survey/classes/event/course_module_viewed.php deleted file mode 100644 index e51c902d31b..00000000000 --- a/mod/survey/classes/event/course_module_viewed.php +++ /dev/null @@ -1,75 +0,0 @@ -. - -/** - * The mod_survey course module viewed event. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_survery course module viewed event. - * - * @property-read array $other { - * Extra information about the event. - * - * - string viewed: what was viewed - * } - * - * @package mod_survey - * @since Moodle 2.7 - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class course_module_viewed extends \core\event\course_module_viewed { - - /** - * Set basic properties for the event. - */ - protected function init() { - $this->data['objecttable'] = 'survey'; - $this->data['crud'] = 'r'; - $this->data['edulevel'] = self::LEVEL_PARTICIPATING; - } - - /** - * Custom validation. - * - * @throws \coding_exception - * @return void - */ - protected function validate_data() { - parent::validate_data(); - if (empty($this->other['viewed'])) { - throw new \coding_exception('Other must contain the key viewed.'); - } - } - - public static function get_objectid_mapping() { - return array('db' => 'survey', 'restore' => 'survey'); - } - - public static function get_other_mapping() { - // No need to map 'viewed'. - return false; - } -} diff --git a/mod/survey/classes/event/report_downloaded.php b/mod/survey/classes/event/report_downloaded.php deleted file mode 100644 index 80af6347e2a..00000000000 --- a/mod/survey/classes/event/report_downloaded.php +++ /dev/null @@ -1,109 +0,0 @@ -. - -/** - * The mod_survey report downloaded event. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_survey report downloaded event class. - * - * @property-read array $other { - * Extra information about the event. - * - * - string type: Type of report format downloaded. - * - int groupid: (optional) report for groupid. - * } - * - * @package mod_survey - * @since Moodle 2.7 - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class report_downloaded extends \core\event\base { - - /** - * Set basic properties for the event. - */ - protected function init() { - $this->data['objecttable'] = 'survey'; - $this->data['crud'] = 'r'; - $this->data['edulevel'] = self::LEVEL_TEACHING; - } - - /** - * Return localised event name. - * - * @return string - */ - public static function get_name() { - return get_string('eventreportdownloaded', 'mod_survey'); - } - - /** - * Returns description of what happened. - * - * @return string - */ - public function get_description() { - return "The user with id '$this->userid' downloaded the report for the survey with course module id '$this->contextinstanceid'."; - } - - /** - * Get URL related to the action. - * - * @return \moodle_url - */ - public function get_url() { - $params = array('id' => $this->contextinstanceid, 'type' => $this->other['type']); - if (isset($this->other['groupid'])) { - $params['group'] = $this->other['groupid']; - } - return new \moodle_url("/mod/survey/download.php", $params); - } - - /** - * Custom validation. - * - * @throws \coding_exception - * @return void - */ - protected function validate_data() { - parent::validate_data(); - if (empty($this->other['type'])) { - throw new \coding_exception('The \'type\' value must be set in other.'); - } - } - - public static function get_objectid_mapping() { - return array('db' => 'survey', 'restore' => 'survey'); - } - - public static function get_other_mapping() { - $othermapped = array(); - $othermapped['groupid'] = array('db' => 'groups', 'restore' => 'group'); - - return $othermapped; - } -} diff --git a/mod/survey/classes/event/report_viewed.php b/mod/survey/classes/event/report_viewed.php deleted file mode 100644 index 605836e5ae3..00000000000 --- a/mod/survey/classes/event/report_viewed.php +++ /dev/null @@ -1,97 +0,0 @@ -. - -/** - * The mod_survey report viewed event. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_survey report viewed event class. - * - * @property-read array $other { - * Extra information about the event. - * - * - string action: (optional) report view. - * - int groupid: (optional) report for groupid. - * } - * - * @package mod_survey - * @since Moodle 2.7 - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class report_viewed extends \core\event\base { - - /** - * Set basic properties for the event. - */ - protected function init() { - $this->data['objecttable'] = 'survey'; - $this->data['crud'] = 'r'; - $this->data['edulevel'] = self::LEVEL_TEACHING; - } - - /** - * Return localised event name. - * - * @return string - */ - public static function get_name() { - return get_string('eventreportviewed', 'mod_survey'); - } - - /** - * Returns description of what happened. - * - * @return string - */ - public function get_description() { - return "The user with id '$this->userid' viewed the report for the survey with course module id '$this->contextinstanceid'."; - } - - /** - * Get URL related to the action. - * - * @return \moodle_url - */ - public function get_url() { - $params = array(); - $params['id'] = $this->contextinstanceid; - if (isset($this->other['action'])) { - $params['action'] = $this->other['action']; - } - return new \moodle_url("/mod/survey/report.php", $params); - } - - public static function get_objectid_mapping() { - return array('db' => 'survey', 'restore' => 'survey'); - } - - public static function get_other_mapping() { - $othermapped = array(); - $othermapped['groupid'] = array('db' => 'groups', 'restore' => 'group'); - - return $othermapped; - } -} diff --git a/mod/survey/classes/event/response_submitted.php b/mod/survey/classes/event/response_submitted.php deleted file mode 100644 index d2638ff68f0..00000000000 --- a/mod/survey/classes/event/response_submitted.php +++ /dev/null @@ -1,99 +0,0 @@ -. - -/** - * The mod_survey response submitted event. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_survey response submitted event class. - * - * @property-read array $other { - * Extra information about the event. - * - * - int surveyid: ID of survey for which response was submitted. - * } - * - * @package mod_survey - * @since Moodle 2.7 - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class response_submitted extends \core\event\base { - - /** - * Set basic properties for the event. - */ - protected function init() { - $this->data['crud'] = 'c'; - $this->data['edulevel'] = self::LEVEL_PARTICIPATING; - } - - /** - * Return localised event name. - * - * @return string - */ - public static function get_name() { - return get_string('eventresponsesubmitted', 'mod_survey'); - } - - /** - * Returns description of what happened. - * - * @return string - */ - public function get_description() { - return "The user with id '$this->userid' submitted a response for the survey with course module id '$this->contextinstanceid'."; - } - - /** - * Get URL related to the action. - * - * @return \moodle_url - */ - public function get_url() { - return new \moodle_url("/mod/survey/view.php", array('id' => $this->contextinstanceid)); - } - - /** - * Custom validation. - * - * @throws \coding_exception - * @return void - */ - protected function validate_data() { - parent::validate_data(); - if (empty($this->other['surveyid'])) { - throw new \coding_exception('The \'surveyid\' value must be set in other.'); - } - } - - public static function get_other_mapping() { - $othermapped = array(); - $othermapped['surveyid'] = array('db' => 'survey', 'restore' => 'survey'); - - return $othermapped; - } -} diff --git a/mod/survey/classes/external.php b/mod/survey/classes/external.php deleted file mode 100644 index 26ddc717a51..00000000000 --- a/mod/survey/classes/external.php +++ /dev/null @@ -1,394 +0,0 @@ -. - -/** - * Survey external API - * - * @package mod_survey - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ - -use core_course\external\helper_for_get_mods_by_courses; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_multiple_structure; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; -use core_external\util; - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->dirroot . '/mod/survey/lib.php'); - -/** - * Survey external functions - * - * @package mod_survey - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ -class mod_survey_external extends external_api { - - /** - * Describes the parameters for get_surveys_by_courses. - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function get_surveys_by_courses_parameters() { - return new external_function_parameters ( - array( - 'courseids' => new external_multiple_structure( - new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array() - ), - ) - ); - } - - /** - * Returns a list of surveys in a provided list of courses, - * if no list is provided all surveys that the user can view will be returned. - * - * @param array $courseids the course ids - * @return array of surveys details - * @since Moodle 3.0 - */ - public static function get_surveys_by_courses($courseids = array()) { - global $CFG, $USER, $DB; - - $returnedsurveys = array(); - $warnings = array(); - - $params = self::validate_parameters(self::get_surveys_by_courses_parameters(), array('courseids' => $courseids)); - - $mycourses = array(); - if (empty($params['courseids'])) { - $mycourses = enrol_get_my_courses(); - $params['courseids'] = array_keys($mycourses); - } - - // Ensure there are courseids to loop through. - if (!empty($params['courseids'])) { - list($courses, $warnings) = util::validate_courses($params['courseids'], $mycourses); - - // Get the surveys in this course, this function checks users visibility permissions. - // We can avoid then additional validate_context calls. - $surveys = get_all_instances_in_courses("survey", $courses); - foreach ($surveys as $survey) { - $context = context_module::instance($survey->coursemodule); - if (empty(trim($survey->intro))) { - $tempo = $DB->get_field("survey", "intro", array("id" => $survey->template)); - $survey->intro = get_string($tempo, "survey"); - } - - // Entry to return. - $surveydetails = helper_for_get_mods_by_courses::standard_coursemodule_element_values( - $survey, 'mod_survey', 'moodle/course:manageactivities', 'mod/survey:participate'); - - if (has_capability('mod/survey:participate', $context)) { - $surveydetails['template'] = $survey->template; - $surveydetails['days'] = $survey->days; - $surveydetails['questions'] = $survey->questions; - $surveydetails['surveydone'] = survey_already_done($survey->id, $USER->id) ? 1 : 0; - } - - if (has_capability('moodle/course:manageactivities', $context)) { - $surveydetails['timecreated'] = $survey->timecreated; - $surveydetails['timemodified'] = $survey->timemodified; - } - $returnedsurveys[] = $surveydetails; - } - } - $result = array(); - $result['surveys'] = $returnedsurveys; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Describes the get_surveys_by_courses return value. - * - * @return external_single_structure - * @since Moodle 3.0 - */ - public static function get_surveys_by_courses_returns() { - return new external_single_structure( - array( - 'surveys' => new external_multiple_structure( - new external_single_structure(array_merge( - helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(true), - [ - 'template' => new external_value(PARAM_INT, 'Survey type', VALUE_OPTIONAL), - 'days' => new external_value(PARAM_INT, 'Days', VALUE_OPTIONAL), - 'questions' => new external_value(PARAM_RAW, 'Question ids', VALUE_OPTIONAL), - 'surveydone' => new external_value(PARAM_INT, 'Did I finish the survey?', VALUE_OPTIONAL), - 'timecreated' => new external_value(PARAM_INT, 'Time of creation', VALUE_OPTIONAL), - 'timemodified' => new external_value(PARAM_INT, 'Time of last modification', VALUE_OPTIONAL), - ] - ), 'Surveys') - ), - 'warnings' => new external_warnings(), - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function view_survey_parameters() { - return new external_function_parameters( - array( - 'surveyid' => new external_value(PARAM_INT, 'survey instance id') - ) - ); - } - - /** - * Trigger the course module viewed event and update the module completion status. - * - * @param int $surveyid the survey instance id - * @return array of warnings and status result - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function view_survey($surveyid) { - global $DB, $USER; - - $params = self::validate_parameters(self::view_survey_parameters(), - array( - 'surveyid' => $surveyid - )); - $warnings = array(); - - // Request and permission validation. - $survey = $DB->get_record('survey', array('id' => $params['surveyid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($survey, 'survey'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - require_capability('mod/survey:participate', $context); - - $viewed = survey_already_done($survey->id, $USER->id) ? 'graph' : 'form'; - - // Trigger course_module_viewed event and completion. - survey_view($survey, $course, $cm, $context, $viewed); - - $result = array(); - $result['status'] = true; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function view_survey_returns() { - return new external_single_structure( - array( - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function get_questions_parameters() { - return new external_function_parameters( - array( - 'surveyid' => new external_value(PARAM_INT, 'survey instance id') - ) - ); - } - - /** - * Get the complete list of questions for the survey, including subquestions. - * - * @param int $surveyid the survey instance id - * @return array of warnings and the question list - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function get_questions($surveyid) { - global $DB, $USER; - - $params = self::validate_parameters(self::get_questions_parameters(), - array( - 'surveyid' => $surveyid - )); - $warnings = array(); - - // Request and permission validation. - $survey = $DB->get_record('survey', array('id' => $params['surveyid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($survey, 'survey'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - require_capability('mod/survey:participate', $context); - - $mainquestions = survey_get_questions($survey); - - foreach ($mainquestions as $question) { - if ($question->type >= 0) { - // Parent is used in subquestions. - $question->parent = 0; - $questions[] = survey_translate_question($question); - - // Check if the question has subquestions. - if ($question->multi) { - $subquestions = survey_get_subquestions($question); - foreach ($subquestions as $sq) { - $sq->parent = $question->id; - $questions[] = survey_translate_question($sq); - } - } - } - } - - $result = array(); - $result['questions'] = $questions; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function get_questions_returns() { - return new external_single_structure( - array( - 'questions' => new external_multiple_structure( - new external_single_structure( - array( - 'id' => new external_value(PARAM_INT, 'Question id'), - 'text' => new external_value(PARAM_RAW, 'Question text'), - 'shorttext' => new external_value(PARAM_RAW, 'Question short text'), - 'multi' => new external_value(PARAM_RAW, 'Subquestions ids'), - 'intro' => new external_value(PARAM_RAW, 'The question intro'), - 'type' => new external_value(PARAM_INT, 'Question type'), - 'options' => new external_value(PARAM_RAW, 'Question options'), - 'parent' => new external_value(PARAM_INT, 'Parent question (for subquestions)'), - ), 'Questions' - ) - ), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Describes the parameters for submit_answers. - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function submit_answers_parameters() { - return new external_function_parameters( - array( - 'surveyid' => new external_value(PARAM_INT, 'Survey id'), - 'answers' => new external_multiple_structure( - new external_single_structure( - array( - 'key' => new external_value(PARAM_RAW, 'Answer key'), - 'value' => new external_value(PARAM_RAW, 'Answer value') - ) - ) - ), - ) - ); - } - - /** - * Submit the answers for a given survey. - * - * @param int $surveyid the survey instance id - * @param array $answers the survey answers - * @return array of warnings and status result - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function submit_answers($surveyid, $answers) { - global $DB, $USER; - - $params = self::validate_parameters(self::submit_answers_parameters(), - array( - 'surveyid' => $surveyid, - 'answers' => $answers - )); - $warnings = array(); - - // Request and permission validation. - $survey = $DB->get_record('survey', array('id' => $params['surveyid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($survey, 'survey'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - require_capability('mod/survey:participate', $context); - - if (survey_already_done($survey->id, $USER->id)) { - throw new moodle_exception("alreadysubmitted", "survey"); - } - - // Build the answers array. Data is cleaned inside the survey_save_answers function. - $answers = array(); - foreach ($params['answers'] as $answer) { - $key = $answer['key']; - $answers[$key] = $answer['value']; - } - - survey_save_answers($survey, $answers, $course, $context); - - $result = array(); - $result['status'] = true; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function submit_answers_returns() { - return new external_single_structure( - array( - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings() - ) - ); - } - -} diff --git a/mod/survey/classes/output/actionbar.php b/mod/survey/classes/output/actionbar.php deleted file mode 100644 index ea50d43879a..00000000000 --- a/mod/survey/classes/output/actionbar.php +++ /dev/null @@ -1,128 +0,0 @@ -. - -namespace mod_survey\output; - -use moodle_url; -use renderable; -use renderer_base; -use templatable; -use url_select; - -/** - * Output the rendered elements for the tertiary nav page action - * - * @package mod_survey - * @copyright 2021 Sujith Haridasan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class actionbar implements renderable, templatable { - /** - * The course id. - * - * @var int $id - */ - private $id; - - /** - * The action decides the url to navigate to. - * - * @var string $action - */ - private $action; - - /** - * Current url. - * - * @var moodle_url $currenturl - */ - private $currenturl; - - /** - * actionbar constructor. - * - * @param int $id The course module id. - * @param string $action The action string. - * @param moodle_url $currenturl The current URL. - */ - public function __construct(int $id, string $action, moodle_url $currenturl) { - $this->id = $id; - $this->action = $action; - $this->currenturl = $currenturl; - } - - /** - * Create select menu for the reports - * - * @return url_select url_select object. - */ - private function create_select_menu(): url_select { - $menu = []; - $actions = $this->get_available_reports(); - - foreach ($actions as $action => $straction) { - $url = new moodle_url($this->currenturl, ['id' => $this->id, 'action' => $action]); - $menu[$url->out(false)] = $straction; - } - return new url_select($menu, $this->currenturl->out(false), null, 'surveyresponseselect'); - } - - /** - * Generate available reports list - * - * @return array The list of available action => action string. - */ - private function get_available_reports(): array { - global $DB; - - $cm = get_coursemodule_from_id('survey', $this->id); - $survey = $DB->get_record("survey", ["id" => $cm->instance]); - - $actions = []; - if ($survey && ($survey->template != SURVEY_CIQ)) { - $actions['summary'] = get_string('summary', 'survey'); - $actions['scales'] = get_string('scales', 'survey'); - } - $actions['questions'] = get_string('questions', 'survey'); - $actions['students'] = get_string('participants'); - - return $actions; - } - - /** - * Data for the template. - * - * @param renderer_base $output renderer_base object. - * @return array data for the template - */ - public function export_for_template(renderer_base $output): array { - global $PAGE; - - $selecturl = $this->create_select_menu(); - $data = [ - 'urlselect' => $selecturl->export_for_template($output) - ]; - - if (has_capability('mod/survey:download', $PAGE->cm->context)) { - $downloadlink = (new moodle_url('/mod/survey/report.php', ['id' => $this->id, 'action' => 'download']))->out(false); - $data['download'] = [ - 'link' => $downloadlink, - 'text' => get_string('downloadresults', 'mod_survey'), - ]; - } - return $data; - } -} diff --git a/mod/survey/classes/privacy/provider.php b/mod/survey/classes/privacy/provider.php deleted file mode 100644 index 0e1ea6fee96..00000000000 --- a/mod/survey/classes/privacy/provider.php +++ /dev/null @@ -1,414 +0,0 @@ -. - -/** - * Data provider. - * - * @package mod_survey - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\privacy; -defined('MOODLE_INTERNAL') || die(); - -use context; -use context_helper; -use context_module; -use core_privacy\local\metadata\collection; -use core_privacy\local\request\approved_contextlist; -use core_privacy\local\request\approved_userlist; -use core_privacy\local\request\helper; -use core_privacy\local\request\transform; -use core_privacy\local\request\userlist; -use core_privacy\local\request\writer; - -require_once($CFG->dirroot . '/mod/survey/lib.php'); - -/** - * Data provider class. - * - * @package mod_survey - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class provider implements - \core_privacy\local\metadata\provider, - \core_privacy\local\request\core_userlist_provider, - \core_privacy\local\request\plugin\provider { - - /** - * Returns metadata. - * - * @param collection $collection The initialised collection to add items to. - * @return collection A listing of user data stored through this system. - */ - public static function get_metadata(collection $collection): collection { - $collection->add_database_table('survey_answers', [ - 'userid' => 'privacy:metadata:answers:userid', - 'question' => 'privacy:metadata:answers:question', - 'answer1' => 'privacy:metadata:answers:answer1', - 'answer2' => 'privacy:metadata:answers:answer2', - 'time' => 'privacy:metadata:answers:time', - ], 'privacy:metadata:answers'); - - $collection->add_database_table('survey_analysis', [ - 'userid' => 'privacy:metadata:analysis:userid', - 'notes' => 'privacy:metadata:analysis:notes', - ], 'privacy:metadata:analysis'); - - return $collection; - } - - /** - * Get the list of contexts that contain user information for the specified user. - * - * @param int $userid The user to search. - * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. - */ - public static function get_contexts_for_userid(int $userid): \core_privacy\local\request\contextlist { - $contextlist = new \core_privacy\local\request\contextlist(); - - // While we should not have an analysis without answers, it's safer to gather contexts by looking at both tables. - $sql = " - SELECT DISTINCT ctx.id - FROM {survey} s - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - JOIN {context} ctx - ON ctx.instanceid = cm.id - AND ctx.contextlevel = :modulelevel - LEFT JOIN {survey_answers} sa - ON sa.survey = s.id - AND sa.userid = :userid1 - LEFT JOIN {survey_analysis} sy - ON sy.survey = s.id - AND sy.userid = :userid2 - WHERE s.template <> 0 - AND (sa.id IS NOT NULL - OR sy.id IS NOT NULL)"; - - $contextlist->add_from_sql($sql, [ - 'survey' => 'survey', - 'modulelevel' => CONTEXT_MODULE, - 'userid1' => $userid, - 'userid2' => $userid, - ]); - - return $contextlist; - } - - /** - * Get the list of users who have data within a context. - * - * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. - */ - public static function get_users_in_context(userlist $userlist) { - $context = $userlist->get_context(); - - if (!is_a($context, \context_module::class)) { - return; - } - - $params = [ - 'survey' => 'survey', - 'modulelevel' => CONTEXT_MODULE, - 'contextid' => $context->id, - ]; - - $sql = " - SELECT sa.userid - FROM {survey} s - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - JOIN {context} ctx - ON ctx.instanceid = cm.id - AND ctx.contextlevel = :modulelevel - JOIN {survey_answers} sa - ON sa.survey = s.id - WHERE ctx.id = :contextid - AND s.template <> 0"; - - $userlist->add_from_sql('userid', $sql, $params); - - $sql = " - SELECT sy.userid - FROM {survey} s - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - JOIN {context} ctx - ON ctx.instanceid = cm.id - AND ctx.contextlevel = :modulelevel - JOIN {survey_analysis} sy - ON sy.survey = s.id - WHERE ctx.id = :contextid - AND s.template <> 0"; - - $userlist->add_from_sql('userid', $sql, $params); - } - - /** - * Export all user data for the specified user, in the specified contexts. - * - * @param approved_contextlist $contextlist The approved contexts to export information for. - */ - public static function export_user_data(approved_contextlist $contextlist) { - global $DB; - - $user = $contextlist->get_user(); - $userid = $user->id; - $cmids = array_reduce($contextlist->get_contexts(), function($carry, $context) { - if ($context->contextlevel == CONTEXT_MODULE) { - $carry[] = $context->instanceid; - } - return $carry; - }, []); - - if (empty($cmids)) { - return; - } - - // Export the answers. - list($insql, $inparams) = $DB->get_in_or_equal($cmids, SQL_PARAMS_NAMED); - $sql = " - SELECT sa.*, - sq.id as qid, - sq.text as qtext, - sq.shorttext as qshorttext, - sq.intro as qintro, - sq.options as qoptions, - sq.type as qtype, - cm.id as cmid - FROM {survey_answers} sa - JOIN {survey_questions} sq - ON sq.id = sa.question - JOIN {survey} s - ON s.id = sa.survey - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - WHERE cm.id $insql - AND sa.userid = :userid - ORDER BY s.id, sq.id"; - $params = array_merge($inparams, ['survey' => 'survey', 'userid' => $userid]); - - $recordset = $DB->get_recordset_sql($sql, $params); - static::recordset_loop_and_export($recordset, 'cmid', [], function($carry, $record) { - $q = survey_translate_question((object) [ - 'text' => $record->qtext, - 'shorttext' => $record->qshorttext, - 'intro' => $record->qintro, - 'options' => $record->qoptions - ]); - $qtype = $record->qtype; - $options = explode(',', $q->options ?? ''); - - $carry[] = [ - 'question' => array_merge((array) $q, [ - 'options' => $qtype > 0 ? $options : '-' - ]), - 'answer' => [ - 'actual' => $qtype > 0 && !empty($record->answer1) ? $options[$record->answer1 - 1] : $record->answer1, - 'preferred' => $qtype > 0 && !empty($record->answer2) ? $options[$record->answer2 - 1] : $record->answer2, - ], - 'time' => transform::datetime($record->time), - ]; - return $carry; - - }, function($cmid, $data) use ($user) { - $context = context_module::instance($cmid); - $contextdata = helper::get_context_data($context, $user); - $contextdata = (object) array_merge((array) $contextdata, ['answers' => $data]); - helper::export_context_files($context, $user); - writer::with_context($context)->export_data([], $contextdata); - }); - - // Export the analysis. - $sql = " - SELECT sy.*, cm.id as cmid - FROM {survey_analysis} sy - JOIN {survey} s - ON s.id = sy.survey - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - WHERE cm.id $insql - AND sy.userid = :userid - ORDER BY s.id"; - $params = array_merge($inparams, ['survey' => 'survey', 'userid' => $userid]); - - $recordset = $DB->get_recordset_sql($sql, $params); - static::recordset_loop_and_export($recordset, 'cmid', null, function($carry, $record) { - $carry = ['notes' => $record->notes]; - return $carry; - }, function($cmid, $data) { - $context = context_module::instance($cmid); - writer::with_context($context)->export_related_data([], 'survey_analysis', (object) $data); - }); - } - - /** - * Delete all data for all users in the specified context. - * - * @param context $context The specific context to delete data for. - */ - public static function delete_data_for_all_users_in_context(context $context) { - global $DB; - - if ($context->contextlevel != CONTEXT_MODULE) { - return; - } - - if ($surveyid = static::get_survey_id_from_context($context)) { - $DB->delete_records('survey_answers', ['survey' => $surveyid]); - $DB->delete_records('survey_analysis', ['survey' => $surveyid]); - } - } - - /** - * Delete all user data for the specified user, in the specified contexts. - * - * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. - */ - public static function delete_data_for_user(approved_contextlist $contextlist) { - global $DB; - - $userid = $contextlist->get_user()->id; - $cmids = array_reduce($contextlist->get_contexts(), function($carry, $context) { - if ($context->contextlevel == CONTEXT_MODULE) { - $carry[] = $context->instanceid; - } - return $carry; - }, []); - if (empty($cmids)) { - return; - } - - // Fetch the survey IDs. - list($insql, $inparams) = $DB->get_in_or_equal($cmids, SQL_PARAMS_NAMED); - $sql = " - SELECT s.id - FROM {survey} s - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - WHERE cm.id $insql"; - $params = array_merge($inparams, ['survey' => 'survey']); - $surveyids = $DB->get_fieldset_sql($sql, $params); - - // Delete all the things. - list($insql, $inparams) = $DB->get_in_or_equal($surveyids, SQL_PARAMS_NAMED); - $params = array_merge($inparams, ['userid' => $userid]); - $DB->delete_records_select('survey_answers', "survey $insql AND userid = :userid", $params); - $DB->delete_records_select('survey_analysis', "survey $insql AND userid = :userid", $params); - } - - /** - * Delete multiple users within a single context. - * - * @param approved_userlist $userlist The approved context and user information to delete information for. - */ - public static function delete_data_for_users(approved_userlist $userlist) { - global $DB; - $context = $userlist->get_context(); - - if ($context->contextlevel != CONTEXT_MODULE) { - return; - } - - // Fetch the survey ID. - $sql = " - SELECT s.id - FROM {survey} s - JOIN {modules} m - ON m.name = :survey - JOIN {course_modules} cm - ON cm.instance = s.id - AND cm.module = m.id - WHERE cm.id = :cmid"; - $params = [ - 'survey' => 'survey', - 'cmid' => $context->instanceid, - ]; - $surveyid = $DB->get_field_sql($sql, $params); - $userids = $userlist->get_userids(); - - // Delete all the things. - list($insql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); - $params['surveyid'] = $surveyid; - - $DB->delete_records_select('survey_answers', "survey = :surveyid AND userid {$insql}", $params); - $DB->delete_records_select('survey_analysis', "survey = :surveyid AND userid {$insql}", $params); - } - - /** - * Get a survey ID from its context. - * - * @param context_module $context The module context. - * @return int - */ - protected static function get_survey_id_from_context(context_module $context) { - $cm = get_coursemodule_from_id('survey', $context->instanceid); - return $cm ? (int) $cm->instance : 0; - } - /** - * Loop and export from a recordset. - * - * @param moodle_recordset $recordset The recordset. - * @param string $splitkey The record key to determine when to export. - * @param mixed $initial The initial data to reduce from. - * @param callable $reducer The function to return the dataset, receives current dataset, and the current record. - * @param callable $export The function to export the dataset, receives the last value from $splitkey and the dataset. - * @return void - */ - protected static function recordset_loop_and_export(\moodle_recordset $recordset, $splitkey, $initial, - callable $reducer, callable $export) { - - $data = $initial; - $lastid = null; - - foreach ($recordset as $record) { - if ($lastid && $record->{$splitkey} != $lastid) { - $export($lastid, $data); - $data = $initial; - } - $data = $reducer($data, $record); - $lastid = $record->{$splitkey}; - } - $recordset->close(); - - if (!empty($lastid)) { - $export($lastid, $data); - } - } -} diff --git a/mod/survey/classes/search/activity.php b/mod/survey/classes/search/activity.php deleted file mode 100644 index d809dbf322d..00000000000 --- a/mod/survey/classes/search/activity.php +++ /dev/null @@ -1,70 +0,0 @@ -. - -/** - * Search area for mod_survey activities. - * - * @package mod_survey - * @copyright 2015 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\search; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Search area for mod_survey activities. - * - * @package mod_survey - * @copyright 2015 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class activity extends \core_search\base_activity { - - /** - * Returns true if this area uses file indexing. - * - * @return bool - */ - public function uses_file_indexing() { - return true; - } - - /** - * Returns recordset containing required data for indexing activities. - * - * Overridden to discard records with courseid = 0. - * - * @param int $modifiedfrom timestamp - * @param \context|null $context Context - * @return \moodle_recordset|null Recordset, or null if no possible activities in given context - */ - public function get_document_recordset($modifiedfrom = 0, ?\context $context = null) { - global $DB; - list ($contextjoin, $contextparams) = $this->get_context_restriction_sql( - $context, $this->get_module_name(), 'modtable'); - if ($contextjoin === null) { - return null; - } - return $DB->get_recordset_sql('SELECT modtable.* FROM {' . $this->get_module_name() . - '} modtable ' . $contextjoin . ' WHERE modtable.' . static::MODIFIED_FIELD_NAME . - ' >= ? AND modtable.course != ? ORDER BY modtable.' . static::MODIFIED_FIELD_NAME . - ' ASC', - array_merge($contextparams, [$modifiedfrom, 0])); - } - -} diff --git a/mod/survey/db/access.php b/mod/survey/db/access.php deleted file mode 100644 index 57e04da9562..00000000000 --- a/mod/survey/db/access.php +++ /dev/null @@ -1,77 +0,0 @@ -. - -/** - * Plugin capabilities - * - * @package mod_survey - * @copyright 2006 Martin Dougiamas - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$capabilities = array( - - 'mod/survey:addinstance' => array( - 'riskbitmask' => RISK_XSS, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => array( - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ), - 'clonepermissionsfrom' => 'moodle/course:manageactivities' - ), - - 'mod/survey:participate' => array( - - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'student' => CAP_ALLOW, - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), - - 'mod/survey:readresponses' => array( - - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), - - 'mod/survey:download' => array( - - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ) - -); - - diff --git a/mod/survey/db/install.php b/mod/survey/db/install.php deleted file mode 100644 index fd9507eec18..00000000000 --- a/mod/survey/db/install.php +++ /dev/null @@ -1,125 +0,0 @@ -. - -/** - * Survey module installation. - * - * @package mod_survey - * @copyright 2009 Petr Skoda (http://skodak.org) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Perform the post-install procedures. - */ -function xmldb_survey_install() { - global $DB; - - // Disable the survey activity module on new installs by default. - $DB->set_field('modules', 'visible', 0, ['name' => 'survey']); - - // Insert survey data. - $records = array( - array_combine(array('course', 'template', 'days', 'timecreated', 'timemodified', 'name', 'intro', 'questions'), array(0, 0, 0, 985017600, 985017600, 'collesaname', 'collesaintro', '25,26,27,28,29,30,43,44')), - array_combine(array('course', 'template', 'days', 'timecreated', 'timemodified', 'name', 'intro', 'questions'), array(0, 0, 0, 985017600, 985017600, 'collespname', 'collespintro', '31,32,33,34,35,36,43,44')), - array_combine(array('course', 'template', 'days', 'timecreated', 'timemodified', 'name', 'intro', 'questions'), array(0, 0, 0, 985017600, 985017600, 'collesapname', 'collesapintro', '37,38,39,40,41,42,43,44')), - array_combine(array('course', 'template', 'days', 'timecreated', 'timemodified', 'name', 'intro', 'questions'), array(0, 0, 0, 985017600, 985017600, 'attlsname', 'attlsintro', '65,67,68')), - array_combine(array('course', 'template', 'days', 'timecreated', 'timemodified', 'name', 'intro', 'questions'), array(0, 0, 0, 985017600, 985017600, 'ciqname', 'ciqintro', '69,70,71,72,73')), - ); - foreach ($records as $record) { - $DB->insert_record('survey', $record, false); - } - - $records = array( - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles1', 'colles1short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles2', 'colles2short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles3', 'colles3short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles4', 'colles4short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles5', 'colles5short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles6', 'colles6short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles7', 'colles7short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles8', 'colles8short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles9', 'colles9short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles10', 'colles10short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles11', 'colles11short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles12', 'colles12short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles13', 'colles13short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles14', 'colles14short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles15', 'colles15short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles16', 'colles16short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles17', 'colles17short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles18', 'colles18short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles19', 'colles19short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles20', 'colles20short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles21', 'colles21short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles22', 'colles22short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles23', 'colles23short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('colles24', 'colles24short', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm1', 'collesm1short', '1,2,3,4', 'collesmintro', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm2', 'collesm2short', '5,6,7,8', 'collesmintro', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm3', 'collesm3short', '9,10,11,12', 'collesmintro', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm4', 'collesm4short', '13,14,15,16', 'collesmintro', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm5', 'collesm5short', '17,18,19,20', 'collesmintro', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm6', 'collesm6short', '21,22,23,24', 'collesmintro', 1, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm1', 'collesm1short', '1,2,3,4', 'collesmintro', 2, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm2', 'collesm2short', '5,6,7,8', 'collesmintro', 2, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm3', 'collesm3short', '9,10,11,12', 'collesmintro', 2, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm4', 'collesm4short', '13,14,15,16', 'collesmintro', 2, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm5', 'collesm5short', '17,18,19,20', 'collesmintro', 2, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm6', 'collesm6short', '21,22,23,24', 'collesmintro', 2, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm1', 'collesm1short', '1,2,3,4', 'collesmintro', 3, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm2', 'collesm2short', '5,6,7,8', 'collesmintro', 3, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm3', 'collesm3short', '9,10,11,12', 'collesmintro', 3, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm4', 'collesm4short', '13,14,15,16', 'collesmintro', 3, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm5', 'collesm5short', '17,18,19,20', 'collesmintro', 3, 'scaletimes5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('collesm6', 'collesm6short', '21,22,23,24', 'collesmintro', 3, 'scaletimes5')), - array_combine(array('text', 'type', 'options'), array('howlong', 1, 'howlongoptions')), - array_combine(array('text', 'type'), array('othercomments', 0)), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls1', 'attls1short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls2', 'attls2short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls3', 'attls3short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls4', 'attls4short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls5', 'attls5short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls6', 'attls6short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls7', 'attls7short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls8', 'attls8short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls9', 'attls9short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls10', 'attls10short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls11', 'attls11short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls12', 'attls12short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls13', 'attls13short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls14', 'attls14short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls15', 'attls15short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls16', 'attls16short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls17', 'attls17short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls18', 'attls18short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls19', 'attls19short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type', 'options'), array('attls20', 'attls20short', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('attlsm1', 'attlsm1', '45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64', 'attlsmintro', 1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('-', '-', '-', '-', 0, '-')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('attlsm2', 'attlsm2', '63,62,59,57,55,49,52,50,48,47', 'attlsmintro', -1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'multi', 'intro', 'type', 'options'), array('attlsm3', 'attlsm3', '46,54,45,51,60,53,56,58,61,64', 'attlsmintro', -1, 'scaleagree5')), - array_combine(array('text', 'shorttext', 'type'), array('ciq1', 'ciq1short', 0)), - array_combine(array('text', 'shorttext', 'type'), array('ciq2', 'ciq2short', 0)), - array_combine(array('text', 'shorttext', 'type'), array('ciq3', 'ciq3short', 0)), - array_combine(array('text', 'shorttext', 'type'), array('ciq4', 'ciq4short', 0)), - array_combine(array('text', 'shorttext', 'type'), array('ciq5', 'ciq5short', 0)), - ); - foreach ($records as $record) { - $DB->insert_record('survey_questions', $record, false); - } - -} diff --git a/mod/survey/db/install.xml b/mod/survey/db/install.xml deleted file mode 100644 index e8611c2af04..00000000000 --- a/mod/survey/db/install.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
-
-
diff --git a/mod/survey/db/log.php b/mod/survey/db/log.php deleted file mode 100644 index c0a791772ec..00000000000 --- a/mod/survey/db/log.php +++ /dev/null @@ -1,37 +0,0 @@ -. - -/** - * Definition of log events - * - * @package mod_survey - * @category log - * @copyright 2010 Petr Skoda (http://skodak.org) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$logs = array( - array('module'=>'survey', 'action'=>'add', 'mtable'=>'survey', 'field'=>'name'), - array('module'=>'survey', 'action'=>'update', 'mtable'=>'survey', 'field'=>'name'), - array('module'=>'survey', 'action'=>'download', 'mtable'=>'survey', 'field'=>'name'), - array('module'=>'survey', 'action'=>'view form', 'mtable'=>'survey', 'field'=>'name'), - array('module'=>'survey', 'action'=>'view graph', 'mtable'=>'survey', 'field'=>'name'), - array('module'=>'survey', 'action'=>'view report', 'mtable'=>'survey', 'field'=>'name'), - array('module'=>'survey', 'action'=>'submit', 'mtable'=>'survey', 'field'=>'name'), -); \ No newline at end of file diff --git a/mod/survey/db/services.php b/mod/survey/db/services.php deleted file mode 100644 index 7ea4d6e2dd9..00000000000 --- a/mod/survey/db/services.php +++ /dev/null @@ -1,68 +0,0 @@ -. - -/** - * Survey external functions and service definitions. - * - * @package mod_survey - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ - -defined('MOODLE_INTERNAL') || die; - -$functions = array( - - 'mod_survey_get_surveys_by_courses' => array( - 'classname' => 'mod_survey_external', - 'methodname' => 'get_surveys_by_courses', - 'description' => 'Returns a list of survey instances in a provided set of courses, - if no courses are provided then all the survey instances the user has access to will be returned.', - 'type' => 'read', - 'capabilities' => '', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_survey_view_survey' => array( - 'classname' => 'mod_survey_external', - 'methodname' => 'view_survey', - 'description' => 'Trigger the course module viewed event and update the module completion status.', - 'type' => 'write', - 'capabilities' => 'mod/survey:participate', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_survey_get_questions' => array( - 'classname' => 'mod_survey_external', - 'methodname' => 'get_questions', - 'description' => 'Get the complete list of questions for the survey, including subquestions.', - 'type' => 'read', - 'capabilities' => 'mod/survey:participate', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_survey_submit_answers' => array( - 'classname' => 'mod_survey_external', - 'methodname' => 'submit_answers', - 'description' => 'Submit the answers for a given survey.', - 'type' => 'write', - 'capabilities' => 'mod/survey:participate', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - -); diff --git a/mod/survey/db/upgrade.php b/mod/survey/db/upgrade.php deleted file mode 100644 index badff3858eb..00000000000 --- a/mod/survey/db/upgrade.php +++ /dev/null @@ -1,56 +0,0 @@ -. - -/** - * This file keeps track of upgrades to the survey module - * - * Sometimes, changes between versions involve - * alterations to database structures and other - * major things that may break installations. - * - * The upgrade function in this file will attempt - * to perform all the necessary actions to upgrade - * your older installation to the current version. - * - * If there's something it cannot do itself, it - * will tell you what you need to do. - * - * The commands in here will all be database-neutral, - * using the methods of database_manager class - * - * Please do not forget to use upgrade_set_timeout() - * before any action that may take longer time to finish. - * - * @package mod_survey - * @copyright 2006 Eloy Lafuente (stronk7) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -function xmldb_survey_upgrade($oldversion) { - // Automatically generated Moodle v4.2.0 release upgrade line. - // Put any upgrade step following this. - - // Automatically generated Moodle v4.3.0 release upgrade line. - // Put any upgrade step following this. - - // Automatically generated Moodle v4.4.0 release upgrade line. - // Put any upgrade step following this. - - // Automatically generated Moodle v4.5.0 release upgrade line. - // Put any upgrade step following this. - - return true; -} diff --git a/mod/survey/deprecatedlib.php b/mod/survey/deprecatedlib.php deleted file mode 100644 index 4f522ffe206..00000000000 --- a/mod/survey/deprecatedlib.php +++ /dev/null @@ -1,31 +0,0 @@ -. - -/** - * List of deprecated mod_survey functions. - * - * @package mod_survey - * @copyright 2021 Shamim Rezaie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * @deprecated since Moodle 3.11 - */ -function survey_get_completion_state() { - $completionclass = \mod_survey\completion\custom_completion::class; - throw new coding_exception(__FUNCTION__ . "() has been removed, please use the '{$completionclass}' class instead"); -} diff --git a/mod/survey/download.php b/mod/survey/download.php deleted file mode 100644 index bf7de9c786c..00000000000 --- a/mod/survey/download.php +++ /dev/null @@ -1,365 +0,0 @@ -. - -/** - * This file is responsible for producing the downloadable versions of a survey - * module. - * - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -require_once ("../../config.php"); - -// Check that all the parameters have been provided. - -$id = required_param('id', PARAM_INT); // Course Module ID -$type = optional_param('type', 'xls', PARAM_ALPHA); -$group = optional_param('group', 0, PARAM_INT); - -if (! $cm = get_coursemodule_from_id('survey', $id)) { - throw new \moodle_exception('invalidcoursemodule'); -} - -if (! $course = $DB->get_record("course", array("id"=>$cm->course))) { - throw new \moodle_exception('coursemisconf'); -} - -$context = context_module::instance($cm->id); - -$PAGE->set_url('/mod/survey/download.php', array('id'=>$id, 'type'=>$type, 'group'=>$group)); - -require_login($course, false, $cm); -require_capability('mod/survey:download', $context) ; - -if (! $survey = $DB->get_record("survey", array("id"=>$cm->instance))) { - throw new \moodle_exception('invalidsurveyid', 'survey'); -} - -$params = array( - 'objectid' => $survey->id, - 'context' => $context, - 'courseid' => $course->id, - 'other' => array('type' => $type, 'groupid' => $group) -); -$event = \mod_survey\event\report_downloaded::create($params); -$event->trigger(); - -/// Check to see if groups are being used in this survey - -$groupmode = groups_get_activity_groupmode($cm); // Groups are being used - -if ($groupmode and $group) { - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', $group, null, false); -} else { - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', '', null, false); - $group = false; -} - -// The order of the questions -$order = explode(",", $survey->questions); - -// Get the actual questions from the database -$questions = $DB->get_records_list("survey_questions", "id", $order); - -// Get an ordered array of questions -$orderedquestions = array(); - -$virtualscales = false; -foreach ($order as $qid) { - $orderedquestions[$qid] = $questions[$qid]; - // Check if this question is using virtual scales - if (!$virtualscales && $questions[$qid]->type < 0) { - $virtualscales = true; - } -} -$nestedorder = array();//will contain the subquestions attached to the main questions -$preparray = array(); - -foreach ($orderedquestions as $qid=>$question) { - //$orderedquestions[$qid]->text = get_string($question->text, "survey"); - if (!empty($question->multi)) { - $actualqids = explode(",", $questions[$qid]->multi); - foreach ($actualqids as $subqid) { - if (!empty($orderedquestions[$subqid]->type)) { - $orderedquestions[$subqid]->type = $questions[$qid]->type; - } - } - } else { - $actualqids = array($qid); - } - if ($virtualscales && $questions[$qid]->type < 0) { - $nestedorder[$qid] = $actualqids; - } else if (!$virtualscales && $question->type >= 0) { - $nestedorder[$qid] = $actualqids; - } else { - //todo andrew this was added by me. Is it correct? - $nestedorder[$qid] = array(); - } -} - -$reversednestedorder = array(); -foreach ($nestedorder as $qid=>$subqidarray) { - foreach ($subqidarray as $subqui) { - $reversednestedorder[$subqui] = $qid; - } -} - -//need to get info on the sub-questions from the db and merge the arrays of questions -$allquestions = array_merge($questions, $DB->get_records_list("survey_questions", "id", array_keys($reversednestedorder))); - -//array_merge() messes up the keys so reinstate them -$questions = array(); -foreach($allquestions as $question) { - $questions[$question->id] = $question; - - //while were iterating over the questions get the question text - $questions[$question->id]->text = get_string($questions[$question->id]->text, "survey"); -} -unset($allquestions); - -// Get and collate all the results in one big array -if (! $surveyanswers = $DB->get_records("survey_answers", array("survey"=>$survey->id), "time ASC")) { - throw new \moodle_exception('cannotfindanswer', 'survey'); -} - -$results = array(); - -foreach ($surveyanswers as $surveyanswer) { - if (!$group || isset($users[$surveyanswer->userid])) { - //$questionid = $reversednestedorder[$surveyanswer->question]; - $questionid = $surveyanswer->question; - if (!array_key_exists($surveyanswer->userid, $results)) { - $results[$surveyanswer->userid] = array('time'=>$surveyanswer->time); - } - $results[$surveyanswer->userid][$questionid]['answer1'] = $surveyanswer->answer1; - $results[$surveyanswer->userid][$questionid]['answer2'] = $surveyanswer->answer2; - } -} - -// Output the file as a valid ODS spreadsheet if required -$coursecontext = context_course::instance($course->id); -$courseshortname = format_string($course->shortname, true, array('context' => $coursecontext)); - -if ($type == "ods") { - require_once("$CFG->libdir/odslib.class.php"); - -/// Calculate file name - $downloadfilename = clean_filename(strip_tags($courseshortname.' '.format_string($survey->name, true))).'.ods'; -/// Creating a workbook - $workbook = new MoodleODSWorkbook("-"); -/// Sending HTTP headers - $workbook->send($downloadfilename); -/// Creating the first worksheet - $myxls = $workbook->add_worksheet(core_text::substr(strip_tags(format_string($survey->name,true)), 0, 31)); - - $header = array("surveyid","surveyname","userid","firstname","lastname","email","idnumber","time", "notes"); - $col=0; - foreach ($header as $item) { - $myxls->write_string(0,$col++,$item); - } - - foreach ($nestedorder as $key => $nestedquestions) { - foreach ($nestedquestions as $key2 => $qid) { - $question = $questions[$qid]; - if ($question->type == "0" || $question->type == "1" || $question->type == "3" || $question->type == "-1") { - $myxls->write_string(0,$col++,"$question->text"); - } - if ($question->type == "2" || $question->type == "3") { - $myxls->write_string(0,$col++,"$question->text (preferred)"); - } - } - } - -// $date = $workbook->addformat(); -// $date->set_num_format('mmmm-d-yyyy h:mm:ss AM/PM'); // ?? adjust the settings to reflect the PHP format below - - $row = 0; - foreach ($results as $user => $rest) { - $col = 0; - $row++; - if (! $u = $DB->get_record("user", array("id"=>$user))) { - throw new \moodle_exception('invaliduserid'); - } - if ($n = $DB->get_record("survey_analysis", array("survey"=>$survey->id, "userid"=>$user))) { - $notes = $n->notes; - } else { - $notes = "No notes made"; - } - $myxls->write_string($row,$col++,$survey->id); - $myxls->write_string($row,$col++,strip_tags(format_text($survey->name,true))); - $myxls->write_string($row,$col++,$user); - $myxls->write_string($row,$col++,$u->firstname); - $myxls->write_string($row,$col++,$u->lastname); - $myxls->write_string($row,$col++,$u->email); - $myxls->write_string($row,$col++,$u->idnumber); - $myxls->write_string($row,$col++, userdate($results[$user]["time"], "%d-%b-%Y %I:%M:%S %p") ); -// $myxls->write_number($row,$col++,$results[$user]["time"],$date); - $myxls->write_string($row,$col++,$notes); - - foreach ($nestedorder as $key => $nestedquestions) { - foreach ($nestedquestions as $key2 => $qid) { - $question = $questions[$qid]; - if ($question->type == "0" || $question->type == "1" || $question->type == "3" || $question->type == "-1") { - $myxls->write_string($row,$col++, $results[$user][$qid]["answer1"] ); - } - if ($question->type == "2" || $question->type == "3") { - $myxls->write_string($row, $col++, $results[$user][$qid]["answer2"] ); - } - } - } - } - $workbook->close(); - - exit; -} - -// Output the file as a valid Excel spreadsheet if required - -if ($type == "xls") { - require_once("$CFG->libdir/excellib.class.php"); - -/// Calculate file name - $downloadfilename = clean_filename(strip_tags($courseshortname.' '.format_string($survey->name,true))).'.xls'; -/// Creating a workbook - $workbook = new MoodleExcelWorkbook("-"); -/// Sending HTTP headers - $workbook->send($downloadfilename); -/// Creating the first worksheet - $myxls = $workbook->add_worksheet(core_text::substr(strip_tags(format_string($survey->name,true)), 0, 31)); - - $header = array("surveyid","surveyname","userid","firstname","lastname","email","idnumber","time", "notes"); - $col=0; - foreach ($header as $item) { - $myxls->write_string(0,$col++,$item); - } - - foreach ($nestedorder as $key => $nestedquestions) { - foreach ($nestedquestions as $key2 => $qid) { - $question = $questions[$qid]; - - if ($question->type == "0" || $question->type == "1" || $question->type == "3" || $question->type == "-1") { - $myxls->write_string(0,$col++,"$question->text"); - } - if ($question->type == "2" || $question->type == "3") { - $myxls->write_string(0,$col++,"$question->text (preferred)"); - } - } - } - -// $date = $workbook->addformat(); -// $date->set_num_format('mmmm-d-yyyy h:mm:ss AM/PM'); // ?? adjust the settings to reflect the PHP format below - - $row = 0; - foreach ($results as $user => $rest) { - $col = 0; - $row++; - if (! $u = $DB->get_record("user", array("id"=>$user))) { - throw new \moodle_exception('invaliduserid'); - } - if ($n = $DB->get_record("survey_analysis", array("survey"=>$survey->id, "userid"=>$user))) { - $notes = $n->notes; - } else { - $notes = "No notes made"; - } - $myxls->write_string($row,$col++,$survey->id); - $myxls->write_string($row,$col++,strip_tags(format_text($survey->name,true))); - $myxls->write_string($row,$col++,$user); - $myxls->write_string($row,$col++,$u->firstname); - $myxls->write_string($row,$col++,$u->lastname); - $myxls->write_string($row,$col++,$u->email); - $myxls->write_string($row,$col++,$u->idnumber); - $myxls->write_string($row,$col++, userdate($results[$user]["time"], "%d-%b-%Y %I:%M:%S %p") ); -// $myxls->write_number($row,$col++,$results[$user]["time"],$date); - $myxls->write_string($row,$col++,$notes); - - foreach ($nestedorder as $key => $nestedquestions) { - foreach ($nestedquestions as $key2 => $qid) { - $question = $questions[$qid]; - if (($question->type == "0" || $question->type == "1" || $question->type == "3" || $question->type == "-1") - && array_key_exists($qid, $results[$user]) ){ - $myxls->write_string($row,$col++, $results[$user][$qid]["answer1"] ); - } - if (($question->type == "2" || $question->type == "3") - && array_key_exists($qid, $results[$user]) ){ - $myxls->write_string($row, $col++, $results[$user][$qid]["answer2"] ); - } - } - } - } - $workbook->close(); - - exit; -} - -// Otherwise, return the text file. - -// Print header to force download - -header("Content-Type: application/download\n"); - -$downloadfilename = clean_filename(strip_tags($courseshortname.' '.format_string($survey->name,true))); -header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\""); - -// Print names of all the fields - -echo "surveyid surveyname userid firstname lastname email idnumber time "; - -foreach ($nestedorder as $key => $nestedquestions) { - foreach ($nestedquestions as $key2 => $qid) { - $question = $questions[$qid]; - if ($question->type == "0" || $question->type == "1" || $question->type == "3" || $question->type == "-1") { - echo "$question->text "; - } - if ($question->type == "2" || $question->type == "3") { - echo "$question->text (preferred) "; - } -} -} -echo "\n"; - -// Print all the lines of data. -foreach ($results as $user => $rest) { - if (! $u = $DB->get_record("user", array("id"=>$user))) { - throw new \moodle_exception('invaliduserid'); - } - echo $survey->id."\t"; - echo strip_tags(format_string($survey->name,true))."\t"; - echo $user."\t"; - echo $u->firstname."\t"; - echo $u->lastname."\t"; - echo $u->email."\t"; - echo $u->idnumber."\t"; - echo userdate($results[$user]["time"], "%d-%b-%Y %I:%M:%S %p")."\t"; - - foreach ($nestedorder as $key => $nestedquestions) { - foreach ($nestedquestions as $key2 => $qid) { - $question = $questions[$qid]; - - if ($question->type == "0" || $question->type == "1" || $question->type == "3" || $question->type == "-1") { - echo $results[$user][$qid]["answer1"]." "; - } - if ($question->type == "2" || $question->type == "3") { - echo $results[$user][$qid]["answer2"]." "; - } - } - } - echo "\n"; -} - -exit; diff --git a/mod/survey/graph.php b/mod/survey/graph.php deleted file mode 100644 index df7378af783..00000000000 --- a/mod/survey/graph.php +++ /dev/null @@ -1,753 +0,0 @@ -. - -/** - * This file is responsible for producing the graph for survey reports - * - * @package mod_survey - * @copyright 2021 Sujith Haridasan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -require_once("../../config.php"); -require_once("$CFG->libdir/graphlib.php"); -require_once("lib.php"); - -$id = required_param('id', PARAM_INT); // Course Module ID. -$type = required_param('type', PARAM_FILE); // Graph Type. -$group = optional_param('group', 0, PARAM_INT); // Group ID. -$sid = optional_param('sid', false, PARAM_INT); // Student ID. -$qid = optional_param('qid', 0, PARAM_INT); // Group ID. - -$url = new moodle_url('/mod/survey/graph.php', array('id' => $id, 'type' => $type)); -if ($group !== 0) { - $url->param('group', $group); -} -if ($sid !== false) { - $url->param('sid', $sid); -} -if ($qid !== 0) { - $url->param('qid', $qid); -} -$PAGE->set_url($url); - -if (!$cm = get_coursemodule_from_id('survey', $id)) { - throw new \moodle_exception('invalidcoursemodule'); -} - -if (!$course = $DB->get_record("course", array("id" => $cm->course))) { - throw new \moodle_exception('coursemisconf'); -} - -if ($sid) { - if (!$user = $DB->get_record("user", array("id" => $sid))) { - throw new \moodle_exception('invaliduserid'); - } -} - -require_login($course, false, $cm); - -$groupmode = groups_get_activity_groupmode($cm); // Groups are being used. -$context = context_module::instance($cm->id); - -if (!has_capability('mod/survey:readresponses', $context)) { - if ($type != "student.png" or $sid != $USER->id) { - throw new \moodle_exception('nopermissiontoshow'); - } else if ($groupmode and !groups_is_member($group)) { - throw new \moodle_exception('nopermissiontoshow'); - } -} - -if (!$survey = $DB->get_record("survey", array("id" => $cm->instance))) { - throw new \moodle_exception('invalidsurveyid', 'survey'); -} - -// Check to see if groups are being used in this survey. -if ($group) { - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', $group, null, false); -} else if (!empty($cm->groupingid)) { - $groups = groups_get_all_groups($courseid, 0, $cm->groupingid); - $groups = array_keys($groups); - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', $groups, null, false); -} else { - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', '', null, false); - $group = false; -} - -$stractual = get_string("actual", "survey"); -$stractualclass = get_string("actualclass", "survey"); - -$strpreferred = get_string("preferred", "survey"); -$strpreferredclass = get_string("preferredclass", "survey"); - -if ($sid || isset($user)) { - $stractualstudent = get_string("actualstudent", "survey", fullname($user)); - $strpreferredstudent = get_string("preferredstudent", "survey", fullname($user)); -} - -$virtualscales = false; // Set default value for case clauses. - -switch ($type) { - - case "question.png": - - $question = $DB->get_record("survey_questions", array("id" => $qid)); - $question->text = wordwrap(get_string($question->text, "survey"), SURVEY_QLENGTH_WRAP); - $question->options = get_string($question->options, "survey"); - - $options = explode(",", $question->options); - - foreach ($options as $key => $unused) { - $buckets1[$key] = 0; - $buckets2[$key] = 0; - } - - if ($aaa = $DB->get_records('survey_answers', array('survey' => $cm->instance, 'question' => $qid))) { - foreach ($aaa as $aa) { - if (!$group or isset($users[$aa->userid])) { - if ($a1 = $aa->answer1) { - $buckets1[$a1 - 1]++; - } - if ($a2 = $aa->answer2) { - $buckets2[$a2 - 1]++; - } - } - } - } - - $maxbuckets1 = max($buckets1); - $maxbuckets2 = max($buckets2); - $maxbuckets = ($maxbuckets1 > $maxbuckets2) ? $maxbuckets1 : $maxbuckets2; - - $graph = new graph($SURVEY_GWIDTH, $SURVEY_GHEIGHT); - $graph->parameter['title'] = "$question->text"; - - $graph->x_data = $options; - - $graph->y_data['answers1'] = $buckets1; - $graph->y_format['answers1'] = array('colour' => 'ltblue', 'bar' => 'fill', 'legend' => $stractual, 'bar_size' => 0.4); - $graph->y_data['answers2'] = $buckets2; - $graph->y_format['answers2'] = array('colour' => 'ltorange', 'bar' => 'fill', 'legend' => $strpreferred, 'bar_size' => 0.2); - - $graph->parameter['legend'] = 'outside-top'; - $graph->parameter['legend_border'] = 'black'; - $graph->parameter['legend_offset'] = 4; - - if (($maxbuckets1 > 0.0) && ($maxbuckets2 > 0.0)) { - $graph->y_order = array('answers1', 'answers2'); - } else if ($maxbuckets1 > 0.0) { - $graph->y_order = array('answers1'); - } else { - $graph->y_order = array('answers2'); - } - - $graph->parameter['y_axis_gridlines'] = $maxbuckets + 1; - $graph->parameter['y_resolution_left'] = 1; - $graph->parameter['y_decimal_left'] = 0; - $graph->parameter['x_axis_angle'] = 20; - $graph->parameter['shadow'] = 'none'; - - $graph->y_tick_labels = null; - $graph->offset_relation = null; - - $graph->draw_stack(); - - break; - - case "multiquestion.png": - - $question = $DB->get_record("survey_questions", array("id" => $qid)); - $question->text = get_string($question->text, "survey"); - $question->options = get_string($question->options, "survey"); - - $options = explode(",", $question->options); - $questionorder = explode(",", $question->multi); - - $qqq = $DB->get_records_list("survey_questions", "id", explode(',', $question->multi)); - - foreach ($questionorder as $i => $val) { - $names[$i] = get_string($qqq["$val"]->shorttext, "survey"); - $buckets1[$i] = 0; - $buckets2[$i] = 0; - $count1[$i] = 0; - $count2[$i] = 0; - $indexof[$val] = $i; - $stdev1[$i] = 0; - $stdev2[$i] = 0; - } - - $aaa = $DB->get_records_select("survey_answers", "((survey = ?) AND (question in ($question->multi)))", - array($cm->instance)); - - if ($aaa) { - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - $index = $indexof[$a->question]; - if ($a->answer1) { - $buckets1[$index] += $a->answer1; - $count1[$index]++; - } - if ($a->answer2) { - $buckets2[$index] += $a->answer2; - $count2[$index]++; - } - } - } - } - - foreach ($questionorder as $i => $val) { - if ($count1[$i]) { - $buckets1[$i] = (float) $buckets1[$i] / (float) $count1[$i]; - } - if ($count2[$i]) { - $buckets2[$i] = (float) $buckets2[$i] / (float) $count2[$i]; - } - } - - if ($aaa) { - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - $index = $indexof[$a->question]; - if ($a->answer1) { - $difference = (float) ($a->answer1 - $buckets1[$index]); - $stdev1[$index] += ($difference * $difference); - } - if ($a->answer2) { - $difference = (float) ($a->answer2 - $buckets2[$index]); - $stdev2[$index] += ($difference * $difference); - } - } - } - } - - foreach ($questionorder as $i => $val) { - if ($count1[$i]) { - $stdev1[$i] = sqrt((float) $stdev1[$i] / ((float) $count1[$i])); - } - if ($count2[$i]) { - $stdev2[$i] = sqrt((float) $stdev2[$i] / ((float) $count2[$i])); - } - $buckets1[$i] = $buckets1[$i] - 1; - $buckets2[$i] = $buckets2[$i] - 1; - } - - $maxbuckets1 = max($buckets1); - $maxbuckets2 = max($buckets2); - - $graph = new graph($SURVEY_GWIDTH, $SURVEY_GHEIGHT); - $graph->parameter['title'] = "$question->text"; - - $graph->x_data = $names; - $graph->y_data['answers1'] = $buckets1; - $graph->y_format['answers1'] = array('colour' => 'ltblue', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $stractual); - $graph->y_data['answers2'] = $buckets2; - $graph->y_format['answers2'] = array('colour' => 'ltorange', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $strpreferred); - $graph->y_data['stdev1'] = $stdev1; - $graph->y_format['stdev1'] = array('colour' => 'ltltblue', 'bar' => 'fill', - 'shadow_offset' => '4', 'legend' => 'none', 'bar_size' => 0.3); - $graph->y_data['stdev2'] = $stdev2; - $graph->y_format['stdev2'] = array('colour' => 'ltltorange', 'bar' => 'fill', - 'shadow_offset' => '4', 'legend' => 'none', 'bar_size' => 0.2); - $graph->offset_relation['stdev1'] = 'answers1'; - $graph->offset_relation['stdev2'] = 'answers2'; - - $graph->parameter['bar_size'] = 0.15; - - $graph->parameter['legend'] = 'outside-top'; - $graph->parameter['legend_border'] = 'black'; - $graph->parameter['legend_offset'] = 4; - - $graph->y_tick_labels = $options; - - if (($maxbuckets1 > 0.0) && ($maxbuckets2 > 0.0)) { - $graph->y_order = array('stdev1', 'answers1', 'stdev2', 'answers2'); - } else if ($maxbuckets1 > 0.0) { - $graph->y_order = array('stdev1', 'answers1'); - } else { - $graph->y_order = array('stdev2', 'answers2'); - } - - $graph->parameter['y_max_left'] = count($options) - 1; - $graph->parameter['y_axis_gridlines'] = count($options); - $graph->parameter['y_resolution_left'] = 1; - $graph->parameter['y_decimal_left'] = 1; - $graph->parameter['x_axis_angle'] = 20; - - $graph->draw(); - - break; - - case "overall.png": - - $qqq = $DB->get_records_list("survey_questions", "id", explode(',', $survey->questions)); - - foreach ($qqq as $key => $qq) { - if ($qq->multi) { - $qqq[$key]->text = get_string($qq->text, "survey"); - $qqq[$key]->options = get_string($qq->options, "survey"); - if ($qq->type < 0) { - $virtualscales = true; - } - } - } - foreach ($qqq as $qq) { // If any virtual, then use JUST virtual, else use JUST nonvirtual. - if ($qq->multi) { - if ($virtualscales && $qq->type < 0) { - $question[] = $qq; - } else if (!$virtualscales && $qq->type > 0) { - $question[] = $qq; - } - } - } - $numquestions = count($question); - - $options = explode(",", $question[0]->options); - $numoptions = count($options); - - for ($i = 0; $i < $numquestions; $i++) { - $names[$i] = $question[$i]->text; - $buckets1[$i] = 0.0; - $buckets2[$i] = 0.0; - $stdev1[$i] = 0.0; - $stdev2[$i] = 0.0; - $count1[$i] = 0; - $count2[$i] = 0; - $subquestions = $question[$i]->multi; // Otherwise next line doesn't work. - $aaa = $DB->get_records_select("survey_answers", "((survey = ?) AND (question in ($subquestions)))", - array($cm->instance)); - - if ($aaa) { - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - if ($a->answer1) { - $buckets1[$i] += $a->answer1; - $count1[$i]++; - } - if ($a->answer2) { - $buckets2[$i] += $a->answer2; - $count2[$i]++; - } - } - } - } - - if ($count1[$i]) { - $buckets1[$i] = (float) $buckets1[$i] / (float) $count1[$i]; - } - if ($count2[$i]) { - $buckets2[$i] = (float) $buckets2[$i] / (float) $count2[$i]; - } - - // Calculate the standard devaiations. - if ($aaa) { - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - if ($a->answer1) { - $difference = (float) ($a->answer1 - $buckets1[$i]); - $stdev1[$i] += ($difference * $difference); - } - if ($a->answer2) { - $difference = (float) ($a->answer2 - $buckets2[$i]); - $stdev2[$i] += ($difference * $difference); - } - } - } - } - - if ($count1[$i]) { - $stdev1[$i] = sqrt((float) $stdev1[$i] / ((float) $count1[$i])); - } - if ($count2[$i]) { - $stdev2[$i] = sqrt((float) $stdev2[$i] / ((float) $count2[$i])); - } - - $buckets1[$i] = $buckets1[$i] - 1; // Hack because there should not be ANY 0 values in the data. - $buckets2[$i] = $buckets2[$i] - 1; - - } - - $maxbuckets1 = max($buckets1); - $maxbuckets2 = max($buckets2); - - $graph = new graph($SURVEY_GWIDTH, $SURVEY_GHEIGHT); - $graph->parameter['title'] = strip_tags(format_string($survey->name, true)); - - $graph->x_data = $names; - - $graph->y_data['answers1'] = $buckets1; - $graph->y_format['answers1'] = array('colour' => 'ltblue', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $stractual); - $graph->y_data['answers2'] = $buckets2; - $graph->y_format['answers2'] = array('colour' => 'ltorange', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $strpreferred); - - $graph->y_data['stdev1'] = $stdev1; - $graph->y_format['stdev1'] = array('colour' => 'ltltblue', 'bar' => 'fill', - 'shadow_offset' => '4', 'legend' => 'none', 'bar_size' => 0.3); - $graph->y_data['stdev2'] = $stdev2; - $graph->y_format['stdev2'] = array('colour' => 'ltltorange', 'bar' => 'fill', - 'shadow_offset' => '4', 'legend' => 'none', 'bar_size' => 0.2); - $graph->offset_relation['stdev1'] = 'answers1'; - $graph->offset_relation['stdev2'] = 'answers2'; - - $graph->parameter['legend'] = 'outside-top'; - $graph->parameter['legend_border'] = 'black'; - $graph->parameter['legend_offset'] = 4; - - $graph->y_tick_labels = $options; - - if (($maxbuckets1 > 0.0) && ($maxbuckets2 > 0.0)) { - $graph->y_order = array('stdev1', 'answers1', 'stdev2', 'answers2'); - } else if ($maxbuckets1 > 0.0) { - $graph->y_order = array('stdev1', 'answers1'); - } else { - $graph->y_order = array('stdev2', 'answers2'); - } - - $graph->parameter['y_max_left'] = $numoptions - 1; - $graph->parameter['y_axis_gridlines'] = $numoptions; - $graph->parameter['y_resolution_left'] = 1; - $graph->parameter['y_decimal_left'] = 1; - $graph->parameter['x_axis_angle'] = 0; - $graph->parameter['x_inner_padding'] = 6; - - $graph->draw(); - - break; - - case "student.png": - - $qqq = $DB->get_records_list("survey_questions", "id", explode(',', $survey->questions)); - - foreach ($qqq as $key => $qq) { - if ($qq->multi) { - $qqq[$key]->text = get_string($qq->text, "survey"); - $qqq[$key]->options = get_string($qq->options, "survey"); - if ($qq->type < 0) { - $virtualscales = true; - } - } - } - foreach ($qqq as $qq) { // If any virtual, then use JUST virtual, else use JUST nonvirtual. - if ($qq->multi) { - if ($virtualscales && $qq->type < 0) { - $question[] = $qq; - } else if (!$virtualscales && $qq->type > 0) { - $question[] = $qq; - } - } - } - $numquestions = count($question); - - $options = explode(",", $question[0]->options); - $numoptions = count($options); - - for ($i = 0; $i < $numquestions; $i++) { - $names[$i] = $question[$i]->text; - $buckets1[$i] = 0.0; - $buckets2[$i] = 0.0; - $count1[$i] = 0; - $count2[$i] = 0; - $studbuckets1[$i] = 0.0; - $studbuckets2[$i] = 0.0; - $studcount1[$i] = 0; - $studcount2[$i] = 0; - $stdev1[$i] = 0.0; - $stdev2[$i] = 0.0; - - $subquestions = $question[$i]->multi; // Otherwise next line doesn't work. - $aaa = $DB->get_records_select("survey_answers", "((survey = ?) AND (question in ($subquestions)))", - array($cm->instance)); - - if ($aaa) { - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - if ($a->userid == $sid) { - if ($a->answer1) { - $studbuckets1[$i] += $a->answer1; - $studcount1[$i]++; - } - if ($a->answer2) { - $studbuckets2[$i] += $a->answer2; - $studcount2[$i]++; - } - } - if ($a->answer1) { - $buckets1[$i] += $a->answer1; - $count1[$i]++; - } - if ($a->answer2) { - $buckets2[$i] += $a->answer2; - $count2[$i]++; - } - } - } - } - - if ($count1[$i]) { - $buckets1[$i] = (float) $buckets1[$i] / (float) $count1[$i]; - } - if ($count2[$i]) { - $buckets2[$i] = (float) $buckets2[$i] / (float) $count2[$i]; - } - if ($studcount1[$i]) { - $studbuckets1[$i] = (float) $studbuckets1[$i] / (float) $studcount1[$i]; - } - if ($studcount2[$i]) { - $studbuckets2[$i] = (float) $studbuckets2[$i] / (float) $studcount2[$i]; - } - - // Calculate the standard devaiations. - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - if ($a->answer1) { - $difference = (float) ($a->answer1 - $buckets1[$i]); - $stdev1[$i] += ($difference * $difference); - } - if ($a->answer2) { - $difference = (float) ($a->answer2 - $buckets2[$i]); - $stdev2[$i] += ($difference * $difference); - } - } - } - - if ($count1[$i]) { - $stdev1[$i] = sqrt((float) $stdev1[$i] / ((float) $count1[$i])); - } - if ($count2[$i]) { - $stdev2[$i] = sqrt((float) $stdev2[$i] / ((float) $count2[$i])); - } - - $buckets1[$i] = $buckets1[$i] - 1; // Hack because there should not be ANY 0 values in the data. - $buckets2[$i] = $buckets2[$i] - 1; - $studbuckets1[$i] = $studbuckets1[$i] - 1; - $studbuckets2[$i] = $studbuckets2[$i] - 1; - - } - - $maxbuckets1 = max($buckets1); - $maxbuckets2 = max($buckets2); - - $graph = new graph($SURVEY_GWIDTH, $SURVEY_GHEIGHT); - $graph->parameter['title'] = strip_tags(format_string($survey->name, true)); - - $graph->x_data = $names; - - $graph->y_data['answers1'] = $buckets1; - $graph->y_format['answers1'] = array('colour' => 'ltblue', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 0.1, 'legend' => $stractualclass); - $graph->y_data['answers2'] = $buckets2; - $graph->y_format['answers2'] = array('colour' => 'ltorange', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 0.1, 'legend' => $strpreferredclass); - $graph->y_data['studanswers1'] = $studbuckets1; - $graph->y_format['studanswers1'] = array('colour' => 'blue', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $stractualstudent); - $graph->y_data['studanswers2'] = $studbuckets2; - $graph->y_format['studanswers2'] = array('colour' => 'orange', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $strpreferredstudent); - $graph->y_data['stdev1'] = $stdev1; - $graph->y_format['stdev1'] = array('colour' => 'ltltblue', 'bar' => 'fill', - 'shadow_offset' => 0.1, 'legend' => 'none', 'bar_size' => 0.3); - $graph->y_data['stdev2'] = $stdev2; - $graph->y_format['stdev2'] = array('colour' => 'ltltorange', 'bar' => 'fill', - 'shadow_offset' => 0.1, 'legend' => 'none', 'bar_size' => 0.2); - $graph->offset_relation['stdev1'] = 'answers1'; - $graph->offset_relation['stdev2'] = 'answers2'; - - $graph->y_tick_labels = $options; - - $graph->parameter['bar_size'] = 0.15; - - $graph->parameter['legend'] = 'outside-top'; - $graph->parameter['legend_border'] = 'black'; - $graph->parameter['legend_offset'] = 4; - - if (($maxbuckets1 > 0.0) && ($maxbuckets2 > 0.0)) { - $graph->y_order = array('stdev1', 'stdev2', 'answers1', 'answers2', 'studanswers1', 'studanswers2'); - } else if ($maxbuckets1 > 0.0) { - $graph->y_order = array('stdev1', 'answers1', 'studanswers1'); - } else { - $graph->y_order = array('stdev2', 'answers2', 'studanswers2'); - } - - $graph->parameter['y_max_left'] = $numoptions - 1; - $graph->parameter['y_axis_gridlines'] = $numoptions; - $graph->parameter['y_resolution_left'] = 1; - $graph->parameter['y_decimal_left'] = 1; - $graph->parameter['x_axis_angle'] = 20; - - $graph->draw(); - break; - - case "studentmultiquestion.png": - - $question = $DB->get_record("survey_questions", array("id" => $qid)); - $question->text = get_string($question->text, "survey"); - $question->options = get_string($question->options, "survey"); - - $options = explode(",", $question->options); - $questionorder = explode(",", $question->multi); - - $qqq = $DB->get_records_list("survey_questions", "id", explode(',', $question->multi)); - - foreach ($questionorder as $i => $val) { - $names[$i] = get_string($qqq[$val]->shorttext, "survey"); - $buckets1[$i] = 0; - $buckets2[$i] = 0; - $count1[$i] = 0; - $count2[$i] = 0; - $indexof[$val] = $i; - $studbuckets1[$i] = 0.0; - $studbuckets2[$i] = 0.0; - $studcount1[$i] = 0; - $studcount2[$i] = 0; - $stdev1[$i] = 0.0; - $stdev2[$i] = 0.0; - } - - $aaa = $DB->get_records_select("survey_answers", "((survey = ?) AND (question in ($question->multi)))", - array($cm->instance)); - - if ($aaa) { - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - $index = $indexof[$a->question]; - if ($a->userid == $sid) { - if ($a->answer1) { - $studbuckets1[$index] += $a->answer1; - $studcount1[$index]++; - } - if ($a->answer2) { - $studbuckets2[$index] += $a->answer2; - $studcount2[$index]++; - } - } - if ($a->answer1) { - $buckets1[$index] += $a->answer1; - $count1[$index]++; - } - if ($a->answer2) { - $buckets2[$index] += $a->answer2; - $count2[$index]++; - } - } - } - } - - foreach ($questionorder as $i => $val) { - if ($count1[$i]) { - $buckets1[$i] = (float) $buckets1[$i] / (float) $count1[$i]; - } - if ($count2[$i]) { - $buckets2[$i] = (float) $buckets2[$i] / (float) $count2[$i]; - } - if ($studcount1[$i]) { - $studbuckets1[$i] = (float) $studbuckets1[$i] / (float) $studcount1[$i]; - } - if ($studcount2[$i]) { - $studbuckets2[$i] = (float) $studbuckets2[$i] / (float) $studcount2[$i]; - } - } - - foreach ($aaa as $a) { - if (!$group or isset($users[$a->userid])) { - $index = $indexof[$a->question]; - if ($a->answer1) { - $difference = (float) ($a->answer1 - $buckets1[$index]); - $stdev1[$index] += ($difference * $difference); - } - if ($a->answer2) { - $difference = (float) ($a->answer2 - $buckets2[$index]); - $stdev2[$index] += ($difference * $difference); - } - } - } - - foreach ($questionorder as $i => $val) { - if ($count1[$i]) { - $stdev1[$i] = sqrt((float) $stdev1[$i] / ((float) $count1[$i])); - } - if ($count2[$i]) { - $stdev2[$i] = sqrt((float) $stdev2[$i] / ((float) $count2[$i])); - } - $buckets1[$i] = $buckets1[$i] - 1; // Hack because there should not be ANY 0 values in the data. - $buckets2[$i] = $buckets2[$i] - 1; - $studbuckets1[$i] = $studbuckets1[$i] - 1; - $studbuckets2[$i] = $studbuckets2[$i] - 1; - } - - $maxbuckets1 = max($buckets1); - $maxbuckets2 = max($buckets2); - - $graph = new graph($SURVEY_GWIDTH, $SURVEY_GHEIGHT); - $graph->parameter['title'] = "$question->text"; - - $graph->x_data = $names; - $graph->y_data['answers1'] = $buckets1; - $graph->y_format['answers1'] = array('colour' => 'ltblue', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 0.1, 'legend' => $stractualclass); - $graph->y_data['answers2'] = $buckets2; - $graph->y_format['answers2'] = array('colour' => 'ltorange', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 0.1, 'legend' => $strpreferredclass); - $graph->y_data['studanswers1'] = $studbuckets1; - $graph->y_format['studanswers1'] = array('colour' => 'blue', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $stractualstudent); - $graph->y_data['studanswers2'] = $studbuckets2; - $graph->y_format['studanswers2'] = array('colour' => 'orange', 'line' => 'line', 'point' => 'square', - 'shadow_offset' => 4, 'legend' => $strpreferredstudent); - $graph->y_data['stdev1'] = $stdev1; - $graph->y_format['stdev1'] = array('colour' => 'ltltblue', 'bar' => 'fill', - 'shadow_offset' => 0.1, 'legend' => 'none', 'bar_size' => 0.3); - $graph->y_data['stdev2'] = $stdev2; - $graph->y_format['stdev2'] = array('colour' => 'ltltorange', 'bar' => 'fill', - 'shadow_offset' => 0.1, 'legend' => 'none', 'bar_size' => 0.2); - $graph->offset_relation['stdev1'] = 'answers1'; - $graph->offset_relation['stdev2'] = 'answers2'; - - $graph->parameter['bar_size'] = 0.15; - - $graph->parameter['legend'] = 'outside-top'; - $graph->parameter['legend_border'] = 'black'; - $graph->parameter['legend_offset'] = 4; - - $graph->y_tick_labels = $options; - - if (($maxbuckets1 > 0.0) && ($maxbuckets2 > 0.0)) { - $graph->y_order = array('stdev1', 'stdev2', 'answers1', 'answers2', 'studanswers1', 'studanswers2'); - } else if ($maxbuckets1 > 0.0) { - $graph->y_order = array('stdev1', 'answers1', 'studanswers1'); - } else { - $graph->y_order = array('stdev2', 'answers2', 'studanswers2'); - } - - $graph->parameter['y_max_left'] = count($options) - 1; - $graph->parameter['y_axis_gridlines'] = count($options); - $graph->parameter['y_resolution_left'] = 1; - $graph->parameter['y_decimal_left'] = 1; - $graph->parameter['x_axis_angle'] = 20; - - $graph->draw(); - - break; - - default: - break; -} - -exit; diff --git a/mod/survey/index.php b/mod/survey/index.php deleted file mode 100644 index f979543b6c7..00000000000 --- a/mod/survey/index.php +++ /dev/null @@ -1,91 +0,0 @@ -set_url('/mod/survey/index.php', array('id'=>$id)); - - if (!$course = $DB->get_record('course', array('id'=>$id))) { - throw new \moodle_exception('invalidcourseid'); - } - - require_course_login($course); - $PAGE->set_pagelayout('incourse'); - - $params = array( - 'context' => context_course::instance($course->id), - 'courseid' => $course->id - ); - $event = \mod_survey\event\course_module_instance_list_viewed::create($params); - $event->trigger(); - - $strsurveys = get_string("modulenameplural", "survey"); - $strname = get_string("name"); - $strstatus = get_string("status"); - $strdone = get_string("done", "survey"); - $strnotdone = get_string("notdone", "survey"); - - $PAGE->navbar->add($strsurveys); - $PAGE->set_title($strsurveys); - $PAGE->set_heading($course->fullname); - echo $OUTPUT->header(); - if (!$PAGE->has_secondary_navigation()) { - echo $OUTPUT->heading($strsurveys); - } - - if (! $surveys = get_all_instances_in_course("survey", $course)) { - notice(get_string('thereareno', 'moodle', $strsurveys), "../../course/view.php?id=$course->id"); - } - - $usesections = course_format_uses_sections($course->format); - - $table = new html_table(); - - if ($usesections) { - $strsectionname = course_get_format($course)->get_generic_section_name(); - $table->head = array ($strsectionname, $strname, $strstatus); - } else { - $table->head = array ($strname, $strstatus); - } - - $currentsection = ''; - - foreach ($surveys as $survey) { - if (isloggedin() and survey_already_done($survey->id, $USER->id)) { - $ss = $strdone; - } else { - $ss = $strnotdone; - } - $printsection = ""; - if ($usesections) { - if ($survey->section !== $currentsection) { - if ($survey->section) { - $printsection = get_section_name($course, $survey->section); - } - if ($currentsection !== "") { - $table->data[] = 'hr'; - } - $currentsection = $survey->section; - } - } - //Calculate the href - if (!$survey->visible) { - //Show dimmed if the mod is hidden - $tt_href = "coursemodule\">".format_string($survey->name,true).""; - } else { - //Show normal if the mod is visible - $tt_href = "coursemodule\">".format_string($survey->name,true).""; - } - - if ($usesections) { - $table->data[] = array ($printsection, $tt_href, "coursemodule\">$ss"); - } else { - $table->data[] = array ($tt_href, "coursemodule\">$ss"); - } - } - - echo "
"; - echo html_writer::table($table); - echo $OUTPUT->footer(); diff --git a/mod/survey/lang/en/survey.php b/mod/survey/lang/en/survey.php deleted file mode 100644 index 4260896339b..00000000000 --- a/mod/survey/lang/en/survey.php +++ /dev/null @@ -1,283 +0,0 @@ -. - -/** - * Strings for component 'survey', language 'en', branch 'MOODLE_20_STABLE' - * - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$string['actual'] = 'Actual'; -$string['actualclass'] = 'Class actual'; -$string['actualstudent'] = '{$a} actual'; -$string['allscales'] = 'All scales, all students'; -$string['alreadysubmitted'] = 'You have already submitted this survey'; -$string['analysisof'] = 'Analysis of {$a}'; -$string['answers'] = 'Answers'; -$string['attlsintro'] = 'The purpose of this questionnaire is to help us evaluate your attitudes towards thinking and learning. - -There are no \'right\' or \'wrong\' answers; we are interested only in your opinion. Please be assured that your responses will be treated with a high degree of confidentiality, and will not affect your assessment.'; -$string['attlsmintro'] = 'In discussion ...'; -$string['attlsm1'] = 'Attitudes Towards Thinking and Learning'; -$string['attlsm2'] = 'Connected learning'; -$string['attlsm3'] = 'Separate learning'; -$string['attlsname'] = 'ATTLS (20 item version)'; -$string['attls1'] = 'In evaluating what someone says, I focus on the quality of their argument, not on the person who\'s presenting it.'; -$string['attls1short'] = 'focus quality of argument'; -$string['attls10'] = 'It\'s important for me to remain as objective as possible when I analyze something.'; -$string['attls10short'] = 'remain objective'; -$string['attls11'] = 'I try to think with people instead of against them.'; -$string['attls11short'] = 'think WITH people'; -$string['attls12'] = 'I have certain criteria I use in evaluating arguments.'; -$string['attls12short'] = 'use criteria to evaluate'; -$string['attls13'] = 'I\'m more likely to try to understand someone else\'s opinion than to try to evaluate it.'; -$string['attls13short'] = 'try to understand'; -$string['attls14'] = 'I try to point out weaknesses in other people\'s thinking to help them clarify their arguments.'; -$string['attls14short'] = 'point out weaknesses'; -$string['attls15'] = 'I tend to put myself in other people\'s shoes when discussing controversial issues, to see why they think the way they do.'; -$string['attls15short'] = 'put myself in their shoes'; -$string['attls16'] = 'One could call my way of analysing things \'putting them on trial\' because I am careful to consider all the evidence.'; -$string['attls16short'] = 'putting on trial'; -$string['attls17'] = 'I value the use of logic and reason over the incorporation of my own concerns when solving problems.'; -$string['attls17short'] = 'I value logic most'; -$string['attls18'] = 'I can obtain insight into opinions that differ from mine through empathy.'; -$string['attls18short'] = 'insight from empathy'; -$string['attls19'] = 'When I encounter people whose opinions seem alien to me, I make a deliberate effort to \'extend\' myself into that person, to try to see how they could have those opinions.'; -$string['attls19short'] = 'make effort to extend'; -$string['attls2'] = 'I like playing devil\'s advocate - arguing the opposite of what someone is saying.'; -$string['attls2short'] = 'play devil\'s advocate'; -$string['attls20'] = 'I spend time figuring out what\'s \'wrong\' with things. For example, I\'ll look for something in a literary interpretation that isn\'t argued well enough.'; -$string['attls20short'] = 'what\'s wrong?'; -$string['attls3'] = 'I like to understand where other people are \'coming from\', what experiences have led them to feel the way they do.'; -$string['attls3short'] = 'where people come from'; -$string['attls4'] = 'The most important part of my education has been learning to understand people who are very different to me.'; -$string['attls4short'] = 'understand different people'; -$string['attls5'] = 'I feel that the best way for me to achieve my own identity is to interact with a variety of other people.'; -$string['attls5short'] = 'interact with variety'; -$string['attls6'] = 'I enjoy hearing the opinions of people who come from backgrounds different to mine - it helps me to understand how the same things can be seen in such different ways.'; -$string['attls6short'] = 'enjoy hearing opinions'; -$string['attls7'] = 'I find that I can strengthen my own position through arguing with someone who disagrees with me.'; -$string['attls7short'] = 'strengthen by argue'; -$string['attls8'] = 'I am always interested in knowing why people say and believe the things they do.'; -$string['attls8short'] = 'know why people do'; -$string['attls9'] = 'I often find myself arguing with the authors of books that I read, trying to logically figure out why they\'re wrong.'; -$string['attls9short'] = 'argue with authors'; -$string['cannotfindanswer'] = 'There are no answers for this survey yet.'; -$string['cannotfindquestion'] = 'Question doesn\'t exist'; -$string['cannotfindsurveytmpt'] = 'No survey templates found!'; -$string['completiondetail:submit'] = 'Submit answers'; -$string['completionsubmit'] = 'Make a submission'; -$string['ciqintro'] = 'While thinking about recent events in this class, answer the questions below.'; -$string['ciqname'] = 'Critical incidents'; -$string['ciq1'] = 'At what moment in class were you most engaged as a learner?'; -$string['ciq1short'] = 'Most engaged'; -$string['ciq2'] = 'At what moment in class were you most distanced as a learner?'; -$string['ciq2short'] = 'Most distanced'; -$string['ciq3'] = 'What action from anyone in the forums did you find most affirming or helpful?'; -$string['ciq3short'] = 'Helpful moment'; -$string['ciq4'] = 'What action from anyone in the forums did you find most puzzling or confusing?'; -$string['ciq4short'] = 'Confusing moment'; -$string['ciq5'] = 'What event surprised you most?'; -$string['ciq5short'] = 'Suprising moment'; -$string['clicktocontinuecheck'] = 'Click here to check and continue'; -$string['collesaintro'] = 'The purpose of this survey is to help us understand how well the online delivery of this unit enabled you to learn. - -Each one of the 24 statements below asks about your experience in this unit. - -There are no \'right\' or \'wrong\' answers; we are interested only in your opinion. Please be assured that your responses will be treated with a high degree of confidentiality, and will not affect your assessment. - -Your carefully considered responses will help us improve the way this unit is presented online in the future. - -Thanks very much.'; -$string['collesaname'] = 'COLLES (Actual)'; -$string['collesapintro'] = 'The purpose of this questionnaire is to help us understand how well the online delivery of this unit enabled you to learn. - -Each couple of the 24 statements below asks you to compare your preferred (ideal) and actual experience in this unit. - -There are no \'right\' or \'wrong\' answers; we are interested only in your opinion. Please be assured that your responses will be treated with a high degree of confidentiality, and will not affect your assessment. - -Your carefully considered responses will help us improve the way this unit is presented online in the future. - -Thanks very much.'; -$string['collesapname'] = 'COLLES (Preferred and Actual)'; -$string['collesmintro'] = 'In this online unit...'; -$string['collesm1'] = 'Relevance'; -$string['collesm1short'] = 'Relevance'; -$string['collesm2'] = 'Reflective thinking'; -$string['collesm2short'] = 'Reflective thinking'; -$string['collesm3'] = 'Interactivity'; -$string['collesm3short'] = 'Interactivity'; -$string['collesm4'] = 'Tutor support'; -$string['collesm4short'] = 'Tutor support'; -$string['collesm5'] = 'Peer support'; -$string['collesm5short'] = 'Peer support'; -$string['collesm6'] = 'Interpretation'; -$string['collesm6short'] = 'Interpretation'; -$string['collespintro'] = 'The purpose of this survey is to help us understand what you value in an online learning experience. - -Each one of the 24 statements below asks about your preferred (ideal) experience in this unit. - -There are no \'right\' or \'wrong\' answers; we are interested only in your opinion. Please be assured that your responses will be treated with a high degree of confidentiality, and will not affect your assessment. - -Your carefully considered responses will help us improve the way this unit is presented online in the future. - -Thanks very much.'; -$string['collespname'] = 'COLLES (Preferred)'; -$string['colles1'] = 'my learning focuses on issues that interest me.'; -$string['colles1short'] = 'focus on interesting issues'; -$string['colles10'] = 'I ask other students to explain their ideas.'; -$string['colles10short'] = 'I ask for explanations'; -$string['colles11'] = 'other students ask me to explain my ideas.'; -$string['colles11short'] = 'I\'m asked to explain'; -$string['colles12'] = 'other students respond to my ideas.'; -$string['colles12short'] = 'students respond to me'; -$string['colles13'] = 'the tutor stimulates my thinking.'; -$string['colles13short'] = 'tutor stimulates thinking'; -$string['colles14'] = 'the tutor encourages me to participate.'; -$string['colles14short'] = 'tutor encourages me'; -$string['colles15'] = 'the tutor models good discourse.'; -$string['colles15short'] = 'tutor models discourse'; -$string['colles16'] = 'the tutor models critical self-reflection.'; -$string['colles16short'] = 'tutor models self-reflection'; -$string['colles17'] = 'other students encourage my participation.'; -$string['colles17short'] = 'students encourage me'; -$string['colles18'] = 'other students praise my contribution.'; -$string['colles18short'] = 'students praise me'; -$string['colles19'] = 'other students value my contribution.'; -$string['colles19short'] = 'students value me'; -$string['colles2'] = 'what I learn is important for my professional practice.'; -$string['colles2short'] = 'important to my practice'; -$string['colles20'] = 'other students empathise with my struggle to learn.'; -$string['colles20short'] = 'students empathise'; -$string['colles21'] = 'I make good sense of other students\' messages.'; -$string['colles21short'] = 'I understand other students'; -$string['colles22'] = 'other students make good sense of my messages.'; -$string['colles22short'] = 'students understand me'; -$string['colles23'] = 'I make good sense of the tutor\'s messages.'; -$string['colles23short'] = 'I understand the tutor'; -$string['colles24'] = 'the tutor makes good sense of my messages.'; -$string['colles24short'] = 'tutor understands me'; -$string['colles3'] = 'I learn how to improve my professional practice.'; -$string['colles3short'] = 'improve my practice'; -$string['colles4'] = 'what I learn connects well with my professional practice.'; -$string['colles4short'] = 'connects with my practice'; -$string['colles5'] = 'I think critically about how I learn.'; -$string['colles5short'] = 'I\'m critical of my learning'; -$string['colles6'] = 'I think critically about my own ideas.'; -$string['colles6short'] = 'I\'m critical of my own ideas'; -$string['colles7'] = 'I think critically about other students\' ideas.'; -$string['colles7short'] = 'I\'m critical of other students'; -$string['colles8'] = 'I think critically about ideas in the readings.'; -$string['colles8short'] = 'I\'m critical of readings'; -$string['colles9'] = 'I explain my ideas to other students.'; -$string['colles9short'] = 'I explain my ideas'; -$string['customintro'] = 'Description'; -$string['deleteallanswers'] = 'All survey responses'; -$string['deleteanalysis'] = 'Response analysis'; -$string['done'] = 'Done'; -$string['download'] = 'Download'; -$string['downloadexcel'] = 'Download data as Excel spreadsheet'; -$string['downloadinfo'] = 'You can download the complete raw data for this survey in a form suitable for analysis in Excel, SPSS or other package.'; -$string['downloadresults'] = 'Download results'; -$string['downloadtext'] = 'Download data as a plain text file'; -$string['editingasurvey'] = 'Editing a survey'; -$string['errorunabletosavenotes'] = 'An error occurred while saving your notes.'; -$string['eventreportdownloaded'] = 'Survey report downloaded'; -$string['eventreportviewed'] = 'Survey report viewed'; -$string['eventresponsesubmitted'] = 'Survey response submitted'; -$string['guestsnotallowed'] = 'Only enrolled users are able to submit surveys'; -$string['howlong'] = 'How long did this survey take you to complete?'; -$string['howlongoptions'] = 'under 1 min,1-2 min,2-3 min,3-4 min,4-5-min,5-10 min,more than 10'; -$string['ifoundthat'] = 'I found that'; -$string['indicator:cognitivedepth'] = 'Survey cognitive'; -$string['indicator:cognitivedepth_help'] = 'This indicator is based on the cognitive depth reached by the student in a Survey activity.'; -$string['indicator:cognitivedepthdef'] = 'Survey cognitive'; -$string['indicator:cognitivedepthdef_help'] = 'The participant has reached this percentage of the cognitive engagement offered by the Survey activities during this analysis interval (Levels = No view, View, Submit)'; -$string['indicator:cognitivedepthdef_link'] = 'Learning_analytics_indicators#Cognitive_depth'; -$string['indicator:socialbreadth'] = 'Survey social'; -$string['indicator:socialbreadth_help'] = 'This indicator is based on the social breadth reached by the student in a Survey activity.'; -$string['indicator:socialbreadthdef'] = 'Survey social'; -$string['indicator:socialbreadthdef_help'] = 'The participant has reached this percentage of the social engagement offered by the Survey activities during this analysis interval (Levels = No participation, Participant alone)'; -$string['indicator:socialbreadthdef_link'] = 'Learning_analytics_indicators#Social_breadth'; -$string['introtext'] = 'Introduction text'; -$string['invalidsurveyid'] = 'Survey ID was incorrect'; -$string['invalidtmptid'] = 'Invalid template id'; -$string['ipreferthat'] = 'I prefer that'; -$string['modulename'] = 'Survey'; -$string['modulename_help'] = 'The survey activity module provides a number of verified survey instruments that have been found useful in assessing and stimulating learning in online environments. A teacher can use these to gather data from their students that will help them learn about their class and reflect on their own teaching. - -Note that these survey tools are pre-populated with questions. Teachers who wish to create their own survey should use the feedback activity module.'; -$string['modulename_link'] = 'mod/survey/view'; -$string['modulenameplural'] = 'Surveys'; -$string['name'] = 'Name'; -$string['newsurveyresponses'] = 'New survey responses'; -$string['nobodyyet'] = 'Nobody has yet completed this survey'; -$string['notdone'] = 'Not done yet'; -$string['notes'] = 'Your private analysis and notes'; -$string['othercomments'] = 'Do you have any other comments?'; -$string['page-mod-survey-x'] = 'Any survey module page'; -$string['peoplecompleted'] = '{$a} people have completed this survey so far'; -$string['pluginadministration'] = 'Survey administration'; -$string['pluginname'] = 'Survey'; -$string['preferred'] = 'Preferred'; -$string['preferredclass'] = 'Class preferred'; -$string['preferredstudent'] = '{$a} preferred'; -$string['privacy:metadata:analysis'] = 'A record of survey answers analysis.'; -$string['privacy:metadata:analysis:notes'] = 'Notes saved against a user\'s answers.'; -$string['privacy:metadata:analysis:userid'] = 'The ID of the user answering the survey.'; -$string['privacy:metadata:answers'] = 'A collection of answers to surveys.'; -$string['privacy:metadata:answers:answer1'] = 'Field to store the answer to a question.'; -$string['privacy:metadata:answers:answer2'] = 'Additional field to store the answer to a question.'; -$string['privacy:metadata:answers:question'] = 'The question.'; -$string['privacy:metadata:answers:time'] = 'The time when the answer was posted.'; -$string['privacy:metadata:answers:userid'] = 'The ID of the user who submitted their answer.'; -$string['question'] = 'Question'; -$string['questions'] = 'Questions'; -$string['questionsnotanswered'] = 'Some of the multiple choice questions have not been answered.'; -$string['report'] = 'Survey report'; -$string['responsereports'] = 'Response reports'; -$string['responses'] = 'Responses'; -$string['savednotes'] = 'Your notes were saved'; -$string['scaleagree5'] = 'Strongly disagree,Somewhat disagree,Neither agree nor disagree,Somewhat agree,Strongly agree'; -$string['scales'] = 'Scales'; -$string['scaletimes5'] = 'Almost never,Seldom,Sometimes,Often,Almost always'; -$string['search:activity'] = 'Survey - activity information'; -$string['seemoredetail'] = 'Click here to see more detail'; -$string['selectedquestions'] = 'Selected questions from a scale, all students'; -$string['summary'] = 'Summary'; -$string['survey:addinstance'] = 'Add a new survey'; -$string['surveycompleted'] = 'You\'ve completed this survey. The graph below shows a summary of your results compared to the class averages.'; -$string['surveycompletednograph'] = 'You have completed this survey.'; -$string['survey:download'] = 'Download responses'; -$string['surveygraph'] = 'Survey graph'; -$string['surveyname'] = 'Survey name'; -$string['survey:participate'] = 'Respond to survey'; -$string['survey:readresponses'] = 'View responses'; -$string['surveysaved'] = 'Survey saved'; -$string['surveytype'] = 'Survey type'; -$string['surveytype_help'] = 'There are 3 available survey types: - -* Attitudes to Thinking and Learning Survey (ATTLS) - For measuring the extent to which a person is a \'connected knower\' (tends to find learning more enjoyable, and is often more cooperative, congenial and more willing to build on the ideas of others) or a \'separate knower\' (tends to take a more critical and argumentative stance to learning) -* Critical incidents survey -* Constructivist On-line Learning Environment Survey (COLLES) - For monitoring the extent to which the interactive capacity of the World Wide Web may be exploited for engaging students in dynamic learning practices'; -$string['surveytype_link'] = 'mod/survey/mod'; -$string['thanksforanswers'] = 'Thanks for answering this survey, {$a}'; -$string['time'] = 'Time'; -$string['notyetanswered'] = 'Not yet answered'; -$string['allquestionrequireanswer'] = 'All questions are required and must be answered.'; diff --git a/mod/survey/lib.php b/mod/survey/lib.php deleted file mode 100644 index 01bd5703599..00000000000 --- a/mod/survey/lib.php +++ /dev/null @@ -1,1193 +0,0 @@ -. - -/** - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Graph size - * @global int $SURVEY_GHEIGHT - */ -global $SURVEY_GHEIGHT; -$SURVEY_GHEIGHT = 500; -/** - * Graph size - * @global int $SURVEY_GWIDTH - */ -global $SURVEY_GWIDTH; -$SURVEY_GWIDTH = 900; -/** - * Question Type - * @global array $SURVEY_QTYPE - */ -global $SURVEY_QTYPE; -$SURVEY_QTYPE = array ( - "-3" => "Virtual Actual and Preferred", - "-2" => "Virtual Preferred", - "-1" => "Virtual Actual", - "0" => "Text", - "1" => "Actual", - "2" => "Preferred", - "3" => "Actual and Preferred", - ); - - -define("SURVEY_COLLES_ACTUAL", "1"); -define("SURVEY_COLLES_PREFERRED", "2"); -define("SURVEY_COLLES_PREFERRED_ACTUAL", "3"); -define("SURVEY_ATTLS", "4"); -define("SURVEY_CIQ", "5"); -// Question length to wrap. -define("SURVEY_QLENGTH_WRAP", "80"); - -require_once(__DIR__ . '/deprecatedlib.php'); - -// STANDARD FUNCTIONS //////////////////////////////////////////////////////// -/** - * Given an object containing all the necessary data, - * (defined by the form in mod_form.php) this function - * will create a new instance and return the id number - * of the new instance. - * - * @global object - * @param object $survey - * @return int|bool - */ -function survey_add_instance($survey) { - global $DB; - - if (!$template = $DB->get_record("survey", array("id"=>$survey->template))) { - return 0; - } - - $survey->questions = $template->questions; - $survey->timecreated = time(); - $survey->timemodified = $survey->timecreated; - - $id = $DB->insert_record("survey", $survey); - - $completiontimeexpected = !empty($survey->completionexpected) ? $survey->completionexpected : null; - \core_completion\api::update_completion_date_event($survey->coursemodule, 'survey', $id, $completiontimeexpected); - - return $id; - -} - -/** - * Given an object containing all the necessary data, - * (defined by the form in mod_form.php) this function - * will update an existing instance with new data. - * - * @global object - * @param object $survey - * @return bool - */ -function survey_update_instance($survey) { - global $DB; - - if (!$template = $DB->get_record("survey", array("id"=>$survey->template))) { - return 0; - } - - $survey->id = $survey->instance; - $survey->questions = $template->questions; - $survey->timemodified = time(); - - $completiontimeexpected = !empty($survey->completionexpected) ? $survey->completionexpected : null; - \core_completion\api::update_completion_date_event($survey->coursemodule, 'survey', $survey->id, $completiontimeexpected); - - return $DB->update_record("survey", $survey); -} - -/** - * Given an ID of an instance of this module, - * this function will permanently delete the instance - * and any data that depends on it. - * - * @global object - * @param int $id - * @return bool - */ -function survey_delete_instance($id) { - global $DB; - - if (! $survey = $DB->get_record("survey", array("id"=>$id))) { - return false; - } - - $cm = get_coursemodule_from_instance('survey', $id); - \core_completion\api::update_completion_date_event($cm->id, 'survey', $id, null); - - $result = true; - - if (! $DB->delete_records("survey_analysis", array("survey"=>$survey->id))) { - $result = false; - } - - if (! $DB->delete_records("survey_answers", array("survey"=>$survey->id))) { - $result = false; - } - - if (! $DB->delete_records("survey", array("id"=>$survey->id))) { - $result = false; - } - - return $result; -} - -/** - * @global object - * @param object $course - * @param object $user - * @param object $mod - * @param object $survey - * @return $result - */ -function survey_user_outline($course, $user, $mod, $survey) { - global $DB; - - if ($answers = $DB->get_records("survey_answers", array('survey'=>$survey->id, 'userid'=>$user->id))) { - $lastanswer = array_pop($answers); - - $result = new stdClass(); - $result->info = get_string("done", "survey"); - $result->time = $lastanswer->time; - return $result; - } - return NULL; -} - -/** - * @global stdObject - * @global object - * @uses SURVEY_CIQ - * @param object $course - * @param object $user - * @param object $mod - * @param object $survey - */ -function survey_user_complete($course, $user, $mod, $survey) { - global $CFG, $DB, $OUTPUT; - - if (survey_already_done($survey->id, $user->id)) { - if ($survey->template == SURVEY_CIQ) { // print out answers for critical incidents - $table = new html_table(); - $table->align = array("left", "left"); - - $questions = $DB->get_records_list("survey_questions", "id", explode(',', $survey->questions)); - $questionorder = explode(",", $survey->questions); - - foreach ($questionorder as $key=>$val) { - $question = $questions[$val]; - $questiontext = get_string($question->shorttext, "survey"); - - if ($answer = survey_get_user_answer($survey->id, $question->id, $user->id)) { - $answertext = "$answer->answer1"; - } else { - $answertext = "No answer"; - } - $table->data[] = array("$questiontext", s($answertext)); - } - echo html_writer::table($table); - - } else { - - survey_print_graph("id=$mod->id&sid=$user->id&type=student.png"); - } - - } else { - print_string("notdone", "survey"); - } -} - -/** - * @global stdClass - * @global object - * @param object $course - * @param mixed $viewfullnames - * @param int $timestamp - * @return bool - */ -function survey_print_recent_activity($course, $viewfullnames, $timestart) { - global $CFG, $DB, $OUTPUT; - - $modinfo = get_fast_modinfo($course); - $ids = array(); - foreach ($modinfo->cms as $cm) { - if ($cm->modname != 'survey') { - continue; - } - if (!$cm->uservisible) { - continue; - } - $ids[$cm->instance] = $cm->instance; - } - - if (!$ids) { - return false; - } - - $slist = implode(',', $ids); // there should not be hundreds of glossaries in one course, right? - - $userfieldsapi = \core_user\fields::for_userpic(); - $allusernames = $userfieldsapi->get_sql('u', false, '', '', false)->selects; - $rs = $DB->get_recordset_sql("SELECT sa.userid, sa.survey, MAX(sa.time) AS time, - $allusernames - FROM {survey_answers} sa - JOIN {user} u ON u.id = sa.userid - WHERE sa.survey IN ($slist) AND sa.time > ? - GROUP BY sa.userid, sa.survey, $allusernames - ORDER BY time ASC", array($timestart)); - if (!$rs->valid()) { - $rs->close(); // Not going to iterate (but exit), close rs - return false; - } - - $surveys = array(); - - foreach ($rs as $survey) { - $cm = $modinfo->instances['survey'][$survey->survey]; - $survey->name = $cm->name; - $survey->cmid = $cm->id; - $surveys[] = $survey; - } - $rs->close(); - - if (!$surveys) { - return false; - } - - echo $OUTPUT->heading(get_string('newsurveyresponses', 'survey') . ':', 6); - foreach ($surveys as $survey) { - $url = $CFG->wwwroot.'/mod/survey/view.php?id='.$survey->cmid; - print_recent_activity_note($survey->time, $survey, $survey->name, $url, false, $viewfullnames); - } - - return true; -} - -// SQL FUNCTIONS //////////////////////////////////////////////////////// - -/** - * @global object - * @param sting $log - * @return array - */ -function survey_log_info($log) { - global $DB; - return $DB->get_record_sql("SELECT s.name, u.firstname, u.lastname, u.picture - FROM {survey} s, {user} u - WHERE s.id = ? AND u.id = ?", array($log->info, $log->userid)); -} - -/** - * @global object - * @param int $surveyid - * @param int $groupid - * @param int $groupingid - * @return array - */ -function survey_get_responses($surveyid, $groupid, $groupingid) { - global $DB; - - $params = array('surveyid'=>$surveyid, 'groupid'=>$groupid, 'groupingid'=>$groupingid); - - if ($groupid) { - $groupsjoin = "JOIN {groups_members} gm ON u.id = gm.userid AND gm.groupid = :groupid "; - - } else if ($groupingid) { - $groupsjoin = "JOIN {groups_members} gm ON u.id = gm.userid - JOIN {groupings_groups} gg ON gm.groupid = gg.groupid AND gg.groupingid = :groupingid "; - } else { - $groupsjoin = ""; - } - - $userfieldsapi = \core_user\fields::for_userpic(); - $userfields = $userfieldsapi->get_sql('u', false, '', '', false)->selects; - return $DB->get_records_sql("SELECT $userfields, MAX(a.time) as time - FROM {survey_answers} a - JOIN {user} u ON a.userid = u.id - $groupsjoin - WHERE a.survey = :surveyid - GROUP BY $userfields - ORDER BY time ASC", $params); -} - -/** - * @global object - * @param int $survey - * @param int $user - * @return array - */ -function survey_get_analysis($survey, $user) { - global $DB; - - return $DB->get_record_sql("SELECT notes - FROM {survey_analysis} - WHERE survey=? AND userid=?", array($survey, $user)); -} - -/** - * @global object - * @param int $survey - * @param int $user - * @param string $notes - */ -function survey_update_analysis($survey, $user, $notes) { - global $DB; - - return $DB->execute("UPDATE {survey_analysis} - SET notes=? - WHERE survey=? - AND userid=?", array($notes, $survey, $user)); -} - -/** - * @global object - * @param int $surveyid - * @param int $groupid - * @param string $sort - * @return array - */ -function survey_get_user_answers($surveyid, $questionid, $groupid, $sort="sa.answer1,sa.answer2 ASC") { - global $DB; - - $params = array('surveyid'=>$surveyid, 'questionid'=>$questionid); - - if ($groupid) { - $groupfrom = ', {groups_members} gm'; - $groupsql = 'AND gm.groupid = :groupid AND u.id = gm.userid'; - $params['groupid'] = $groupid; - } else { - $groupfrom = ''; - $groupsql = ''; - } - - $userfieldsapi = \core_user\fields::for_userpic(); - $userfields = $userfieldsapi->get_sql('u', false, '', '', false)->selects; - return $DB->get_records_sql("SELECT sa.*, $userfields - FROM {survey_answers} sa, {user} u $groupfrom - WHERE sa.survey = :surveyid - AND sa.question = :questionid - AND u.id = sa.userid $groupsql - ORDER BY $sort", $params); -} - -/** - * @global object - * @param int $surveyid - * @param int $questionid - * @param int $userid - * @return stdClass|false - */ -function survey_get_user_answer($surveyid, $questionid, $userid) { - global $DB; - - return $DB->get_record_sql("SELECT sa.* - FROM {survey_answers} sa - WHERE sa.survey = ? - AND sa.question = ? - AND sa.userid = ?", array($surveyid, $questionid, $userid)); -} - -// MODULE FUNCTIONS //////////////////////////////////////////////////////// -/** - * @global object - * @param int $survey - * @param int $user - * @param string $notes - * @return bool|int - */ -function survey_add_analysis($survey, $user, $notes) { - global $DB; - - $record = new stdClass(); - $record->survey = $survey; - $record->userid = $user; - $record->notes = $notes; - - return $DB->insert_record("survey_analysis", $record, false); -} -/** - * @global object - * @param int $survey - * @param int $user - * @return bool - */ -function survey_already_done($survey, $user) { - global $DB; - - return $DB->record_exists("survey_answers", array("survey"=>$survey, "userid"=>$user)); -} -/** - * @param int $surveyid - * @param int $groupid - * @param int $groupingid - * @return int - */ -function survey_count_responses($surveyid, $groupid, $groupingid) { - if ($responses = survey_get_responses($surveyid, $groupid, $groupingid)) { - return count($responses); - } else { - return 0; - } -} - -/** - * @param int $cmid - * @param array $results - * @param int $courseid - */ -function survey_print_all_responses($cmid, $results, $courseid) { - global $OUTPUT; - $table = new html_table(); - $table->head = array ("", get_string("name"), get_string("time")); - $table->align = array ("", "left", "left"); - $table->size = array (35, "", "" ); - - foreach ($results as $a) { - $table->data[] = array($OUTPUT->user_picture($a, array('courseid'=>$courseid)), - html_writer::link("report.php?action=student&student=$a->id&id=$cmid", fullname($a)), - userdate($a->time)); - } - - echo html_writer::table($table); -} - -/** - * @global object - * @param int $templateid - * @return string - */ -function survey_get_template_name($templateid) { - global $DB; - - if ($templateid) { - if ($ss = $DB->get_record("surveys", array("id"=>$templateid))) { - return $ss->name; - } - } else { - return ""; - } -} - - -/** - * @param string $name - * @param array $numwords - * @return string - */ -function survey_shorten_name ($name, $numwords) { - $words = explode(" ", $name); - $output = ''; - for ($i=0; $i < $numwords; $i++) { - $output .= $words[$i]." "; - } - return $output; -} - -/** - * @todo Check this function - * - * @global object - * @global object - * @global int - * @global void This is never defined - * @global object This is defined twice? - * @param object $question - */ -function survey_print_multi($question) { - global $USER, $DB, $qnum, $DB, $OUTPUT; //TODO: this is sloppy globals abuse - - $stripreferthat = get_string("ipreferthat", "survey"); - $strifoundthat = get_string("ifoundthat", "survey"); - $strdefault = get_string('notyetanswered', 'survey'); - $strresponses = get_string('responses', 'survey'); - - echo $OUTPUT->heading($question->text, 3); - echo "\n"; - - $options = explode( ",", $question->options); - $numoptions = count($options); - - // COLLES Actual (which is having questions of type 1) and COLLES Preferred (type 2) - // expect just one answer per question. COLLES Actual and Preferred (type 3) expects - // two answers per question. ATTLS (having a single question of type 1) expects one - // answer per question. CIQ is not using multiquestions (i.e. a question with subquestions). - // Note that the type of subquestions does not really matter, it's the type of the - // question itself that determines everything. - $oneanswer = ($question->type == 1 || $question->type == 2) ? true : false; - - // COLLES Preferred (having questions of type 2) will use the radio elements with the name - // like qP1, qP2 etc. COLLES Actual and ATTLS have radios like q1, q2 etc. - if ($question->type == 2) { - $P = "P"; - } else { - $P = ""; - } - - echo ""; - echo ""; - echo ""; - foreach ($options as $key => $val) { - echo "\n"; - } - echo "\n"; - - echo "\n"; - - $subquestions = survey_get_subquestions($question); - - foreach ($subquestions as $q) { - $qnum++; - if ($oneanswer) { - $rowclass = survey_question_rowclass($qnum); - } else { - $rowclass = survey_question_rowclass(round($qnum / 2)); - } - if ($q->text) { - $q->text = get_string($q->text, "survey"); - } - - echo ""; - if ($oneanswer) { - echo "\n"; - - $default = get_accesshide($strdefault); - echo ""; - - for ($i=1;$i<=$numoptions;$i++) { - $hiddentext = get_accesshide($options[$i-1]); - $id = "q$P" . $q->id . "_$i"; - echo ""; - } - } else { - echo "\n"; - - $default = get_accesshide($strdefault); - echo ''; - - - for ($i=1;$i<=$numoptions;$i++) { - $hiddentext = get_accesshide($options[$i-1]); - $id = "qP" . $q->id . "_$i"; - echo ""; - } - echo ""; - - echo ""; - echo "\n"; - - $default = get_accesshide($strdefault); - echo ''; - - for ($i=1;$i<=$numoptions;$i++) { - $hiddentext = get_accesshide($options[$i-1]); - $id = "q" . $q->id . "_$i"; - echo ""; - } - } - echo "\n"; - } - echo "
$strresponses". get_string('notyetanswered', 'survey'). "$val
$question->intro
"; - echo "$qnum   "; - echo $q->text .""; - echo "$qnum   "; - $qnum++; - echo "$stripreferthat   "; - echo "$q->text
"; - echo "$qnum   "; - echo "$strifoundthat   "; - echo "$q->text
"; -} - - -/** - * @global object - * @global int - * @param object $question - */ -function survey_print_single($question) { - global $DB, $qnum, $OUTPUT; - - $rowclass = survey_question_rowclass(0); - - $qnum++; - - echo "
\n"; - echo "\n"; - echo ""; - echo "\n"; - echo "
\n"; - - - if ($question->type == 0) { // Plain text field - echo ""; - - } else if ($question->type > 0) { // Choose one of a number - $strchoose = get_string("choose"); - echo ""; - - } else if ($question->type < 0) { // Choose several of a number - $options = explode( ",", $question->options); - echo $OUTPUT->notification("This question type not supported yet"); - } - - echo "
"; - -} - -/** - * - * @param int $qnum - * @return string - */ -function survey_question_rowclass($qnum) { - - if ($qnum) { - return $qnum % 2 ? 'r0' : 'r1'; - } else { - return 'r0'; - } -} - -/** - * @global object - * @global int - * @global int - * @param string $url - */ -function survey_print_graph($url) { - global $CFG, $SURVEY_GHEIGHT, $SURVEY_GWIDTH; - - echo "wwwroot/mod/survey/graph.php?$url\" alt=\"".get_string("surveygraph", "survey")."\" />"; -} - -/** - * List the actions that correspond to a view of this module. - * This is used by the participation report. - * - * Note: This is not used by new logging system. Event with - * crud = 'r' and edulevel = LEVEL_PARTICIPATING will - * be considered as view action. - * - * @return array - */ -function survey_get_view_actions() { - return array('download','view all','view form','view graph','view report'); -} - -/** - * List the actions that correspond to a post of this module. - * This is used by the participation report. - * - * Note: This is not used by new logging system. Event with - * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING - * will be considered as post action. - * - * @return array - */ -function survey_get_post_actions() { - return array('submit'); -} - - -/** - * Implementation of the function for printing the form elements that control - * whether the course reset functionality affects the survey. - * - * @param MoodleQuickForm $mform form passed by reference - */ -function survey_reset_course_form_definition(&$mform) { - $mform->addElement('header', 'surveyheader', get_string('modulenameplural', 'survey')); - $mform->addElement('static', 'surveydelete', get_string('delete')); - $mform->addElement('checkbox', 'reset_survey_answers', get_string('deleteallanswers', 'survey')); - $mform->addElement('checkbox', 'reset_survey_analysis', get_string('deleteanalysis', 'survey')); - $mform->hideIf('reset_survey_analysis', 'reset_survey_answers', 'checked'); -} - -/** - * Course reset form defaults. - * @return array - */ -function survey_reset_course_form_defaults($course) { - return array('reset_survey_answers'=>1, 'reset_survey_analysis'=>1); -} - -/** - * Actual implementation of the reset course functionality, delete all the - * survey responses for course $data->courseid. - * - * @global object - * @param $data the data submitted from the reset course. - * @return array status array - */ -function survey_reset_userdata($data) { - global $DB; - - $componentstr = get_string('modulenameplural', 'survey'); - $status = array(); - - $surveyssql = "SELECT ch.id - FROM {survey} ch - WHERE ch.course=?"; - $params = array($data->courseid); - - if (!empty($data->reset_survey_answers)) { - $DB->delete_records_select('survey_answers', "survey IN ($surveyssql)", $params); - $DB->delete_records_select('survey_analysis', "survey IN ($surveyssql)", $params); - $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallanswers', 'survey'), 'error'=>false); - } - - if (!empty($data->reset_survey_analysis)) { - $DB->delete_records_select('survey_analysis', "survey IN ($surveyssql)", $params); - $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallanswers', 'survey'), 'error'=>false); - } - - // No date shifting. - // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. - // See MDL-9367. - - return $status; -} - -/** - * @uses FEATURE_GROUPS - * @uses FEATURE_GROUPINGS - * @uses FEATURE_MOD_INTRO - * @uses FEATURE_COMPLETION_TRACKS_VIEWS - * @uses FEATURE_GRADE_HAS_GRADE - * @uses FEATURE_GRADE_OUTCOMES - * @param string $feature FEATURE_xx constant for requested feature - * @return mixed True if module supports feature, false if not, null if doesn't know or string for the module purpose. - */ -function survey_supports($feature) { - switch($feature) { - case FEATURE_GROUPS: return true; - case FEATURE_GROUPINGS: return true; - case FEATURE_MOD_INTRO: return true; - case FEATURE_COMPLETION_TRACKS_VIEWS: return true; - case FEATURE_COMPLETION_HAS_RULES: return true; - case FEATURE_GRADE_HAS_GRADE: return false; - case FEATURE_GRADE_OUTCOMES: return false; - case FEATURE_BACKUP_MOODLE2: return true; - case FEATURE_SHOW_DESCRIPTION: return true; - case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_COMMUNICATION; - - default: return null; - } -} - -/** - * This function extends the settings navigation block for the site. - * - * It is safe to rely on PAGE here as we will only ever be within the module - * context when this is called - * - * @param settings_navigation $settings - * @param navigation_node $surveynode - */ -function survey_extend_settings_navigation(settings_navigation $settings, navigation_node $surveynode) { - global $DB; - - $cm = get_coursemodule_from_id('survey', $settings->get_page()->cm->id); - $context = context_module::instance($cm->id); - - // Check to see if groups are being used in this survey, confirm user can access. - $groupmode = groups_get_activity_groupmode($cm); - $currentgroup = groups_get_activity_group($cm, true); - - if (has_capability('mod/survey:readresponses', $context) && - !($currentgroup === 0 && $groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context))) { - - $survey = $DB->get_record("survey", ["id" => $cm->instance]); - $url = new moodle_url('/mod/survey/report.php', ['id' => $cm->id]); - if ($survey && ($survey->template != SURVEY_CIQ)) { - $url->param('action', 'summary'); - } else { - $url->param('action', 'questions'); - } - $surveynode->add(get_string("responsereports", "survey"), $url); - } -} - -/** - * Return a list of page types - * @param string $pagetype current page type - * @param stdClass $parentcontext Block's parent context - * @param stdClass $currentcontext Current context of block - */ -function survey_page_type_list($pagetype, $parentcontext, $currentcontext) { - $module_pagetype = array('mod-survey-*'=>get_string('page-mod-survey-x', 'survey')); - return $module_pagetype; -} - -/** - * Mark the activity completed (if required) and trigger the course_module_viewed event. - * - * @param stdClass $survey survey object - * @param stdClass $course course object - * @param stdClass $cm course module object - * @param stdClass $context context object - * @param string $viewed which page viewed - * @since Moodle 3.0 - */ -function survey_view($survey, $course, $cm, $context, $viewed) { - - // Trigger course_module_viewed event. - $params = array( - 'context' => $context, - 'objectid' => $survey->id, - 'courseid' => $course->id, - 'other' => array('viewed' => $viewed) - ); - - $event = \mod_survey\event\course_module_viewed::create($params); - $event->add_record_snapshot('course_modules', $cm); - $event->add_record_snapshot('course', $course); - $event->add_record_snapshot('survey', $survey); - $event->trigger(); - - // Completion. - $completion = new completion_info($course); - $completion->set_module_viewed($cm); -} - -/** - * Helper function for ordering a set of questions by the given ids. - * - * @param array $questions array of questions objects - * @param array $questionorder array of questions ids indicating the correct order - * @return array list of questions ordered - * @since Moodle 3.0 - */ -function survey_order_questions($questions, $questionorder) { - - $finalquestions = array(); - foreach ($questionorder as $qid) { - $finalquestions[] = $questions[$qid]; - } - return $finalquestions; -} - -/** - * Translate the question texts and options. - * - * @param stdClass $question question object - * @return stdClass question object with all the text fields translated - * @since Moodle 3.0 - */ -function survey_translate_question($question) { - - if ($question->text) { - $question->text = get_string($question->text, "survey"); - } - - if ($question->shorttext) { - $question->shorttext = get_string($question->shorttext, "survey"); - } - - if ($question->intro) { - $question->intro = get_string($question->intro, "survey"); - } - - if ($question->options) { - $question->options = get_string($question->options, "survey"); - } - return $question; -} - -/** - * Returns the questions for a survey (ordered). - * - * @param stdClass $survey survey object - * @return array list of questions ordered - * @since Moodle 3.0 - * @throws moodle_exception - */ -function survey_get_questions($survey) { - global $DB; - - $questionids = explode(',', $survey->questions); - if (! $questions = $DB->get_records_list("survey_questions", "id", $questionids)) { - throw new moodle_exception('cannotfindquestion', 'survey'); - } - - return survey_order_questions($questions, $questionids); -} - -/** - * Returns subquestions for a given question (ordered). - * - * @param stdClass $question questin object - * @return array list of subquestions ordered - * @since Moodle 3.0 - */ -function survey_get_subquestions($question) { - global $DB; - - $questionids = explode(',', $question->multi); - $questions = $DB->get_records_list("survey_questions", "id", $questionids); - - return survey_order_questions($questions, $questionids); -} - -/** - * Save the answer for the given survey - * - * @param stdClass $survey a survey object - * @param array $answersrawdata the answers to be saved - * @param stdClass $course a course object (required for trigger the submitted event) - * @param stdClass $context a context object (required for trigger the submitted event) - * @since Moodle 3.0 - */ -function survey_save_answers($survey, $answersrawdata, $course, $context) { - global $DB, $USER; - - $answers = array(); - - // Sort through the data and arrange it. - // This is necessary because some of the questions may have two answers, eg Question 1 -> 1 and P1. - foreach ($answersrawdata as $key => $val) { - if ($key != "userid" && $key != "id") { - if (substr($key, 0, 1) == "q") { - $key = clean_param(substr($key, 1), PARAM_ALPHANUM); // Keep everything but the 'q', number or P number. - } - if (substr($key, 0, 1) == "P") { - $realkey = (int) substr($key, 1); - $answers[$realkey][1] = $val; - } else { - $answers[$key][0] = $val; - } - } - } - - // Now store the data. - $timenow = time(); - $answerstoinsert = array(); - foreach ($answers as $key => $val) { - if ($key != 'sesskey') { - $newdata = new stdClass(); - $newdata->time = $timenow; - $newdata->userid = $USER->id; - $newdata->survey = $survey->id; - $newdata->question = $key; - if (!empty($val[0])) { - $newdata->answer1 = $val[0]; - } else { - $newdata->answer1 = ""; - } - if (!empty($val[1])) { - $newdata->answer2 = $val[1]; - } else { - $newdata->answer2 = ""; - } - - $answerstoinsert[] = $newdata; - } - } - - if (!empty($answerstoinsert)) { - $DB->insert_records("survey_answers", $answerstoinsert); - } - - // Update completion state. - $cm = get_coursemodule_from_instance('survey', $survey->id, $course->id); - $completion = new completion_info($course); - if (isloggedin() && !isguestuser() && $completion->is_enabled($cm) && $survey->completionsubmit) { - $completion->update_state($cm, COMPLETION_COMPLETE); - } - - $params = array( - 'context' => $context, - 'courseid' => $course->id, - 'other' => array('surveyid' => $survey->id) - ); - $event = \mod_survey\event\response_submitted::create($params); - $event->trigger(); -} - -/** - * Check if the module has any update that affects the current user since a given time. - * - * @param cm_info $cm course module data - * @param int $from the time to check updates from - * @param array $filter if we need to check only specific updates - * @return stdClass an object with the different type of areas indicating if they were updated or not - * @since Moodle 3.2 - */ -function survey_check_updates_since(cm_info $cm, $from, $filter = array()) { - global $DB, $USER; - - $updates = new stdClass(); - if (!has_capability('mod/survey:participate', $cm->context)) { - return $updates; - } - $updates = course_check_module_updates_since($cm, $from, array(), $filter); - - $updates->answers = (object) array('updated' => false); - $select = 'survey = ? AND userid = ? AND time > ?'; - $params = array($cm->instance, $USER->id, $from); - $answers = $DB->get_records_select('survey_answers', $select, $params, '', 'id'); - if (!empty($answers)) { - $updates->answers->updated = true; - $updates->answers->itemids = array_keys($answers); - } - - // Now, teachers should see other students updates. - if (has_capability('mod/survey:readresponses', $cm->context)) { - $select = 'survey = ? AND time > ?'; - $params = array($cm->instance, $from); - - if (groups_get_activity_groupmode($cm) == SEPARATEGROUPS) { - $groupusers = array_keys(groups_get_activity_shared_group_members($cm)); - if (empty($groupusers)) { - return $updates; - } - list($insql, $inparams) = $DB->get_in_or_equal($groupusers); - $select .= ' AND userid ' . $insql; - $params = array_merge($params, $inparams); - } - - $updates->useranswers = (object) array('updated' => false); - $answers = $DB->get_records_select('survey_answers', $select, $params, '', 'id'); - if (!empty($answers)) { - $updates->useranswers->updated = true; - $updates->useranswers->itemids = array_keys($answers); - } - } - return $updates; -} - -/** - * This function receives a calendar event and returns the action associated with it, or null if there is none. - * - * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event - * is not displayed on the block. - * - * @param calendar_event $event - * @param \core_calendar\action_factory $factory - * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). - * @return \core_calendar\local\event\entities\action_interface|null - */ -function mod_survey_core_calendar_provide_event_action(calendar_event $event, - \core_calendar\action_factory $factory, - int $userid = 0) { - global $USER; - - if (empty($userid)) { - $userid = $USER->id; - } - - $cm = get_fast_modinfo($event->courseid, $userid)->instances['survey'][$event->instance]; - $context = context_module::instance($cm->id); - - if (!has_capability('mod/survey:participate', $context, $userid)) { - return null; - } - - $completion = new \completion_info($cm->get_course()); - - $completiondata = $completion->get_data($cm, false, $userid); - - if ($completiondata->completionstate != COMPLETION_INCOMPLETE) { - return null; - } - - return $factory->create_instance( - get_string('view'), - new \moodle_url('/mod/survey/view.php', ['id' => $cm->id]), - 1, - true - ); -} - -/** - * Add a get_coursemodule_info function in case any survey type wants to add 'extra' information - * for the course (see resource). - * - * Given a course_module object, this function returns any "extra" information that may be needed - * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. - * - * @param stdClass $coursemodule The coursemodule object (record). - * @return cached_cm_info An object on information that the courses - * will know about (most noticeably, an icon). - */ -function survey_get_coursemodule_info($coursemodule) { - global $DB; - - $dbparams = ['id' => $coursemodule->instance]; - $fields = 'id, name, intro, introformat, completionsubmit'; - if (!$survey = $DB->get_record('survey', $dbparams, $fields)) { - return false; - } - - $result = new cached_cm_info(); - $result->name = $survey->name; - - if ($coursemodule->showdescription) { - // Convert intro to html. Do not filter cached version, filters run at display time. - $result->content = format_module_intro('survey', $survey, $coursemodule->id, false); - } - - // Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'. - if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) { - $result->customdata['customcompletionrules']['completionsubmit'] = $survey->completionsubmit; - } - - return $result; -} - -/** - * Callback which returns human-readable strings describing the active completion custom rules for the module instance. - * - * @param cm_info|stdClass $cm object with fields ->completion and ->customdata['customcompletionrules'] - * @return array $descriptions the array of descriptions for the custom rules. - */ -function mod_survey_get_completion_active_rule_descriptions($cm) { - // Values will be present in cm_info, and we assume these are up to date. - if (empty($cm->customdata['customcompletionrules']) - || $cm->completion != COMPLETION_TRACKING_AUTOMATIC) { - return []; - } - - $descriptions = []; - foreach ($cm->customdata['customcompletionrules'] as $key => $val) { - switch ($key) { - case 'completionsubmit': - if (!empty($val)) { - $descriptions[] = get_string('completionsubmit', 'survey'); - } - break; - default: - break; - } - } - return $descriptions; -} diff --git a/mod/survey/mod_form.php b/mod/survey/mod_form.php deleted file mode 100644 index 3578829ae3c..00000000000 --- a/mod/survey/mod_form.php +++ /dev/null @@ -1,93 +0,0 @@ -dirroot.'/course/moodleform_mod.php'); - -class mod_survey_mod_form extends moodleform_mod { - - function definition() { - global $CFG, $DB; - - $mform =& $this->_form; - - $strrequired = get_string('required'); - -//------------------------------------------------------------------------------- - $mform->addElement('header', 'general', get_string('general', 'form')); - - $mform->addElement('text', 'name', get_string('name'), array('size'=>'64')); - if (!empty($CFG->formatstringstriptags)) { - $mform->setType('name', PARAM_TEXT); - } else { - $mform->setType('name', PARAM_CLEANHTML); - } - $mform->addRule('name', null, 'required', null, 'client'); - - if (!$options = $DB->get_records_menu("survey", array("template"=>0), "name", "id, name")) { - throw new \moodle_exception('cannotfindsurveytmpt', 'survey'); - } - - foreach ($options as $id => $name) { - $options[$id] = get_string($name, "survey"); - } - $options = array(''=>get_string('choose').'...') + $options; - $mform->addElement('select', 'template', get_string("surveytype", "survey"), $options); - $mform->addRule('template', $strrequired, 'required', null, 'client'); - $mform->addHelpButton('template', 'surveytype', 'survey'); - - $this->standard_intro_elements(get_string('customintro', 'survey')); - - $this->standard_coursemodule_elements(); - -//------------------------------------------------------------------------------- - // buttons - $this->add_action_buttons(); - } - - /** - * Allows module to modify the data returned by form get_data(). - * This method is also called in the bulk activity completion form. - * - * Only available on moodleform_mod. - * - * @param stdClass $data the form data to be modified. - */ - public function data_postprocessing($data) { - parent::data_postprocessing($data); - if (!empty($data->completionunlocked)) { - // Turn off completion settings if the checkboxes aren't ticked. - $suffix = $this->get_suffix(); - $completion = $data->{'completion' . $suffix}; - $autocompletion = !empty($completion) && $completion == COMPLETION_TRACKING_AUTOMATIC; - if (!$autocompletion || empty($data->{'completionsubmit' . $suffix})) { - $data->{'completionsubmit' . $suffix} = 0; - } - } - } - - /** - * Add completion rules to form. - * @return array - */ - public function add_completion_rules() { - $mform =& $this->_form; - $suffix = $this->get_suffix(); - $completionsubmitel = 'completionsubmit' . $suffix; - $mform->addElement('checkbox', $completionsubmitel, '', get_string('completionsubmit', 'survey')); - // Enable this completion rule by default. - $mform->setDefault($completionsubmitel, 1); - return [$completionsubmitel]; - } - - /** - * Enable completion rules - * @param array $data - * @return bool - */ - public function completion_rule_enabled($data) { - $suffix = $this->get_suffix(); - return !empty($data['completionsubmit' . $suffix]); - } -} diff --git a/mod/survey/pix/monologo.svg b/mod/survey/pix/monologo.svg deleted file mode 100644 index 6c426dd0a14..00000000000 --- a/mod/survey/pix/monologo.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/mod/survey/renderer.php b/mod/survey/renderer.php deleted file mode 100644 index 3c2fd6b9938..00000000000 --- a/mod/survey/renderer.php +++ /dev/null @@ -1,39 +0,0 @@ -. - -/** - * Output the actionbar for this activity. - * - * @package mod_survey - * @copyright 2021 Sujith Haridasan - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Renderer for the mod_survey tertiary nav - */ -class mod_survey_renderer extends plugin_renderer_base { - - /** - * Renders the action bar for the mod_survey report page. - * - * @param \mod_survey\output\actionbar $actionbar Data for the template - * @return bool|string rendered HTML string from the template. - */ - public function response_actionbar(\mod_survey\output\actionbar $actionbar) { - return $this->render_from_template('mod_survey/response_action_bar', $actionbar->export_for_template($this)); - } -} diff --git a/mod/survey/report.php b/mod/survey/report.php deleted file mode 100644 index a8eda86d111..00000000000 --- a/mod/survey/report.php +++ /dev/null @@ -1,526 +0,0 @@ -. - -/** - * This file is responsible for producing the survey reports - * - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -require_once("../../config.php"); -require_once("lib.php"); - -// Check that all the parameters have been provided. - -$id = required_param('id', PARAM_INT); // Course Module ID. -$action = optional_param('action', '', PARAM_ALPHA); // What to look at. -$qid = optional_param('qid', 0, PARAM_RAW); // Question IDs comma-separated list. -$student = optional_param('student', 0, PARAM_INT); // Student ID. -$notes = optional_param('notes', '', PARAM_RAW); // Save teachers notes. - -$qids = explode(',', $qid); -$qids = clean_param_array($qids, PARAM_INT); -$qid = implode(',', $qids); - -if (!$cm = get_coursemodule_from_id('survey', $id)) { - throw new moodle_exception('invalidcoursemodule'); -} - -if (!$course = $DB->get_record("course", array("id" => $cm->course))) { - throw new moodle_exception('coursemisconf'); -} - -$url = new moodle_url('/mod/survey/report.php', array('id' => $id)); -if ($action !== '') { - $url->param('action', $action); -} -if ($qid !== 0) { - $url->param('qid', $qid); -} -if ($student !== 0) { - $url->param('student', $student); -} -if ($notes !== '') { - $url->param('notes', $notes); -} -$PAGE->set_url($url); - -require_login($course, false, $cm); - -$context = context_module::instance($cm->id); - -require_capability('mod/survey:readresponses', $context); - -if (!$survey = $DB->get_record("survey", array("id" => $cm->instance))) { - throw new moodle_exception('invalidsurveyid', 'survey'); -} - -if (!$template = $DB->get_record("survey", array("id" => $survey->template))) { - throw new moodle_exception('invalidtmptid', 'survey'); -} - -$showscales = ($template->name != 'ciqname'); - -$strreport = get_string("report", "survey"); -$strsurvey = get_string("modulename", "survey"); -$strsurveys = get_string("modulenameplural", "survey"); -$strsummary = get_string("summary", "survey"); -$strscales = get_string("scales", "survey"); -$strquestion = get_string("question", "survey"); -$strquestions = get_string("questions", "survey"); -$strdownload = get_string("download", "survey"); -$strallscales = get_string("allscales", "survey"); -$strselectedquestions = get_string("selectedquestions", "survey"); -$strseemoredetail = get_string("seemoredetail", "survey"); -$strnotes = get_string("notes", "survey"); - -$PAGE->set_title("$course->shortname: " . format_string($survey->name)); -$PAGE->set_heading($course->fullname); -$PAGE->activityheader->set_attrs([ - 'hidecompletion' => true, - 'description' => '' -]); - -// Activate the secondary nav tab. -navigation_node::override_active_url(new moodle_url('/mod/survey/report.php', ['id' => $id, 'action' => 'summary'])); - -$actionbar = new \mod_survey\output\actionbar($id, $action, $url); -echo $OUTPUT->header(); -$renderer = $PAGE->get_renderer('mod_survey'); -echo $renderer->response_actionbar($actionbar); - -// Check to see if groups are being used in this survey. -$groupmode = groups_get_activity_groupmode($cm); -if ($groupmode != NOGROUPS) { - $menuaction = $action == "student" ? "students" : $action; - - // Get the current activity group, confirm user can access. - $currentgroup = groups_get_activity_group($cm, true); - if ($currentgroup === 0 && $groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) { - throw new moodle_exception('notingroup'); - } - - $groupsactivitymenu = groups_print_activity_menu($cm, new moodle_url('/mod/survey/report.php', - ['id' => $cm->id, 'action' => $menuaction, 'qid' => $qid]), true); -} else { - $currentgroup = 0; - $groupsactivitymenu = null; -} - -$params = array( - 'objectid' => $survey->id, - 'context' => $context, - 'courseid' => $course->id, - 'relateduserid' => $student, - 'other' => array('action' => $action, 'groupid' => $currentgroup) -); -$event = \mod_survey\event\report_viewed::create($params); -$event->trigger(); - -if ($currentgroup) { - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', $currentgroup, null, false); -} else if (!empty($cm->groupingid)) { - $groups = groups_get_all_groups($courseid, 0, $cm->groupingid); - $groups = array_keys($groups); - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', $groups, null, false); -} else { - $users = get_users_by_capability($context, 'mod/survey:participate', '', '', '', '', '', null, false); - $group = false; -} - -$groupingid = $cm->groupingid; - -// Print the menu across the top. - -$virtualscales = false; - -switch ($action) { - - case "summary": - // If survey type is Critical incidents then we don't show summary report. - if ($survey->template == SURVEY_CIQ) { - throw new moodle_exception('cannotviewreport'); - } - echo $OUTPUT->heading($strsummary, 3); - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - if (survey_count_responses($survey->id, $currentgroup, $groupingid)) { - echo ""; - } else { - echo $OUTPUT->notification(get_string("nobodyyet", "survey"), 'info', false); - } - break; - - case "scales": - // If survey type is Critical incidents then we don't show scales report. - if ($survey->template == SURVEY_CIQ) { - throw new moodle_exception('cannotviewreport'); - } - echo $OUTPUT->heading($strscales, 3); - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - if (!$results = survey_get_responses($survey->id, $currentgroup, $groupingid)) { - echo $OUTPUT->notification(get_string("nobodyyet", "survey"), 'info', false); - - } else { - - $questions = $DB->get_records_list("survey_questions", "id", explode(',', $survey->questions)); - $questionorder = explode(",", $survey->questions); - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - if ($question->type < 0) { // We have some virtual scales. Just show them. - $virtualscales = true; - break; - } - } - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - if ($question->multi) { - if (!empty($virtualscales) && $question->type > 0) { // Don't show non-virtual scales if virtual. - continue; - } - echo "

multi\">"; - survey_print_graph("id=$id&qid=$question->id&group=$currentgroup&type=multiquestion.png"); - echo "


"; - } - } - } - - break; - - case "questions": - - if ($qid) { // Just get one multi-question. - $questions = $DB->get_records_select("survey_questions", "id in ($qid)"); - $questionorder = explode(",", $qid); - - if ($scale = $DB->get_records("survey_questions", array("multi" => $qid))) { - $scale = array_pop($scale); - echo $OUTPUT->heading("$scale->text - $strselectedquestions", 3); - } else { - echo $OUTPUT->heading($strselectedquestions, 3); - } - - } else { // Get all top-level questions. - $questions = $DB->get_records_list("survey_questions", "id", explode(',', $survey->questions)); - $questionorder = explode(",", $survey->questions); - - echo $OUTPUT->heading($strquestions, 3); - } - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - if (!$results = survey_get_responses($survey->id, $currentgroup, $groupingid)) { - echo $OUTPUT->notification(get_string("nobodyyet", "survey"), 'info', false); - - } else { - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - if ($question->type < 0) { // We have some virtual scales. DON'T show them. - $virtualscales = true; - break; - } - } - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - - if ($question->type < 0) { // We have some virtual scales. DON'T show them. - continue; - } - $question->text = get_string($question->text, "survey"); - - if ($question->multi) { - echo $OUTPUT->heading($question->text . ':', 4); - - $subquestions = survey_get_subquestions($question); - foreach ($subquestions as $subquestion) { - if ($subquestion->type > 0) { - echo "

"; - echo "id\">"; - survey_print_graph("id=$id&qid=$subquestion->id&group=$currentgroup&type=question.png"); - echo "

"; - } - } - } else if ($question->type > 0) { - echo "

"; - echo "id\">"; - survey_print_graph("id=$id&qid=$question->id&group=$currentgroup&type=question.png"); - echo "

"; - - } else { - $table = new html_table(); - $table->head = array($question->text); - $table->align = array("left"); - - $contents = ''; - - if ($aaa = survey_get_user_answers($survey->id, $question->id, $currentgroup, "sa.time ASC")) { - foreach ($aaa as $a) { - $contents .= ""; - $contents .= ''; - $contents .= ''; - $contents .= ""; - } - } - $contents .= "
' . fullname($a) . '' . s($a->answer1) . '
"; - - $table->data[] = array($contents); - - echo html_writer::table($table); - - echo $OUTPUT->spacer(array('height' => 30)); // Should be done with CSS instead. - } - } - } - - break; - - case "question": - if (!$question = $DB->get_record("survey_questions", array("id" => $qid))) { - throw new \moodle_exception('cannotfindquestion', 'survey'); - } - $question->text = get_string($question->text, "survey"); - - $answers = explode(",", get_string($question->options, "survey")); - - echo $OUTPUT->heading("$strquestion: $question->text", 3); - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - $strname = get_string("name", "survey"); - $strtime = get_string("time", "survey"); - $stractual = get_string("actual", "survey"); - $strpreferred = get_string("preferred", "survey"); - $strdateformat = get_string("strftimedatetime"); - - $table = new html_table(); - $table->head = array("", $strname, $strtime, $stractual, $strpreferred); - $table->align = array("left", "left", "left", "left", "right"); - $table->size = array(35, "", "", "", ""); - - if ($aaa = survey_get_user_answers($survey->id, $question->id, $currentgroup)) { - foreach ($aaa as $a) { - if ($a->answer1) { - $answer1 = "$a->answer1 - " . $answers[$a->answer1 - 1]; - } else { - $answer1 = " "; - } - if ($a->answer2) { - $answer2 = "$a->answer2 - " . $answers[$a->answer2 - 1]; - } else { - $answer2 = " "; - } - $table->data[] = array( - $OUTPUT->user_picture($a, array('courseid' => $course->id)), - "userid\">" . fullname($a) . "", - userdate($a->time), - s($answer1), s($answer2)); - - } - } - - echo html_writer::table($table); - - break; - - case "students": - - echo $OUTPUT->heading(get_string("analysisof", "survey", get_string('participants')), 3); - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - if (!$results = survey_get_responses($survey->id, $currentgroup, $groupingid)) { - echo $OUTPUT->notification(get_string("nobodyyet", "survey"), 'info', false); - } else { - survey_print_all_responses($cm->id, $results, $course->id); - } - - break; - - case "student": - $user = core_user::get_user($student, '*', MUST_EXIST); - if ($currentgroup && !array_key_exists($user->id, $users)) { - throw new moodle_exception('usernotavailable', 'error'); - } - - echo $OUTPUT->heading(get_string("analysisof", "survey", fullname($user)), 3); - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - if ($notes != '' and confirm_sesskey()) { - if (survey_get_analysis($survey->id, $user->id)) { - if (!survey_update_analysis($survey->id, $user->id, $notes)) { - echo $OUTPUT->notification(get_string("errorunabletosavenotes", "survey"), "notifyproblem"); - } else { - echo $OUTPUT->notification(get_string("savednotes", "survey"), "notifysuccess"); - } - } else { - if (!survey_add_analysis($survey->id, $user->id, $notes)) { - echo $OUTPUT->notification(get_string("errorunabletosavenotes", "survey"), "notifyproblem"); - } else { - echo $OUTPUT->notification(get_string("savednotes", "survey"), "notifysuccess"); - } - } - } - - echo "

"; - echo $OUTPUT->user_picture($user, array('courseid' => $course->id)); - echo "

"; - - $questions = $DB->get_records_list("survey_questions", "id", explode(',', $survey->questions)); - $questionorder = explode(",", $survey->questions); - - if ($showscales) { - // Print overall summary. - echo "

"; - survey_print_graph("id=$id&sid=$student&type=student.png"); - echo "

"; - - // Print scales. - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - if ($question->type < 0) { // We have some virtual scales. Just show them. - $virtualscales = true; - break; - } - } - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - if ($question->multi) { - if ($virtualscales && $question->type > 0) { // Don't show non-virtual scales if virtual. - continue; - } - echo "

"; - echo "multi\">"; - survey_print_graph("id=$id&qid=$question->id&sid=$student&type=studentmultiquestion.png"); - echo "


"; - } - } - } - - // Print non-scale questions. - - foreach ($questionorder as $key => $val) { - $question = $questions[$val]; - if ($question->type == 0 or $question->type == 1) { - if ($answer = survey_get_user_answer($survey->id, $question->id, $user->id)) { - $table = new html_table(); - $table->head = array(get_string($question->text, "survey")); - $table->align = array("left"); - if (!empty($question->options) && $answer->answer1 > 0) { - $answers = explode(',', get_string($question->options, 'survey')); - if ($answer->answer1 <= count($answers)) { - $table->data[] = array(s($answers[$answer->answer1 - 1])); // No html here, just plain text. - } else { - $table->data[] = array(s($answer->answer1)); // No html here, just plain text. - } - } else { - $table->data[] = array(s($answer->answer1)); // No html here, just plain text. - } - echo html_writer::table($table); - echo $OUTPUT->spacer(array('height' => 30)); - } - } - } - - if ($rs = survey_get_analysis($survey->id, $user->id)) { - $notes = $rs->notes; - } else { - $notes = ""; - } - echo "
"; - echo "
"; - echo "
"; - echo "

$strnotes:

"; - echo "
"; - echo "
"; - echo ""; - echo ""; - echo ""; - echo "id\" />"; - echo ""; - echo "
"; - echo "
"; - echo "
"; - - break; - - case "download": - echo $OUTPUT->heading($strdownload, 3); - - if ($groupsactivitymenu) { - echo html_writer::div($groupsactivitymenu, 'mb-2'); - } - - require_capability('mod/survey:download', $context); - - $numusers = survey_count_responses($survey->id, $currentgroup, $groupingid); - if ($numusers > 0) { - echo html_writer::tag('p', get_string("downloadinfo", "survey"), array('class' => 'centerpara')); - - echo $OUTPUT->container_start('reportbuttons'); - $options = array(); - $options["id"] = "$cm->id"; - $options["group"] = $currentgroup; - - $options["type"] = "ods"; - echo $OUTPUT->single_button(new moodle_url("download.php", $options), get_string("downloadods")); - - $options["type"] = "xls"; - echo $OUTPUT->single_button(new moodle_url("download.php", $options), get_string("downloadexcel")); - - $options["type"] = "txt"; - echo $OUTPUT->single_button(new moodle_url("download.php", $options), get_string("downloadtext")); - echo $OUTPUT->container_end(); - - } else { - echo $OUTPUT->notification(get_string("nobodyyet", "survey"), 'info', false); - } - - break; - - default: - throw new moodle_exception('cannotviewreport'); - -} -echo $OUTPUT->footer(); diff --git a/mod/survey/save.php b/mod/survey/save.php deleted file mode 100644 index e721c410b77..00000000000 --- a/mod/survey/save.php +++ /dev/null @@ -1,78 +0,0 @@ -. - -/** - * This file is responsible for saving the results of a users survey and displaying - * the final message. - * - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - require_once('../../config.php'); - require_once('lib.php'); - - -// Make sure this is a legitimate posting - - if (!$formdata = data_submitted() or !confirm_sesskey()) { - throw new \moodle_exception('cannotcallscript'); - } - - $id = required_param('id', PARAM_INT); // Course Module ID - - if (! $cm = get_coursemodule_from_id('survey', $id)) { - throw new \moodle_exception('invalidcoursemodule'); - } - - if (! $course = $DB->get_record("course", array("id"=>$cm->course))) { - throw new \moodle_exception('coursemisconf'); - } - - $PAGE->set_url('/mod/survey/save.php', array('id'=>$id)); - require_login($course, false, $cm); - - $context = context_module::instance($cm->id); - require_capability('mod/survey:participate', $context); - - if (! $survey = $DB->get_record("survey", array("id"=>$cm->instance))) { - throw new \moodle_exception('invalidsurveyid', 'survey'); - } - - $strsurveysaved = get_string('surveysaved', 'survey'); - - $PAGE->set_title($strsurveysaved); - $PAGE->set_heading($course->fullname); - echo $OUTPUT->header(); - echo $OUTPUT->heading(format_string($survey->name)); - - if (survey_already_done($survey->id, $USER->id)) { - notice(get_string("alreadysubmitted", "survey"), get_local_referer(false)); - exit; - } - - survey_save_answers($survey, $formdata, $course, $context); - -// Print the page and finish up. - - notice(get_string("thanksforanswers","survey", $USER->firstname), "$CFG->wwwroot/course/view.php?id=$course->id"); - - exit; - - - diff --git a/mod/survey/styles.css b/mod/survey/styles.css deleted file mode 100644 index b012018f67e..00000000000 --- a/mod/survey/styles.css +++ /dev/null @@ -1,42 +0,0 @@ -.path-mod-survey .smalltext { - font-size: 0.75em; -} - -.path-mod-survey .surveytable .rblock label { - display: block; -} - -.path-mod-survey .surveytable .foundthat, -.path-mod-survey .surveytable .preferthat { - white-space: nowrap; -} - -.path-mod-survey .surveytable .buttoncell { - width: 5%; -} - -.path-mod-survey .surveytable .optioncell, -.path-mod-survey .surveytable .questioncell { - width: 50%; - vertical-align: top; -} - -.path-mod-survey .surveytable .whitecell { - background-color: white; -} - -.path-mod-survey #surveyform th { - font-weight: normal; - text-align: left; -} - -.path-mod-survey #surveyform th.hresponse { - text-align: center; - width: 9%; -} - -#page-mod-survey-report .fullnamecell { - width: 10%; - vertical-align: top; - white-space: nowrap; -} \ No newline at end of file diff --git a/mod/survey/templates/response_action_bar.mustache b/mod/survey/templates/response_action_bar.mustache deleted file mode 100644 index f0a7c7fd46c..00000000000 --- a/mod/survey/templates/response_action_bar.mustache +++ /dev/null @@ -1,72 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template mod_survey/response_action_bar - Actions bar for the reports page UI. - Classes required for JS: - * none - Context variables required for this template: - * see mod/survey/classes/output/actionbar.php - Example context (json): - { - "download": { - "link": "http://foobar", - "text": "foobar site", - "urlselect": { - "id": "url_select123", - "sesskey": "sesskey", - "action": "http://localhost/moodle/course/jumpto.php", - "disabled": false, - "formid": "surveyresponseselect", - "classes": "urlselect", - "options": [ - { - "name": "Summary", - "value": "/mod/survey/report.php?id=12&action=summary", - "selected": true - }, - { - "name": "Scales", - "value": "/mod/survey/report.php?id=12&action=scales", - "selected": false - }, - { - "name": "Questions", - "value": "/mod/survey/report.php?id=12&action=questions", - "selected": false - }, - { - "name": "Participants", - "value": "/mod/survey/report.php?id=12&action=students", - "selected": false - } - ] - } - } - } -}} -
-
- {{#urlselect}} - - {{/urlselect}} - {{#download}} - - {{/download}} -
-
diff --git a/mod/survey/tests/backup/restore_date_test.php b/mod/survey/tests/backup/restore_date_test.php deleted file mode 100644 index d88ba393b6d..00000000000 --- a/mod/survey/tests/backup/restore_date_test.php +++ /dev/null @@ -1,73 +0,0 @@ -. - -namespace mod_survey\backup; - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; -require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php"); - -/** - * Restore date tests. - * - * @package mod_survey - * @copyright 2017 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class restore_date_test extends \restore_date_testcase { - - public function test_restore_dates(): void { - global $DB; - - list($course, $survey) = $this->create_course_and_module('survey'); - $context = \context_module::instance($survey->cmid); - - // Build our questions and responses array. - $realquestions = array(); - $questions = survey_get_questions($survey); - $i = 5; - foreach ($questions as $q) { - if ($q->type > 0) { - if ($q->multi) { - $subquestions = survey_get_subquestions($q); - foreach ($subquestions as $sq) { - $key = 'q' . $sq->id; - $realquestions[$key] = $i % 5 + 1; - $i++; - } - } else { - $key = 'q' . $q->id; - $realquestions[$key] = $i % 5 + 1; - $i++; - } - } - } - survey_save_answers($survey, $realquestions, $course, $context); - // We do not want second differences to fail our test because of execution delays. - $DB->set_field('survey_answers', 'time', $this->startdate); - - // Do backup and restore. - $newcourseid = $this->backup_and_restore($course); - $newsurvey = $DB->get_record('survey', ['course' => $newcourseid]); - $this->assertFieldsNotRolledForward($survey, $newsurvey, ['timecreated', 'timemodified']); - - $answers = $DB->get_records('survey_answers', ['survey' => $newsurvey->id]); - foreach ($answers as $answer) { - $this->assertEquals($this->startdate, $answer->time); - } - } -} diff --git a/mod/survey/tests/behat/survey_completion.feature b/mod/survey/tests/behat/survey_completion.feature deleted file mode 100644 index ca050a23d38..00000000000 --- a/mod/survey/tests/behat/survey_completion.feature +++ /dev/null @@ -1,65 +0,0 @@ -@mod @mod_survey @core_completion @javascript -Feature: A teacher can use activity completion to track a student progress - In order to use activity completion - As a teacher - I need to set survey activities and enable activity completion - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | Teacher | 1 | teacher1@example.com | - | student1 | Student | 1 | student1@example.com | - And the following "courses" exist: - | fullname | shortname | category | enablecompletion | - | Course 1 | C1 | 0 | 1 | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - | student1 | C1 | student | - And I enable "survey" "mod" plugin - And I log in as "teacher1" - - Scenario: Require survey view - Given the following "activities" exist: - | activity | name | course | idnumber | template | completion | completionview | completionsubmit | - | survey | Test survey name | C1 | survey1 | 5 | 2 | 1 | 0 | - And I am on the "Test survey name" "survey activity" page - # Teacher view. - And "Test survey name" should have the "View" completion condition - # Student view. - When I am on the "Course 1" course page logged in as student1 - And the "View" completion condition of "Test survey name" is displayed as "todo" - And I follow "Test survey name" - And I am on "Course 1" course homepage - Then the "View" completion condition of "Test survey name" is displayed as "done" - - Scenario: Require survey submission - Given the following "activities" exist: - | activity | name | course | idnumber | template | completion | completionview | completionsubmit | - | survey | Test survey name | C1 | survey1 | 5 | 2 | 1 | 1 | - And I am on the "Test survey name" "survey activity" page - # Teacher view. - And "Test survey name" should have the "Submit answers" completion condition - # Student view. - When I am on the "Course 1" course page logged in as student1 - And the "Submit answers" completion condition of "Test survey name" is displayed as "todo" - And I follow "Test survey name" - And the "Submit answers" completion condition of "Test survey name" is displayed as "todo" - And I press "Submit" - And I am on "Course 1" course homepage - And the "Submit answers" completion condition of "Test survey name" is displayed as "done" - And I follow "Test survey name" - And the "Submit answers" completion condition of "Test survey name" is displayed as "done" - - Scenario: A student can manually mark the survey activity as done but a teacher cannot - Given the following "activities" exist: - | activity | name | course | idnumber | completion | - | survey | Test survey name | C1 | survey1 | 1 | - And I am on "Course 1" course homepage - # Teacher view. - And "Test survey name" should have the "Mark as done" completion condition - # Student view. - When I am on the "survey1" Activity page logged in as student1 - Then the manual completion button of "Test survey name" is displayed as "Mark as done" - And I toggle the manual completion state of "Test survey name" - And the manual completion button of "Test survey name" is displayed as "Done" diff --git a/mod/survey/tests/behat/survey_critical_incidents.feature b/mod/survey/tests/behat/survey_critical_incidents.feature deleted file mode 100644 index 67e0102af7e..00000000000 --- a/mod/survey/tests/behat/survey_critical_incidents.feature +++ /dev/null @@ -1,47 +0,0 @@ -@mod @mod_survey @javascript -Feature: A teacher navigates to response reports of students - If survey activity is configured for critical students - Only questions and particiats pages should be visible under response reports - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | Teacher | 1 | teacher1@example.com | - | student1 | Student | 1 | student1@example.com | - | student2 | Student | 1 | student2@example.com | - And the following "courses" exist: - | fullname | shortname | category | enablecompletion | - | Course 1 | C1 | 0 | 1 | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - | student1 | C1 | student | - | student2 | C1 | student | - And I enable "survey" "mod" plugin - And the following "activities" exist: - | activity | name | course | idnumber | template | - | survey | Test survey name | C1 | survey1 | 5 | - - Scenario: Only questions and participants page should be available under response reports as teacher - Given I am on the "Test survey name" "survey activity" page logged in as student1 - And I set the field "At what moment in class were you most engaged as a learner?" to "most engaged as student1" - And I set the field "At what moment in class were you most distanced as a learner?" to "most distanced as student1" - And I set the field "What action from anyone in the forums did you find most affirming or helpful?" to "most helpful student1" - And I set the field "What action from anyone in the forums did you find most puzzling or confusing?" to "most confusing student1" - And I set the field "What event surprised you most?" to "most surprised student1" - And I press "Submit" - And I press "Continue" - And I am on the "Test survey name" "survey activity" page logged in as student2 - And I set the field "At what moment in class were you most engaged as a learner?" to "most engaged as student2" - And I set the field "At what moment in class were you most distanced as a learner?" to "most distanced as student2" - And I set the field "What action from anyone in the forums did you find most affirming or helpful?" to "most helpful student2" - And I set the field "What action from anyone in the forums did you find most puzzling or confusing?" to "most confusing student2" - And I set the field "What event surprised you most?" to "most surprised student1" - And I press "Submit" - And I press "Continue" - When I am on the "Test survey name" "survey activity" page logged in as teacher1 - And I navigate to "Response reports" in current page administration - Then I should not see "Summary" - And I should not see "Scales" - And I should see "Questions" - And I should see "Participants" diff --git a/mod/survey/tests/behat/survey_description.feature b/mod/survey/tests/behat/survey_description.feature deleted file mode 100644 index ce574f79c54..00000000000 --- a/mod/survey/tests/behat/survey_description.feature +++ /dev/null @@ -1,31 +0,0 @@ -@mod @mod_survey -Feature: The default introduction is displayed when the activity description is empty - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | Teacher | 1 | teacher1@example.com | - And the following "courses" exist: - | fullname | shortname | format | - | Course 1 | C1 | topics | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - And I enable "survey" "mod" plugin - And the following "activities" exist: - | activity | name | course | idnumber | template | - | survey | Test survey name | C1 | survey1 | 1 | - - Scenario: Display the default survey introduction when activity description is empty - Given I am on the "Test survey name" "survey activity" page logged in as "teacher1" - And I should see "Test survey 1" - When I am on the "Test survey name" "survey activity editing" page - And I set the following fields to these values: - | Description | | - And I press "Save and display" - Then I should see "The purpose of this survey is to help us understand" - And I am on the "Test survey name" "survey activity editing" page - And I set the following fields to these values: - | Survey type | ATTLS (20 item version) | - And I press "Save and display" - And I should see "The purpose of this questionnaire is to help us evaluate" diff --git a/mod/survey/tests/behat/survey_groups.feature b/mod/survey/tests/behat/survey_groups.feature deleted file mode 100644 index 616fc574f42..00000000000 --- a/mod/survey/tests/behat/survey_groups.feature +++ /dev/null @@ -1,86 +0,0 @@ -@mod @mod_survey -Feature: Viewing response reports by group - In order to view reponse reports on a large course - As a teacher - I need to filter the users on the response reports by group - - Background: - And the following "courses" exist: - | fullname | shortname | - | Test Course 1 | C1 | - And the following "groups" exist: - | name | course | idnumber | participation | - | Group 1 | C1 | G1 | 1 | - | Group 2 | C1 | G2 | 1 | - | Group 3 | C1 | G3 | 0 | - And the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | TeacherG1 | 1 | teacher1@example.com | - | noneditor1 | NoneditorG1 | 1 | noneditor1@example.com | - | noneditor2 | NoneditorNone | 2 | noneditor2@example.com | - | user1 | User1G1 | 1 | user1@example.com | - | user2 | User2G2 | 2 | user2@example.com | - | user3 | User3None | 3 | user3@example.com | - | user4 | User4NPgroup | 4 | user4@example.com | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - | noneditor1 | C1 | teacher | - | noneditor2 | C1 | teacher | - | user1 | C1 | student | - | user2 | C1 | student | - | user3 | C1 | student | - | user4 | C1 | student | - And the following "group members" exist: - | user | group | - | teacher1 | G1 | - | noneditor1 | G1 | - | user1 | G1 | - | user2 | G2 | - | user4 | G3 | - And I enable "survey" "mod" plugin - And the following "activities" exist: - | activity | name | intro | course | idnumber | groupmode | template | - | survey | Separate survey | survey with separate groups | C1 | survey1 | 1 | 5 | - | survey | Visible survey | survey with visible groups | C1 | survey2 | 2 | 5 | - And I am on the "Separate survey" "survey activity" page logged in as user1 - And I press "Submit" - And I am on the "Separate survey" "survey activity" page logged in as user2 - And I press "Submit" - And I am on the "Separate survey" "survey activity" page logged in as user3 - And I press "Submit" - And I am on the "Separate survey" "survey activity" page logged in as user4 - And I press "Submit" - And I am on the "Visible survey" "survey activity" page logged in as user1 - And I press "Submit" - And I am on the "Visible survey" "survey activity" page logged in as user2 - And I press "Submit" - And I am on the "Visible survey" "survey activity" page logged in as user3 - And I press "Submit" - And I am on the "Visible survey" "survey activity" page logged in as user4 - And I press "Submit" - - Scenario Outline: Editing teachers should see all groups on the Results page. Non-editing teachers should see just their own - groups in Separate groups mode, all groups in Visible groups mode. - Given I am on the "" "survey activity" page logged in as "" - And I follow "Response reports" - Then I see "All participants" - And I see "Group 1" - And I see "Group 2" - And I should not see "Group 3" - And I see "User1G1" - And I see "User2G2" - And I see "User3None" - And I see "User4NPgroup" - - Examples: - | survey | user | all | G1 | G2 | user1 | user2 | user3 | user4 | - | survey1 | teacher1 | should | should | should | should | should | should | should | - | survey1 | noneditor1 | should not | should | should not | should | should not | should not | should not | - | survey2 | teacher1 | should | should | should | should | should | should | should | - | survey2 | noneditor1 | should | should | should | should | should not | should not | should not | - | survey2 | noneditor2 | should | should | should | should | should not | should not | should not | - - Scenario: Non-editing teacher without access to any groups should not see survey results in separate groups mode - Given I am on the "survey1" "survey activity" page logged in as "noneditor2" - Then I should not see "Response reports" diff --git a/mod/survey/tests/behat/survey_types.feature b/mod/survey/tests/behat/survey_types.feature deleted file mode 100644 index 0e345070ab8..00000000000 --- a/mod/survey/tests/behat/survey_types.feature +++ /dev/null @@ -1,48 +0,0 @@ -@mod @mod_survey -Feature: A teacher can set three types of survey activity - In order to use verified survey instruments - As a teacher - I need to set survey activities and select which survey type suits my needs - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | Teacher | 1 | teacher1@example.com | - And the following "courses" exist: - | fullname | shortname | format | - | Course 1 | C1 | topics | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - And I enable "survey" "mod" plugin - And I log in as "teacher1" - - Scenario: Switching between the three survey types - Given the following "activities" exist: - | activity | name | course | idnumber | - | survey | Test survey name | C1 | survey1 | - And I am on the "Test survey name" "survey activity editing" page - And I set the following fields to these values: - | Survey type | ATTLS (20 item version) | - And I press "Save and display" - Then I should see "Attitudes Towards Thinking and Learning" - And I navigate to "Settings" in current page administration - And I set the following fields to these values: - | Survey type | Critical incidents | - And I press "Save and display" - And I should see "At what moment in class were you most engaged as a learner?" - And I navigate to "Settings" in current page administration - And I set the following fields to these values: - | Survey type | COLLES (Preferred and Actual) | - And I press "Save and display" - And I should see "In this online unit..." - And I should see "my learning focuses on issues that interest me." - - Scenario: Survey activity is created via UI - Given I add a survey activity to course "Course 1" section "1" - And I set the following fields to these values: - | Name | Test survey name | - | Description | Test survey description | - | Survey type | ATTLS (20 item version) | - When I press "Save and return to course" - Then I should see "Test survey name" diff --git a/mod/survey/tests/behat/survey_validation.feature b/mod/survey/tests/behat/survey_validation.feature deleted file mode 100644 index 7898f44adbd..00000000000 --- a/mod/survey/tests/behat/survey_validation.feature +++ /dev/null @@ -1,25 +0,0 @@ -@mod @mod_survey @javascript -Feature: When some answers are not selected, the survey should not be submitted - In order to submit valid responses - As a student - I need to fill values - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | - | student1 | Student | 1 | student1@example.com | - And the following "courses" exist: - | fullname | shortname | - | Course 1 | C1 | - And the following "course enrolments" exist: - | user | course | role | - | student1 | C1 | student | - And I enable "survey" "mod" plugin - - Scenario: Require survey view - Given the following "activities" exist: - | activity | name | course | - | survey | Test survey name | C1 | - And I am on the "Test survey name" "survey activity" page logged in as "student1" - When I press "Submit" - Then I should see "Some of the multiple choice questions have not been answered." in the "Error" "dialogue" diff --git a/mod/survey/tests/custom_completion_test.php b/mod/survey/tests/custom_completion_test.php deleted file mode 100644 index d2bb3d9583d..00000000000 --- a/mod/survey/tests/custom_completion_test.php +++ /dev/null @@ -1,217 +0,0 @@ -. - -/** - * Contains unit tests for core_completion/activity_custom_completion. - * - * @package mod_survey - * @copyright Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -declare(strict_types=1); - -namespace mod_survey; - -use advanced_testcase; -use cm_info; -use coding_exception; -use mod_survey\completion\custom_completion; -use moodle_exception; - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; -require_once($CFG->libdir . '/completionlib.php'); - -/** - * Class for unit testing mod_survey/activity_custom_completion. - * - * @package mod_survey - * @copyright Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class custom_completion_test extends advanced_testcase { - - /** - * Data provider for get_state(). - * - * @return array[] - */ - public static function get_state_provider(): array { - return [ - 'Undefined rule' => [ - 'somenonexistentrule', COMPLETION_DISABLED, false, null, coding_exception::class - ], - 'Rule not available' => [ - 'completionsubmit', COMPLETION_DISABLED, false, null, moodle_exception::class - ], - 'Rule available, user has not submitted' => [ - 'completionsubmit', COMPLETION_ENABLED, false, COMPLETION_INCOMPLETE, null - ], - 'Rule available, user has submitted' => [ - 'completionsubmit', COMPLETION_ENABLED, true, COMPLETION_COMPLETE, null - ], - ]; - } - - /** - * Test for get_state(). - * - * @dataProvider get_state_provider - * @param string $rule The custom completion rule. - * @param int $available Whether this rule is available. - * @param bool $submitted - * @param int|null $status Expected status. - * @param string|null $exception Expected exception. - */ - public function test_get_state(string $rule, int $available, ?bool $submitted, ?int $status, ?string $exception): void { - global $DB; - - if (!is_null($exception)) { - $this->expectException($exception); - } - - // Custom completion rule data for cm_info::customdata. - $customdataval = [ - 'customcompletionrules' => [ - $rule => $available - ] - ]; - - // Build a mock cm_info instance. - $mockcminfo = $this->getMockBuilder(cm_info::class) - ->disableOriginalConstructor() - ->onlyMethods(['__get']) - ->getMock(); - - // Mock the return of the magic getter method when fetching the cm_info object's customdata and instance values. - $mockcminfo->expects($this->any()) - ->method('__get') - ->will($this->returnValueMap([ - ['customdata', $customdataval], - ['instance', 1], - ])); - - // Mock the DB calls. - $DB = $this->createMock(get_class($DB)); - $DB->expects($this->atMost(1)) - ->method('record_exists') - ->willReturn($submitted); - - $customcompletion = new custom_completion($mockcminfo, 2); - $this->assertEquals($status, $customcompletion->get_state($rule)); - } - - /** - * Test for get_defined_custom_rules(). - */ - public function test_get_defined_custom_rules(): void { - $rules = custom_completion::get_defined_custom_rules(); - $this->assertCount(1, $rules); - $this->assertEquals('completionsubmit', reset($rules)); - } - - /** - * Test for get_defined_custom_rule_descriptions(). - */ - public function test_get_custom_rule_descriptions(): void { - // Get defined custom rules. - $rules = custom_completion::get_defined_custom_rules(); - - // Build a mock cm_info instance. - $mockcminfo = $this->getMockBuilder(cm_info::class) - ->disableOriginalConstructor() - ->onlyMethods(['__get']) - ->getMock(); - - // Instantiate a custom_completion object using the mocked cm_info. - $customcompletion = new custom_completion($mockcminfo, 1); - - // Get custom rule descriptions. - $ruledescriptions = $customcompletion->get_custom_rule_descriptions(); - - // Confirm that defined rules and rule descriptions are consistent with each other. - $this->assertEquals(count($rules), count($ruledescriptions)); - foreach ($rules as $rule) { - $this->assertArrayHasKey($rule, $ruledescriptions); - } - } - - /** - * Test for is_defined(). - */ - public function test_is_defined(): void { - // Build a mock cm_info instance. - $mockcminfo = $this->getMockBuilder(cm_info::class) - ->disableOriginalConstructor() - ->getMock(); - - $customcompletion = new custom_completion($mockcminfo, 1); - - // Rule is defined. - $this->assertTrue($customcompletion->is_defined('completionsubmit')); - - // Undefined rule. - $this->assertFalse($customcompletion->is_defined('somerandomrule')); - } - - /** - * Data provider for test_get_available_custom_rules(). - * - * @return array[] - */ - public static function get_available_custom_rules_provider(): array { - return [ - 'Completion submit available' => [ - COMPLETION_ENABLED, ['completionsubmit'] - ], - 'Completion submit not available' => [ - COMPLETION_DISABLED, [] - ], - ]; - } - - /** - * Test for get_available_custom_rules(). - * - * @dataProvider get_available_custom_rules_provider - * @param int $status - * @param array $expected - */ - public function test_get_available_custom_rules(int $status, array $expected): void { - $customdataval = [ - 'customcompletionrules' => [ - 'completionsubmit' => $status - ] - ]; - - // Build a mock cm_info instance. - $mockcminfo = $this->getMockBuilder(cm_info::class) - ->disableOriginalConstructor() - ->onlyMethods(['__get']) - ->getMock(); - - // Mock the return of magic getter for the customdata attribute. - $mockcminfo->expects($this->any()) - ->method('__get') - ->with('customdata') - ->willReturn($customdataval); - - $customcompletion = new custom_completion($mockcminfo, 1); - $this->assertEquals($expected, $customcompletion->get_available_custom_rules()); - } -} diff --git a/mod/survey/tests/event/events_test.php b/mod/survey/tests/event/events_test.php deleted file mode 100644 index 1c232a066c0..00000000000 --- a/mod/survey/tests/event/events_test.php +++ /dev/null @@ -1,139 +0,0 @@ -. - -/** - * Events tests. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\event; - -/** - * Events tests class. - * - * @package mod_survey - * @copyright 2014 Rajesh Taneja - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class events_test extends \advanced_testcase { - - /** - * Setup. - */ - public function setUp(): void { - parent::setUp(); - $this->resetAfterTest(); - // Survey module is disabled by default, enable it for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - } - - /** - * Test report downloaded event. - */ - public function test_report_downloaded(): void { - // There is no proper API to call to generate chapters for a book, so what we are - // doing here is simply making sure that the events returns the right information. - - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - $params = array( - 'objectid' => $survey->id, - 'context' => \context_module::instance($survey->cmid), - 'courseid' => $course->id, - 'other' => array('type' => 'xls') - ); - $event = \mod_survey\event\report_downloaded::create($params); - - // Triggering and capturing the event. - $sink = $this->redirectEvents(); - $event->trigger(); - $events = $sink->get_events(); - $this->assertCount(1, $events); - $event = reset($events); - - // Checking that the event contains the expected values. - $this->assertInstanceOf('\mod_survey\event\report_downloaded', $event); - $this->assertEquals(\context_module::instance($survey->cmid), $event->get_context()); - $this->assertEquals($survey->id, $event->objectid); - $this->assertEventContextNotUsed($event); - } - - /** - * Test report viewed event. - */ - public function test_report_viewed(): void { - // There is no proper API to call to generate chapters for a book, so what we are - // doing here is simply making sure that the events returns the right information. - - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - $params = array( - 'objectid' => $survey->id, - 'context' => \context_module::instance($survey->cmid), - 'courseid' => $course->id - ); - $event = \mod_survey\event\report_viewed::create($params); - - // Triggering and capturing the event. - $sink = $this->redirectEvents(); - $event->trigger(); - $events = $sink->get_events(); - $this->assertCount(1, $events); - $event = reset($events); - - // Checking that the event contains the expected values. - $this->assertInstanceOf('\mod_survey\event\report_viewed', $event); - $this->assertEquals(\context_module::instance($survey->cmid), $event->get_context()); - $this->assertEquals($survey->id, $event->objectid); - } - - /** - * Test response submitted event. - */ - public function test_response_submitted(): void { - // There is no proper API to call to generate chapters for a book, so what we are - // doing here is simply making sure that the events returns the right information. - - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - $params = array( - 'context' => \context_module::instance($survey->cmid), - 'courseid' => $course->id, - 'other' => array('surveyid' => $survey->id) - ); - $event = \mod_survey\event\response_submitted::create($params); - - // Triggering and capturing the event. - $sink = $this->redirectEvents(); - $event->trigger(); - $events = $sink->get_events(); - $this->assertCount(1, $events); - $event = reset($events); - - // Checking that the event contains the expected values. - $this->assertInstanceOf('\mod_survey\event\response_submitted', $event); - $this->assertEquals(\context_module::instance($survey->cmid), $event->get_context()); - $this->assertEquals($survey->id, $event->other['surveyid']); - $this->assertEventContextNotUsed($event); - } -} diff --git a/mod/survey/tests/externallib_test.php b/mod/survey/tests/externallib_test.php deleted file mode 100644 index b065e7da52b..00000000000 --- a/mod/survey/tests/externallib_test.php +++ /dev/null @@ -1,414 +0,0 @@ -. - -namespace mod_survey; - -use core_external\external_api; -use externallib_advanced_testcase; -use mod_survey_external; - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; - -require_once($CFG->dirroot . '/webservice/tests/helpers.php'); -require_once($CFG->dirroot . '/mod/survey/lib.php'); - -/** - * Survey module external functions tests - * - * @package mod_survey - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ -class externallib_test extends externallib_advanced_testcase { - - /** @var \stdClass course record. */ - protected $course; - - /** @var \stdClass activity record. */ - protected $survey; - - /** @var \context_module context instance. */ - protected $context; - - /** @var \StdClass course module. */ - protected $cm; - - /** @var \StdClass student record. */ - protected $student; - - /** @var \StdClass teacher record. */ - protected $teacher; - - /** @var \StdClass student role. */ - protected $studentrole; - - /** @var \StdClass teacher role. */ - protected $teacherrole; - - /** - * Set up for every test - */ - public function setUp(): void { - global $DB; - parent::setUp(); - $this->resetAfterTest(); - $this->setAdminUser(); - - // Survey module is disabled by default, enable it for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - - // Setup test data. - $this->course = $this->getDataGenerator()->create_course(); - $this->survey = $this->getDataGenerator()->create_module('survey', array('course' => $this->course->id)); - $this->context = \context_module::instance($this->survey->cmid); - $this->cm = get_coursemodule_from_instance('survey', $this->survey->id); - - // Create users. - $this->student = self::getDataGenerator()->create_user(); - $this->teacher = self::getDataGenerator()->create_user(); - - // Users enrolments. - $this->studentrole = $DB->get_record('role', array('shortname' => 'student')); - $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); - $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual'); - $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual'); - } - - - /* - * Test get surveys by courses - */ - public function test_mod_survey_get_surveys_by_courses(): void { - global $DB; - - // Create additional course. - $course2 = self::getDataGenerator()->create_course(); - - // Second survey. - $record = new \stdClass(); - $record->course = $course2->id; - $survey2 = self::getDataGenerator()->create_module('survey', $record); - // Force empty intro. - $DB->set_field('survey', 'intro', '', array('id' => $survey2->id)); - - // Execute real Moodle enrolment as we'll call unenrol() method on the instance later. - $enrol = enrol_get_plugin('manual'); - $enrolinstances = enrol_get_instances($course2->id, true); - foreach ($enrolinstances as $courseenrolinstance) { - if ($courseenrolinstance->enrol == "manual") { - $instance2 = $courseenrolinstance; - break; - } - } - $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id); - - self::setUser($this->student); - - $returndescription = mod_survey_external::get_surveys_by_courses_returns(); - - // Create what we expect to be returned when querying the two courses. - // First for the student user. - $expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'lang', - 'template', 'days', 'questions', 'surveydone'); - - // Add expected coursemodule and data. - $survey1 = $this->survey; - $survey1->coursemodule = $survey1->cmid; - $survey1->introformat = 1; - $survey1->surveydone = 0; - $survey1->section = 0; - $survey1->visible = true; - $survey1->groupmode = 0; - $survey1->groupingid = 0; - $survey1->introfiles = []; - $survey1->lang = ''; - - $survey2->coursemodule = $survey2->cmid; - $survey2->introformat = 1; - $survey2->surveydone = 0; - $survey2->section = 0; - $survey2->visible = true; - $survey2->groupmode = 0; - $survey2->groupingid = 0; - $tempo = $DB->get_field("survey", "intro", array("id" => $survey2->template)); - $survey2->intro = nl2br(get_string($tempo, "survey")); - $survey2->introfiles = []; - $survey2->lang = ''; - - foreach ($expectedfields as $field) { - $expected1[$field] = $survey1->{$field}; - $expected2[$field] = $survey2->{$field}; - } - - $expectedsurveys = array($expected2, $expected1); - - // Call the external function passing course ids. - $result = mod_survey_external::get_surveys_by_courses(array($course2->id, $this->course->id)); - $result = external_api::clean_returnvalue($returndescription, $result); - - $this->assertEquals($expectedsurveys, $result['surveys']); - $this->assertCount(0, $result['warnings']); - - // Call the external function without passing course id. - $result = mod_survey_external::get_surveys_by_courses(); - $result = external_api::clean_returnvalue($returndescription, $result); - $this->assertEquals($expectedsurveys, $result['surveys']); - $this->assertCount(0, $result['warnings']); - - // Unenrol user from second course and alter expected surveys. - $enrol->unenrol_user($instance2, $this->student->id); - array_shift($expectedsurveys); - - // Call the external function without passing course id. - $result = mod_survey_external::get_surveys_by_courses(); - $result = external_api::clean_returnvalue($returndescription, $result); - $this->assertEquals($expectedsurveys, $result['surveys']); - - // Call for the second course we unenrolled the user from, expected warning. - $result = mod_survey_external::get_surveys_by_courses(array($course2->id)); - $this->assertCount(1, $result['warnings']); - $this->assertEquals('1', $result['warnings'][0]['warningcode']); - $this->assertEquals($course2->id, $result['warnings'][0]['itemid']); - - // Now, try as a teacher for getting all the additional fields. - self::setUser($this->teacher); - - $additionalfields = array('timecreated', 'timemodified', 'section', 'visible', 'groupmode', 'groupingid'); - - foreach ($additionalfields as $field) { - $expectedsurveys[0][$field] = $survey1->{$field}; - } - - $result = mod_survey_external::get_surveys_by_courses(); - $result = external_api::clean_returnvalue($returndescription, $result); - $this->assertEquals($expectedsurveys, $result['surveys']); - - // Admin also should get all the information. - self::setAdminUser(); - - $result = mod_survey_external::get_surveys_by_courses(array($this->course->id)); - $result = external_api::clean_returnvalue($returndescription, $result); - $this->assertEquals($expectedsurveys, $result['surveys']); - - // Now, prohibit capabilities. - $this->setUser($this->student); - $contextcourse1 = \context_course::instance($this->course->id); - // Prohibit capability = mod/survey:participate on Course1 for students. - assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $contextcourse1->id); - accesslib_clear_all_caches_for_unit_testing(); - - $surveys = mod_survey_external::get_surveys_by_courses(array($this->course->id)); - $surveys = external_api::clean_returnvalue(mod_survey_external::get_surveys_by_courses_returns(), $surveys); - $this->assertFalse(isset($surveys['surveys'][0]['intro'])); - } - - /** - * Test view_survey - */ - public function test_view_survey(): void { - global $DB; - - // Test invalid instance id. - try { - mod_survey_external::view_survey(0); - $this->fail('Exception expected due to invalid mod_survey instance id.'); - } catch (\moodle_exception $e) { - $this->assertEquals('invalidrecord', $e->errorcode); - } - - // Test not-enrolled user. - $usernotenrolled = self::getDataGenerator()->create_user(); - $this->setUser($usernotenrolled); - try { - mod_survey_external::view_survey($this->survey->id); - $this->fail('Exception expected due to not enrolled user.'); - } catch (\moodle_exception $e) { - $this->assertEquals('requireloginerror', $e->errorcode); - } - - // Test user with full capabilities. - $this->setUser($this->student); - - // Trigger and capture the event. - $sink = $this->redirectEvents(); - - $result = mod_survey_external::view_survey($this->survey->id); - $result = external_api::clean_returnvalue(mod_survey_external::view_survey_returns(), $result); - $this->assertTrue($result['status']); - - $events = $sink->get_events(); - $this->assertCount(1, $events); - $event = array_shift($events); - - // Checking that the event contains the expected values. - $this->assertInstanceOf('\mod_survey\event\course_module_viewed', $event); - $this->assertEquals($this->context, $event->get_context()); - $moodlesurvey = new \moodle_url('/mod/survey/view.php', array('id' => $this->cm->id)); - $this->assertEquals($moodlesurvey, $event->get_url()); - $this->assertEventContextNotUsed($event); - $this->assertNotEmpty($event->get_name()); - - // Test user with no capabilities. - // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. - assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); - accesslib_clear_all_caches_for_unit_testing(); - - try { - mod_survey_external::view_survey($this->survey->id); - $this->fail('Exception expected due to missing capability.'); - } catch (\moodle_exception $e) { - $this->assertEquals('nopermissions', $e->errorcode); - } - - } - - /** - * Test get_questions - */ - public function test_get_questions(): void { - global $DB; - - // Test user with full capabilities. - $this->setUser($this->student); - - // Build our expectation array. - $expectedquestions = array(); - $questions = survey_get_questions($this->survey); - foreach ($questions as $q) { - if ($q->type >= 0) { - $expectedquestions[$q->id] = $q; - if ($q->multi) { - $subquestions = survey_get_subquestions($q); - foreach ($subquestions as $sq) { - $expectedquestions[$sq->id] = $sq; - } - } - } - } - - $result = mod_survey_external::get_questions($this->survey->id); - $result = external_api::clean_returnvalue(mod_survey_external::get_questions_returns(), $result); - - // Check we receive the same questions. - $this->assertCount(0, $result['warnings']); - foreach ($result['questions'] as $q) { - $this->assertEquals(get_string($expectedquestions[$q['id']]->text, 'survey'), $q['text']); - $this->assertEquals(get_string($expectedquestions[$q['id']]->shorttext, 'survey'), $q['shorttext']); - $this->assertEquals($expectedquestions[$q['id']]->multi, $q['multi']); - $this->assertEquals($expectedquestions[$q['id']]->type, $q['type']); - // Parent questions must have parent eq to 0. - if ($q['multi']) { - $this->assertEquals(0, $q['parent']); - $this->assertEquals(get_string($expectedquestions[$q['id']]->options, 'survey'), $q['options']); - } - } - - // Test user with no capabilities. - // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. - assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); - accesslib_clear_all_caches_for_unit_testing(); - - try { - mod_survey_external::get_questions($this->survey->id); - $this->fail('Exception expected due to missing capability.'); - } catch (\moodle_exception $e) { - $this->assertEquals('nopermissions', $e->errorcode); - } - } - - /** - * Test submit_answers - */ - public function test_submit_answers(): void { - global $DB; - - // Test user with full capabilities. - $this->setUser($this->student); - - // Build our questions and responses array. - $realquestions = array(); - $questions = survey_get_questions($this->survey); - $i = 5; - foreach ($questions as $q) { - if ($q->type >= 0) { - if ($q->multi) { - $subquestions = survey_get_subquestions($q); - foreach ($subquestions as $sq) { - $realquestions[] = array( - 'key' => 'q' . $sq->id, - 'value' => $i % 5 + 1 // Values between 1 and 5. - ); - $i++; - } - } else { - $realquestions[] = array( - 'key' => 'q' . $q->id, - 'value' => $i % 5 + 1 - ); - $i++; - } - } - } - - $result = mod_survey_external::submit_answers($this->survey->id, $realquestions); - $result = external_api::clean_returnvalue(mod_survey_external::submit_answers_returns(), $result); - - $this->assertTrue($result['status']); - $this->assertCount(0, $result['warnings']); - - $dbanswers = $DB->get_records_menu('survey_answers', array('survey' => $this->survey->id), '', 'question, answer1'); - foreach ($realquestions as $q) { - $id = str_replace('q', '', $q['key']); - $this->assertEquals($q['value'], $dbanswers[$id]); - } - - // Submit again, we expect an error here. - try { - mod_survey_external::submit_answers($this->survey->id, $realquestions); - $this->fail('Exception expected due to answers already submitted.'); - } catch (\moodle_exception $e) { - $this->assertEquals('alreadysubmitted', $e->errorcode); - } - - // Test user with no capabilities. - // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. - assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); - accesslib_clear_all_caches_for_unit_testing(); - - try { - mod_survey_external::submit_answers($this->survey->id, $realquestions); - $this->fail('Exception expected due to missing capability.'); - } catch (\moodle_exception $e) { - $this->assertEquals('nopermissions', $e->errorcode); - } - - // Test not-enrolled user. - $usernotenrolled = self::getDataGenerator()->create_user(); - $this->setUser($usernotenrolled); - try { - mod_survey_external::submit_answers($this->survey->id, $realquestions); - $this->fail('Exception expected due to not enrolled user.'); - } catch (\moodle_exception $e) { - $this->assertEquals('requireloginerror', $e->errorcode); - } - } - -} diff --git a/mod/survey/tests/generator/lib.php b/mod/survey/tests/generator/lib.php deleted file mode 100644 index 9ba63ea8817..00000000000 --- a/mod/survey/tests/generator/lib.php +++ /dev/null @@ -1,75 +0,0 @@ -. - -/** - * mod_survey data generator. - * - * @package mod_survey - * @category test - * @copyright 2013 Marina Glancy - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * mod_survey data generator class. - * - * @package mod_survey - * @category test - * @copyright 2013 Marina Glancy - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class mod_survey_generator extends testing_module_generator { - - /** - * Cached list of available templates. - * @var array - */ - private $templates = null; - - public function reset() { - $this->templates = null; - parent::reset(); - } - - public function create_instance($record = null, ?array $options = null) { - global $DB; - - if ($this->templates === null) { - $this->templates = $DB->get_records_menu('survey', array('template' => 0), 'name', 'id, name'); - } - if (empty($this->templates)) { - throw new moodle_exception('cannotfindsurveytmpt', 'survey'); - } - $record = (array)$record; - if (isset($record['template']) && !is_number($record['template'])) { - // Substitute template name with template id. - $record['template'] = array_search($record['template'], $this->templates); - } - if (isset($record['template']) && !array_key_exists($record['template'], $this->templates)) { - throw new moodle_exception('cannotfindsurveytmpt', 'survey'); - } - - // Add default values for survey. - if (!isset($record['template'])) { - reset($this->templates); - $record['template'] = key($this->templates); - } - - return parent::create_instance($record, (array)$options); - } -} diff --git a/mod/survey/tests/generator_test.php b/mod/survey/tests/generator_test.php deleted file mode 100644 index 1854b0b53f3..00000000000 --- a/mod/survey/tests/generator_test.php +++ /dev/null @@ -1,98 +0,0 @@ -. - -namespace mod_survey; - -/** - * Genarator tests class for mod_survey. - * - * @package mod_survey - * @category test - * @copyright 2013 Marina Glancy - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class generator_test extends \advanced_testcase { - - /** - * Setup testcase. - */ - public function setUp(): void { - parent::setUp(); - // Survey module is disabled by default, enable it for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - } - - public function test_create_instance(): void { - global $DB; - $this->resetAfterTest(); - $this->setAdminUser(); - - $course = $this->getDataGenerator()->create_course(); - - $this->assertFalse($DB->record_exists('survey', array('course' => $course->id))); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course)); - $records = $DB->get_records('survey', array('course' => $course->id), 'id'); - $this->assertEquals(1, count($records)); - $this->assertTrue(array_key_exists($survey->id, $records)); - - $params = array('course' => $course->id, 'name' => 'Another survey'); - $survey = $this->getDataGenerator()->create_module('survey', $params); - $records = $DB->get_records('survey', array('course' => $course->id), 'id'); - $this->assertEquals(2, count($records)); - $this->assertEquals('Another survey', $records[$survey->id]->name); - } - - public function test_create_instance_with_template(): void { - global $DB; - $this->resetAfterTest(); - $this->setAdminUser(); - - $course = $this->getDataGenerator()->create_course(); - $templates = $DB->get_records_menu('survey', array('template' => 0), 'name', 'id, name'); - $firsttemplateid = key($templates); - - // By default survey is created with the first available template. - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course)); - $record = $DB->get_record('survey', array('id' => $survey->id)); - $this->assertEquals($firsttemplateid, $record->template); - - // Survey can be created specifying the template id. - $tmplid = array_search('ciqname', $templates); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course, - 'template' => $tmplid)); - $record = $DB->get_record('survey', array('id' => $survey->id)); - $this->assertEquals($tmplid, $record->template); - - // Survey can be created specifying the template name instead of id. - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course, - 'template' => 'collesaname')); - $record = $DB->get_record('survey', array('id' => $survey->id)); - $this->assertEquals(array_search('collesaname', $templates), $record->template); - - // Survey can not be created specifying non-existing template id or name. - try { - $this->getDataGenerator()->create_module('survey', array('course' => $course, - 'template' => 87654)); - $this->fail('Exception about non-existing numeric template is expected'); - } catch (\Exception $e) {} - try { - $this->getDataGenerator()->create_module('survey', array('course' => $course, - 'template' => 'nonexistingcode')); - $this->fail('Exception about non-existing string template is expected'); - } catch (\Exception $e) {} - } -} diff --git a/mod/survey/tests/lib_test.php b/mod/survey/tests/lib_test.php deleted file mode 100644 index 30e5135afcb..00000000000 --- a/mod/survey/tests/lib_test.php +++ /dev/null @@ -1,404 +0,0 @@ -. - -/** - * Unit tests for mod_survey lib - * - * @package mod_survey - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ -namespace mod_survey; - -defined('MOODLE_INTERNAL') || die(); - - -/** - * Unit tests for mod_survey lib - * - * @package mod_survey - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ -class lib_test extends \advanced_testcase { - - /** - * Prepares things before this test case is initialised - * @return void - */ - public static function setUpBeforeClass(): void { - global $CFG; - require_once($CFG->dirroot . '/mod/survey/lib.php'); - parent::setUpBeforeClass(); - } - - /** - * Setup testcase. - */ - public function setUp(): void { - parent::setUp(); - // Survey module is disabled by default, enable it for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - } - - /** - * Test survey_view - * @return void - */ - public function test_survey_view(): void { - global $CFG; - - $CFG->enablecompletion = 1; - $this->resetAfterTest(); - - $this->setAdminUser(); - // Setup test data. - $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id), - array('completion' => 2, 'completionview' => 1)); - $context = \context_module::instance($survey->cmid); - $cm = get_coursemodule_from_instance('survey', $survey->id); - - // Trigger and capture the event. - $sink = $this->redirectEvents(); - - survey_view($survey, $course, $cm, $context, 'form'); - - $events = $sink->get_events(); - // 2 additional events thanks to completion. - $this->assertCount(3, $events); - $event = array_shift($events); - - // Checking that the event contains the expected values. - $this->assertInstanceOf('\mod_survey\event\course_module_viewed', $event); - $this->assertEquals($context, $event->get_context()); - $moodleurl = new \moodle_url('/mod/survey/view.php', array('id' => $cm->id)); - $this->assertEquals($moodleurl, $event->get_url()); - $this->assertEquals('form', $event->other['viewed']); - $this->assertEventContextNotUsed($event); - $this->assertNotEmpty($event->get_name()); - // Check completion status. - $completion = new \completion_info($course); - $completiondata = $completion->get_data($cm); - $this->assertEquals(1, $completiondata->completionstate); - - } - - /** - * Test survey_order_questions - */ - public function test_survey_order_questions(): void { - global $DB; - - $this->resetAfterTest(); - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - $orderedquestionids = explode(',', $survey->questions); - $surveyquestions = $DB->get_records_list("survey_questions", "id", $orderedquestionids); - - $questionsordered = survey_order_questions($surveyquestions, $orderedquestionids); - - // Check one by one the correct order. - for ($i = 0; $i < count($orderedquestionids); $i++) { - $this->assertEquals($orderedquestionids[$i], $questionsordered[$i]->id); - } - } - - /** - * Test survey_save_answers - */ - public function test_survey_save_answers(): void { - global $DB; - - $this->resetAfterTest(); - $this->setAdminUser(); - - // Setup test data. - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - $context = \context_module::instance($survey->cmid); - - // Build our questions and responses array. - $realquestions = array(); - $questions = survey_get_questions($survey); - $i = 5; - foreach ($questions as $q) { - if ($q->type > 0) { - if ($q->multi) { - $subquestions = survey_get_subquestions($q); - foreach ($subquestions as $sq) { - $key = 'q' . $sq->id; - $realquestions[$key] = $i % 5 + 1; - $i++; - } - } else { - $key = 'q' . $q->id; - $realquestions[$key] = $i % 5 + 1; - $i++; - } - } - } - - $sink = $this->redirectEvents(); - survey_save_answers($survey, $realquestions, $course, $context); - - // Check the stored answers, they must match. - $dbanswers = $DB->get_records_menu('survey_answers', array('survey' => $survey->id), '', 'question, answer1'); - foreach ($realquestions as $key => $value) { - $id = str_replace('q', '', $key); - $this->assertEquals($value, $dbanswers[$id]); - } - - // Check events. - $events = $sink->get_events(); - $this->assertCount(1, $events); - $event = array_shift($events); - - // Checking that the event contains the expected values. - $this->assertInstanceOf('\mod_survey\event\response_submitted', $event); - $this->assertEquals($context, $event->get_context()); - $this->assertEquals($survey->id, $event->other['surveyid']); - } - - public function test_survey_core_calendar_provide_event_action(): void { - $this->resetAfterTest(); - $this->setAdminUser(); - - // Create the activity. - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - // Create a calendar event. - $event = $this->create_action_event($course->id, $survey->id, - \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); - - // Create an action factory. - $factory = new \core_calendar\action_factory(); - - // Decorate action event. - $actionevent = mod_survey_core_calendar_provide_event_action($event, $factory); - - // Confirm the event was decorated. - $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); - $this->assertEquals(get_string('view'), $actionevent->get_name()); - $this->assertInstanceOf('moodle_url', $actionevent->get_url()); - $this->assertEquals(1, $actionevent->get_item_count()); - $this->assertTrue($actionevent->is_actionable()); - } - - public function test_survey_core_calendar_provide_event_action_for_user(): void { - global $CFG; - - $this->resetAfterTest(); - $this->setAdminUser(); - - // Create the activity. - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - // Create a student and enrol into the course. - $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); - - // Create a calendar event. - $event = $this->create_action_event($course->id, $survey->id, - \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); - - // Now log out. - $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. - $this->setUser(); - - // Create an action factory. - $factory = new \core_calendar\action_factory(); - - // Decorate action event for the student. - $actionevent = mod_survey_core_calendar_provide_event_action($event, $factory, $student->id); - - // Confirm the event was decorated. - $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); - $this->assertEquals(get_string('view'), $actionevent->get_name()); - $this->assertInstanceOf('moodle_url', $actionevent->get_url()); - $this->assertEquals(1, $actionevent->get_item_count()); - $this->assertTrue($actionevent->is_actionable()); - } - - public function test_survey_core_calendar_provide_event_action_as_non_user(): void { - global $CFG; - - $this->resetAfterTest(); - $this->setAdminUser(); - - // Create the activity. - $course = $this->getDataGenerator()->create_course(); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id)); - - // Create a calendar event. - $event = $this->create_action_event($course->id, $survey->id, - \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); - - // Log out the user and set force login to true. - \core\session\manager::init_empty_session(); - $CFG->forcelogin = true; - - // Create an action factory. - $factory = new \core_calendar\action_factory(); - - // Decorate action event. - $actionevent = mod_survey_core_calendar_provide_event_action($event, $factory); - - // Ensure result was null. - $this->assertNull($actionevent); - } - - public function test_survey_core_calendar_provide_event_action_already_completed(): void { - global $CFG; - - $this->resetAfterTest(); - $this->setAdminUser(); - - $CFG->enablecompletion = 1; - - // Create the activity. - $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id), - array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); - - // Get some additional data. - $cm = get_coursemodule_from_instance('survey', $survey->id); - - // Create a calendar event. - $event = $this->create_action_event($course->id, $survey->id, - \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); - - // Mark the activity as completed. - $completion = new \completion_info($course); - $completion->set_module_viewed($cm); - - // Create an action factory. - $factory = new \core_calendar\action_factory(); - - // Decorate action event. - $actionevent = mod_survey_core_calendar_provide_event_action($event, $factory); - - // Ensure result was null. - $this->assertNull($actionevent); - } - - public function test_survey_core_calendar_provide_event_action_already_completed_for_user(): void { - global $CFG; - - $this->resetAfterTest(); - $this->setAdminUser(); - - $CFG->enablecompletion = 1; - - // Create the activity. - $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); - $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id), - array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS)); - - // Create 2 students and enrol them into the course. - $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); - $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); - - // Get some additional data. - $cm = get_coursemodule_from_instance('survey', $survey->id); - - // Create a calendar event. - $event = $this->create_action_event($course->id, $survey->id, - \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED); - - // Mark the activity as completed for the $student1. - $completion = new \completion_info($course); - $completion->set_module_viewed($cm, $student1->id); - - // Now log in as $student2. - $this->setUser($student2); - - // Create an action factory. - $factory = new \core_calendar\action_factory(); - - // Decorate action event for $student1. - $actionevent = mod_survey_core_calendar_provide_event_action($event, $factory, $student1->id); - - // Ensure result was null. - $this->assertNull($actionevent); - } - - /** - * Creates an action event. - * - * @param int $courseid The course id. - * @param int $instanceid The instance id. - * @param string $eventtype The event type. - * @return bool|calendar_event - */ - private function create_action_event($courseid, $instanceid, $eventtype) { - $event = new \stdClass(); - $event->name = 'Calendar event'; - $event->modulename = 'survey'; - $event->courseid = $courseid; - $event->instance = $instanceid; - $event->type = CALENDAR_EVENT_TYPE_ACTION; - $event->eventtype = $eventtype; - $event->timestart = time(); - - return \calendar_event::create($event); - } - - /** - * Test the callback responsible for returning the completion rule descriptions. - * This function should work given either an instance of the module (cm_info), such as when checking the active rules, - * or if passed a stdClass of similar structure, such as when checking the the default completion settings for a mod type. - */ - public function test_mod_survey_completion_get_active_rule_descriptions(): void { - $this->resetAfterTest(); - $this->setAdminUser(); - - // Two activities, both with automatic completion. One has the 'completionsubmit' rule, one doesn't. - $course = $this->getDataGenerator()->create_course(['enablecompletion' => 2]); - $survey1 = $this->getDataGenerator()->create_module('survey', [ - 'course' => $course->id, - 'completion' => 2, - 'completionsubmit' => 1, - ]); - $survey2 = $this->getDataGenerator()->create_module('survey', [ - 'course' => $course->id, - 'completion' => 2, - 'completionsubmit' => 0, - ]); - $cm1 = \cm_info::create(get_coursemodule_from_instance('survey', $survey1->id)); - $cm2 = \cm_info::create(get_coursemodule_from_instance('survey', $survey2->id)); - - // Data for the stdClass input type. - // This type of input would occur when checking the default completion rules for an activity type, where we don't have - // any access to cm_info, rather the input is a stdClass containing completion and customdata attributes, just like cm_info. - $moddefaults = new \stdClass(); - $moddefaults->customdata = ['customcompletionrules' => ['completionsubmit' => 1]]; - $moddefaults->completion = 2; - - $activeruledescriptions = [get_string('completionsubmit', 'survey')]; - $this->assertEquals(mod_survey_get_completion_active_rule_descriptions($cm1), $activeruledescriptions); - $this->assertEquals(mod_survey_get_completion_active_rule_descriptions($cm2), []); - $this->assertEquals(mod_survey_get_completion_active_rule_descriptions($moddefaults), $activeruledescriptions); - $this->assertEquals(mod_survey_get_completion_active_rule_descriptions(new \stdClass()), []); - } -} diff --git a/mod/survey/tests/privacy/provider_test.php b/mod/survey/tests/privacy/provider_test.php deleted file mode 100644 index 356aac1facb..00000000000 --- a/mod/survey/tests/privacy/provider_test.php +++ /dev/null @@ -1,534 +0,0 @@ -. - -/** - * Data provider tests. - * - * @package mod_survey - * @category test - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace mod_survey\privacy; - -defined('MOODLE_INTERNAL') || die(); -global $CFG; - -use core_privacy\tests\provider_testcase; -use core_privacy\local\request\approved_contextlist; -use core_privacy\local\request\approved_userlist; -use core_privacy\local\request\transform; -use core_privacy\local\request\writer; -use mod_survey\privacy\provider; - -require_once($CFG->dirroot . '/mod/survey/lib.php'); - -/** - * Data provider testcase class. - * - * @package mod_survey - * @category test - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class provider_test extends provider_testcase { - - public function setUp(): void { - global $PAGE; - parent::setUp(); - $this->resetAfterTest(); - $PAGE->get_renderer('core'); - - // Survey module is disabled by default, enable it for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - } - - public function test_get_contexts_for_userid(): void { - $dg = $this->getDataGenerator(); - - $c1 = $dg->create_course(); - $c2 = $dg->create_course(); - $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]); - $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm2a = $dg->create_module('survey', ['template' => 1, 'course' => $c2]); - $cm2b = $dg->create_module('survey', ['template' => 1, 'course' => $c2]); - $u1 = $dg->create_user(); - $u2 = $dg->create_user(); - - $this->create_answer($cm1a->id, 1, $u1->id); - $this->create_answer($cm1a->id, 1, $u2->id); - $this->create_answer($cm1b->id, 1, $u2->id); - $this->create_answer($cm2a->id, 1, $u1->id); - $this->create_analysis($cm2b->id, $u1->id); - $this->create_analysis($cm1c->id, $u2->id); - - $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); - $this->assertCount(3, $contextids); - $this->assertTrue(in_array(\context_module::instance($cm1a->cmid)->id, $contextids)); - $this->assertTrue(in_array(\context_module::instance($cm2a->cmid)->id, $contextids)); - $this->assertTrue(in_array(\context_module::instance($cm2b->cmid)->id, $contextids)); - - $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); - $this->assertCount(3, $contextids); - $this->assertTrue(in_array(\context_module::instance($cm1a->cmid)->id, $contextids)); - $this->assertTrue(in_array(\context_module::instance($cm1b->cmid)->id, $contextids)); - $this->assertTrue(in_array(\context_module::instance($cm1c->cmid)->id, $contextids)); - } - - /** - * Test for provider::test_get_users_in_context(). - */ - public function test_get_users_in_context(): void { - $dg = $this->getDataGenerator(); - $component = 'mod_survey'; - - $c1 = $dg->create_course(); - $c2 = $dg->create_course(); - $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]); - $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm2 = $dg->create_module('survey', ['template' => 1, 'course' => $c2]); - $cm1acontext = \context_module::instance($cm1a->cmid); - $cm1bcontext = \context_module::instance($cm1b->cmid); - $cm2context = \context_module::instance($cm2->cmid); - - $u1 = $dg->create_user(); - $u2 = $dg->create_user(); - $bothusers = [$u1->id, $u2->id]; - sort($bothusers); - - $this->create_answer($cm1a->id, 1, $u1->id); - $this->create_answer($cm1b->id, 1, $u1->id); - $this->create_answer($cm1b->id, 1, $u2->id); - $this->create_answer($cm2->id, 1, $u2->id); - $this->create_analysis($cm2->id, $u1->id); - - // Cm1a should only contain u1. - $userlist = new \core_privacy\local\request\userlist($cm1acontext, $component); - provider::get_users_in_context($userlist); - - $this->assertCount(1, $userlist); - $this->assertEquals([$u1->id], $userlist->get_userids()); - - // Cm1b should contain u1 and u2 (both have answers). - $userlist = new \core_privacy\local\request\userlist($cm1bcontext, $component); - provider::get_users_in_context($userlist); - - $this->assertCount(2, $userlist); - $actual = $userlist->get_userids(); - sort($actual); - $this->assertEquals($bothusers, $actual); - - // Cm2 should contain u1 (analysis) and u2 (answer). - $userlist = new \core_privacy\local\request\userlist($cm2context, $component); - provider::get_users_in_context($userlist); - - $this->assertCount(2, $userlist); - $actual = $userlist->get_userids(); - sort($actual); - $this->assertEquals($bothusers, $actual); - } - - public function test_delete_data_for_all_users_in_context(): void { - global $DB; - $dg = $this->getDataGenerator(); - - $c1 = $dg->create_course(); - $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]); - $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $u1 = $dg->create_user(); - $u2 = $dg->create_user(); - - $this->create_answer($cm1a->id, 1, $u1->id); - $this->create_answer($cm1a->id, 1, $u2->id); - $this->create_answer($cm1b->id, 1, $u2->id); - $this->create_answer($cm1c->id, 1, $u1->id); - $this->create_analysis($cm1a->id, $u1->id); - $this->create_analysis($cm1b->id, $u1->id); - $this->create_analysis($cm1a->id, $u2->id); - $this->create_analysis($cm1c->id, $u2->id); - - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - - // Deleting the course does nothing. - provider::delete_data_for_all_users_in_context(\context_course::instance($c1->id)); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - - provider::delete_data_for_all_users_in_context(\context_module::instance($cm1c->cmid)); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - - provider::delete_data_for_all_users_in_context(\context_module::instance($cm1a->cmid)); - $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - } - - public function test_delete_data_for_user(): void { - global $DB; - $dg = $this->getDataGenerator(); - - $c1 = $dg->create_course(); - $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]); - $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $u1 = $dg->create_user(); - $u2 = $dg->create_user(); - - $this->create_answer($cm1a->id, 1, $u1->id); - $this->create_answer($cm1a->id, 1, $u2->id); - $this->create_answer($cm1b->id, 1, $u2->id); - $this->create_answer($cm1c->id, 1, $u1->id); - $this->create_analysis($cm1a->id, $u1->id); - $this->create_analysis($cm1b->id, $u1->id); - $this->create_analysis($cm1a->id, $u2->id); - $this->create_analysis($cm1c->id, $u2->id); - - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - - provider::delete_data_for_user(new approved_contextlist($u1, 'mod_survey', [ - \context_course::instance($c1->id)->id, - \context_module::instance($cm1a->cmid)->id, - \context_module::instance($cm1b->cmid)->id, - ])); - $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - } - - /** - * Test for provider::delete_data_for_users(). - */ - public function test_delete_data_for_users(): void { - global $DB; - $dg = $this->getDataGenerator(); - $component = 'mod_survey'; - - $c1 = $dg->create_course(); - $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]); - $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]); - $cm1acontext = \context_module::instance($cm1a->cmid); - $cm1bcontext = \context_module::instance($cm1b->cmid); - - $u1 = $dg->create_user(); - $u2 = $dg->create_user(); - - $this->create_answer($cm1a->id, 1, $u1->id); - $this->create_answer($cm1a->id, 1, $u2->id); - $this->create_analysis($cm1a->id, $u1->id); - $this->create_analysis($cm1a->id, $u2->id); - $this->create_answer($cm1b->id, 1, $u2->id); - $this->create_analysis($cm1b->id, $u1->id); - $this->create_answer($cm1c->id, 1, $u1->id); - $this->create_analysis($cm1c->id, $u2->id); - - // Confirm data exists before deletion. - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - - // Ensure only approved user data is deleted. - $approveduserids = [$u1->id]; - $approvedlist = new approved_userlist($cm1acontext, $component, $approveduserids); - provider::delete_data_for_users($approvedlist); - - $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id])); - - $approveduserids = [$u1->id, $u2->id]; - $approvedlist = new approved_userlist($cm1bcontext, $component, $approveduserids); - provider::delete_data_for_users($approvedlist); - - $this->assertFalse($DB->record_exists('survey_answers', ['survey' => $cm1b->id])); - $this->assertFalse($DB->record_exists('survey_analysis', ['survey' => $cm1b->id])); - - $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id])); - $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id])); - } - - public function test_export_data_for_user(): void { - global $DB; - $dg = $this->getDataGenerator(); - - $templates = $DB->get_records_menu('survey', array('template' => 0), 'name', 'name, id'); - - $c1 = $dg->create_course(); - $s1a = $dg->create_module('survey', ['template' => $templates['attlsname'], 'course' => $c1]); - $s1b = $dg->create_module('survey', ['template' => $templates['ciqname'], 'course' => $c1]); - $s1c = $dg->create_module('survey', ['template' => $templates['collesapname'], 'course' => $c1]); - $u1 = $dg->create_user(); - $u2 = $dg->create_user(); - - $s1actx = \context_module::instance($s1a->cmid); - $s1bctx = \context_module::instance($s1b->cmid); - $s1cctx = \context_module::instance($s1c->cmid); - - $this->answer_survey($s1a, $u1, $c1, $s1actx); - $this->answer_survey($s1b, $u1, $c1, $s1bctx); - $this->create_analysis($s1a->id, $u1->id, 'Hello,'); - - $this->answer_survey($s1a, $u2, $c1, $s1actx); - $this->answer_survey($s1c, $u2, $c1, $s1cctx); - $this->create_analysis($s1b->id, $u2->id, 'World!'); - - provider::export_user_data(new approved_contextlist($u1, 'mod_survey', [$s1actx->id, $s1bctx->id, $s1cctx->id])); - - $data = writer::with_context($s1actx)->get_data([]); - $this->assertNotEmpty($data); - $this->assert_exported_answers($data->answers, $u1, $s1a); - $data = writer::with_context($s1actx)->get_related_data([], 'survey_analysis'); - $this->assertEquals('Hello,', $data->notes); - - $data = writer::with_context($s1bctx)->get_data([]); - $this->assertNotEmpty($data); - $this->assert_exported_answers($data->answers, $u1, $s1b); - $data = writer::with_context($s1bctx)->get_related_data([], 'survey_analysis'); - $this->assertEmpty($data); - - $data = writer::with_context($s1cctx)->get_data([]); - $this->assertEmpty($data); - $data = writer::with_context($s1cctx)->get_related_data([], 'survey_analysis'); - $this->assertEmpty($data); - - writer::reset(); - provider::export_user_data(new approved_contextlist($u2, 'mod_survey', [$s1actx->id, $s1bctx->id, $s1cctx->id])); - - $data = writer::with_context($s1actx)->get_data([]); - $this->assertNotEmpty($data); - $this->assert_exported_answers($data->answers, $u2, $s1a); - $data = writer::with_context($s1actx)->get_related_data([], 'survey_analysis'); - $this->assertEmpty($data); - - $data = writer::with_context($s1bctx)->get_data([]); - $this->assertEmpty($data); - $data = writer::with_context($s1bctx)->get_related_data([], 'survey_analysis'); - $this->assertEquals('World!', $data->notes); - - $data = writer::with_context($s1cctx)->get_data([]); - $this->assertNotEmpty($data); - $this->assert_exported_answers($data->answers, $u2, $s1c); - $data = writer::with_context($s1cctx)->get_related_data([], 'survey_analysis'); - $this->assertEmpty($data); - } - - /** - * Answer a survey in a predictable manner. - * - * @param stdClass $survey The survey. - * @param stdClass $user The user. - * @param stdClass $course The course. - * @param context_module $context The module context. - * @return void - */ - protected function answer_survey($survey, $user, $course, \context_module $context) { - global $USER; - - $userid = $user->id; - $questions = survey_get_questions($survey); - $answer = function(&$answers, $q) use ($userid) { - $key = 'q' . ($q->type == 2 ? 'P' : '') . $q->id; - - if ($q->type < 1) { - $a = "A:{$q->id}:{$userid}"; - $answers[$key] = $a; - - } else if ($q->type < 3) { - $options = explode(',', get_string($q->options, 'mod_survey')); - $answers[$key] = ($q->id + $userid) % count($options) + 1; - - } else { - $options = explode(',', get_string($q->options, 'mod_survey')); - $answers["q{$q->id}"] = ($q->id + $userid) % count($options) + 1; - $answers["qP{$q->id}"] = ($q->id + $userid + 1) % count($options) + 1; - } - - }; - - foreach ($questions as $q) { - if ($q->type < 0) { - continue; - } else if ($q->type > 0 && $q->multi) { - $subquestions = survey_get_subquestions($q); - foreach ($subquestions as $sq) { - $answer($answers, $sq); - } - } else { - $answer($answers, $q); - } - } - - $origuser = $USER; - $this->setUser($user); - survey_save_answers($survey, $answers, $course, $context); - $this->setUser($origuser); - } - - /** - * Assert the answers provided to a survey. - * - * @param array $answers The answers. - * @param object $user The user. - * @param object $survey The survey. - * @return void - */ - protected function assert_exported_answers($answers, $user, $survey) { - global $DB; - - $userid = $user->id; - $questionids = explode(',', $survey->questions); - $topquestions = $DB->get_records_list('survey_questions', 'id', $questionids, 'id'); - $questions = []; - - foreach ($topquestions as $q) { - if ($q->type < 0) { - continue; - } else if ($q->type > 0 && $q->multi) { - $questionids = explode(',', $q->multi); - $subqs = $DB->get_records_list('survey_questions', 'id', $questionids, 'id'); - } else { - $subqs = [$q]; - } - foreach ($subqs as $sq) { - $questions[] = $sq; - } - } - - $this->assertCount(count($questions), $answers); - - $answer = reset($answers); - foreach ($questions as $question) { - $qtype = $question->type; - $question = survey_translate_question($question); - $options = $qtype > 0 ? explode(',', $question->options) : '-'; - $this->assertEquals($question->text, $answer['question']['text']); - $this->assertEquals($question->shorttext, $answer['question']['shorttext']); - $this->assertEquals($question->intro, $answer['question']['intro']); - $this->assertEquals($options, $answer['question']['options']); - - if ($qtype < 1) { - $this->assertEquals("A:{$question->id}:{$userid}", $answer['answer']['actual']); - - } else if ($qtype == 1 || $qtype == 2) { - $chosen = ($question->id + $userid) % count($options); - $key = $qtype == 1 ? 'actual' : 'preferred'; - $this->assertEquals($options[$chosen], $answer['answer'][$key]); - - } else { - $chosen = ($question->id + $userid) % count($options); - $this->assertEquals($options[$chosen], $answer['answer']['actual']); - $chosen = ($question->id + $userid + 1) % count($options); - $this->assertEquals($options[$chosen], $answer['answer']['preferred']); - } - - // Grab next answer, if any. - $answer = next($answers); - } - - } - - /** - * Create analysis. - * - * @param int $surveyid The survey ID. - * @param int $userid The user ID. - * @param string $notes The nodes. - * @return stdClass - */ - protected function create_analysis($surveyid, $userid, $notes = '') { - global $DB; - $record = (object) [ - 'survey' => $surveyid, - 'userid' => $userid, - 'notes' => $notes - ]; - $record->id = $DB->insert_record('survey_analysis', $record); - return $record; - } - - /** - * Create answer. - * - * @param int $surveyid The survey ID. - * @param int $questionid The question ID. - * @param int $userid The user ID. - * @param string $answer1 The first answer field. - * @param string $answer2 The second answer field. - * @return stdClass - */ - protected function create_answer($surveyid, $questionid, $userid, $answer1 = '', $answer2 = '') { - global $DB; - $record = (object) [ - 'survey' => $surveyid, - 'question' => $questionid, - 'userid' => $userid, - 'answer1' => $answer1, - 'answer2' => $answer2, - 'time' => time() - ]; - $record->id = $DB->insert_record('survey_answers', $record); - return $record; - } - -} diff --git a/mod/survey/tests/search/search_test.php b/mod/survey/tests/search/search_test.php deleted file mode 100644 index 6f72a731aeb..00000000000 --- a/mod/survey/tests/search/search_test.php +++ /dev/null @@ -1,85 +0,0 @@ -. - -/** - * Unit test for mod_survey searching. - * - * This is needed because the activity.php class overrides default behaviour. - * - * @package mod_survey - * @category test - * @copyright 2017 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_survey\search; - -/** - * Unit test for mod_survey searching. - * - * This is needed because the activity.php class overrides default behaviour. - * - * @package mod_survey - * @category test - * @copyright 2017 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class search_test extends \advanced_testcase { - - /** - * Setup testcase. - */ - public function setUp(): void { - parent::setUp(); - // Survey module is disabled by default, enable it for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - } - - /** - * Test survey_view - * @return void - */ - public function test_survey_indexing(): void { - global $CFG; - - $this->resetAfterTest(); - - require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php'); - \testable_core_search::instance(); - $area = \core_search\manager::get_search_area('mod_survey-activity'); - - // Setup test data. - $generator = $this->getDataGenerator(); - $course = $generator->create_course(); - $survey1 = $generator->create_module('survey', ['course' => $course->id]); - $survey2 = $generator->create_module('survey', ['course' => $course->id]); - - // Get all surveys for indexing - note that there are special entries in the table with - // course zero which should not be returned. - $rs = $area->get_document_recordset(); - $this->assertEquals(2, iterator_count($rs)); - $rs->close(); - - // Test specific context and course context. - $rs = $area->get_document_recordset(0, \context_module::instance($survey1->cmid)); - $this->assertEquals(1, iterator_count($rs)); - $rs->close(); - $rs = $area->get_document_recordset(0, \context_course::instance($course->id)); - $this->assertEquals(2, iterator_count($rs)); - $rs->close(); - } -} diff --git a/mod/survey/version.php b/mod/survey/version.php deleted file mode 100644 index 821f1bfebd3..00000000000 --- a/mod/survey/version.php +++ /dev/null @@ -1,30 +0,0 @@ -. - -/** - * Version information - * - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->version = 2024100700; // The current module version (Date: YYYYMMDDXX). -$plugin->requires = 2024100100; // Requires this Moodle version. -$plugin->component = 'mod_survey'; // Full name of the plugin (used for diagnostics) -$plugin->cron = 0; diff --git a/mod/survey/view.php b/mod/survey/view.php deleted file mode 100644 index 078530887b8..00000000000 --- a/mod/survey/view.php +++ /dev/null @@ -1,184 +0,0 @@ -. - -/** - * This file is responsible for displaying the survey - * - * @package mod_survey - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -require_once("../../config.php"); -require_once("lib.php"); - -$id = required_param('id', PARAM_INT); // Course Module ID. - -if (! $cm = get_coursemodule_from_id('survey', $id)) { - throw new \moodle_exception('invalidcoursemodule'); -} - -$cm = cm_info::create($cm); - -if (! $course = $DB->get_record("course", array("id" => $cm->course))) { - throw new \moodle_exception('coursemisconf'); -} - -$PAGE->set_url('/mod/survey/view.php', array('id' => $id)); -require_login($course, false, $cm); -$context = context_module::instance($cm->id); - -require_capability('mod/survey:participate', $context); - -if (! $survey = $DB->get_record("survey", array("id" => $cm->instance))) { - throw new \moodle_exception('invalidsurveyid', 'survey'); -} - -if (! $template = $DB->get_record("survey", array("id" => $survey->template))) { - throw new \moodle_exception('invalidtmptid', 'survey'); -} - -$showscales = ($template->name != 'ciqname'); - -// Check the survey hasn't already been filled out. -$surveyalreadydone = survey_already_done($survey->id, $USER->id); -if ($surveyalreadydone) { - // Trigger course_module_viewed event and completion. - survey_view($survey, $course, $cm, $context, 'graph'); -} else { - survey_view($survey, $course, $cm, $context, 'form'); -} - -$strsurvey = get_string("modulename", "survey"); -$PAGE->set_title($survey->name); -$PAGE->set_heading($course->fullname); -// No need to show the description if the survey is done and a graph page is to be shown. -if ($surveyalreadydone && $showscales) { - $PAGE->activityheader->set_description(''); -} else { - // If the survey has empty description, display the default one. - $trimmedintro = trim($survey->intro); - if (empty($trimmedintro)) { - $tempo = $DB->get_field("survey", "intro", array("id" => $survey->template)); - $PAGE->activityheader->set_description(get_string($tempo, "survey")); - } -} -$PAGE->add_body_class('limitedwidth'); - -echo $OUTPUT->header(); - -// Check to see if groups are being used in this survey. -if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used. - $currentgroup = groups_get_activity_group($cm); -} else { - $currentgroup = 0; -} -$groupingid = $cm->groupingid; - -if (has_capability('mod/survey:readresponses', $context) or ($groupmode == VISIBLEGROUPS)) { - $currentgroup = 0; -} - -if (!$cm->visible) { - notice(get_string("activityiscurrentlyhidden")); -} - -if (!is_enrolled($context)) { - echo $OUTPUT->notification(get_string("guestsnotallowed", "survey")); -} - -if ($surveyalreadydone) { - $numusers = survey_count_responses($survey->id, $currentgroup, $groupingid); - if ($showscales) { - // Ensure that graph.php will allow the user to see the graph. - if (has_capability('mod/survey:readresponses', $context) || !$groupmode || groups_is_member($currentgroup)) { - - echo $OUTPUT->box(get_string("surveycompleted", "survey")); - echo $OUTPUT->box(get_string("peoplecompleted", "survey", $numusers)); - - echo '
'; - survey_print_graph("id=$cm->id&sid=$USER->id&group=$currentgroup&type=student.png"); - echo '
'; - } else { - echo $OUTPUT->box(get_string("surveycompletednograph", "survey")); - echo $OUTPUT->box(get_string("peoplecompleted", "survey", $numusers)); - } - - } else { - - echo $OUTPUT->spacer(array('height' => 30, 'width' => 1), true); // Should be done with CSS instead. - - $questions = survey_get_questions($survey); - foreach ($questions as $question) { - - if ($question->type == 0 or $question->type == 1) { - if ($answer = survey_get_user_answer($survey->id, $question->id, $USER->id)) { - $table = new html_table(); - $table->head = array(get_string($question->text, "survey")); - $table->align = array ("left"); - $table->data[] = array(s($answer->answer1));// No html here, just plain text. - echo html_writer::table($table); - echo $OUTPUT->spacer(array('height' => 30, 'width' => 1), true); - } - } - } - } - - echo $OUTPUT->footer(); - exit; -} - -echo "
"; -echo '
'; -echo ""; -echo ""; - -echo '
'. get_string('allquestionrequireanswer', 'survey'). '
'; - -// Get all the major questions in order. -$questions = survey_get_questions($survey); - -global $qnum; // TODO: ugly globals hack for survey_print_*(). -$qnum = 0; -foreach ($questions as $question) { - - if ($question->type >= 0) { - - $question = survey_translate_question($question); - - if ($question->multi) { - survey_print_multi($question); - } else { - survey_print_single($question); - } - } -} - -if (!is_enrolled($context)) { - echo '
'; - echo "
"; - echo $OUTPUT->footer(); - exit; -} - -$PAGE->requires->js_call_amd('mod_survey/validation', 'ensureRadiosChosen', array('surveyform')); - -echo '
'; -echo ''; -echo ''; -echo ""; - -echo $OUTPUT->footer(); diff --git a/version.php b/version.php index 79d7bbf8ebd..5ce882bc91c 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2024120500.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2024120500.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '5.0dev (Build: 20241205)'; // Human-friendly version name From 8e5ac0e34f89d76d35ccaae3db563e0cc6c2f82e Mon Sep 17 00:00:00 2001 From: Laurent David Date: Thu, 31 Oct 2024 10:45:58 +0100 Subject: [PATCH 2/8] MDL-82457 mod_chat: Remove mod_chat from Moodle 5.0 --- .upgradenotes/MDL-82457-2024103109453585.yml | 5 + lib/db/upgrade.php | 9 + mod/chat/README.txt | 34 - mod/chat/backup/moodle1/lib.php | 138 -- .../backup_chat_activity_task.class.php | 69 - .../backup/moodle2/backup_chat_stepslib.php | 67 - .../restore_chat_activity_task.class.php | 111 -- .../backup/moodle2/restore_chat_stepslib.php | 83 - mod/chat/beep.mp3 | Bin 969 -> 0 bytes mod/chat/chat_ajax.php | 162 -- mod/chat/chatd.php | 1093 ----------- .../analytics/indicator/activity_base.php | 111 -- .../analytics/indicator/cognitive_depth.php | 56 - .../analytics/indicator/social_breadth.php | 56 - mod/chat/classes/dates.php | 58 - .../course_module_instance_list_viewed.php | 38 - .../classes/event/course_module_viewed.php | 47 - mod/chat/classes/event/message_sent.php | 93 - mod/chat/classes/event/sessions_viewed.php | 108 -- mod/chat/classes/external.php | 833 --------- .../external/chat_message_exporter.php | 101 - mod/chat/classes/external/view_sessions.php | 121 -- mod/chat/classes/privacy/provider.php | 333 ---- mod/chat/classes/search/activity.php | 46 - mod/chat/classes/task/cron_task.php | 65 - mod/chat/db/access.php | 114 -- mod/chat/db/events.php | 34 - mod/chat/db/install.php | 33 - mod/chat/db/install.xml | 94 - mod/chat/db/log.php | 34 - mod/chat/db/services.php | 108 -- mod/chat/db/tasks.php | 36 - mod/chat/db/upgrade.php | 39 - mod/chat/empty.php | 9 - mod/chat/gui_ajax/index.php | 114 -- mod/chat/gui_ajax/module.js | 265 --- mod/chat/gui_ajax/theme/bubble/bubbles.png | Bin 1612 -> 0 bytes mod/chat/gui_ajax/theme/bubble/chat.css | 249 --- mod/chat/gui_ajax/theme/bubble/config.php | 50 - mod/chat/gui_ajax/theme/bubble/horizontal.png | Bin 282 -> 0 bytes mod/chat/gui_ajax/theme/bubble/input.png | Bin 95 -> 0 bytes mod/chat/gui_ajax/theme/bubble/vertical.png | Bin 191 -> 0 bytes mod/chat/gui_ajax/theme/compact/chat.css | 102 -- mod/chat/gui_ajax/theme/compact/config.php | 37 - mod/chat/gui_ajax/theme/compact/input.png | Bin 95 -> 0 bytes .../gui_ajax/theme/course_theme/config.php | 37 - mod/chat/gui_basic/index.php | 213 --- mod/chat/gui_header_js/chatinput.php | 80 - mod/chat/gui_header_js/chatmsg.php | 8 - mod/chat/gui_header_js/index.php | 100 - mod/chat/gui_header_js/insert.php | 78 - mod/chat/gui_header_js/jsupdate.php | 192 -- mod/chat/gui_header_js/jsupdated.php | 248 --- mod/chat/gui_header_js/module.js | 150 -- mod/chat/gui_header_js/users.php | 141 -- mod/chat/gui_sockets/chat_gui_sockets.js | 14 - mod/chat/gui_sockets/chatinput.php | 59 - mod/chat/gui_sockets/index.php | 92 - mod/chat/index.php | 105 -- mod/chat/lang/en/chat.php | 177 -- mod/chat/lib.php | 1630 ----------------- mod/chat/locallib.php | 254 --- mod/chat/mod_form.php | 80 - mod/chat/pix/monologo.svg | 6 - mod/chat/renderer.php | 106 -- mod/chat/report.php | 274 --- mod/chat/settings.php | 62 - mod/chat/styles.css | 114 -- mod/chat/tests/backup/restore_date_test.php | 64 - mod/chat/tests/behat/behat_mod_chat.php | 76 - .../behat/chat_activity_completion.feature | 56 - .../tests/behat/chat_calendar_events.feature | 36 - .../tests/behat/chat_course_reset.feature | 56 - mod/chat/tests/behat/chat_group_mode.feature | 61 - .../chat_no_calendar_capabilities.feature | 49 - .../behat/chat_view_past_session.feature | 48 - mod/chat/tests/dates_test.php | 138 -- mod/chat/tests/event/events_test.php | 185 -- .../tests/external/view_sessions_test.php | 139 -- mod/chat/tests/externallib_test.php | 502 ----- mod/chat/tests/format_message_test.php | 163 -- mod/chat/tests/generator/lib.php | 75 - mod/chat/tests/generator_test.php | 57 - mod/chat/tests/lib_test.php | 748 -------- mod/chat/tests/privacy/provider_test.php | 439 ----- mod/chat/upgrade.txt | 18 - mod/chat/version.php | 29 - mod/chat/view.php | 179 -- version.php | 2 +- 89 files changed, 15 insertions(+), 12480 deletions(-) create mode 100644 .upgradenotes/MDL-82457-2024103109453585.yml delete mode 100644 mod/chat/README.txt delete mode 100644 mod/chat/backup/moodle1/lib.php delete mode 100644 mod/chat/backup/moodle2/backup_chat_activity_task.class.php delete mode 100644 mod/chat/backup/moodle2/backup_chat_stepslib.php delete mode 100644 mod/chat/backup/moodle2/restore_chat_activity_task.class.php delete mode 100644 mod/chat/backup/moodle2/restore_chat_stepslib.php delete mode 100644 mod/chat/beep.mp3 delete mode 100644 mod/chat/chat_ajax.php delete mode 100644 mod/chat/chatd.php delete mode 100644 mod/chat/classes/analytics/indicator/activity_base.php delete mode 100644 mod/chat/classes/analytics/indicator/cognitive_depth.php delete mode 100644 mod/chat/classes/analytics/indicator/social_breadth.php delete mode 100644 mod/chat/classes/dates.php delete mode 100644 mod/chat/classes/event/course_module_instance_list_viewed.php delete mode 100644 mod/chat/classes/event/course_module_viewed.php delete mode 100644 mod/chat/classes/event/message_sent.php delete mode 100644 mod/chat/classes/event/sessions_viewed.php delete mode 100644 mod/chat/classes/external.php delete mode 100644 mod/chat/classes/external/chat_message_exporter.php delete mode 100644 mod/chat/classes/external/view_sessions.php delete mode 100644 mod/chat/classes/privacy/provider.php delete mode 100644 mod/chat/classes/search/activity.php delete mode 100644 mod/chat/classes/task/cron_task.php delete mode 100644 mod/chat/db/access.php delete mode 100644 mod/chat/db/events.php delete mode 100644 mod/chat/db/install.php delete mode 100644 mod/chat/db/install.xml delete mode 100644 mod/chat/db/log.php delete mode 100644 mod/chat/db/services.php delete mode 100644 mod/chat/db/tasks.php delete mode 100644 mod/chat/db/upgrade.php delete mode 100644 mod/chat/empty.php delete mode 100644 mod/chat/gui_ajax/index.php delete mode 100644 mod/chat/gui_ajax/module.js delete mode 100644 mod/chat/gui_ajax/theme/bubble/bubbles.png delete mode 100644 mod/chat/gui_ajax/theme/bubble/chat.css delete mode 100644 mod/chat/gui_ajax/theme/bubble/config.php delete mode 100644 mod/chat/gui_ajax/theme/bubble/horizontal.png delete mode 100644 mod/chat/gui_ajax/theme/bubble/input.png delete mode 100644 mod/chat/gui_ajax/theme/bubble/vertical.png delete mode 100644 mod/chat/gui_ajax/theme/compact/chat.css delete mode 100644 mod/chat/gui_ajax/theme/compact/config.php delete mode 100644 mod/chat/gui_ajax/theme/compact/input.png delete mode 100644 mod/chat/gui_ajax/theme/course_theme/config.php delete mode 100644 mod/chat/gui_basic/index.php delete mode 100644 mod/chat/gui_header_js/chatinput.php delete mode 100644 mod/chat/gui_header_js/chatmsg.php delete mode 100644 mod/chat/gui_header_js/index.php delete mode 100644 mod/chat/gui_header_js/insert.php delete mode 100644 mod/chat/gui_header_js/jsupdate.php delete mode 100644 mod/chat/gui_header_js/jsupdated.php delete mode 100644 mod/chat/gui_header_js/module.js delete mode 100644 mod/chat/gui_header_js/users.php delete mode 100644 mod/chat/gui_sockets/chat_gui_sockets.js delete mode 100644 mod/chat/gui_sockets/chatinput.php delete mode 100644 mod/chat/gui_sockets/index.php delete mode 100644 mod/chat/index.php delete mode 100644 mod/chat/lang/en/chat.php delete mode 100644 mod/chat/lib.php delete mode 100644 mod/chat/locallib.php delete mode 100644 mod/chat/mod_form.php delete mode 100644 mod/chat/pix/monologo.svg delete mode 100644 mod/chat/renderer.php delete mode 100644 mod/chat/report.php delete mode 100644 mod/chat/settings.php delete mode 100644 mod/chat/styles.css delete mode 100644 mod/chat/tests/backup/restore_date_test.php delete mode 100644 mod/chat/tests/behat/behat_mod_chat.php delete mode 100644 mod/chat/tests/behat/chat_activity_completion.feature delete mode 100644 mod/chat/tests/behat/chat_calendar_events.feature delete mode 100644 mod/chat/tests/behat/chat_course_reset.feature delete mode 100644 mod/chat/tests/behat/chat_group_mode.feature delete mode 100644 mod/chat/tests/behat/chat_no_calendar_capabilities.feature delete mode 100644 mod/chat/tests/behat/chat_view_past_session.feature delete mode 100644 mod/chat/tests/dates_test.php delete mode 100644 mod/chat/tests/event/events_test.php delete mode 100644 mod/chat/tests/external/view_sessions_test.php delete mode 100644 mod/chat/tests/externallib_test.php delete mode 100644 mod/chat/tests/format_message_test.php delete mode 100644 mod/chat/tests/generator/lib.php delete mode 100644 mod/chat/tests/generator_test.php delete mode 100644 mod/chat/tests/lib_test.php delete mode 100644 mod/chat/tests/privacy/provider_test.php delete mode 100644 mod/chat/upgrade.txt delete mode 100644 mod/chat/version.php delete mode 100644 mod/chat/view.php diff --git a/.upgradenotes/MDL-82457-2024103109453585.yml b/.upgradenotes/MDL-82457-2024103109453585.yml new file mode 100644 index 00000000000..75f62132fe8 --- /dev/null +++ b/.upgradenotes/MDL-82457-2024103109453585.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-82457 +notes: + mod: + - message: Remove mod_chat from Moodle 5.0 + type: removed diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index c9032d23690..2b645c0ad73 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1312,5 +1312,14 @@ function xmldb_main_upgrade($oldversion) { // Main savepoint reached. upgrade_main_savepoint(true, 2024120500.01); } + + // Remove chat. + if ($oldversion < 2024120500.02) { + if (!file_exists($CFG->dirroot . "/mod/chat/version.php")) { + uninstall_plugin('mod', 'chat'); + } + // Main savepoint reached. + upgrade_main_savepoint(true, 2024120500.02); + } return true; } diff --git a/mod/chat/README.txt b/mod/chat/README.txt deleted file mode 100644 index d495677cca0..00000000000 --- a/mod/chat/README.txt +++ /dev/null @@ -1,34 +0,0 @@ -Official Chat Module for Moodle ------------------------------- - -The chat module now supports a backend daemon for -more efficiency. - -It's still buggy and being worked on, but if you -want to test it and help out here are some quick -instructions: - -1) Admin -> Config -> Modules -> Chat -> Settings - -2) Set the method to "sockets" and set up the ports etc - -3) Start the server like this (from the Unix command line): - - cd moodle/mod/chat - php chatd.php --start & - -4) Go to a chat room in Moodle and open it as normal. - ------- - -KNOWN PROBLEMS - - - User list is not always working - - Some browsers (eg Safari) cause lines to be repeated - by 10 - 20 times - - Occasionally "Document was empty" messages - -Help solving these very welcome! - - -Martin, 31 July 2004 diff --git a/mod/chat/backup/moodle1/lib.php b/mod/chat/backup/moodle1/lib.php deleted file mode 100644 index 1e7d2a7dda8..00000000000 --- a/mod/chat/backup/moodle1/lib.php +++ /dev/null @@ -1,138 +0,0 @@ -. - -/** - * 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_chat - * @copyright 2011 Aparup Banerjee - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Chat conversion handler - */ -class moodle1_mod_chat_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/CHAT 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( - 'chat', '/MOODLE_BACKUP/COURSE/MODULES/MOD/CHAT', - array( - 'newfields' => array( - 'introformat' => 0 - ) - ) - ) - ); - } - - /** - * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/CHAT - * data available - */ - public function process_chat($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); - - // Replay the upgrade step 2010050101. - if ($CFG->texteditors !== 'textarea') { - $data['intro'] = text_to_html($data['intro'], false, false, true); - $data['introformat'] = FORMAT_HTML; - } - - // Get a fresh new file manager for this instance. - $this->fileman = $this->converter->get_file_manager($contextid, 'mod_chat'); - - // 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 chat.xml. - $this->open_xml_writer("activities/chat_{$this->moduleid}/chat.xml"); - $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $this->moduleid, - 'modulename' => 'chat', 'contextid' => $contextid)); - $this->xmlwriter->begin_tag('chat', array('id' => $instanceid)); - - foreach ($data as $field => $value) { - if ($field <> 'id') { - $this->xmlwriter->full_tag($field, $value); - } - } - - $this->xmlwriter->begin_tag('messages'); - - return $data; - } - - /** - * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/CHAT/MESSAGES/MESSAGE - * data available - */ - public function process_chat_message($data) { - // MDL-46466 - Should this be empty? - } - - /** - * This is executed when we reach the closing tag of our 'chat' path - */ - public function on_chat_end() { - // Close chat.xml. - $this->xmlwriter->end_tag('messages'); - $this->xmlwriter->end_tag('chat'); - $this->xmlwriter->end_tag('activity'); - $this->close_xml_writer(); - - // Write inforef.xml. - $this->open_xml_writer("activities/chat_{$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/mod/chat/backup/moodle2/backup_chat_activity_task.class.php b/mod/chat/backup/moodle2/backup_chat_activity_task.class.php deleted file mode 100644 index a546f01cc04..00000000000 --- a/mod/chat/backup/moodle2/backup_chat_activity_task.class.php +++ /dev/null @@ -1,69 +0,0 @@ -. - -/** - * Defines backup_chat_activity_task class - * - * @package mod_chat - * @category backup - * @copyright 2010 onwards Dongsheng Cai - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/mod/chat/backup/moodle2/backup_chat_stepslib.php'); - -/** - * Provides the steps to perform one complete backup of the Chat instance - */ -class backup_chat_activity_task extends backup_activity_task { - - /** - * No specific settings for this activity - */ - protected function define_my_settings() { - } - - /** - * Defines a backup step to store the instance data in the chat.xml file - */ - protected function define_my_steps() { - $this->add_step(new backup_chat_activity_structure_step('chat_structure', 'chat.xml')); - } - - /** - * 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 . '/mod/chat', '#'); - - // Link to the list of chats. - $pattern = "#(".$base."\/index.php\?id\=)([0-9]+)#"; - $content = preg_replace($pattern, '$@CHATINDEX*$2@$', $content); - - // Link to chat view by moduleid. - $pattern = "#(".$base."\/view.php\?id\=)([0-9]+)#"; - $content = preg_replace($pattern, '$@CHATVIEWBYID*$2@$', $content); - - return $content; - } -} diff --git a/mod/chat/backup/moodle2/backup_chat_stepslib.php b/mod/chat/backup/moodle2/backup_chat_stepslib.php deleted file mode 100644 index 0c791905067..00000000000 --- a/mod/chat/backup/moodle2/backup_chat_stepslib.php +++ /dev/null @@ -1,67 +0,0 @@ -. - -/** - * @package mod_chat - * @subpackage backup-moodle2 - * @copyright 2010 onwards Dongsheng Cai - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Define all the backup steps that will be used by the backup_chat_activity_task - */ -class backup_chat_activity_structure_step extends backup_activity_structure_step { - protected function define_structure() { - $userinfo = $this->get_setting_value('userinfo'); - - // Define each element separated. - $chat = new backup_nested_element('chat', array('id'), array( - 'name', 'intro', 'introformat', 'keepdays', 'studentlogs', - 'chattime', 'schedule', 'timemodified')); - $messages = new backup_nested_element('messages'); - - $message = new backup_nested_element('message', array('id'), array( - 'userid', 'groupid', 'system', 'message_text', 'timestamp')); - - // It is not cool to have two tags with same name, so we need to rename message field to message_text. - $message->set_source_alias('message', 'message_text'); - // Renamed 'issystem' into 'system', for backward compatibility: 'system' is now a reserved word in MySQL 8.0.3+. - $message->set_source_alias('issystem', 'system'); - - // Build the tree. - $chat->add_child($messages); - $messages->add_child($message); - - // Define sources. - $chat->set_source_table('chat', array('id' => backup::VAR_ACTIVITYID)); - - // User related messages only happen if we are including user info. - if ($userinfo) { - $message->set_source_table('chat_messages', array('chatid' => backup::VAR_PARENTID)); - } - - // Define id annotations. - $message->annotate_ids('user', 'userid'); - $message->annotate_ids('group', 'groupid'); - - // Annotate the file areas in chat module. - $chat->annotate_files('mod_chat', 'intro', null); // The chat_intro area doesn't use itemid. - - // Return the root element (chat), wrapped into standard activity structure. - return $this->prepare_activity_structure($chat); - } -} diff --git a/mod/chat/backup/moodle2/restore_chat_activity_task.class.php b/mod/chat/backup/moodle2/restore_chat_activity_task.class.php deleted file mode 100644 index bb9b0cf712b..00000000000 --- a/mod/chat/backup/moodle2/restore_chat_activity_task.class.php +++ /dev/null @@ -1,111 +0,0 @@ -. - -/** - * @package mod_chat - * @subpackage backup-moodle2 - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/mod/chat/backup/moodle2/restore_chat_stepslib.php'); - -/** - * chat restore task that provides all the settings and steps to perform one - * complete restore of the activity - */ -class restore_chat_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() { - // Chat only has one structure step. - $this->add_step(new restore_chat_activity_structure_step('chat_structure', 'chat.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('chat', array('intro'), 'chat'); - $contents[] = new restore_decode_content('chat_messages', array('message'), 'chat_message'); - - 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('CHATVIEWBYID', '/mod/chat/view.php?id=$1', 'course_module'); - $rules[] = new restore_decode_rule('CHATINDEX', '/mod/chat/index.php?id=$1', 'course'); - - return $rules; - - } - - /** - * Define the restore log rules that will be applied - * by the {@link restore_logs_processor} when restoring - * chat 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('chat', 'add', 'view.php?id={course_module}', '{chat}'); - $rules[] = new restore_log_rule('chat', 'update', 'view.php?id={course_module}', '{chat}'); - $rules[] = new restore_log_rule('chat', 'view', 'view.php?id={course_module}', '{chat}'); - $rules[] = new restore_log_rule('chat', 'talk', 'view.php?id={course_module}', '{chat}'); - $rules[] = new restore_log_rule('chat', 'report', 'report.php?id={course_module}', '{chat}'); - - 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('chat', 'view all', 'index.php?id={course}', null); - - return $rules; - } -} diff --git a/mod/chat/backup/moodle2/restore_chat_stepslib.php b/mod/chat/backup/moodle2/restore_chat_stepslib.php deleted file mode 100644 index c4c64dd5e61..00000000000 --- a/mod/chat/backup/moodle2/restore_chat_stepslib.php +++ /dev/null @@ -1,83 +0,0 @@ -. - -/** - * @package mod_chat - * @subpackage backup-moodle2 - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Define all the restore steps that will be used by the restore_chat_activity_task - */ - -/** - * Structure step to restore one chat activity - */ -class restore_chat_activity_structure_step extends restore_activity_structure_step { - - protected function define_structure() { - - $paths = array(); - $userinfo = $this->get_setting_value('userinfo'); - - $paths[] = new restore_path_element('chat', '/activity/chat'); - if ($userinfo) { - $paths[] = new restore_path_element('chat_message', '/activity/chat/messages/message'); - } - - // Return the paths wrapped into standard activity structure. - return $this->prepare_activity_structure($paths); - } - - protected function process_chat($data) { - global $DB; - - $data = (object)$data; - $oldid = $data->id; - $data->course = $this->get_courseid(); - - // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. - // See MDL-9367. - $data->chattime = $this->apply_date_offset($data->chattime); - - // Insert the chat record. - $newitemid = $DB->insert_record('chat', $data); - // Immediately after inserting "activity" record, call this. - $this->apply_activity_instance($newitemid); - } - - protected function process_chat_message($data) { - global $DB; - - $data = (object)$data; - $oldid = $data->id; - $data->chatid = $this->get_new_parentid('chat'); - $data->userid = $this->get_mappingid('user', $data->userid); - $data->groupid = $this->get_mappingid('group', $data->groupid); - $data->message = $data->message_text; - $data->issystem = $data->system; - - $newitemid = $DB->insert_record('chat_messages', $data); - $this->set_mapping('chat_message', $oldid, $newitemid); // Because of decode. - } - - protected function after_execute() { - // Add chat related files, no need to match by itemname (just internally handled context). - $this->add_related_files('mod_chat', 'intro', null); - } -} diff --git a/mod/chat/beep.mp3 b/mod/chat/beep.mp3 deleted file mode 100644 index 6cfa71d1ad7242993e10fa97de43714e66568adb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcmbW0YeoaBP+Y>N4H?bYAQI(AR!&c%F0npZ{|XCpkWhfsuHp zr==yJ=!RiVDOrW;RpHW=GHEylBVq$N{}0KB)p=-uiJB`~-+)C?q*ACT3Mncnu2M8p zm?#D)#wmc}uK^hGF=4J}=z{_|4-<=7q7FJ!_+_7zl?CF3<%BSTX(Sff7)}ED2HPBu z5gu#r0cfAQsfSL9EIuVlIoqsd~V!{IG2o1~pyi&fp`d*SW@_H;>+9)|jxuFU9x zFbYC-k^buJI0f*|!=1+do>VhY@2Fk_v*!TrPZ__a_F9JZrKZZ~`Z9)-L;pud;Xj=3 zkzR||J;+y9G@gRRb-q0-=yR(+hHa#>0Bxb;4$Bz*l2sz7Tk&u~IVYU-(8}-C4M_ywZ zfJIhJ|LRl&?h)A@Jo2Ffr0TVE( zeB?kEV=c&hc4rg6)wkR?C5EM9#cC@)+?~t``H9@T=!@R_Ij)V=@#7e7jM5Z5tYB;L zepO^i{f^9RzH{k4Yn}y&srQRL@6Jkalkv6il2@yP83`B0JEt zYrZa#XF*#7O)JMh%cYOhbg0*=>i}4Xk8Z9Hm|cxt@B6yGOYc-O`_1E=Yl?v(FPMHZ f_Hk!QtTG`?8WAB~rPJw1KjfcFq8Ts@_5YXOHs1i~ diff --git a/mod/chat/chat_ajax.php b/mod/chat/chat_ajax.php deleted file mode 100644 index b925808d657..00000000000 --- a/mod/chat/chat_ajax.php +++ /dev/null @@ -1,162 +0,0 @@ -. - -define('AJAX_SCRIPT', true); - -require(__DIR__.'/../../config.php'); -require_once(__DIR__ . '/lib.php'); - -$action = optional_param('action', '', PARAM_ALPHANUM); -$beepid = optional_param('beep', '', PARAM_RAW); -$chatsid = required_param('chat_sid', PARAM_ALPHANUM); -$theme = required_param('chat_theme', PARAM_ALPHANUMEXT); -$chatmessage = optional_param('chat_message', '', PARAM_RAW); -$chatlasttime = optional_param('chat_lasttime', 0, PARAM_INT); -$chatlastrow = optional_param('chat_lastrow', 1, PARAM_INT); - -if (!confirm_sesskey()) { - throw new moodle_exception('invalidsesskey', 'error'); -} - -if (!$chatuser = $DB->get_record('chat_users', array('sid' => $chatsid))) { - throw new moodle_exception('notlogged', 'chat'); -} -if (!$chat = $DB->get_record('chat', array('id' => $chatuser->chatid))) { - throw new moodle_exception('invaliduserid', 'error'); -} -if (!$course = $DB->get_record('course', array('id' => $chat->course))) { - throw new moodle_exception('invalidcourseid', 'error'); -} -if (!$cm = get_coursemodule_from_instance('chat', $chat->id, $course->id)) { - throw new moodle_exception('invalidcoursemodule', 'error'); -} - -if (!isloggedin()) { - throw new moodle_exception('notlogged', 'chat'); -} - -// Set up $PAGE so that format_text will work properly. -$PAGE->set_cm($cm, $course, $chat); -$PAGE->set_url('/mod/chat/chat_ajax.php', array('chat_sid' => $chatsid)); - -require_login($course, false, $cm); - -$context = context_module::instance($cm->id); -require_capability('mod/chat:chat', $context); - -ob_start(); -header('Expires: Sun, 28 Dec 1997 09:32:45 GMT'); -header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); -header('Cache-Control: no-cache, must-revalidate'); -header('Pragma: no-cache'); -header('Content-Type: text/html; charset=utf-8'); - -switch ($action) { - case 'init': - $users = chat_get_users($chatuser->chatid, $chatuser->groupid, $cm->groupingid); - $users = chat_format_userlist($users, $course); - $response['users'] = $users; - echo json_encode($response); - break; - - case 'chat': - \core\session\manager::write_close(); - chat_delete_old_users(); - $chatmessage = clean_text($chatmessage, FORMAT_MOODLE); - - if (!empty($beepid)) { - $chatmessage = 'beep '.$beepid; - } - - if (!empty($chatmessage)) { - - chat_send_chatmessage($chatuser, $chatmessage, 0, $cm); - - $chatuser->lastmessageping = time() - 2; - $DB->update_record('chat_users', $chatuser); - - // Response OK message. - echo json_encode(true); - ob_end_flush(); - } - break; - - case 'update': - if ((time() - $chatlasttime) > $CFG->chat_old_ping) { - chat_delete_old_users(); - } - - if ($latestmessage = chat_get_latest_message($chatuser->chatid, $chatuser->groupid)) { - $chatnewlasttime = $latestmessage->timestamp; - } else { - $chatnewlasttime = 0; - } - - if ($chatlasttime == 0) { - $chatlasttime = time() - $CFG->chat_old_ping; - } - - $messages = chat_get_latest_messages($chatuser, $chatlasttime); - - if (!empty($messages)) { - $num = count($messages); - } else { - $num = 0; - } - $chatnewrow = ($chatlastrow + $num) % 2; - $senduserlist = false; - if ($messages && ($chatlasttime != $chatnewlasttime)) { - foreach ($messages as $n => &$message) { - $tmp = new stdClass(); - // When somebody enter room, user list will be updated. - if (!empty($message->issystem)) { - $senduserlist = true; - } - if ($html = chat_format_message_theme($message, $chatuser, $USER, $cm->groupingid, $theme)) { - $message->mymessage = ($USER->id == $message->userid); - $message->message = $html->html; - if (!empty($html->type)) { - $message->type = $html->type; - } - } else { - unset($messages[$n]); - } - } - } - - if ($senduserlist) { - // Return users when system message arrives. - $users = chat_format_userlist(chat_get_users($chatuser->chatid, $chatuser->groupid, $cm->groupingid), $course); - $response['users'] = $users; - } - - $DB->set_field('chat_users', 'lastping', time(), array('id' => $chatuser->id)); - - $response['lasttime'] = $chatnewlasttime; - $response['lastrow'] = $chatnewrow; - if ($messages) { - $response['msgs'] = $messages; - } - - echo json_encode($response); - header('Content-Length: ' . ob_get_length()); - - ob_end_flush(); - break; - - default: - break; -} diff --git a/mod/chat/chatd.php b/mod/chat/chatd.php deleted file mode 100644 index 3be05f6508f..00000000000 --- a/mod/chat/chatd.php +++ /dev/null @@ -1,1093 +0,0 @@ -. - -/** - * Chat daemon - * - * @package mod_chat - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -define('CLI_SCRIPT', true); - -require(__DIR__.'/../../config.php'); -require_once($CFG->dirroot . '/mod/chat/lib.php'); - -// Browser quirks. -define('QUIRK_CHUNK_UPDATE', 0x0001); - -// Connection telltale. -define('CHAT_CONNECTION', 0x10); -// Connections: Incrementing sequence, 0x10 to 0x1f. -define('CHAT_CONNECTION_CHANNEL', 0x11); - -// Sidekick telltale. -define('CHAT_SIDEKICK', 0x20); -// Sidekicks: Incrementing sequence, 0x21 to 0x2f. -define('CHAT_SIDEKICK_USERS', 0x21); -define('CHAT_SIDEKICK_MESSAGE', 0x22); -define('CHAT_SIDEKICK_BEEP', 0x23); - -$phpversion = phpversion(); -echo 'Moodle chat daemon v1.0 on PHP '.$phpversion."\n\n"; - -// Set up all the variables we need. - -// The $CFG variables are now defined in database by chat/lib.php. - -$_SERVER['PHP_SELF'] = 'dummy'; -$_SERVER['SERVER_NAME'] = 'dummy'; -$_SERVER['HTTP_USER_AGENT'] = 'dummy'; - -$_SERVER['SERVER_NAME'] = $CFG->chat_serverhost; -$_SERVER['PHP_SELF'] = "http://$CFG->chat_serverhost:$CFG->chat_serverport/mod/chat/chatd.php"; - -core_php_time_limit::raise(0); -error_reporting(E_ALL); - -function chat_empty_connection() { - return array('sid' => null, 'handle' => null, 'ip' => null, 'port' => null, 'groupid' => null); -} - -class ChatConnection { - // Chat-related info. - public $sid = null; - public $type = null; - - // PHP-level info. - public $handle = null; - - // TCP/IP. - public $ip = null; - public $port = null; - - public function __construct($resource) { - $this->handle = $resource; - @socket_getpeername($this->handle, $this->ip, $this->port); - } -} - -class ChatDaemon { - public $_resetsocket = false; - public $_readytogo = false; - public $_logfile = false; - public $_trace_to_console = true; - public $_trace_to_stdout = true; - public $_logfile_name = 'chatd.log'; - public $_last_idle_poll = 0; - - public $connectionsunidentified = array(); // Connections not identified yet. - public $connectionsside = array(); // Sessions with sidekicks waiting for the main connection to be processed. - public $connectionshalf = array(); // Sessions that have valid connections but not all of them. - public $connectionssets = array(); // Sessions with complete connection sets. - public $setsinfo = array(); // Keyed by sessionid exactly like conn_sets, one of these for each of those. - public $chatrooms = array(); // Keyed by chatid, holding arrays of data. - - /** @var int error reporting level. */ - public $_trace_level; - - /** @var bool true if function_name exists and is a function, false otherwise. */ - public $_pcntl_exists; - - /** @var int */ - public $_time_rest_socket; - - /** @var string beep file location. */ - public $_beepsoundsrc; - - /** @var int update frequency records. */ - public $_freq_update_records; - - /** @var int upper limit value in seconds to detect a user has disconnected or not. */ - public $_freq_poll_idle_chat; - - /** @var resource|false a file pointer resource on success, or false on error. */ - public $_stdout; - - /** @var array user data with session ID as the key. */ - public $sets_info = []; - - /** @var array connection data with session ID as the key. */ - public $conn_sets = []; - - /** @var array connection data. */ - public $conn_side = []; - - /** @var array connection data. */ - public $conn_half = []; - - /** @var array connection data. */ - public $conn_ufo = []; - - /** @var resource|Socket socket resource. */ - public $listen_socket; - - // IMPORTANT: $connectionssets, $setsinfo and $chatrooms must remain synchronized! - // Pay extra attention when you write code that affects any of them! - - public function __construct() { - $this->_trace_level = E_ALL ^ E_USER_NOTICE; - $this->_pcntl_exists = function_exists('pcntl_fork'); - $this->_time_rest_socket = 20; - $this->_beepsoundsrc = $GLOBALS['CFG']->wwwroot.'/mod/chat/beep.mp3'; - $this->_freq_update_records = 20; - $this->_freq_poll_idle_chat = $GLOBALS['CFG']->chat_old_ping; - $this->_stdout = fopen('php://stdout', 'w'); - if ($this->_stdout) { - // Avoid double traces for everything. - $this->_trace_to_console = false; - } - } - - public function error_handler($errno, $errmsg, $filename, $linenum, $vars) { - // Checks if an error needs to be suppressed due to @. - if (error_reporting() != 0) { - $this->trace($errmsg.' on line '.$linenum, $errno); - } - return true; - } - - public function poll_idle_chats($now) { - $this->trace('Polling chats to detect disconnected users'); - if (!empty($this->chatrooms)) { - foreach ($this->chatrooms as $chatid => $chatroom) { - if (!empty($chatroom['users'])) { - foreach ($chatroom['users'] as $sessionid => $userid) { - // We will be polling each user as required. - $this->trace('...shall we poll '.$sessionid.'?'); - if (!empty($this->sets_info[$sessionid]) && isset($this->sets_info[$sessionid]['chatuser']) && - // Having tried to exclude race conditions as already done in user_lazy_update() - // please do the real job by checking the last poll. - ($this->sets_info[$sessionid]['chatuser']->lastmessageping < $this->_last_idle_poll)) { - $this->trace('YES!'); - // This user hasn't been polled since his last message. - $result = $this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], ''); - if ($result === false) { - // User appears to have disconnected. - $this->disconnect_session($sessionid); - } - } - } - } - } - } - $this->_last_idle_poll = $now; - } - - public function query_start() { - return $this->_readytogo; - } - - public function trace($message, $level = E_USER_NOTICE) { - $severity = ''; - - switch($level) { - case E_USER_WARNING: - $severity = '*IMPORTANT* '; - break; - case E_USER_ERROR: - $severity = ' *CRITICAL* '; - break; - case E_NOTICE: - case E_WARNING: - $severity = ' *CRITICAL* [php] '; - break; - } - - $date = date('[Y-m-d H:i:s] '); - $message = $date.$severity.$message."\n"; - - if ($this->_trace_level & $level) { - // It is accepted for output. - - // Error-class traces go to STDERR too. - if ($level & E_USER_ERROR) { - fwrite(STDERR, $message); - } - - // Emit the message to wherever we should. - if ($this->_trace_to_stdout) { - fwrite($this->_stdout, $message); - fflush($this->_stdout); - } - if ($this->_trace_to_console) { - echo $message; - flush(); - } - if ($this->_logfile) { - fwrite($this->_logfile, $message); - fflush($this->_logfile); - } - } - } - - public function write_data($connection, $text) { - $written = @socket_write($connection, $text, strlen($text)); - if ($written === false) { - return false; - } - return true; - } - - public function user_lazy_update($sessionid) { - global $DB; - - if (empty($this->sets_info[$sessionid])) { - $this->trace('user_lazy_update() called for an invalid SID: '.$sessionid, E_USER_WARNING); - return false; - } - - // Does promote_final() already finish its job? - if (!isset($this->sets_info[$sessionid]['lastinfocommit'])) { - return false; - } - - $now = time(); - - // We 'll be cheating a little, and NOT updating the record data as - // often as we can, so that we save on DB queries (imagine MANY users). - if ($now - $this->sets_info[$sessionid]['lastinfocommit'] > $this->_freq_update_records) { - // Commit to permanent storage. - $this->sets_info[$sessionid]['lastinfocommit'] = $now; - $DB->update_record('chat_users', $this->sets_info[$sessionid]['chatuser']); - } - return true; - } - - public function get_user_window($sessionid) { - global $CFG, $OUTPUT; - - static $str; - - $info = &$this->sets_info[$sessionid]; - - $timenow = time(); - - if (empty($str)) { - $str = new stdClass(); - $str->idle = get_string("idle", "chat"); - $str->beep = get_string("beep", "chat"); - $str->day = get_string("day"); - $str->days = get_string("days"); - $str->hour = get_string("hour"); - $str->hours = get_string("hours"); - $str->min = get_string("min"); - $str->mins = get_string("mins"); - $str->sec = get_string("sec"); - $str->secs = get_string("secs"); - $str->years = get_string('years'); - } - - ob_start(); - $refreshinval = $CFG->chat_refresh_userlist * 1000; - echo << - - - -EOD; - - // Get the users from that chatroom. - $users = $this->chatrooms[$info['chatid']]['users']; - - foreach ($users as $usersessionid => $userid) { - // Fetch each user's sessionid and then the rest of his data from $this->sets_info. - $userinfo = $this->sets_info[$usersessionid]; - - $lastping = $timenow - $userinfo['chatuser']->lastmessageping; - - echo '"; - } - - echo '
'; - - $link = '/user/view.php?id='.$userinfo['user']->id.'&course='.$userinfo['courseid']; - $anchortagcontents = $OUTPUT->user_picture($userinfo['user'], array('courseid' => $userinfo['courseid'])); - - $action = new popup_action('click', $link, 'user'.$userinfo['chatuser']->id); - $anchortag = $OUTPUT->action_link($link, $anchortagcontents, $action); - - echo $anchortag; - echo ""; - echo "

"; - echo fullname($userinfo['user'])."
"; - echo "$str->idle: ".format_time($lastping, $str)." "; - echo ''.$str->beep."\n"; - echo "

"; - echo "
'; - echo "\n\n"; - - return ob_get_clean(); - - } - - public function new_ufo_id() { - static $id = 0; - if ($id++ === 0x1000000) { // Cycling very very slowly to prevent overflow. - $id = 0; - } - return $id; - } - - public function process_sidekicks($sessionid) { - if (empty($this->conn_side[$sessionid])) { - return true; - } - foreach ($this->conn_side[$sessionid] as $sideid => $sidekick) { - // TODO: is this late-dispatch working correctly? - $this->dispatch_sidekick($sidekick['handle'], $sidekick['type'], $sessionid, $sidekick['customdata']); - unset($this->conn_side[$sessionid][$sideid]); - } - return true; - } - - public function dispatch_sidekick($handle, $type, $sessionid, $customdata) { - global $CFG, $DB; - - switch($type) { - case CHAT_SIDEKICK_BEEP: - - // Incoming beep. - $msg = new stdClass; - $msg->chatid = $this->sets_info[$sessionid]['chatid']; - $msg->userid = $this->sets_info[$sessionid]['userid']; - $msg->groupid = $this->sets_info[$sessionid]['groupid']; - $msg->issystem = 0; - $msg->message = 'beep '.$customdata['beep']; - $msg->timestamp = time(); - - // Commit to DB. - chat_send_chatmessage($this->sets_info[$sessionid]['chatuser'], $msg->message, false, - $this->sets_info[$sessionid]['cm']); - - // OK, now push it out to all users. - $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']); - - // Update that user's lastmessageping. - $this->sets_info[$sessionid]['chatuser']->lastping = $msg->timestamp; - $this->sets_info[$sessionid]['chatuser']->lastmessageping = $msg->timestamp; - $this->user_lazy_update($sessionid); - - // We did our work, but before slamming the door on the poor browser - // show the courtesy of responding to the HTTP request. Otherwise, some - // browsers decide to get vengeance by flooding us with repeat requests. - - $header = "HTTP/1.1 200 OK\n"; - $header .= "Connection: close\n"; - $header .= "Date: ".date('r')."\n"; - $header .= "Server: Moodle\n"; - $header .= "Content-Type: text/html; charset=utf-8\n"; - $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n"; - $header .= "Cache-Control: no-cache, must-revalidate\n"; - $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n"; - $header .= "\n"; - - // That's enough headers for one lousy dummy response. - $this->write_data($handle, $header); - // All done. - break; - - case CHAT_SIDEKICK_USERS: - // A request to paint a user window. - - $content = $this->get_user_window($sessionid); - - $header = "HTTP/1.1 200 OK\n"; - $header .= "Connection: close\n"; - $header .= "Date: ".date('r')."\n"; - $header .= "Server: Moodle\n"; - $header .= "Content-Type: text/html; charset=utf-8\n"; - $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n"; - $header .= "Cache-Control: no-cache, must-revalidate\n"; - $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n"; - $header .= "Content-Length: ".strlen($content)."\n"; - - // The refresh value is 2 seconds higher than the configuration variable. - // This is because we are doing JS refreshes all the time. - // However, if the JS doesn't work for some reason, we still want to refresh once in a while. - $header .= "Refresh: ".(intval($CFG->chat_refresh_userlist) + 2). - "; url=http://$CFG->chat_serverhost:$CFG->chat_serverport/?win=users&". - "chat_sid=".$sessionid."\n"; - $header .= "\n"; - - // That's enough headers for one lousy dummy response. - $this->trace('writing users http response to handle '.$handle); - $this->write_data($handle, $header . $content); - - // Update that user's lastping. - $this->sets_info[$sessionid]['chatuser']->lastping = time(); - $this->user_lazy_update($sessionid); - - break; - - case CHAT_SIDEKICK_MESSAGE: - // Incoming message. - - // Browser stupidity protection from duplicate messages. - $messageindex = intval($customdata['index']); - - if ($this->sets_info[$sessionid]['lastmessageindex'] >= $messageindex) { - // We have already broadcasted that! - break; - } else { - // Update our info. - $this->sets_info[$sessionid]['lastmessageindex'] = $messageindex; - } - - $msg = new stdClass; - $msg->chatid = $this->sets_info[$sessionid]['chatid']; - $msg->userid = $this->sets_info[$sessionid]['userid']; - $msg->groupid = $this->sets_info[$sessionid]['groupid']; - $msg->issystem = 0; - $msg->message = urldecode($customdata['message']); // Have to undo the browser's encoding. - $msg->timestamp = time(); - - if (empty($msg->message)) { - // Someone just hit ENTER, send them on their way. - break; - } - - // A slight hack to prevent malformed SQL inserts. - $origmsg = $msg->message; - $msg->message = $msg->message; - - // Commit to DB. - chat_send_chatmessage($this->sets_info[$sessionid]['chatuser'], $msg->message, false, - $this->sets_info[$sessionid]['cm']); - - // Undo the hack. - $msg->message = $origmsg; - - // OK, now push it out to all users. - $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']); - - // Update that user's lastmessageping. - $this->sets_info[$sessionid]['chatuser']->lastping = $msg->timestamp; - $this->sets_info[$sessionid]['chatuser']->lastmessageping = $msg->timestamp; - $this->user_lazy_update($sessionid); - - // We did our work, but before slamming the door on the poor browser - // show the courtesy of responding to the HTTP request. Otherwise, some - // browsers decide to get vengeance by flooding us with repeat requests. - - $header = "HTTP/1.1 200 OK\n"; - $header .= "Connection: close\n"; - $header .= "Date: ".date('r')."\n"; - $header .= "Server: Moodle\n"; - $header .= "Content-Type: text/html; charset=utf-8\n"; - $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n"; - $header .= "Cache-Control: no-cache, must-revalidate\n"; - $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n"; - $header .= "\n"; - - // That's enough headers for one lousy dummy response. - $this->write_data($handle, $header); - - // All done. - break; - } - - socket_shutdown($handle); - socket_close($handle); - } - - public function promote_final($sessionid, $customdata) { - global $DB; - - if (isset($this->conn_sets[$sessionid])) { - $this->trace('Set cannot be finalized: Session '.$sessionid.' is already active'); - return false; - } - - $chatuser = $DB->get_record('chat_users', array('sid' => $sessionid)); - if ($chatuser === false) { - $this->dismiss_half($sessionid); - return false; - } - $chat = $DB->get_record('chat', array('id' => $chatuser->chatid)); - if ($chat === false) { - $this->dismiss_half($sessionid); - return false; - } - $user = $DB->get_record('user', array('id' => $chatuser->userid)); - if ($user === false) { - $this->dismiss_half($sessionid); - return false; - } - $course = $DB->get_record('course', array('id' => $chat->course)); - if ($course === false) { - $this->dismiss_half($sessionid); - return false; - } - if (!($cm = get_coursemodule_from_instance('chat', $chat->id, $course->id))) { - $this->dismiss_half($sessionid); - return false; - } - - global $CHAT_HTMLHEAD_JS; - - $this->conn_sets[$sessionid] = $this->conn_half[$sessionid]; - - // This whole thing needs to be purged of redundant info, and the - // code base to follow suit. But AFTER development is done. - $this->sets_info[$sessionid] = array( - 'lastinfocommit' => 0, - 'lastmessageindex' => 0, - 'course' => $course, - 'courseid' => $course->id, - 'chatuser' => $chatuser, - 'chatid' => $chat->id, - 'cm' => $cm, - 'user' => $user, - 'userid' => $user->id, - 'groupid' => $chatuser->groupid, - 'lang' => $chatuser->lang, - 'quirks' => $customdata['quirks'] - ); - - // If we know nothing about this chatroom, initialize it and add the user. - if (!isset($this->chatrooms[$chat->id]['users'])) { - $this->chatrooms[$chat->id]['users'] = array($sessionid => $user->id); - } else { - // Otherwise just add the user. - $this->chatrooms[$chat->id]['users'][$sessionid] = $user->id; - } - - $header = "HTTP/1.1 200 OK\n"; - $header .= "Connection: close\n"; - $header .= "Date: ".date('r')."\n"; - $header .= "Server: Moodle\n"; - $header .= "Content-Type: text/html; charset=utf-8\n"; - $header .= "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT\n"; - $header .= "Cache-Control: no-cache, must-revalidate\n"; - $header .= "Expires: Wed, 4 Oct 1978 09:32:45 GMT\n"; - $header .= "\n"; - - $this->dismiss_half($sessionid, false); - $this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $header . $CHAT_HTMLHEAD_JS); - $this->trace('Connection accepted: ' - .$this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL] - .', SID: ' - .$sessionid - .' UID: ' - .$chatuser->userid - .' GID: ' - .$chatuser->groupid, E_USER_WARNING); - - // Finally, broadcast the "entered the chat" message. - - $msg = new stdClass; - $msg->chatid = $chatuser->chatid; - $msg->userid = $chatuser->userid; - $msg->groupid = $chatuser->groupid; - $msg->issystem = 1; - $msg->message = 'enter'; - $msg->timestamp = time(); - - chat_send_chatmessage($chatuser, $msg->message, true); - $this->message_broadcast($msg, $this->sets_info[$sessionid]['user']); - - return true; - } - - public function promote_ufo($handle, $type, $sessionid, $customdata) { - if (empty($this->conn_ufo)) { - return false; - } - foreach ($this->conn_ufo as $id => $ufo) { - if ($ufo->handle == $handle) { - // OK, got the id of the UFO, but what is it? - - if ($type & CHAT_SIDEKICK) { - // Is the main connection ready? - if (isset($this->conn_sets[$sessionid])) { - // Yes, so dispatch this sidekick now and be done with it. - $this->dispatch_sidekick($handle, $type, $sessionid, $customdata); - $this->dismiss_ufo($handle, false); - } else { - // No, so put it in the waiting list. - $this->trace('sidekick waiting'); - $this->conn_side[$sessionid][] = array('type' => $type, 'handle' => $handle, 'customdata' => $customdata); - } - return true; - } - - // If it's not a sidekick, at this point it can only be da man. - - if ($type & CHAT_CONNECTION) { - // This forces a new connection right now. - $this->trace('Incoming connection from '.$ufo->ip.':'.$ufo->port); - - // Do we have such a connection active? - if (isset($this->conn_sets[$sessionid])) { - // Yes, so regrettably we cannot promote you. - $this->trace('Connection rejected: session '.$sessionid.' is already final'); - $this->dismiss_ufo($handle, true, 'Your SID was rejected.'); - return false; - } - - // Join this with what we may have already. - $this->conn_half[$sessionid][$type] = $handle; - - // Do the bookkeeping. - $this->promote_final($sessionid, $customdata); - - // It's not a UFO anymore. - $this->dismiss_ufo($handle, false); - - // Dispatch waiting sidekicks. - $this->process_sidekicks($sessionid); - - return true; - } - } - } - return false; - } - - public function dismiss_half($sessionid, $disconnect = true) { - if (!isset($this->conn_half[$sessionid])) { - return false; - } - if ($disconnect) { - foreach ($this->conn_half[$sessionid] as $handle) { - @socket_shutdown($handle); - @socket_close($handle); - } - } - unset($this->conn_half[$sessionid]); - return true; - } - - public function dismiss_set($sessionid) { - if (!empty($this->conn_sets[$sessionid])) { - foreach ($this->conn_sets[$sessionid] as $handle) { - // Since we want to dismiss this, don't generate any errors if it's dead already. - @socket_shutdown($handle); - @socket_close($handle); - } - } - $chatroom = $this->sets_info[$sessionid]['chatid']; - $userid = $this->sets_info[$sessionid]['userid']; - unset($this->conn_sets[$sessionid]); - unset($this->sets_info[$sessionid]); - unset($this->chatrooms[$chatroom]['users'][$sessionid]); - $this->trace('Removed all traces of user with session '.$sessionid, E_USER_NOTICE); - return true; - } - - public function dismiss_ufo($handle, $disconnect = true, $message = null) { - if (empty($this->conn_ufo)) { - return false; - } - foreach ($this->conn_ufo as $id => $ufo) { - if ($ufo->handle == $handle) { - unset($this->conn_ufo[$id]); - if ($disconnect) { - if (!empty($message)) { - $this->write_data($handle, $message."\n\n"); - } - socket_shutdown($handle); - socket_close($handle); - } - return true; - } - } - return false; - } - - public function conn_accept() { - $readsocket = array($this->listen_socket); - $write = null; - $except = null; - $changed = socket_select($readsocket, $write, $except, 0, 0); - - if (!$changed) { - return false; - } - $handle = socket_accept($this->listen_socket); - if (!$handle) { - return false; - } - - $newconn = new ChatConnection($handle); - $id = $this->new_ufo_id(); - $this->conn_ufo[$id] = $newconn; - } - - public function conn_activity_ufo(&$handles) { - $monitor = array(); - if (!empty($this->conn_ufo)) { - foreach ($this->conn_ufo as $ufoid => $ufo) { - // Avoid socket_select() warnings by preventing the check over invalid resources. - if (is_resource($ufo->handle)) { - $monitor[$ufoid] = $ufo->handle; - } else { - $this->dismiss_ufo($ufo->handle, false); - } - } - } - - if (empty($monitor)) { - $handles = array(); - return 0; - } - - $a = null; - $b = null; - $retval = socket_select($monitor, $a, $b, null); - $handles = $monitor; - - return $retval; - } - - public function message_broadcast($message, $sender) { - - if (empty($this->conn_sets)) { - return true; - } - - $now = time(); - - // First of all, mark this chatroom as having had activity now. - $this->chatrooms[$message->chatid]['lastactivity'] = $now; - - foreach ($this->sets_info as $sessionid => $info) { - // We need to get handles from users that are in the same chatroom, same group. - if ($info['chatid'] == $message->chatid && - ($info['groupid'] == $message->groupid || $message->groupid == 0)) { - - // Simply give them the message. - $output = chat_format_message_manually($message, $info['courseid'], $sender, $info['user']); - if ($output !== false) { - $this->trace('Delivering message "'.$output->text.'" to ' . - $this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL]); - - if ($output->beep) { - $playscript = '(function() { var audioElement = document.createElement("audio");' . "\n"; - $playscript .= 'audioElement.setAttribute("src", "'.$this->_beepsoundsrc.'");' . "\n"; - $playscript .= 'audioElement.play(); })();' . "\n"; - $this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], - ''); - } - - if ($info['quirks'] & QUIRK_CHUNK_UPDATE) { - $output->html .= $GLOBALS['CHAT_DUMMY_DATA']; - $output->html .= $GLOBALS['CHAT_DUMMY_DATA']; - $output->html .= $GLOBALS['CHAT_DUMMY_DATA']; - } - - if (!$this->write_data($this->conn_sets[$sessionid][CHAT_CONNECTION_CHANNEL], $output->html)) { - $this->disconnect_session($sessionid); - } - } - } - } - } - - public function disconnect_session($sessionid) { - global $DB; - - $info = $this->sets_info[$sessionid]; - - $DB->delete_records('chat_users', array('sid' => $sessionid)); - $msg = new stdClass; - $msg->chatid = $info['chatid']; - $msg->userid = $info['userid']; - $msg->groupid = $info['groupid']; - $msg->issystem = 1; - $msg->message = 'exit'; - $msg->timestamp = time(); - - $this->trace('User has disconnected, destroying uid '.$info['userid'].' with SID '.$sessionid, E_USER_WARNING); - chat_send_chatmessage($info['chatuser'], $msg->message, true); - - // IMPORTANT, kill him BEFORE broadcasting, otherwise we 'll get infinite recursion! - $latesender = $info['user']; - $this->dismiss_set($sessionid); - $this->message_broadcast($msg, $latesender); - } - - public function fatal($message) { - $message .= "\n"; - if ($this->_logfile) { - $this->trace($message, E_USER_ERROR); - } - echo "FATAL ERROR:: $message\n"; - die(); - } - - public function init_sockets() { - global $CFG; - - $this->trace('Setting up sockets'); - - if (false === ($this->listen_socket = socket_create(AF_INET, SOCK_STREAM, 0))) { - // Failed to create socket. - $lasterr = socket_last_error(); - $this->fatal('socket_create() failed: '. socket_strerror($lasterr).' ['.$lasterr.']'); - } - - if (!socket_bind($this->listen_socket, $CFG->chat_serverip, $CFG->chat_serverport)) { - // Failed to bind socket. - $lasterr = socket_last_error(); - $this->fatal('socket_bind() failed: '. socket_strerror($lasterr).' ['.$lasterr.']'); - } - - if (!socket_listen($this->listen_socket, $CFG->chat_servermax)) { - // Failed to get socket to listen. - $lasterr = socket_last_error(); - $this->fatal('socket_listen() failed: '. socket_strerror($lasterr).' ['.$lasterr.']'); - } - - // Socket has been initialized and is ready. - $this->trace('Socket opened on port '.$CFG->chat_serverport); - - // What exactly does this do? http://www.unixguide.net/network/socketfaq/4.5.shtml is still not enlightening enough for me. - socket_set_option($this->listen_socket, SOL_SOCKET, SO_REUSEADDR, 1); - socket_set_nonblock($this->listen_socket); - } - - public function cli_switch($switch, $param = null) { - switch($switch) { // LOL! - case 'reset': - // Reset sockets. - $this->_resetsocket = true; - return false; - case 'start': - // Start the daemon. - $this->_readytogo = true; - return false; - break; - case 'v': - // Verbose mode. - $this->_trace_level = E_ALL; - return false; - break; - case 'l': - // Use logfile. - if (!empty($param)) { - $this->_logfile_name = $param; - } - $this->_logfile = @fopen($this->_logfile_name, 'a+'); - if ($this->_logfile == false) { - $this->fatal('Failed to open '.$this->_logfile_name.' for writing'); - } - return false; - default: - // Unrecognized. - $this->fatal('Unrecognized command line switch: '.$switch); - break; - } - return false; - } - -} - -$daemon = new ChatDaemon; -set_error_handler(array($daemon, 'error_handler')); - -// Check the parameters. - -unset($argv[0]); -$commandline = implode(' ', $argv); -if (strpos($commandline, '-') === false) { - if (!empty($commandline)) { - // We cannot have received any meaningful parameters. - $daemon->fatal('Garbage in command line'); - } -} else { - // Parse command line. - $switches = preg_split('/(-{1,2}[a-zA-Z]+) */', $commandline, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); - - // Taking advantage of the fact that $switches is indexed with incrementing numeric keys. - // We will be using that to pass additional information to those switches who need it. - $numswitches = count($switches); - - // Fancy way to give a "hyphen" boolean flag to each "switch". - $switches = array_map(function($x) { - return array("str" => $x, "hyphen" => (substr($x, 0, 1) == "-")); - }, $switches); - - for ($i = 0; $i < $numswitches; ++$i) { - - $switch = $switches[$i]['str']; - $params = ($i == $numswitches - 1 ? null : - ($switches[$i + 1]['hyphen'] ? null : trim($switches[$i + 1]['str'])) - ); - - if (substr($switch, 0, 2) == '--') { - // Double-hyphen switch. - $daemon->cli_switch(strtolower(substr($switch, 2)), $params); - } else if (substr($switch, 0, 1) == '-') { - // Single-hyphen switch(es), may be more than one run together. - $switch = substr($switch, 1); // Get rid of the "-". - $len = strlen($switch); - for ($j = 0; $j < $len; ++$j) { - $daemon->cli_switch(strtolower(substr($switch, $j, 1)), $params); - } - } - } -} - -if (!$daemon->query_start()) { - // For some reason we didn't start, so print out some info. - echo 'Starts the Moodle chat socket server on port '.$CFG->chat_serverport; - echo "\n\n"; - echo "Usage: chatd.php [parameters]\n\n"; - echo "Parameters:\n"; - echo " --start Starts the daemon\n"; - echo " -v Verbose mode (prints trivial information messages)\n"; - echo " -l [logfile] Log all messages to logfile (if not specified, chatd.log)\n"; - echo "Example:\n"; - echo " chatd.php --start -l\n\n"; - die(); -} - -if (!function_exists('socket_set_option')) { - echo "Error: Function socket_set_option() does not exist.\n"; - echo "Possibly PHP has not been compiled with --enable-sockets.\n\n"; - die(); -} - -$daemon->init_sockets(); - -$daemon->trace('Started Moodle chatd on port '.$CFG->chat_serverport.', listening socket '.$daemon->listen_socket, E_USER_WARNING); - -// Clear the decks of old stuff. -$DB->delete_records('chat_users', array('version' => 'sockets')); - -while (true) { - $active = array(); - - // First of all, let's see if any of our UFOs have identified itself. - if ($daemon->conn_activity_ufo($active)) { - foreach ($active as $handle) { - $readsocket = array($handle); - $write = null; - $except = null; - $changed = socket_select($readsocket, $write, $except, 0, 0); - - if ($changed > 0) { - // Let's see what it has to say. - - $data = socket_read($handle, 2048); // Should be more than 512 to prevent empty pages and repeated messages! - if (empty($data)) { - continue; - } - - if (strlen($data) == 2048) { // If socket_read has more data, ignore all data. - $daemon->trace('UFO with '.$handle.': Data too long; connection closed', E_USER_WARNING); - $daemon->dismiss_ufo($handle, true, 'Data too long; connection closed'); - continue; - } - - // Ignore desktop browser fake "favorite icon" requests. - if (strpos($data, 'GET /favicon.ico HTTP') === 0) { - // Known malformed data, drop it without any further notice. - continue; - } - - if (!preg_match('/win=(chat|users|message|beep).*&chat_sid=([a-zA-Z0-9]*) HTTP/', $data, $info)) { - // Malformed data. - $daemon->trace('UFO with '.$handle.': Request with malformed data; connection closed', E_USER_WARNING); - $daemon->dismiss_ufo($handle, true, 'Request with malformed data; connection closed'); - continue; - } - - $type = $info[1]; - $sessionid = $info[2]; - - $customdata = array(); - - switch($type) { - case 'chat': - $type = CHAT_CONNECTION_CHANNEL; - $customdata['quirks'] = 0; - if (strpos($data, 'Safari')) { - $daemon->trace('Safari identified...', E_USER_WARNING); - $customdata['quirks'] += QUIRK_CHUNK_UPDATE; - } - break; - case 'users': - $type = CHAT_SIDEKICK_USERS; - break; - case 'beep': - $type = CHAT_SIDEKICK_BEEP; - if (!preg_match('/beep=([^&]*)[& ]/', $data, $info)) { - $daemon->trace('Beep sidekick did not contain a valid userid', E_USER_WARNING); - $daemon->dismiss_ufo($handle, true, 'Request with malformed data; connection closed'); - continue 2; - } else { - $customdata = array('beep' => intval($info[1])); - } - break; - case 'message': - $type = CHAT_SIDEKICK_MESSAGE; - if (!preg_match('/chat_message=([^&]*)[& ]chat_msgidnr=([^&]*)[& ]/', $data, $info)) { - $daemon->trace('Message sidekick did not contain a valid message', E_USER_WARNING); - $daemon->dismiss_ufo($handle, true, 'Request with malformed data; connection closed'); - continue 2; - } else { - $customdata = array('message' => $info[1], 'index' => $info[2]); - } - break; - default: - $daemon->trace('UFO with '.$handle.': Request with unknown type; connection closed', E_USER_WARNING); - $daemon->dismiss_ufo($handle, true, 'Request with unknown type; connection closed'); - continue 2; - break; - } - - // OK, now we know it's something good. Promote it and pass it all the data it needs. - $daemon->promote_ufo($handle, $type, $sessionid, $customdata); - continue; - } - } - } - - $now = time(); - - // Clean up chatrooms with no activity as required. - if ($now - $daemon->_last_idle_poll >= $daemon->_freq_poll_idle_chat) { - $daemon->poll_idle_chats($now); - } - - // Finally, accept new connections. - $daemon->conn_accept(); - - usleep($daemon->_time_rest_socket); -} - -@socket_shutdown($daemon->listen_socket, 0); -die("\n\n-- terminated --\n"); - diff --git a/mod/chat/classes/analytics/indicator/activity_base.php b/mod/chat/classes/analytics/indicator/activity_base.php deleted file mode 100644 index 1264e171755..00000000000 --- a/mod/chat/classes/analytics/indicator/activity_base.php +++ /dev/null @@ -1,111 +0,0 @@ -. - -/** - * Activity base class. - * - * @package mod_chat - * @copyright 2017 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\analytics\indicator; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Activity base class. - * - * @package mod_chat - * @copyright 2017 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity { - - /** - * feedback_viewed_events - * - * @return string[] - */ - protected function feedback_viewed_events() { - return array('\mod_chat\event\course_module_viewed', '\mod_chat\event\message_sent', - '\mod_chat\event\sessions_viewed'); - } - - /** - * feedback_replied_events - * - * @return string[] - */ - protected function feedback_replied_events() { - return array('\mod_chat\event\message_sent'); - } - - /** - * feedback_post_action - * - * @param \cm_info $cm - * @param int $contextid - * @param int $userid - * @param string[] $eventnames - * @param int $after - * @return bool - */ - protected function feedback_post_action(\cm_info $cm, $contextid, $userid, $eventnames, $after = false) { - - if (empty($this->activitylogs[$contextid][$userid])) { - return false; - } - - $logs = $this->activitylogs[$contextid][$userid]; - - if (empty($logs['\mod_chat\event\message_sent'])) { - // No feedback viewed if there is no submission. - return false; - } - - // First user message time. - $firstmessage = $logs['\mod_chat\event\message_sent']->timecreated[0]; - - // We consider feedback another user messages. - foreach ($this->activitylogs[$contextid] as $anotheruserid => $logs) { - if ($anotheruserid == $userid) { - continue; - } - if (empty($logs['\mod_chat\event\message_sent'])) { - continue; - } - $firstmessagesenttime = $logs['\mod_chat\event\message_sent']->timecreated[0]; - - if (parent::feedback_post_action($cm, $contextid, $userid, $eventnames, $firstmessagesenttime)) { - return true; - } - // Continue with the next user. - } - - return false; - } - - /** - * feedback_check_grades - * - * @return bool - */ - protected function feedback_check_grades() { - // Chat's feedback is not contained in grades. - return false; - } -} diff --git a/mod/chat/classes/analytics/indicator/cognitive_depth.php b/mod/chat/classes/analytics/indicator/cognitive_depth.php deleted file mode 100644 index 4343c3c2023..00000000000 --- a/mod/chat/classes/analytics/indicator/cognitive_depth.php +++ /dev/null @@ -1,56 +0,0 @@ -. - -/** - * Cognitive depth indicator - chat. - * - * @package mod_chat - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\analytics\indicator; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Cognitive depth indicator - chat. - * - * @package mod_chat - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class cognitive_depth extends activity_base { - - /** - * Returns the name. - * - * If there is a corresponding '_help' string this will be shown as well. - * - * @return \lang_string - */ - public static function get_name(): \lang_string { - return new \lang_string('indicator:cognitivedepth', 'mod_chat'); - } - - public function get_indicator_type() { - return self::INDICATOR_COGNITIVE; - } - - public function get_cognitive_depth_level(\cm_info $cm) { - return self::COGNITIVE_LEVEL_4; - } -} diff --git a/mod/chat/classes/analytics/indicator/social_breadth.php b/mod/chat/classes/analytics/indicator/social_breadth.php deleted file mode 100644 index f7b64e4c16a..00000000000 --- a/mod/chat/classes/analytics/indicator/social_breadth.php +++ /dev/null @@ -1,56 +0,0 @@ -. - -/** - * Social breadth indicator - chat. - * - * @package mod_chat - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\analytics\indicator; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Social breadth indicator - chat. - * - * @package mod_chat - * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class social_breadth extends activity_base { - - /** - * Returns the name. - * - * If there is a corresponding '_help' string this will be shown as well. - * - * @return \lang_string - */ - public static function get_name(): \lang_string { - return new \lang_string('indicator:socialbreadth', 'mod_chat'); - } - - public function get_indicator_type() { - return self::INDICATOR_SOCIAL; - } - - public function get_social_breadth_level(\cm_info $cm) { - return self::SOCIAL_LEVEL_2; - } -} diff --git a/mod/chat/classes/dates.php b/mod/chat/classes/dates.php deleted file mode 100644 index cffdd87a092..00000000000 --- a/mod/chat/classes/dates.php +++ /dev/null @@ -1,58 +0,0 @@ -. - -/** - * Contains the class for fetching the important dates in mod_chat for a given module instance and a user. - * - * @package mod_chat - * @copyright 2021 Dongsheng Cai - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -declare(strict_types=1); - -namespace mod_chat; - -use core\activity_dates; - -/** - * Class for fetching the important dates in mod_chat for a given module instance and a user. - * - */ -class dates extends activity_dates { - /** - * Returns a list of important dates in mod_chat. - * - * @return array - */ - protected function get_dates(): array { - $customdata = $this->cm->customdata; - $chat = (object) $customdata; - $chattime = $chat->chattime ?? 0; - $now = time(); - if (!empty($chat->schedule) && $chattime > $now) { - return [ - [ - 'dataid' => 'chattime', - 'label' => get_string('nextchattime', 'mod_chat'), - 'timestamp' => (int) $chattime - ] - ]; - } - - return []; - } -} diff --git a/mod/chat/classes/event/course_module_instance_list_viewed.php b/mod/chat/classes/event/course_module_instance_list_viewed.php deleted file mode 100644 index b3df3382205..00000000000 --- a/mod/chat/classes/event/course_module_instance_list_viewed.php +++ /dev/null @@ -1,38 +0,0 @@ -. - -/** - * The mod_chat instance list viewed event. - * - * @package mod_chat - * @copyright 2013 onwards Ankit Agarwal - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\event; -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_chat instance list viewed event class. - * - * @package mod_chat - * @since Moodle 2.7 - * @copyright 2013 onwards Ankit Agarwal - * @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 { -} - diff --git a/mod/chat/classes/event/course_module_viewed.php b/mod/chat/classes/event/course_module_viewed.php deleted file mode 100644 index 854699262a5..00000000000 --- a/mod/chat/classes/event/course_module_viewed.php +++ /dev/null @@ -1,47 +0,0 @@ -. - -/** - * The mod_chat course module viewed event. - * - * @package mod_chat - * @copyright 2014 Petr Skoda - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\event; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_chat course module viewed event class. - * - * @package mod_chat - * @since Moodle 2.7 - * @copyright 2014 Petr Skoda - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class course_module_viewed extends \core\event\course_module_viewed { - protected function init() { - $this->data['crud'] = 'r'; - $this->data['edulevel'] = self::LEVEL_PARTICIPATING; - $this->data['objecttable'] = 'chat'; - } - - public static function get_objectid_mapping() { - return array('db' => 'chat', 'restore' => 'chat'); - } -} diff --git a/mod/chat/classes/event/message_sent.php b/mod/chat/classes/event/message_sent.php deleted file mode 100644 index ab491a3bdd4..00000000000 --- a/mod/chat/classes/event/message_sent.php +++ /dev/null @@ -1,93 +0,0 @@ -. - -/** - * The mod_chat message sent event. - * - * @package mod_chat - * @copyright 2013 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\event; -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_chat message sent event class. - * - * @package mod_chat - * @since Moodle 2.6 - * @copyright 2013 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class message_sent extends \core\event\base { - - /** - * Returns description of what happened. - * - * @return string - */ - public function get_description() { - return "The user with id '$this->relateduserid' has sent a message in the chat with course module id - '$this->contextinstanceid'."; - } - - /** - * Return localised event name. - * - * @return string - */ - public static function get_name() { - return get_string('eventmessagesent', 'mod_chat'); - } - - /** - * Get URL related to the action - * - * @return \moodle_url - */ - public function get_url() { - return new \moodle_url('/mod/chat/view.php', array('id' => $this->contextinstanceid)); - } - - /** - * Init method. - * - * @return void - */ - protected function init() { - $this->data['crud'] = 'c'; - $this->data['edulevel'] = self::LEVEL_PARTICIPATING; - $this->data['objecttable'] = 'chat_messages'; - } - - /** - * 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.'); - } - } - - public static function get_objectid_mapping() { - return array('db' => 'chat_messages', 'restore' => 'chat_message'); - } -} diff --git a/mod/chat/classes/event/sessions_viewed.php b/mod/chat/classes/event/sessions_viewed.php deleted file mode 100644 index 77d2caafb47..00000000000 --- a/mod/chat/classes/event/sessions_viewed.php +++ /dev/null @@ -1,108 +0,0 @@ -. - -/** - * The mod_chat sessions viewed event. - * - * @package mod_chat - * @copyright 2013 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\event; -defined('MOODLE_INTERNAL') || die(); - -/** - * The mod_chat sessions viewed event class. - * - * @property-read array $other { - * Extra information about the event. - * - * - int start: start of period. - * - int end: end of period. - * } - * - * @package mod_chat - * @since Moodle 2.6 - * @copyright 2013 Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class sessions_viewed extends \core\event\base { - - /** - * Returns description of what happened. - * - * @return string - */ - public function get_description() { - return "The user with id '$this->userid' has viewed the sessions of the chat with course module id - '$this->contextinstanceid'."; - } - - /** - * Return localised event name. - * - * @return string - */ - public static function get_name() { - return get_string('eventsessionsviewed', 'mod_chat'); - } - - /** - * Get URL related to the action - * - * @return \moodle_url - */ - public function get_url() { - return new \moodle_url('/mod/chat/report.php', array('id' => $this->contextinstanceid)); - } - - /** - * Init method. - * - * @return void - */ - protected function init() { - $this->data['crud'] = 'r'; - $this->data['edulevel'] = self::LEVEL_OTHER; - $this->data['objecttable'] = 'chat'; - } - - /** - * Custom validation. - * - * @throws \coding_exception - * @return void - */ - protected function validate_data() { - parent::validate_data(); - if (!isset($this->other['start'])) { - throw new \coding_exception('The \'start\' value must be set in other.'); - } - if (!isset($this->other['end'])) { - throw new \coding_exception('The \'end\' value must be set in other.'); - } - } - - public static function get_objectid_mapping() { - return array('db' => 'chat', 'restore' => 'chat'); - } - - public static function get_other_mapping() { - // Nothing to map. - return false; - } -} diff --git a/mod/chat/classes/external.php b/mod/chat/classes/external.php deleted file mode 100644 index 5f75d30b9e8..00000000000 --- a/mod/chat/classes/external.php +++ /dev/null @@ -1,833 +0,0 @@ -. - -/** - * Chat external API - * - * @package mod_chat - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->dirroot . '/mod/chat/lib.php'); - -use core_course\external\helper_for_get_mods_by_courses; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_multiple_structure; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; -use core_external\util; -use mod_chat\external\chat_message_exporter; - -/** - * Chat external functions - * - * @package mod_chat - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ -class mod_chat_external extends external_api { - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function login_user_parameters() { - return new external_function_parameters( - array( - 'chatid' => new external_value(PARAM_INT, 'chat instance id'), - 'groupid' => new external_value(PARAM_INT, 'group id, 0 means that the function will determine the user group', - VALUE_DEFAULT, 0), - ) - ); - } - - /** - * Log the current user into a chat room in the given chat. - * - * @param int $chatid the chat instance id - * @param int $groupid the user group id - * @return array of warnings and the chat unique session id - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function login_user($chatid, $groupid = 0) { - global $DB; - - $params = self::validate_parameters(self::login_user_parameters(), - array( - 'chatid' => $chatid, - 'groupid' => $groupid - )); - $warnings = array(); - - // Request and permission validation. - $chat = $DB->get_record('chat', array('id' => $params['chatid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - require_capability('mod/chat:chat', $context); - - if (!empty($params['groupid'])) { - $groupid = $params['groupid']; - // Determine is the group is visible to user. - if (!groups_group_visible($groupid, $course, $cm)) { - throw new moodle_exception('notingroup'); - } - } else { - // Check to see if groups are being used here. - if ($groupmode = groups_get_activity_groupmode($cm)) { - $groupid = groups_get_activity_group($cm); - // Determine is the group is visible to user (this is particullary for the group 0). - if (!groups_group_visible($groupid, $course, $cm)) { - throw new moodle_exception('notingroup'); - } - } else { - $groupid = 0; - } - } - - // Get the unique chat session id. - // Since we are going to use the chat via Web Service requests we set the ajax version (since it's the most similar). - if (!$chatsid = chat_login_user($chat->id, 'ajax', $groupid, $course)) { - throw new moodle_exception('cantlogin', 'chat'); - } - - $result = array(); - $result['chatsid'] = $chatsid; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function login_user_returns() { - return new external_single_structure( - array( - 'chatsid' => new external_value(PARAM_ALPHANUM, 'unique chat session id'), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function get_chat_users_parameters() { - return new external_function_parameters( - array( - 'chatsid' => new external_value(PARAM_ALPHANUM, 'chat session id (obtained via mod_chat_login_user)') - ) - ); - } - - /** - * Get the list of users in the given chat session. - * - * @param int $chatsid the chat session id - * @return array of warnings and the user lists - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function get_chat_users($chatsid) { - global $DB, $PAGE; - - $params = self::validate_parameters(self::get_chat_users_parameters(), - array( - 'chatsid' => $chatsid - )); - $warnings = array(); - - // Request and permission validation. - if (!$chatuser = $DB->get_record('chat_users', array('sid' => $params['chatsid']))) { - throw new moodle_exception('notlogged', 'chat'); - } - $chat = $DB->get_record('chat', array('id' => $chatuser->chatid), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - require_capability('mod/chat:chat', $context); - - // First, delete old users from the chats. - chat_delete_old_users(); - - $users = chat_get_users($chatuser->chatid, $chatuser->groupid, $cm->groupingid); - $returnedusers = array(); - - foreach ($users as $user) { - - $userpicture = new user_picture($user); - $userpicture->size = 1; // Size f1. - $profileimageurl = $userpicture->get_url($PAGE)->out(false); - - $returnedusers[] = array( - 'id' => $user->id, - 'fullname' => fullname($user), - 'profileimageurl' => $profileimageurl - ); - } - - $result = array(); - $result['users'] = $returnedusers; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function get_chat_users_returns() { - return new external_single_structure( - array( - 'users' => new external_multiple_structure( - new external_single_structure( - array( - 'id' => new external_value(PARAM_INT, 'user id'), - 'fullname' => new external_value(PARAM_NOTAGS, 'user full name'), - 'profileimageurl' => new external_value(PARAM_URL, 'user picture URL'), - ) - ), - 'list of users' - ), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function send_chat_message_parameters() { - return new external_function_parameters( - array( - 'chatsid' => new external_value(PARAM_ALPHANUM, 'chat session id (obtained via mod_chat_login_user)'), - 'messagetext' => new external_value(PARAM_RAW, 'the message text'), - 'beepid' => new external_value(PARAM_RAW, 'the beep id', VALUE_DEFAULT, ''), - - ) - ); - } - - /** - * Send a message on the given chat session. - * - * @param int $chatsid the chat session id - * @param string $messagetext the message text - * @param string $beepid the beep message id - * @return array of warnings and the new message id (0 if the message was empty) - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function send_chat_message($chatsid, $messagetext, $beepid = '') { - global $DB; - - $params = self::validate_parameters(self::send_chat_message_parameters(), - array( - 'chatsid' => $chatsid, - 'messagetext' => $messagetext, - 'beepid' => $beepid - )); - $warnings = array(); - - // Request and permission validation. - if (!$chatuser = $DB->get_record('chat_users', array('sid' => $params['chatsid']))) { - throw new moodle_exception('notlogged', 'chat'); - } - $chat = $DB->get_record('chat', array('id' => $chatuser->chatid), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - require_capability('mod/chat:chat', $context); - - $chatmessage = clean_text($params['messagetext'], FORMAT_MOODLE); - - if (!empty($params['beepid'])) { - $chatmessage = 'beep ' . $params['beepid']; - } - - if (!empty($chatmessage)) { - // Send the message. - $messageid = chat_send_chatmessage($chatuser, $chatmessage, 0, $cm); - // Update ping time. - $chatuser->lastmessageping = time() - 2; - $DB->update_record('chat_users', $chatuser); - } else { - $messageid = 0; - } - - $result = array(); - $result['messageid'] = $messageid; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function send_chat_message_returns() { - return new external_single_structure( - array( - 'messageid' => new external_value(PARAM_INT, 'message sent id'), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function get_chat_latest_messages_parameters() { - return new external_function_parameters( - array( - 'chatsid' => new external_value(PARAM_ALPHANUM, 'chat session id (obtained via mod_chat_login_user)'), - 'chatlasttime' => new external_value(PARAM_INT, 'last time messages were retrieved (epoch time)', VALUE_DEFAULT, 0) - ) - ); - } - - /** - * Get the latest messages from the given chat session. - * - * @param int $chatsid the chat session id - * @param int $chatlasttime last time messages were retrieved (epoch time) - * @return array of warnings and the new message id (0 if the message was empty) - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function get_chat_latest_messages($chatsid, $chatlasttime = 0) { - global $DB, $CFG; - - $params = self::validate_parameters(self::get_chat_latest_messages_parameters(), - array( - 'chatsid' => $chatsid, - 'chatlasttime' => $chatlasttime - )); - $warnings = array(); - - // Request and permission validation. - if (!$chatuser = $DB->get_record('chat_users', array('sid' => $params['chatsid']))) { - throw new moodle_exception('notlogged', 'chat'); - } - $chat = $DB->get_record('chat', array('id' => $chatuser->chatid), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - require_capability('mod/chat:chat', $context); - - $chatlasttime = $params['chatlasttime']; - if ((time() - $chatlasttime) > $CFG->chat_old_ping) { - chat_delete_old_users(); - } - - // Set default chat last time (to not retrieve all the conversations). - if ($chatlasttime == 0) { - $chatlasttime = time() - $CFG->chat_old_ping; - } - - if ($latestmessage = chat_get_latest_message($chatuser->chatid, $chatuser->groupid)) { - $chatnewlasttime = $latestmessage->timestamp; - } else { - $chatnewlasttime = 0; - } - - $messages = chat_get_latest_messages($chatuser, $chatlasttime); - $returnedmessages = array(); - - foreach ($messages as $message) { - // FORMAT_MOODLE is mandatory in the chat plugin. - [$messageformatted] = \core_external\util::format_text( - $message->message, - FORMAT_MOODLE, - $context->id, - 'mod_chat', - '', - 0 - ); - - $returnedmessages[] = array( - 'id' => $message->id, - 'userid' => $message->userid, - 'system' => (bool) $message->issystem, - 'message' => $messageformatted, - 'timestamp' => $message->timestamp, - ); - } - - // Update our status since we are active in the chat. - $DB->set_field('chat_users', 'lastping', time(), array('id' => $chatuser->id)); - - $result = array(); - $result['messages'] = $returnedmessages; - $result['chatnewlasttime'] = $chatnewlasttime; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function get_chat_latest_messages_returns() { - return new external_single_structure( - array( - 'messages' => new external_multiple_structure( - new external_single_structure( - array( - 'id' => new external_value(PARAM_INT, 'message id'), - 'userid' => new external_value(PARAM_INT, 'user id'), - 'system' => new external_value(PARAM_BOOL, 'true if is a system message (like user joined)'), - 'message' => new external_value(PARAM_RAW, 'message text'), - 'timestamp' => new external_value(PARAM_INT, 'timestamp for the message'), - ) - ), - 'list of users' - ), - 'chatnewlasttime' => new external_value(PARAM_INT, 'new last time'), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function view_chat_parameters() { - return new external_function_parameters( - array( - 'chatid' => new external_value(PARAM_INT, 'chat instance id') - ) - ); - } - - /** - * Trigger the course module viewed event and update the module completion status. - * - * @param int $chatid the chat instance id - * @return array of warnings and status result - * @since Moodle 3.0 - * @throws moodle_exception - */ - public static function view_chat($chatid) { - global $DB, $CFG; - - $params = self::validate_parameters(self::view_chat_parameters(), - array( - 'chatid' => $chatid - )); - $warnings = array(); - - // Request and permission validation. - $chat = $DB->get_record('chat', array('id' => $params['chatid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - require_capability('mod/chat:chat', $context); - - // Call the url/lib API. - chat_view($chat, $course, $cm, $context); - - $result = array(); - $result['status'] = true; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.0 - */ - public static function view_chat_returns() { - return new external_single_structure( - array( - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings() - ) - ); - } - - - /** - * Describes the parameters for get_chats_by_courses. - * - * @return external_function_parameters - * @since Moodle 3.0 - */ - public static function get_chats_by_courses_parameters() { - return new external_function_parameters ( - array( - 'courseids' => new external_multiple_structure( - new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array() - ), - ) - ); - } - - /** - * Returns a list of chats in a provided list of courses, - * if no list is provided all chats that the user can view will be returned. - * - * @param array $courseids the course ids - * @return array of chats details - * @since Moodle 3.0 - */ - public static function get_chats_by_courses($courseids = array()) { - global $CFG; - - $returnedchats = array(); - $warnings = array(); - - $params = self::validate_parameters(self::get_chats_by_courses_parameters(), array('courseids' => $courseids)); - - $courses = array(); - if (empty($params['courseids'])) { - $courses = enrol_get_my_courses(); - $params['courseids'] = array_keys($courses); - } - - // Ensure there are courseids to loop through. - if (!empty($params['courseids'])) { - - list($courses, $warnings) = util::validate_courses($params['courseids'], $courses); - - // Get the chats in this course, this function checks users visibility permissions. - // We can avoid then additional validate_context calls. - $chats = get_all_instances_in_courses("chat", $courses); - foreach ($chats as $chat) { - $chatcontext = context_module::instance($chat->coursemodule); - - $chatdetails = helper_for_get_mods_by_courses::standard_coursemodule_element_values($chat, 'mod_chat'); - - if (has_capability('mod/chat:chat', $chatcontext)) { - $chatdetails['chatmethod'] = $CFG->chat_method; - $chatdetails['keepdays'] = $chat->keepdays; - $chatdetails['studentlogs'] = $chat->studentlogs; - $chatdetails['chattime'] = $chat->chattime; - $chatdetails['schedule'] = $chat->schedule; - } - - if (has_capability('moodle/course:manageactivities', $chatcontext)) { - $chatdetails['timemodified'] = $chat->timemodified; - } - $returnedchats[] = $chatdetails; - } - } - $result = array(); - $result['chats'] = $returnedchats; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Describes the get_chats_by_courses return value. - * - * @return external_single_structure - * @since Moodle 3.0 - */ - public static function get_chats_by_courses_returns() { - return new external_single_structure( - array( - 'chats' => new external_multiple_structure( - new external_single_structure(array_merge( - helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(), - [ - 'chatmethod' => new external_value(PARAM_PLUGIN, 'chat method (sockets, ajax, header_js)', - VALUE_OPTIONAL), - 'keepdays' => new external_value(PARAM_INT, 'keep days', VALUE_OPTIONAL), - 'studentlogs' => new external_value(PARAM_INT, 'student logs visible to everyone', VALUE_OPTIONAL), - 'chattime' => new external_value(PARAM_INT, 'chat time', VALUE_OPTIONAL), - 'schedule' => new external_value(PARAM_INT, 'schedule type', VALUE_OPTIONAL), - 'timemodified' => new external_value(PARAM_INT, 'time of last modification', VALUE_OPTIONAL), - ] - ), 'Chats') - ), - 'warnings' => new external_warnings(), - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.4 - */ - public static function get_sessions_parameters() { - return new external_function_parameters( - array( - 'chatid' => new external_value(PARAM_INT, 'Chat instance id.'), - 'groupid' => new external_value(PARAM_INT, 'Get messages from users in this group. - 0 means that the function will determine the user group', VALUE_DEFAULT, 0), - 'showall' => new external_value(PARAM_BOOL, 'Whether to show completed sessions or not.', VALUE_DEFAULT, false), - ) - ); - } - - /** - * Retrieves chat sessions for a given chat. - * - * @param int $chatid the chat instance id - * @param int $groupid filter messages by this group. 0 to determine the group. - * @param bool $showall whether to include incomplete sessions or not - * @return array of warnings and the sessions - * @since Moodle 3.4 - * @throws moodle_exception - */ - public static function get_sessions($chatid, $groupid = 0, $showall = false) { - global $DB; - - $params = self::validate_parameters(self::get_sessions_parameters(), - array( - 'chatid' => $chatid, - 'groupid' => $groupid, - 'showall' => $showall, - )); - $sessions = $warnings = array(); - - // Request and permission validation. - $chat = $DB->get_record('chat', array('id' => $params['chatid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - if (empty($chat->studentlogs) && !has_capability('mod/chat:readlog', $context)) { - throw new moodle_exception('nopermissiontoseethechatlog', 'chat'); - } - - if (!empty($params['groupid'])) { - $groupid = $params['groupid']; - // Determine is the group is visible to user. - if (!groups_group_visible($groupid, $course, $cm)) { - throw new moodle_exception('notingroup'); - } - } else { - // Check to see if groups are being used here. - if ($groupmode = groups_get_activity_groupmode($cm)) { - $groupid = groups_get_activity_group($cm); - // Determine is the group is visible to user (this is particullary for the group 0). - if (!groups_group_visible($groupid, $course, $cm)) { - throw new moodle_exception('notingroup'); - } - } else { - $groupid = 0; - } - } - - $messages = chat_get_session_messages($chat->id, $groupid, 0, 0, 'timestamp DESC'); - if ($messages) { - $chatsessions = chat_get_sessions($messages, $params['showall']); - // Format sessions for external. - foreach ($chatsessions as $session) { - $sessionusers = array(); - foreach ($session->sessionusers as $sessionuser => $usermessagecount) { - $sessionusers[] = array( - 'userid' => $sessionuser, - 'messagecount' => $usermessagecount - ); - } - $session->sessionusers = $sessionusers; - $sessions[] = $session; - } - } - - $result = array(); - $result['sessions'] = $sessions; - $result['warnings'] = $warnings; - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.4 - */ - public static function get_sessions_returns() { - return new external_single_structure( - array( - 'sessions' => new external_multiple_structure( - new external_single_structure( - array( - 'sessionstart' => new external_value(PARAM_INT, 'Session start time.'), - 'sessionend' => new external_value(PARAM_INT, 'Session end time.'), - 'sessionusers' => new external_multiple_structure( - new external_single_structure( - array( - 'userid' => new external_value(PARAM_INT, 'User id.'), - 'messagecount' => new external_value(PARAM_INT, 'Number of messages in the session.'), - ) - ), 'Session users.' - ), - 'iscomplete' => new external_value(PARAM_BOOL, 'Whether the session is completed or not.'), - ) - ), - 'list of users' - ), - 'warnings' => new external_warnings() - ) - ); - } - - /** - * Returns description of method parameters - * - * @return external_function_parameters - * @since Moodle 3.4 - */ - public static function get_session_messages_parameters() { - return new external_function_parameters( - array( - 'chatid' => new external_value(PARAM_INT, 'Chat instance id.'), - 'sessionstart' => new external_value(PARAM_INT, 'The session start time (timestamp).'), - 'sessionend' => new external_value(PARAM_INT, 'The session end time (timestamp).'), - 'groupid' => new external_value(PARAM_INT, 'Get messages from users in this group. - 0 means that the function will determine the user group', VALUE_DEFAULT, 0), - ) - ); - } - - /** - * Retrieves messages of the given chat session. - * - * @param int $chatid the chat instance id - * @param int $sessionstart the session start time (timestamp) - * @param int $sessionend the session end time (timestamp) - * @param int $groupid filter messages by this group. 0 to determine the group. - * @return array of warnings and the messages - * @since Moodle 3.4 - * @throws moodle_exception - */ - public static function get_session_messages($chatid, $sessionstart, $sessionend, $groupid = 0) { - global $DB, $PAGE; - - $params = self::validate_parameters(self::get_session_messages_parameters(), - array( - 'chatid' => $chatid, - 'sessionstart' => $sessionstart, - 'sessionend' => $sessionend, - 'groupid' => $groupid, - )); - $messages = $warnings = array(); - - // Request and permission validation. - $chat = $DB->get_record('chat', array('id' => $params['chatid']), '*', MUST_EXIST); - list($course, $cm) = get_course_and_cm_from_instance($chat, 'chat'); - - $context = context_module::instance($cm->id); - self::validate_context($context); - - if (empty($chat->studentlogs) && !has_capability('mod/chat:readlog', $context)) { - throw new moodle_exception('nopermissiontoseethechatlog', 'chat'); - } - - if (!empty($params['groupid'])) { - $groupid = $params['groupid']; - // Determine is the group is visible to user. - if (!groups_group_visible($groupid, $course, $cm)) { - throw new moodle_exception('notingroup'); - } - } else { - // Check to see if groups are being used here. - if ($groupmode = groups_get_activity_groupmode($cm)) { - $groupid = groups_get_activity_group($cm); - // Determine is the group is visible to user (this is particullary for the group 0). - if (!groups_group_visible($groupid, $course, $cm)) { - throw new moodle_exception('notingroup'); - } - } else { - $groupid = 0; - } - } - - $messages = chat_get_session_messages($chat->id, $groupid, $params['sessionstart'], $params['sessionend'], - 'timestamp ASC'); - if ($messages) { - foreach ($messages as $message) { - $exporter = new chat_message_exporter($message, array('context' => $context)); - $returneditems[] = $exporter->export($PAGE->get_renderer('core')); - } - } - - $result = array( - 'messages' => $messages, - 'warnings' => $warnings, - ); - return $result; - } - - /** - * Returns description of method result value - * - * @return \core_external\external_description - * @since Moodle 3.4 - */ - public static function get_session_messages_returns() { - return new external_single_structure( - array( - 'messages' => new external_multiple_structure( - chat_message_exporter::get_read_structure() - ), - 'warnings' => new external_warnings() - ) - ); - } -} diff --git a/mod/chat/classes/external/chat_message_exporter.php b/mod/chat/classes/external/chat_message_exporter.php deleted file mode 100644 index 1f3cac48b67..00000000000 --- a/mod/chat/classes/external/chat_message_exporter.php +++ /dev/null @@ -1,101 +0,0 @@ -. - -/** - * Class for exporting a chat message. - * - * @package mod_chat - * @copyright 2017 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace mod_chat\external; -defined('MOODLE_INTERNAL') || die(); - -use core\external\exporter; - -/** - * Class for exporting a chat message. - * - * @copyright 2017 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class chat_message_exporter extends exporter { - - /** - * Defines exporter properties. - * - * @return array - */ - protected static function define_properties() { - return array( - 'id' => array( - 'type' => PARAM_INT, - 'description' => 'The message record id.', - ), - 'chatid' => array( - 'type' => PARAM_INT, - 'description' => 'The chat id.', - 'default' => 0, - ), - 'userid' => array( - 'type' => PARAM_INT, - 'description' => 'The user who wrote the message.', - 'default' => 0, - ), - 'groupid' => array( - 'type' => PARAM_INT, - 'description' => 'The group this message belongs to.', - 'default' => 0, - ), - 'issystem' => array( - 'type' => PARAM_BOOL, - 'description' => 'Whether is a system message or not.', - 'default' => false, - ), - 'message' => array( - 'type' => PARAM_RAW, - 'description' => 'The message text.', - ), - 'timestamp' => array( - 'type' => PARAM_INT, - 'description' => 'The message timestamp (indicates when the message was sent).', - 'default' => 0, - ), - ); - } - - /** - * Defines related information. - * - * @return array - */ - protected static function define_related() { - return array( - 'context' => 'context', - ); - } - - /** - * Get the formatting parameters for the name. - * - * @return array - */ - protected function get_format_parameters_for_message() { - return [ - 'component' => 'mod_chat', - ]; - } -} diff --git a/mod/chat/classes/external/view_sessions.php b/mod/chat/classes/external/view_sessions.php deleted file mode 100644 index 474cc11d60b..00000000000 --- a/mod/chat/classes/external/view_sessions.php +++ /dev/null @@ -1,121 +0,0 @@ -. - -namespace mod_chat\external; - -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; - -/** - * External service to log viewed previous chat sessions. - * - * @package mod_chat - * @category external - * @copyright 2023 Rodrigo Mady - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 4.3 - */ -class view_sessions extends external_api { - /** - * Returns description of method parameters - * - * @return external_function_parameters - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'cmid' => new external_value(PARAM_INT, 'Course module id', VALUE_REQUIRED), - 'start' => new external_value(PARAM_INT, 'Session start time', VALUE_DEFAULT, 0), - 'end' => new external_value(PARAM_INT, 'Session end time', VALUE_DEFAULT, 0), - ]); - } - - /** - * Execute the chat view sessions event. - * - * @param int $cmid the chat course module id - * @param null|int $start - * @param null|int $end - * @return array - * @throws \restricted_context_exception - */ - public static function execute(int $cmid, ?int $start = 0, ?int $end = 0): array { - global $DB; - $warnings = []; - $status = false; - // Validate the cmid ID. - [ - 'cmid' => $cmid, - 'start' => $start, - 'end' => $end, - ] = self::validate_parameters(self::execute_parameters(), [ - 'cmid' => $cmid, - 'start' => $start, - 'end' => $end, - ]); - if (!$cm = get_coursemodule_from_id('chat', $cmid)) { - throw new \moodle_exception('invalidcoursemodule', 'error'); - } - if (!$chat = $DB->get_record('chat', ['id' => $cm->instance])) { - throw new \moodle_exception('invalidcoursemodule', 'error'); - } - - $context = \context_module::instance($cm->id); - self::validate_context($context); - - // Check capability. - if (has_capability('mod/chat:readlog', $context)) { - $params = [ - 'context' => $context, - 'objectid' => $chat->id, - 'other' => [ - 'start' => $start, - 'end' => $end - ] - ]; - $event = \mod_chat\event\sessions_viewed::create($params); - $status = true; - $event->add_record_snapshot('chat', $chat); - $event->trigger(); - } else { - $warnings[] = [ - 'item' => $cm->id, - 'warningcode' => 'nopermissiontoseethechatlog', - 'message' => get_string('nopermissiontoseethechatlog', 'chat') - ]; - } - - $result = [ - 'status' => $status, - 'warnings' => $warnings - ]; - return $result; - } - - /** - * Describe the return structure of the external service. - * - * @return external_single_structure - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings() - ]); - } -} diff --git a/mod/chat/classes/privacy/provider.php b/mod/chat/classes/privacy/provider.php deleted file mode 100644 index d6f24a643ff..00000000000 --- a/mod/chat/classes/privacy/provider.php +++ /dev/null @@ -1,333 +0,0 @@ -. - -/** - * Data provider. - * - * @package mod_chat - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\privacy; -defined('MOODLE_INTERNAL') || die(); - -use context; -use context_helper; -use context_module; -use moodle_recordset; -use stdClass; -use core_privacy\local\metadata\collection; -use core_privacy\local\request\approved_contextlist; -use core_privacy\local\request\approved_userlist; -use core_privacy\local\request\contextlist; -use core_privacy\local\request\helper; -use core_privacy\local\request\transform; -use core_privacy\local\request\userlist; -use core_privacy\local\request\writer; - -/** - * Data provider class. - * - * @package mod_chat - * @copyright 2018 Frédéric Massart - * @author Frédéric Massart - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class provider implements - \core_privacy\local\metadata\provider, - \core_privacy\local\request\core_userlist_provider, - \core_privacy\local\request\plugin\provider { - - /** - * Returns metadata. - * - * @param collection $collection The initialised collection to add items to. - * @return collection A listing of user data stored through this system. - */ - public static function get_metadata(collection $collection): collection { - - $collection->add_database_table('chat_messages', [ - 'userid' => 'privacy:metadata:messages:userid', - 'message' => 'privacy:metadata:messages:message', - 'issystem' => 'privacy:metadata:messages:issystem', - 'timestamp' => 'privacy:metadata:messages:timestamp', - ], 'privacy:metadata:messages'); - - // The tables chat_messages_current and chat_users are not exported/deleted - // because they are considered as short-lived data and are deleted on a - // regular basis by cron, or during normal requests. TODO MDL-62006. - - $collection->add_database_table('chat_messages_current', [ - 'userid' => 'privacy:metadata:messages:userid', - 'message' => 'privacy:metadata:messages:message', - 'issystem' => 'privacy:metadata:messages:issystem', - 'timestamp' => 'privacy:metadata:messages:timestamp' - ], 'privacy:metadata:chat_messages_current'); - - $collection->add_database_table('chat_users', [ - 'userid' => 'privacy:metadata:chat_users:userid', - 'version' => 'privacy:metadata:chat_users:version', - 'ip' => 'privacy:metadata:chat_users:ip', - 'firstping' => 'privacy:metadata:chat_users:firstping', - 'lastping' => 'privacy:metadata:chat_users:lastping', - 'lastmessageping' => 'privacy:metadata:chat_users:lastmessageping', - 'lang' => 'privacy:metadata:chat_users:lang' - ], 'privacy:metadata:chat_users'); - - return $collection; - } - - /** - * Get the list of contexts that contain user information for the specified user. - * - * @param int $userid The user to search. - * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. - */ - public static function get_contexts_for_userid(int $userid): \core_privacy\local\request\contextlist { - $contextlist = new \core_privacy\local\request\contextlist(); - - $sql = " - SELECT DISTINCT ctx.id - FROM {chat} c - JOIN {modules} m - ON m.name = :chat - JOIN {course_modules} cm - ON cm.instance = c.id - AND cm.module = m.id - JOIN {context} ctx - ON ctx.instanceid = cm.id - AND ctx.contextlevel = :modulelevel - JOIN {chat_messages} chm - ON chm.chatid = c.id - WHERE chm.userid = :userid"; - - $params = [ - 'chat' => 'chat', - 'modulelevel' => CONTEXT_MODULE, - 'userid' => $userid, - ]; - $contextlist->add_from_sql($sql, $params); - - return $contextlist; - } - - /** - * Get the list of users who have data within a context. - * - * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. - */ - public static function get_users_in_context(userlist $userlist) { - $context = $userlist->get_context(); - - if (!is_a($context, \context_module::class)) { - return; - } - - $params = [ - 'instanceid' => $context->instanceid, - 'modulename' => 'chat', - ]; - - $sql = "SELECT chm.userid - FROM {course_modules} cm - JOIN {modules} m ON m.id = cm.module AND m.name = :modulename - JOIN {chat} c ON c.id = cm.instance - JOIN {chat_messages} chm ON chm.chatid = c.id - WHERE cm.id = :instanceid"; - - $userlist->add_from_sql('userid', $sql, $params); - } - - /** - * Export all user data for the specified user, in the specified contexts. - * - * @param approved_contextlist $contextlist The approved contexts to export information for. - */ - public static function export_user_data(approved_contextlist $contextlist) { - global $DB; - - $user = $contextlist->get_user(); - $userid = $user->id; - $cmids = array_reduce($contextlist->get_contexts(), function($carry, $context) { - if ($context->contextlevel == CONTEXT_MODULE) { - $carry[] = $context->instanceid; - } - return $carry; - }, []); - if (empty($cmids)) { - return; - } - - $chatidstocmids = static::get_chat_ids_to_cmids_from_cmids($cmids); - $chatids = array_keys($chatidstocmids); - - // Export the messages. - list($insql, $inparams) = $DB->get_in_or_equal($chatids, SQL_PARAMS_NAMED); - $params = array_merge($inparams, ['userid' => $userid]); - $recordset = $DB->get_recordset_select('chat_messages', "chatid $insql AND userid = :userid", $params, 'timestamp, id'); - static::recordset_loop_and_export($recordset, 'chatid', [], function($carry, $record) use ($user, $chatidstocmids) { - $message = $record->message; - if ($record->issystem) { - $message = get_string('message' . $record->message, 'mod_chat', fullname($user)); - } - $carry[] = [ - 'message' => $message, - 'sent_at' => transform::datetime($record->timestamp), - 'is_system_generated' => transform::yesno($record->issystem), - ]; - return $carry; - - }, function($chatid, $data) use ($user, $chatidstocmids) { - $context = context_module::instance($chatidstocmids[$chatid]); - $contextdata = helper::get_context_data($context, $user); - $finaldata = (object) array_merge((array) $contextdata, ['messages' => $data]); - helper::export_context_files($context, $user); - writer::with_context($context)->export_data([], $finaldata); - }); - } - - /** - * Delete all data for all users in the specified context. - * - * @param context $context The specific context to delete data for. - */ - public static function delete_data_for_all_users_in_context(context $context) { - global $DB; - - if ($context->contextlevel != CONTEXT_MODULE) { - return; - } - - $cm = get_coursemodule_from_id('chat', $context->instanceid); - if (!$cm) { - return; - } - - $chatid = $cm->instance; - $DB->delete_records_select('chat_messages', 'chatid = :chatid', ['chatid' => $chatid]); - $DB->delete_records_select('chat_messages_current', 'chatid = :chatid', ['chatid' => $chatid]); - $DB->delete_records_select('chat_users', 'chatid = :chatid', ['chatid' => $chatid]); - } - - /** - * Delete all user data for the specified user, in the specified contexts. - * - * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. - */ - public static function delete_data_for_user(approved_contextlist $contextlist) { - global $DB; - - $userid = $contextlist->get_user()->id; - $cmids = array_reduce($contextlist->get_contexts(), function($carry, $context) { - if ($context->contextlevel == CONTEXT_MODULE) { - $carry[] = $context->instanceid; - } - return $carry; - }, []); - if (empty($cmids)) { - return; - } - - $chatidstocmids = static::get_chat_ids_to_cmids_from_cmids($cmids); - $chatids = array_keys($chatidstocmids); - - list($insql, $inparams) = $DB->get_in_or_equal($chatids, SQL_PARAMS_NAMED); - $sql = "chatid $insql AND userid = :userid"; - $params = array_merge($inparams, ['userid' => $userid]); - - $DB->delete_records_select('chat_messages', $sql, $params); - $DB->delete_records_select('chat_messages_current', $sql, $params); - $DB->delete_records_select('chat_users', $sql, $params); - } - - - /** - * Delete multiple users within a single context. - * - * @param approved_userlist $userlist The approved context and user information to delete information for. - */ - public static function delete_data_for_users(approved_userlist $userlist) { - global $DB; - - $context = $userlist->get_context(); - $cm = $DB->get_record('course_modules', ['id' => $context->instanceid]); - $chat = $DB->get_record('chat', ['id' => $cm->instance]); - - list($userinsql, $userinparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); - $params = array_merge(['chatid' => $chat->id], $userinparams); - $sql = "chatid = :chatid AND userid {$userinsql}"; - - $DB->delete_records_select('chat_messages', $sql, $params); - $DB->delete_records_select('chat_messages_current', $sql, $params); - $DB->delete_records_select('chat_users', $sql, $params); - } - - /** - * Return a dict of chat IDs mapped to their course module ID. - * - * @param array $cmids The course module IDs. - * @return array In the form of [$chatid => $cmid]. - */ - protected static function get_chat_ids_to_cmids_from_cmids(array $cmids) { - global $DB; - list($insql, $inparams) = $DB->get_in_or_equal($cmids, SQL_PARAMS_NAMED); - $sql = " - SELECT c.id, cm.id AS cmid - FROM {chat} c - JOIN {modules} m - ON m.name = :chat - JOIN {course_modules} cm - ON cm.instance = c.id - AND cm.module = m.id - WHERE cm.id $insql"; - $params = array_merge($inparams, ['chat' => 'chat']); - return $DB->get_records_sql_menu($sql, $params); - } - - /** - * Loop and export from a recordset. - * - * @param moodle_recordset $recordset The recordset. - * @param string $splitkey The record key to determine when to export. - * @param mixed $initial The initial data to reduce from. - * @param callable $reducer The function to return the dataset, receives current dataset, and the current record. - * @param callable $export The function to export the dataset, receives the last value from $splitkey and the dataset. - * @return void - */ - protected static function recordset_loop_and_export(moodle_recordset $recordset, $splitkey, $initial, - callable $reducer, callable $export) { - - $data = $initial; - $lastid = null; - - foreach ($recordset as $record) { - if ($lastid && $record->{$splitkey} != $lastid) { - $export($lastid, $data); - $data = $initial; - } - $data = $reducer($data, $record); - $lastid = $record->{$splitkey}; - } - $recordset->close(); - - if (!empty($lastid)) { - $export($lastid, $data); - } - } - -} diff --git a/mod/chat/classes/search/activity.php b/mod/chat/classes/search/activity.php deleted file mode 100644 index 98bed370926..00000000000 --- a/mod/chat/classes/search/activity.php +++ /dev/null @@ -1,46 +0,0 @@ -. - -/** - * Search area for mod_chat activities. - * - * @package mod_chat - * @copyright 2015 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace mod_chat\search; - -defined('MOODLE_INTERNAL') || die(); - -/** - * Search area for mod_chat activities. - * - * @package mod_chat - * @copyright 2015 David Monllao {@link http://www.davidmonllao.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class activity extends \core_search\base_activity { - - /** - * Returns true if this area uses file indexing. - * - * @return bool - */ - public function uses_file_indexing() { - return true; - } -} diff --git a/mod/chat/classes/task/cron_task.php b/mod/chat/classes/task/cron_task.php deleted file mode 100644 index f933c83dabc..00000000000 --- a/mod/chat/classes/task/cron_task.php +++ /dev/null @@ -1,65 +0,0 @@ -. - -/** - * A scheduled task for chat cron. - * - * @package mod_chat - * @copyright 2019 Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace mod_chat\task; - -defined('MOODLE_INTERNAL') || die(); - -/** - * The main schedule task for the chat module. - * - * @package mod_chat - * @copyright 2019 Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class cron_task extends \core\task\scheduled_task { - - /** - * Get a descriptive name for this task (shown to admins). - * - * @return string - */ - public function get_name() { - return get_string('crontask', 'mod_chat'); - } - - /** - * Run chat cron. - */ - public function execute() { - global $CFG, $DB; - require_once($CFG->dirroot . '/mod/chat/lib.php'); - - chat_update_chat_times(); - chat_delete_old_users(); - - $timenow = time(); - $subselect = "SELECT c.keepdays - FROM {chat} c - WHERE c.id = {chat_messages}.chatid"; - $DB->delete_records_select('chat_messages', "($subselect) > 0 AND timestamp < (? - ($subselect) * ?)", - [$timenow, DAYSECS]); - - $DB->delete_records_select('chat_messages_current', "timestamp < ?", [$timenow - 8 * HOURSECS]); - } -} diff --git a/mod/chat/db/access.php b/mod/chat/db/access.php deleted file mode 100644 index 9c4e6801dbd..00000000000 --- a/mod/chat/db/access.php +++ /dev/null @@ -1,114 +0,0 @@ -. - -/** - * Plugin capabilities - * - * @package mod_chat - * @copyright 2006 Martin Dougiamas - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$capabilities = array( - - 'mod/chat:addinstance' => array( - 'riskbitmask' => RISK_XSS, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => array( - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ), - 'clonepermissionsfrom' => 'moodle/course:manageactivities' - ), - - 'mod/chat:chat' => array( - - 'riskbitmask' => RISK_SPAM, - - 'captype' => 'write', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'student' => CAP_ALLOW, - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), - - 'mod/chat:readlog' => array( - - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'student' => CAP_ALLOW, - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), - - 'mod/chat:deletelog' => array( - - 'captype' => 'write', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW - ) - ), - - 'mod/chat:exportparticipatedsession' => array( - - 'riskbitmask' => RISK_PERSONAL, - - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW, - // Not student - nervous about allowing this by default. - ), - - ), - - 'mod/chat:exportsession' => array( - - 'riskbitmask' => RISK_PERSONAL, - - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW, - ), - ), - - 'mod/chat:view' => array( - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'user' => CAP_ALLOW, - 'guest' => CAP_ALLOW - ) - ) -); diff --git a/mod/chat/db/events.php b/mod/chat/db/events.php deleted file mode 100644 index 85b9d9bc69c..00000000000 --- a/mod/chat/db/events.php +++ /dev/null @@ -1,34 +0,0 @@ -. - -/** - * Event observers definition. - * - * @package mod_chat - * @category event - * @copyright 2010 Dongsheng Cai - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$observers = array( - - // User logging out. - array( - 'eventname' => '\core\event\user_loggedout', - 'callback' => 'chat_user_logout', - 'includefile' => '/mod/chat/lib.php' - ) -); diff --git a/mod/chat/db/install.php b/mod/chat/db/install.php deleted file mode 100644 index a05ae06e445..00000000000 --- a/mod/chat/db/install.php +++ /dev/null @@ -1,33 +0,0 @@ -. - -/** - * Chat module installation. - * - * @package mod_chat - * @copyright 2024 Sara Arjona - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -/** - * Perform the post-install procedures. - */ -function xmldb_chat_install() { - global $DB; - - // Disable the chat activity module on new installs by default. - $DB->set_field('modules', 'visible', 0, ['name' => 'chat']); -} diff --git a/mod/chat/db/install.xml b/mod/chat/db/install.xml deleted file mode 100644 index dfc44d0257a..00000000000 --- a/mod/chat/db/install.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
diff --git a/mod/chat/db/log.php b/mod/chat/db/log.php deleted file mode 100644 index 5cde13bf2e8..00000000000 --- a/mod/chat/db/log.php +++ /dev/null @@ -1,34 +0,0 @@ -. - -/** - * Definition of log events - * - * @package mod_chat - * @category log - * @copyright 2010 Petr Skoda (http://skodak.org) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$logs = array( - array('module' => 'chat', 'action' => 'view', 'mtable' => 'chat', 'field' => 'name'), - array('module' => 'chat', 'action' => 'add', 'mtable' => 'chat', 'field' => 'name'), - array('module' => 'chat', 'action' => 'update', 'mtable' => 'chat', 'field' => 'name'), - array('module' => 'chat', 'action' => 'report', 'mtable' => 'chat', 'field' => 'name'), - array('module' => 'chat', 'action' => 'talk', 'mtable' => 'chat', 'field' => 'name'), -); diff --git a/mod/chat/db/services.php b/mod/chat/db/services.php deleted file mode 100644 index 6cc8a0ffe3e..00000000000 --- a/mod/chat/db/services.php +++ /dev/null @@ -1,108 +0,0 @@ -. - -/** - * Chat external functions and service definitions. - * - * @package mod_chat - * @category external - * @copyright 2015 Juan Leyva - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.0 - */ - -defined('MOODLE_INTERNAL') || die; - -$functions = array( - - 'mod_chat_login_user' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'login_user', - 'description' => 'Log a user into a chat room in the given chat.', - 'type' => 'write', - 'capabilities' => 'mod/chat:chat', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_chat_get_chat_users' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'get_chat_users', - 'description' => 'Get the list of users in the given chat session.', - 'type' => 'read', - 'capabilities' => 'mod/chat:chat', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_chat_send_chat_message' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'send_chat_message', - 'description' => 'Send a message on the given chat session.', - 'type' => 'write', - 'capabilities' => 'mod/chat:chat', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_chat_get_chat_latest_messages' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'get_chat_latest_messages', - 'description' => 'Get the latest messages from the given chat session.', - 'type' => 'read', - 'capabilities' => 'mod/chat:chat', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_chat_view_chat' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'view_chat', - 'description' => 'Trigger the course module viewed event and update the module completion status.', - 'type' => 'write', - 'capabilities' => 'mod/chat:chat', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_chat_get_chats_by_courses' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'get_chats_by_courses', - 'description' => 'Returns a list of chat instances in a provided set of courses, - if no courses are provided then all the chat instances the user has access to will be returned.', - 'type' => 'read', - 'capabilities' => '', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - 'mod_chat_get_sessions' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'get_sessions', - 'description' => 'Retrieves chat sessions for a given chat.', - 'type' => 'read', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - 'mod_chat_get_session_messages' => array( - 'classname' => 'mod_chat_external', - 'methodname' => 'get_session_messages', - 'description' => 'Retrieves messages of the given chat session.', - 'type' => 'read', - 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) - ), - - 'mod_chat_view_sessions' => [ - 'classname' => 'mod_chat\external\view_sessions', - 'methodname' => 'execute', - 'description' => 'Trigger the chat session viewed event.', - 'type' => 'write', - 'capabilities' => 'mod/chat:readlog', - 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE] - ], -); diff --git a/mod/chat/db/tasks.php b/mod/chat/db/tasks.php deleted file mode 100644 index a49ca7ebc25..00000000000 --- a/mod/chat/db/tasks.php +++ /dev/null @@ -1,36 +0,0 @@ -. - -/** - * Definition of chat scheduled tasks. - * - * @package mod_chat - * @copyright 2019 Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); -$tasks = array( - array( - 'classname' => '\mod_chat\task\cron_task', - 'blocking' => 0, - 'minute' => '*/5', - 'hour' => '*', - 'day' => '*', - 'month' => '*', - 'dayofweek' => '*' - ) -); diff --git a/mod/chat/db/upgrade.php b/mod/chat/db/upgrade.php deleted file mode 100644 index c17577f43b1..00000000000 --- a/mod/chat/db/upgrade.php +++ /dev/null @@ -1,39 +0,0 @@ -. - -/** - * Upgrade code for the chat activity - * - * @package mod_chat - * @copyright 2006 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -function xmldb_chat_upgrade($oldversion) { - // Automatically generated Moodle v4.2.0 release upgrade line. - // Put any upgrade step following this. - - // Automatically generated Moodle v4.3.0 release upgrade line. - // Put any upgrade step following this. - - // Automatically generated Moodle v4.4.0 release upgrade line. - // Put any upgrade step following this. - - // Automatically generated Moodle v4.5.0 release upgrade line. - // Put any upgrade step following this. - - return true; -} diff --git a/mod/chat/empty.php b/mod/chat/empty.php deleted file mode 100644 index c06c35e0d51..00000000000 --- a/mod/chat/empty.php +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/mod/chat/gui_ajax/index.php b/mod/chat/gui_ajax/index.php deleted file mode 100644 index 42d5cd18c3c..00000000000 --- a/mod/chat/gui_ajax/index.php +++ /dev/null @@ -1,114 +0,0 @@ -. - -require_once('../../../config.php'); -require_once('../lib.php'); - -$id = required_param('id', PARAM_INT); -$groupid = optional_param('groupid', 0, PARAM_INT); // Only for teachers. -$theme = optional_param('chat_theme', 'course_theme', PARAM_SAFEDIR); // The value course_theme == the current theme. - -$url = new moodle_url('/mod/chat/gui_ajax/index.php', array('id' => $id)); -if ($groupid !== 0) { - $url->param('groupid', $groupid); -} -$PAGE->set_url($url); -$PAGE->set_popup_notification_allowed(false); // No popup notifications in the chat window. -$PAGE->requires->strings_for_js(array('coursetheme', 'bubble', 'compact'), 'mod_chat'); - -$chat = $DB->get_record('chat', array('id' => $id), '*', MUST_EXIST); -$course = $DB->get_record('course', array('id' => $chat->course), '*', MUST_EXIST); -$cm = get_coursemodule_from_instance('chat', $chat->id, $course->id, false, MUST_EXIST); - -$context = context_module::instance($cm->id); -require_login($course, false, $cm); -require_capability('mod/chat:chat', $context); - -// Check to see if groups are being used here. -if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used. - if ($groupid = groups_get_activity_group($cm)) { - if (!$group = groups_get_group($groupid)) { - throw new \moodle_exception('invalidgroupid'); - } - $groupname = ': '.$group->name; - } else { - $groupname = ': '.get_string('allparticipants'); - } -} else { - $groupid = 0; - $groupname = ''; -} -// If requested theme doesn't exist, use default 'bubble' theme. -if ($theme != 'course_theme' and !file_exists(__DIR__ . '/theme/'.$theme.'/chat.css')) { - $theme = 'compact'; -} - -// Log into the chat room. -if (!$chatsid = chat_login_user($chat->id, 'ajax', $groupid, $course)) { - throw new \moodle_exception('cantlogin', 'chat'); -} -$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id))); -$module = array( - 'name' => 'mod_chat_ajax', // Chat gui's are not real plugins, we have to break the naming standards for JS modules here. - 'fullpath' => '/mod/chat/gui_ajax/module.js', - 'requires' => array('base', 'dom', 'event', 'event-mouseenter', 'event-key', 'json-parse', 'io', 'overlay', 'yui2-resize', - 'yui2-layout', 'yui2-menu'), - 'strings' => array(array('send', 'chat'), array('sending', 'chat'), array('inputarea', 'chat'), array('userlist', 'chat'), - array('modulename', 'chat'), array('beep', 'chat'), array('talk', 'chat')) -); -$modulecfg = array( - 'home' => $CFG->wwwroot.'/mod/chat/view.php?id='.$cm->id, - 'chaturl' => $CFG->wwwroot.'/mod/chat/gui_ajax/index.php?id='.$id, - 'theme' => $theme, - 'userid' => $USER->id, - 'sid' => $chatsid, - 'timer' => 3000, - 'chat_lasttime' => 0, - 'chat_lastrow' => null, - 'chatroom_name' => $courseshortname . ": " . format_string($chat->name, true) . $groupname -); -$PAGE->requires->js_init_call('M.mod_chat_ajax.init', array($modulecfg), false, $module); - -$PAGE->set_title(get_string('modulename', 'chat').": $courseshortname: ".format_string($chat->name, true)."$groupname"); -$PAGE->add_body_class('yui-skin-sam'); -$PAGE->activityheader->disable(); -$PAGE->set_pagelayout('embedded'); -if ( $theme != 'course_theme') { - $PAGE->requires->css('/mod/chat/gui_ajax/theme/'.$theme.'/chat.css'); -} - -echo $OUTPUT->header(); -echo $OUTPUT->box(html_writer::tag('h2', get_string('participants'), array('class' => 'accesshide')) . - '
    ', '', 'chat-userlist'); -echo $OUTPUT->box('', '', 'chat-options'); -echo $OUTPUT->box(html_writer::tag('h2', get_string('messages', 'chat'), array('class' => 'accesshide')) . - '
      ', '', 'chat-messages'); -$table = new html_table(); -$table->data = [[ - '
      '. - ''. - '' .$OUTPUT->help_icon('usingchat', 'chat'). '
      ' . - '
      ', -]]; -echo $OUTPUT->box(html_writer::tag('h2', get_string('composemessage', 'chat'), array('class' => 'accesshide')) . - html_writer::table($table), '', 'chat-input-area'); -echo $OUTPUT->box('', '', 'chat-notify'); -echo $OUTPUT->footer(); diff --git a/mod/chat/gui_ajax/module.js b/mod/chat/gui_ajax/module.js deleted file mode 100644 index 231392f4a15..00000000000 --- a/mod/chat/gui_ajax/module.js +++ /dev/null @@ -1,265 +0,0 @@ -/* - * NOTE: the /mod/chat/gui_header_js/ is not a real plugin, - * ideally this code should be in /mod/chat/module.js - */ - -/** - * @namespace M.mod_chat_ajax - */ -M.mod_chat_ajax = M.mod_chat_ajax || {}; - -/** - * Init ajax based Chat UI. - * @namespace M.mod_chat_ajax - * @function - * @param {YUI} Y - * @param {Object} cfg configuration data - */ -M.mod_chat_ajax.init = function(Y, cfg) { - - var gui_ajax = { - - // Properties. - api : M.cfg.wwwroot + '/mod/chat/chat_ajax.php?sesskey=' + M.cfg.sesskey, // The path to the ajax callback script. - cfg : {}, // A configuration variable. - interval : null, // The interval object for refreshes. - layout : null, // A reference to the layout used in this module. - messages : [], // An array of messages. - scrollable : true, // True is scrolling should occur. - thememenu : null, // A reference to the menu for changing themes. - - // Elements - messageinput : null, - sendbutton : null, - messagebox : null, - - init : function(cfg) { - this.cfg = cfg; - this.cfg.req_count = this.cfg.req_count || 0; - participantswidth = 180; - if (Y.one('#input-message').get('docWidth') < 640) { - participantswidth = 120; - } - this.layout = new Y.YUI2.widget.Layout({ - units : [ - {position: 'right', width: participantswidth, resize: true, gutter: '1px', scroll: true, body: 'chat-userlist', animate: false}, - {position: 'bottom', height: 42, resize: false, body: 'chat-input-area', gutter: '1px', collapse: false, resize: false}, - {position: 'center', body: 'chat-messages', gutter: '0px', scroll: true} - ] - }); - - this.layout.on('render', function() { - var unit = this.getUnitByPosition('right'); - if (unit) { - unit.on('close', function() { - closeLeft(); - }); - } - }, this.layout); - this.layout.render(); - - // Gather the general elements. - this.messageinput = Y.one('#input-message'); - this.sendbutton = Y.one('#button-send'); - this.messagebox = Y.one('#chat-messages'); - - // Set aria attributes to messagebox and chat-userlist. - this.messagebox.set('role', 'log'); - this.messagebox.set('aria-live', 'polite'); - var userlist = Y.one('#chat-userlist'); - userlist.set('aria-live', 'polite'); - userlist.set('aria-relevant', 'all'); - - // Attach the default events for this module. - this.sendbutton.on('click', this.send, this); - this.messagebox.on('mouseenter', function() { - this.scrollable = false; - }, this); - this.messagebox.on('mouseleave', function() { - this.scrollable = true; - }, this); - - // Send the message when the enter key is pressed. - Y.on('key', this.send, this.messageinput, 'press:13', this); - - document.title = this.cfg.chatroom_name; - - // Prepare and execute the first AJAX request of information. - Y.io(this.api,{ - method : 'POST', - data : build_querystring({ - action : 'init', - chat_init : 1, - chat_sid : this.cfg.sid, - chat_theme : this.cfg.theme - }), - on : { - success : function(tid, outcome) { - this.messageinput.removeAttribute('disabled'); - this.messageinput.set('value', ''); - this.messageinput.focus(); - try { - var data = Y.JSON.parse(outcome.responseText); - } catch (ex) { - return; - } - this.update_users(data.users); - } - }, - context : this - }); - - var scope = this; - this.interval = setInterval(function() { - scope.update_messages(); - }, this.cfg.timer, this); - - // Create and initalise theme changing menu. - this.thememenu = new Y.YUI2.widget.Menu('basicmenu', {xy:[0,0]}); - this.thememenu.addItems([ - {text: M.util.get_string('bubble', 'mod_chat'), url: this.cfg.chaturl + '&chat_theme=bubble'}, - {text: M.util.get_string('compact', 'mod_chat'), url: this.cfg.chaturl + '&chat_theme=compact'}, - {text: M.util.get_string('coursetheme', 'mod_chat'), url: this.cfg.chaturl + '&chat_theme=course_theme'} - ]); - this.thememenu.render(document.body); - Y.one('#choosetheme').on('click', function(e) { - this.moveTo((e.pageX - 20), (e.pageY - 20)); - this.show(); - }, this.thememenu); - - // Set the data-placement for the help-icon to display all the content. - this.helpicon = Y.one('#button-send + a'); - this.dataset = this.helpicon.get('dataset'); - this.dataset.placement = 'top'; - this.helpicon.set('dataset', this.dataset); - }, - - append_message : function(key, message, row) { - var item = Y.Node.create('
    • ' + message.message + '
    • '); - item.addClass((message.mymessage) ? 'mdl-chat-my-entry' : 'mdl-chat-entry'); - Y.one('#messages-list').append(item); - if (message.type && message.type == 'beep') { - var audioElement = document.createElement('audio'); - audioElement.setAttribute('src', '../beep.mp3'); - audioElement.play(); - } - }, - - send : function(e, beep) { - if((this.messageinput.get('value') != '') || (typeof beep != 'undefined')) { - this.sendbutton.set('value', M.util.get_string('sending', 'chat')); - var data = { - chat_message : (!beep) ? this.messageinput.get('value') : '', - chat_sid : this.cfg.sid, - chat_theme : this.cfg.theme - }; - if (beep) { - data.beep = beep - } - data.action = 'chat'; - - Y.io(this.api, { - method : 'POST', - data : build_querystring(data), - on : { - success : this.send_callback - }, - context : this - }); - } - }, - - send_callback : function(tid, outcome, args) { - try { - var data = Y.JSON.parse(outcome.responseText); - } catch (ex) { - return; - } - this.sendbutton.set('value', M.util.get_string('send', 'chat')); - this.messageinput.set('value', ''); - clearInterval(this.interval); - this.update_messages(); - var scope = this; - this.interval = setInterval(function() { - scope.update_messages(); - }, this.cfg.timer, this); - }, - - talkto: function (e, name) { - this.messageinput.set('value', "To " + name + ": "); - this.messageinput.focus(); - }, - - update_messages : function() { - this.cfg.req_count++; - Y.io(this.api, { - method : 'POST', - data : build_querystring({ - action: 'update', - chat_lastrow : this.cfg.chat_lastrow || false, - chat_lasttime : this.cfg.chat_lasttime, - chat_sid : this.cfg.sid, - chat_theme : this.cfg.theme - }), - on : { - success : this.update_messages_callback - }, - context : this - }); - }, - - update_messages_callback : function(tid, outcome) { - try { - var data = Y.JSON.parse(outcome.responseText); - } catch (ex) { - return; - } - if (data.error) { - clearInterval(this.interval); - alert(data.error); - window.location = this.cfg.home; - } - this.cfg.chat_lasttime = data.lasttime; - this.cfg.chat_lastrow = data.lastrow; - // Update messages. - for (var key in data.msgs){ - if (!M.util.in_array(key, this.messages)) { - this.messages.push(key); - this.append_message(key, data.msgs[key], data.lastrow); - } - } - // Update users. - this.update_users(data.users); - // Scroll to the bottom of the message list - if (this.scrollable) { - Y.Node.getDOMNode(this.messagebox).parentNode.scrollTop += 500; - } - this.messageinput.focus(); - }, - - update_users : function(users) { - if (!users) { - return; - } - var list = Y.one('#users-list'); - list.get('children').remove(); - for (var i in users) { - var li = Y.Node.create('
    • ' + users[i].picture + '
    • '); - if (users[i].id == this.cfg.userid) { - li.all('td').item(1).append(Y.Node.create('' + users[i].name + '')); - } else { - li.all('td').item(1).append(Y.Node.create('')); - var talk = Y.Node.create('' + M.util.get_string('talk', 'chat') + ''); - talk.on('click', this.talkto, this, users[i].name); - var beep = Y.Node.create('' + M.util.get_string('beep', 'chat') + ''); - beep.on('click', this.send, this, users[i].id); - li.all('td').item(1).append(Y.Node.create('
      ').append(talk).append(' ').append(beep)); - } - list.append(li); - } - } - - }; - - gui_ajax.init(cfg); -}; diff --git a/mod/chat/gui_ajax/theme/bubble/bubbles.png b/mod/chat/gui_ajax/theme/bubble/bubbles.png deleted file mode 100644 index 208dcfd86c70238ce3fe3a53eb9f79fccb87033a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1612 zcmV-S2DABzP)FM9!-~0Rf{r&y%@$vZh_`~UJ^z`)Z z?(XdD?DzNgyW(Tyd)tw$L4|KkrA$?xy)($dn)@Oa3`$k^D}^YioV?d_}3R^9)Q;o;%T%*>9kLEhfp z&+>oZ;NZ>8&E4t3!otFvuWs4d*`29@$=;XW{*=zxL+Wd~gU(b2l$W7E^q zs=0%epM9LXQK!pU=Kq}8{EMT;QQ-8Qz1M!MwUnBybHL$t;r*fX^z+#JiKe%K%6v31PpiPQFi#_4se%w@CJV7<|e&D6Z6$yTV$RI}M&(ej1b`jXuH zl+NXr%Uq}rh?Syt zmY{vR;#`-haFw@6;QXGJxk%0NeU6cb$K;2m!Dgw%ZQJgd)7Z$@+{@wnrsDjiuE=xI zfujkjv$ceSLkPyJF<{p#T5>4hNvi0009ANkl*~u+C?(Dl7&$dz9n$^y>ZFKJ3*|xpBxcbKVee}m7Vz%-cvAw7$ zULYkHvnyCo>{pY|V0LkQ-TW#jwp$5CpxB;0w-%Nbc;y5Gve}CSvukEis@NmrXo|#Q z+f4Puf0dUPRI`FuD#^oFM{2g;y;noQsmm`Y%sa~0nrvHtz8R(%$jj`t9Tgb4sx{j3 zK~_I~&+l~zv~0b{n^G>FqkLn2706bwE-HbSx@ZQPxzbvd!qz&eM5DzeG?=#3km7*Z znqp8WJep8Q%fpvex>2^8e?WBVAciS;9vqAjOvN?i>>;R9spFi)LJkR2LmKKXCqXPk zskUVjRFy9Ui1`4S*Dt54)Ee++#{6z$NnrrxDqiJAm^D%|(7nB>HQuF4Ie}GX7H;HM zp9e)_dEx?bUaSKk7S`GL3P5P{y*o3~)6+9*Cz??Rm|X#xIU!@ycu#e8bmL7c-zx?=z*O|a2L}!uym`avtPROy2fsLhvNd|!M`PE8CoL9BnuRhM4u^;8qYzUa zJFoq0@#5Vklj&^}Wp_)<;^A5c0?;*n{NwA7_vuNG>KT2-3u-x4F>(DZM;^N1G|uR*T{r#o^JVvU zE2*7>2DV(d>d=Y^>+s><*8g&z@Wp>_B{Q%{u6BPiaO3(f6FJ+rKk<@q&z`sLyXJfu zxkd`(^38wcjGRGReaFM^KGNR)&Z}=E{5|nJwZ015#ZPa(f=&S|pjJNziNde|0000< KMNUMnLSTY;B+Zln diff --git a/mod/chat/gui_ajax/theme/bubble/chat.css b/mod/chat/gui_ajax/theme/bubble/chat.css deleted file mode 100644 index 0c4a55f7c0e..00000000000 --- a/mod/chat/gui_ajax/theme/bubble/chat.css +++ /dev/null @@ -1,249 +0,0 @@ -.yui-skin-sam .yui-layout .yui-layout-hd { - border: 0; -} - -.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd-nohd { - border: 0; -} - -.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd { - border: 0; -} - -.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-unit-right { - background: white; -} - -.yui-skin-sam .yui-layout-unit-bottom { - background: #f2f2f2; -} - -.yui-skin-sam .yui-layout-unit-right { - background: #eef2f8; -} - -.yui-skin-sam .yui-layout-unit-center { - background: white; -} - -.yui-skin-sam .yui-layout-unit-top { - background: #ffe39d; -} - -.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd { - background: transparent; -} - -#chat-messages { - padding-top: 15px; -} - -#input-message { - background: #fff url(input.png) repeat-x scroll 0 0; - padding: 0 9px; - border: 1px solid #999; - border-radius: 9px; - -moz-border-radius: 9px; -} - -.mdl-chat-entry, -.mdl-chat-my-entry { - clear: both; -} - -.mdl-chat-entry .chat-event { - padding-bottom: 15px; -} - -.chat-message .chat-message-meta { - padding-top: 15px; - padding-bottom: 15px; -} - -.chat-message .chat-message-meta .user { - white-space: nowrap; -} - -.chat-message .picture { - vertical-align: middle; -} - -.chat-message .right { - text-align: right; -} - -.chat-message .left { - text-align: left; -} -/*rtl:ignore*/ -.chat-message .right, -.chat-message .left { - direction: ltr; -} - -#chat-input-area, -#chat-input-area table.generaltable, -#chat-input-area table.generaltable td.cell { - background: #92b3e8; - border: 0; - height: 100%; -} - -#chat-userlist { - background: #e3e8f0; - height: 100%; -} - -/** - * The following CSS is a cut down version of PURE CSS SPEECH BUBBLES. - * Moodle only uses a small subset of the original. - * The original version is available at http://nicolasgallagher.com/pure-css-speech-bubbles/ - */ - -/* ------------------------------------------ -PURE CSS SPEECH BUBBLES -by Nicolas Gallagher -- http://nicolasgallagher.com/pure-css-speech-bubbles/ - -http://nicolasgallagher.com -http://twitter.com/necolas - -Created: 02 March 2010 -Version: 1.2 (03 March 2011) - -Dual licensed under MIT and GNU GPLv2 © Nicolas Gallagher ------------------------------------------- */ - -.triangle-border { - position: relative; - padding: 10px; - margin: 1em 0 3em; - border: 2px solid #5a8f00; - color: #333; - background: #fff; - /* css3 */ - -webkit-border-radius: 10px; - -moz-border-radius: 10px; - border-radius: 10px; - - /* moodle specific */ - margin-top: 0; - /* end moodle specific */ -} - -/* moodle specific */ - -@media all and (max-device-width: 320px) { - .triangle-border { - width: 50%; - } -} - -@media all and (min-device-width: 321px) and (max-device-width: 640px) { - .triangle-border { - width: 60%; - } -} - -@media all and (min-device-width: 641px) { - .triangle-border { - width: 65%; - } -} -/* end moodle specific */ - -/* Variant : for left positioned triangle ------------------------------------------- */ - -.triangle-border.left { - margin-left: 30px; - /* moodle specific */ - float: right; - /* end moodle specific */ -} - -/* Variant : for right positioned triangle ------------------------------------------- */ - -.triangle-border.right { - margin-right: 30px; - /* moodle specific */ - float: left; - /* end moodle specific */ -} - -.triangle-border:before { - content: ""; - position: absolute; - bottom: -20px; /* value = - border-top-width - border-bottom-width */ - left: 40px; /* controls horizontal position */ - border-width: 20px 20px 0; - border-style: solid; - border-color: #5a8f00 transparent; - /* reduce the damage in FF3.0 */ - display: block; - width: 0; -} - -/* creates the smaller triangle */ -.triangle-border:after { - content: ""; - position: absolute; - bottom: -13px; /* value = - border-top-width - border-bottom-width */ - left: 47px; /* value = (:before left) + (:before border-left) - (:after border-left) */ - border-width: 13px 13px 0; - border-style: solid; - border-color: #fff transparent; - /* reduce the damage in FF3.0 */ - display: block; - width: 0; -} - -/* Variant : left ------------------------------------------- */ - -/* creates the larger triangle */ -.triangle-border.left:before { - top: 7px; /* controls vertical position */ - bottom: auto; - left: -24px; /* value = - border-left-width - border-right-width */ - border-width: 10px 24px 10px 0; - border-color: transparent #5a8f00; -} - -/* creates the smaller triangle */ -.triangle-border.left:after { - top: 8px; /* value = (:before top) + (:before border-top) - (:after border-top) */ - bottom: auto; - left: -21px; /* value = - border-left-width - border-right-width */ - border-width: 9px 21px 9px 0; - border-color: transparent #fff; -} - -/* Variant : right ------------------------------------------- */ - -/* creates the larger triangle */ -.triangle-border.right:before { - top: 7px; /* controls vertical position */ - bottom: auto; - left: auto; - right: -24px; /* value = - border-left-width - border-right-width */ - border-width: 10px 0 10px 24px; - border-color: transparent #5a8f00; -} - -/* creates the smaller triangle */ -.triangle-border.right:after { - top: 8px; /* value = (:before top) + (:before border-top) - (:after border-top) */ - bottom: auto; - left: auto; - right: -21px; /* value = - border-left-width - border-right-width */ - border-width: 9px 0 9px 21px; - border-color: transparent #fff; -} - -#button-send + a > i.text-info { - /* stylelint-disable-next-line declaration-no-important */ - color: black !important; -} diff --git a/mod/chat/gui_ajax/theme/bubble/config.php b/mod/chat/gui_ajax/theme/bubble/config.php deleted file mode 100644 index b1eb941e1e6..00000000000 --- a/mod/chat/gui_ajax/theme/bubble/config.php +++ /dev/null @@ -1,50 +0,0 @@ -. - -$chattheme_cfg = new stdClass(); -$chattheme_cfg->avatar = true; -$chattheme_cfg->align = true; -$chattheme_cfg->event_message = <<