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/.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/.upgradenotes/MDL-82457-2024111508372872.yml b/.upgradenotes/MDL-82457-2024111508372872.yml new file mode 100644 index 00000000000..6116ca77ec1 --- /dev/null +++ b/.upgradenotes/MDL-82457-2024111508372872.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-82457 +notes: + core_analytics: + - message: Remove chat and survey from core_analytics. + type: removed diff --git a/.upgradenotes/MDL-82457-2024111508380503.yml b/.upgradenotes/MDL-82457-2024111508380503.yml new file mode 100644 index 00000000000..258c45f1ed1 --- /dev/null +++ b/.upgradenotes/MDL-82457-2024111508380503.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-82457 +notes: + core_adminpresets: + - message: Remove chat and survey from Adminpresets. + type: removed diff --git a/.upgradenotes/MDL-82457-2024111508383709.yml b/.upgradenotes/MDL-82457-2024111508383709.yml new file mode 100644 index 00000000000..79306834243 --- /dev/null +++ b/.upgradenotes/MDL-82457-2024111508383709.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-82457 +notes: + tool_brickfield: + - message: Remove chat and survey support from tool_brickfield. + type: removed diff --git a/.upgradenotes/MDL-82457-2024111508390338.yml b/.upgradenotes/MDL-82457-2024111508390338.yml new file mode 100644 index 00000000000..3fa8a920919 --- /dev/null +++ b/.upgradenotes/MDL-82457-2024111508390338.yml @@ -0,0 +1,5 @@ +issueNumber: MDL-82457 +notes: + tool_mobile: + - message: Remove chat and survey support from tool_mobile. + type: removed diff --git a/.upgradenotes/MDL-82457-2024111509052922.yml b/.upgradenotes/MDL-82457-2024111509052922.yml new file mode 100644 index 00000000000..879996d8ad6 --- /dev/null +++ b/.upgradenotes/MDL-82457-2024111509052922.yml @@ -0,0 +1,10 @@ +issueNumber: MDL-82457 +notes: + theme_boost: + - message: >- + Remove chat and survey styles. Important note: the styles have been + moved to the plugins as CSS files (and not SCSS) so themes might now + need to override the mod_chat and mod_survey styles specifically as css + does not have any definition for primary, gray and other colors + accessible in the original scss version. + type: removed \ No newline at end of file diff --git a/admin/presets/classes/helper.php b/admin/presets/classes/helper.php index b081c49b1e5..cba8576777f 100644 --- a/admin/presets/classes/helper.php +++ b/admin/presets/classes/helper.php @@ -193,14 +193,12 @@ class helper { // Set Activity chooser tabs to "Starred, Recommended, All". static::add_item($presetid, 'activitychoosertabmode', '4'); - // Modules: Hide chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop. - static::add_plugin($presetid, 'mod', 'chat', false); + // Modules: Hide database, external tool (lti), IMS content package (imscp), lesson, SCORM, wiki, workshop. static::add_plugin($presetid, 'mod', 'data', false); static::add_plugin($presetid, 'mod', 'lti', false); static::add_plugin($presetid, 'mod', 'imscp', false); static::add_plugin($presetid, 'mod', 'lesson', false); static::add_plugin($presetid, 'mod', 'scorm', false); - static::add_plugin($presetid, 'mod', 'survey', false); static::add_plugin($presetid, 'mod', 'wiki', false); static::add_plugin($presetid, 'mod', 'workshop', false); diff --git a/admin/presets/tests/fixtures/import_settings_plugins.xml b/admin/presets/tests/fixtures/import_settings_plugins.xml index c09ac84cfc9..3c3e37c68b8 100644 --- a/admin/presets/tests/fixtures/import_settings_plugins.xml +++ b/admin/presets/tests/fixtures/import_settings_plugins.xml @@ -1,7 +1,7 @@ Imported preset - <p dir="ltr" style="text-align:left;">Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced. Plugins: disabled block_html, mod_database and mod_chat plugins and enabled atto_html, block_activity_modules and mod_lesson.</p> + <p dir="ltr" style="text-align:left;">Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced. Plugins: disabled block_html, mod_database and mod_page plugins and enabled atto_html, block_activity_modules and mod_lesson.</p> 1631615985 http://demo.moodle Ada Lovelace @@ -30,7 +30,7 @@ 1 - 0 + 0 0 1 diff --git a/admin/presets/tests/fixtures/import_starter_name.xml b/admin/presets/tests/fixtures/import_starter_name.xml index a3265077d1e..8e1ab105232 100644 --- a/admin/presets/tests/fixtures/import_starter_name.xml +++ b/admin/presets/tests/fixtures/import_starter_name.xml @@ -1,7 +1,7 @@ Starter - <p dir="ltr" style="text-align:left;">Badges disabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced. Plugins: disabled block_html, mod_database and mod_chat plugins and enabled atto_html and block_activity_modules.</p> + <p dir="ltr" style="text-align:left;">Badges disabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced. Plugins: disabled block_html, mod_database and mod_page plugins and enabled atto_html and block_activity_modules.</p> 1631615985 http://demo.moodle Ada Lovelace @@ -30,7 +30,7 @@ 1 - 0 + 0 0 1 diff --git a/admin/presets/tests/helper_test.php b/admin/presets/tests/helper_test.php index c453cf0d56e..630bc468630 100644 --- a/admin/presets/tests/helper_test.php +++ b/admin/presets/tests/helper_test.php @@ -331,7 +331,7 @@ final class helper_test extends \advanced_testcase { ], 'plugins' => [ 'assign' => 1, - 'chat' => 0, + 'wiki' => 0, 'data' => 0, 'lesson' => 0, ], @@ -371,7 +371,7 @@ final class helper_test extends \advanced_testcase { ], 'plugins' => [ 'assign' => 1, - 'chat' => 0, + 'page' => 0, 'data' => 0, 'lesson' => 1, ], diff --git a/admin/presets/tests/manager_test.php b/admin/presets/tests/manager_test.php index cfa6dbd3814..2d97144c004 100644 --- a/admin/presets/tests/manager_test.php +++ b/admin/presets/tests/manager_test.php @@ -506,7 +506,7 @@ final class manager_test extends \advanced_testcase { 'activity_modules' => 1, ], 'mod' => [ - 'chat' => 0, + 'page' => 0, 'data' => 0, 'lesson' => 1, ], diff --git a/admin/renderer.php b/admin/renderer.php index ef81b63786b..e18477bef82 100644 --- a/admin/renderer.php +++ b/admin/renderer.php @@ -295,7 +295,6 @@ class core_admin_renderer extends plugin_renderer_base { $output .= $this->header(); $output .= $this->output->heading(get_string('notifications', 'admin')); - $output .= $this->upgrade_news_message(); $output .= $this->maturity_info($maturity); $output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : ''; $output .= $this->insecure_dataroot_warning($insecuredataroot); @@ -755,22 +754,6 @@ class core_admin_renderer extends plugin_renderer_base { return $this->box($copyrighttext, 'copyright'); } - /** - * Display a transient notification for important upgrades messages for - * specific releases. - * - * @return string HTML to output. - */ - protected function upgrade_news_message() { - return $this->notification( - get_string('importantupdates_content', 'admin'), - 'info', - false, - get_string('importantupdates_title', 'admin'), - 'i/circleinfo, core' - ); - } - /** * Display a warning about installing development code if necesary. * @param int $maturity diff --git a/admin/roles/tests/privacy/provider_test.php b/admin/roles/tests/privacy/provider_test.php index 427a9a09921..3bf8aa6f5aa 100644 --- a/admin/roles/tests/privacy/provider_test.php +++ b/admin/roles/tests/privacy/provider_test.php @@ -77,7 +77,7 @@ final class provider_test extends provider_testcase { $course = $this->getDataGenerator()->create_course(); $course2 = $this->getDataGenerator()->create_course(); $coursecat = $this->getDataGenerator()->create_category(); - $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]); + $cm = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); $cmcontext = \context_module::instance($cm->cmid); $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id)); $cmcontext2 = \context_module::instance($page->cmid); @@ -125,7 +125,7 @@ final class provider_test extends provider_testcase { $course = $this->getDataGenerator()->create_course(); $course2 = $this->getDataGenerator()->create_course(); $coursecat = $this->getDataGenerator()->create_category(); - $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]); + $cm = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); $cmcontext = \context_module::instance($cm->cmid); $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id)); $cmcontext2 = \context_module::instance($page->cmid); @@ -257,7 +257,7 @@ final class provider_test extends provider_testcase { $coursecat = $this->getDataGenerator()->create_category(); $coursecatcontext = \context_coursecat::instance($coursecat->id); $systemcontext = \context_system::instance(); - $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]); + $cm = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); $cmcontext = \context_module::instance($cm->cmid); $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST); @@ -348,7 +348,7 @@ final class provider_test extends provider_testcase { $coursecat = $this->getDataGenerator()->create_category(); $coursecatcontext = \context_coursecat::instance($coursecat->id); $systemcontext = \context_system::instance(); - $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]); + $cm = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); $cmcontext = \context_module::instance($cm->cmid); $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); $manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST); @@ -499,8 +499,8 @@ final class provider_test extends provider_testcase { // Create course category. $coursecat = $this->getDataGenerator()->create_category(); $coursecatcontext = \context_coursecat::instance($coursecat->id); - // Create chat module. - $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course1->id]); + // Create assignment module. + $cm = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); $cmcontext = \context_module::instance($cm->cmid); $systemcontext = \context_system::instance(); @@ -619,8 +619,8 @@ final class provider_test extends provider_testcase { // Create course category. $coursecat = $this->getDataGenerator()->create_category(); $coursecatcontext = \context_coursecat::instance($coursecat->id); - // Create chat module. - $cm = $this->getDataGenerator()->create_module('chat', ['course' => $course1->id]); + // Create assignment module. + $cm = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); $cmcontext = \context_module::instance($cm->cmid); $systemcontext = \context_system::instance(); diff --git a/admin/tool/admin_presets/tests/local/action/import_test.php b/admin/tool/admin_presets/tests/local/action/import_test.php index 2cbfd70a8a6..0e0ea9a5c5e 100644 --- a/admin/tool/admin_presets/tests/local/action/import_test.php +++ b/admin/tool/admin_presets/tests/local/action/import_test.php @@ -154,7 +154,7 @@ final class import_test extends \advanced_testcase { 'activity_modules' => 1, ], 'mod' => [ - 'chat' => 0, + 'page' => 0, 'data' => 0, 'lesson' => 1, ], diff --git a/admin/tool/behat/tests/behat/data_generators.feature b/admin/tool/behat/tests/behat/data_generators.feature index c4aa5975c06..021cb6e6009 100644 --- a/admin/tool/behat/tests/behat/data_generators.feature +++ b/admin/tool/behat/tests/behat/data_generators.feature @@ -150,13 +150,10 @@ Feature: Set up contextual data for tests Given the following "courses" exist: | fullname | shortname | | Course 1 | C1 | - And I enable "chat" "mod" plugin - And I enable "survey" "mod" plugin And the following "activities" exist: | activity | name | intro | course | idnumber | | assign | Test assignment name | Test assignment description | C1 | assign1 | | book | Test book name | Test book description | C1 | book1 | - | chat | Test chat name | Test chat description | C1 | chat1 | | choice | Test choice name | Test choice description | C1 | choice1 | | data | Test database name | Test database description | C1 | data1 | | feedback | Test feedback name | Test feedback description | C1 | feedback1 | @@ -171,7 +168,6 @@ Feature: Set up contextual data for tests | quiz | Test quiz name | Test quiz description | C1 | quiz1 | | resource | Test resource name | Test resource description | C1 | resource1 | | scorm | Test scorm name | Test scorm description | C1 | scorm1 | - | survey | Test survey name | Test survey description | C1 | survey1 | | url | Test url name | Test url description | C1 | url1 | | wiki | Test wiki name | Test wiki description | C1 | wiki1 | | workshop | Test workshop name | Test workshop description | C1 | workshop1 | @@ -186,7 +182,6 @@ Feature: Set up contextual data for tests # Assignment 2.2 module type is disabled by default # And I should see "Test assignment22 name" And I should see "Test book name" - And I should see "Test chat name" And I should see "Test choice name" And I should see "Test database name" # Feedback module type is disabled by default @@ -203,7 +198,6 @@ Feature: Set up contextual data for tests And I should see "Test quiz name" And I should see "Test resource name" And I should see "Test scorm name" - And I should see "Test survey name" And I should see "Test url name" And I should see "Test wiki name" And I should see "Test workshop name" diff --git a/admin/tool/brickfield/classes/local/areas/mod_chat/intro.php b/admin/tool/brickfield/classes/local/areas/mod_chat/intro.php deleted file mode 100644 index 5f3d42ddef4..00000000000 --- a/admin/tool/brickfield/classes/local/areas/mod_chat/intro.php +++ /dev/null @@ -1,45 +0,0 @@ -. - -namespace tool_brickfield\local\areas\mod_chat; - -use tool_brickfield\local\areas\module_area_base; - -/** - * Chat intro observer. - * - * @package tool_brickfield - * @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class intro extends module_area_base { - - /** - * Get table name. - * @return string - */ - public function get_tablename(): string { - return 'chat'; - } - - /** - * Get field name. - * @return string - */ - public function get_fieldname(): string { - return 'intro'; - } -} diff --git a/admin/tool/brickfield/classes/local/areas/mod_chat/name.php b/admin/tool/brickfield/classes/local/areas/mod_chat/name.php deleted file mode 100644 index 11e37271f76..00000000000 --- a/admin/tool/brickfield/classes/local/areas/mod_chat/name.php +++ /dev/null @@ -1,45 +0,0 @@ -. - -namespace tool_brickfield\local\areas\mod_chat; - -use tool_brickfield\local\areas\module_area_base; - -/** - * Chat name observer. - * - * @package tool_brickfield - * @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class name extends module_area_base { - - /** - * Get table name. - * @return string - */ - public function get_tablename(): string { - return 'chat'; - } - - /** - * Get field name. - * @return string - */ - public function get_fieldname(): string { - return 'name'; - } -} diff --git a/admin/tool/brickfield/classes/local/areas/mod_survey/intro.php b/admin/tool/brickfield/classes/local/areas/mod_survey/intro.php deleted file mode 100644 index 6f4f983a18b..00000000000 --- a/admin/tool/brickfield/classes/local/areas/mod_survey/intro.php +++ /dev/null @@ -1,45 +0,0 @@ -. - -namespace tool_brickfield\local\areas\mod_survey; - -use tool_brickfield\local\areas\module_area_base; - -/** - * Survey activity intro observer. - * - * @package tool_brickfield - * @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class intro extends module_area_base { - - /** - * Get table name. - * @return string - */ - public function get_tablename(): string { - return 'survey'; - } - - /** - * Get field name. - * @return string - */ - public function get_fieldname(): string { - return 'intro'; - } -} diff --git a/admin/tool/brickfield/classes/local/areas/mod_survey/name.php b/admin/tool/brickfield/classes/local/areas/mod_survey/name.php deleted file mode 100644 index ef980950dd8..00000000000 --- a/admin/tool/brickfield/classes/local/areas/mod_survey/name.php +++ /dev/null @@ -1,45 +0,0 @@ -. - -namespace tool_brickfield\local\areas\mod_survey; - -use tool_brickfield\local\areas\module_area_base; - -/** - * Survey activity name observer. - * - * @package tool_brickfield - * @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class name extends module_area_base { - - /** - * Get table name. - * @return string - */ - public function get_tablename(): string { - return 'survey'; - } - - /** - * Get field name. - * @return string - */ - public function get_fieldname(): string { - return 'name'; - } -} diff --git a/admin/tool/mobile/classes/api.php b/admin/tool/mobile/classes/api.php index 824ea13b0e0..71f6e9abd39 100644 --- a/admin/tool/mobile/classes/api.php +++ b/admin/tool/mobile/classes/api.php @@ -503,8 +503,8 @@ class api { $availablemods = core_plugin_manager::instance()->get_plugins_of_type('mod'); $coursemodules = array(); $appsupportedmodules = array( - 'assign', 'bigbluebuttonbn', 'book', 'chat', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', - 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop'); + 'assign', 'bigbluebuttonbn', 'book', 'choice', 'data', 'feedback', 'folder', 'forum', 'glossary', 'h5pactivity', + 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz', 'resource', 'scorm', 'url', 'wiki', 'workshop'); foreach ($availablemods as $mod) { if (in_array($mod->name, $appsupportedmodules)) { diff --git a/auth/mnet/db/tasks.php b/auth/mnet/db/tasks.php index 37722c085dd..43caf28ec51 100644 --- a/auth/mnet/db/tasks.php +++ b/auth/mnet/db/tasks.php @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . /** - * Definition of chat scheduled tasks. + * Definition of mnet scheduled tasks. * * @package auth_mnet * @copyright 2019 Simey Lameze diff --git a/backup/cc/sheets/moodle_blti_export.xml b/backup/cc/sheets/moodle_blti_export.xml index ae4ba820a90..0f4a5fa2bd1 100644 --- a/backup/cc/sheets/moodle_blti_export.xml +++ b/backup/cc/sheets/moodle_blti_export.xml @@ -529,24 +529,6 @@ 1311692185 0 - - mod/survey:readresponses - 1 - 1311692181 - 0 - - - mod/survey:participate - 1 - 1311692181 - 0 - - - mod/survey:download - 1 - 1311692181 - 0 - mod/scorm:viewscores 1 @@ -907,24 +889,6 @@ 1311692127 0 - - mod/chat:readlog - 1 - 1311692125 - 0 - - - mod/chat:deletelog - 1 - 1311692125 - 0 - - - mod/chat:chat - 1 - 1311692125 - 0 - mod/assignment:view 1 @@ -1166,12 +1130,6 @@ 1311692184 0 - - mod/survey:participate - 1 - 1311692181 - 0 - mod/scorm:viewscores 1 @@ -1298,18 +1256,6 @@ 1311692127 0 - - mod/chat:readlog - 1 - 1311692125 - 0 - - - mod/chat:chat - 1 - 1311692125 - 0 - mod/assignment:view 1 diff --git a/backup/tests/privacy/provider_test.php b/backup/tests/privacy/provider_test.php index 4bee5289d87..0dbb730d645 100644 --- a/backup/tests/privacy/provider_test.php +++ b/backup/tests/privacy/provider_test.php @@ -312,7 +312,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $component = 'core_backup'; $course = $this->getDataGenerator()->create_course(); - $activity = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]); + $activity = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); $user = $this->getDataGenerator()->create_user(); $user2 = $this->getDataGenerator()->create_user(); @@ -408,7 +408,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $course2 = $this->getDataGenerator()->create_course(); $coursecontext2 = \context_course::instance($course2->id); // Create an activity. - $activity = $this->getDataGenerator()->create_module('chat', ['course' => $course1->id]); + $activity = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); $activitycontext = \context_module::instance($activity->cmid); // Create user1. $user1 = $this->getDataGenerator()->create_user(); diff --git a/blocks/activity_modules/tests/behat/block_activity_modules.feature b/blocks/activity_modules/tests/behat/block_activity_modules.feature index ede3a73e0a9..d925524cafd 100644 --- a/blocks/activity_modules/tests/behat/block_activity_modules.feature +++ b/blocks/activity_modules/tests/behat/block_activity_modules.feature @@ -4,16 +4,11 @@ Feature: Block activity modules As a manager I can add activities block in a course or on the frontpage - Background: - Given I enable "chat" "mod" plugin - And I enable "survey" "mod" plugin - Scenario: Add activities block on the frontpage Given the following "activities" exist: | activity | name | intro | course | idnumber | | assign | Frontpage assignment name | Frontpage assignment description | Acceptance test site | assign0 | | book | Frontpage book name | Frontpage book description | Acceptance test site | book0 | - | chat | Frontpage chat name | Frontpage chat description | Acceptance test site | chat0 | | choice | Frontpage choice name | Frontpage choice description | Acceptance test site | choice0 | | data | Frontpage database name | Frontpage database description | Acceptance test site | data0 | | feedback | Frontpage feedback name | Frontpage feedback description | Acceptance test site | feedback0 | @@ -28,7 +23,6 @@ Feature: Block activity modules | glossary | Frontpage glossary name | Frontpage glossary description | Acceptance test site | glossary0 | | scorm | Frontpage scorm name | Frontpage scorm description | Acceptance test site | scorm0 | | lesson | Frontpage lesson name | Frontpage lesson description | Acceptance test site | lesson0 | - | survey | Frontpage survey name | Frontpage survey description | Acceptance test site | survey0 | | url | Frontpage url name | Frontpage url description | Acceptance test site | url0 | | wiki | Frontpage wiki name | Frontpage wiki description | Acceptance test site | wiki0 | | workshop | Frontpage workshop name | Frontpage workshop description | Acceptance test site | workshop0 | @@ -40,9 +34,6 @@ Feature: Block activity modules And I click on "Assignments" "link" in the "Activities" "block" Then I should see "Frontpage assignment name" And I am on site homepage - And I click on "Chats" "link" in the "Activities" "block" - And I should see "Frontpage chat name" - And I am on site homepage And I click on "Choices" "link" in the "Activities" "block" And I should see "Frontpage choice name" And I am on site homepage @@ -92,7 +83,6 @@ Feature: Block activity modules | activity | name | intro | course | idnumber | | assign | Test assignment name | Test assignment description | C1 | assign1 | | book | Test book name | Test book description | C1 | book1 | - | chat | Test chat name | Test chat description | C1 | chat1 | | choice | Test choice name | Test choice description | C1 | choice1 | | data | Test database name | Test database description | C1 | data1 | | feedback | Test feedback name | Test feedback description | C1 | feedback1 | @@ -107,7 +97,6 @@ Feature: Block activity modules | quiz | Test quiz name | Test quiz description | C1 | quiz1 | | resource | Test resource name | Test resource description | C1 | resource1 | | scorm | Test scorm name | Test scorm description | C1 | scorm1 | - | survey | Test survey name | Test survey description | C1 | survey1 | | url | Test url name | Test url description | C1 | url1 | | wiki | Test wiki name | Test wiki description | C1 | wiki1 | | workshop | Test workshop name | Test workshop description | C1 | workshop1 | @@ -118,9 +107,6 @@ Feature: Block activity modules And I click on "Assignments" "link" in the "Activities" "block" Then I should see "Test assignment name" And I am on "Course 1" course homepage - And I click on "Chats" "link" in the "Activities" "block" - And I should see "Test chat name" - And I am on "Course 1" course homepage And I click on "Choices" "link" in the "Activities" "block" And I should see "Test choice name" And I am on "Course 1" course homepage diff --git a/blocks/recentlyaccesseditems/tests/externallib_test.php b/blocks/recentlyaccesseditems/tests/externallib_test.php index 32f71b6a47f..4110d8d620a 100644 --- a/blocks/recentlyaccesseditems/tests/externallib_test.php +++ b/blocks/recentlyaccesseditems/tests/externallib_test.php @@ -84,8 +84,8 @@ final class externallib_test extends externallib_advanced_testcase { // Student access all assignments. foreach ($assign as $module) { - $event = \mod_chat\event\course_module_viewed::create(array('context' => \context_module::instance($module->cmid), - 'objectid' => $module->id)); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($module->cmid), + 'objectid' => $module->id]); $event->trigger(); $this->waitForSecond(); } diff --git a/blocks/recentlyaccesseditems/tests/observer_test.php b/blocks/recentlyaccesseditems/tests/observer_test.php index 5c2b1d652ff..8f3a155f70d 100644 --- a/blocks/recentlyaccesseditems/tests/observer_test.php +++ b/blocks/recentlyaccesseditems/tests/observer_test.php @@ -56,8 +56,8 @@ final class observer_test extends \advanced_testcase { /** @var \stdClass course glossary. */ protected $glossary; - /** @var \stdClass course chat. */ - protected $chat; + /** @var \stdClass course assignment. */ + protected $assign; /** * Set up for every test @@ -88,7 +88,7 @@ final class observer_test extends \advanced_testcase { // Create items. $this->forum = $this->getDataGenerator()->create_module('forum', array('course' => $this->course)); $this->glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $this->course)); - $this->chat = $this->getDataGenerator()->create_module('chat', array('course' => $this->course)); + $this->assign = $this->getDataGenerator()->create_module('assign', ['course' => $this->course]); } /** @@ -109,28 +109,28 @@ final class observer_test extends \advanced_testcase { 'objectid' => $this->forum->id)); $event->trigger(); - // Student access chat activity. + // Student access assignment activity. $this->setUser($this->student); - $event1 = \mod_chat\event\course_module_viewed::create(array('context' => \context_module::instance($this->chat->cmid), - 'objectid' => $this->chat->id)); + $event1 = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($this->assign->cmid), + 'objectid' => $this->assign->id]); $event1->trigger(); $records = $DB->count_records($this->table, array('userid' => $this->teacher->id, 'courseid' => $this->course->id, 'cmid' => $this->forum->cmid)); $this->assertEquals(1, $records); - $records = $DB->count_records($this->table, array('userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' => - $this->chat->cmid)); + $records = $DB->count_records($this->table, ['userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' => + $this->assign->cmid]); $this->assertEquals(1, $records); $this->waitForSecond(); - // Student access chat activity again after 1 second (no new record created, timeaccess updated). - $event2 = \mod_chat\event\course_module_viewed::create(array('context' => \context_module::instance($this->chat->cmid), - 'objectid' => $this->chat->id)); + // Student access assignment activity again after 1 second (no new record created, timeaccess updated). + $event2 = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($this->assign->cmid), + 'objectid' => $this->assign->id]); $event2->trigger(); - $records = $DB->get_records($this->table, array('userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' => - $this->chat->cmid)); + $records = $DB->get_records($this->table, ['userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' => + $this->assign->cmid]); $this->assertCount(1, $records); $this->assertEquals($event2->timecreated, array_shift($records)->timeaccess); @@ -154,15 +154,15 @@ final class observer_test extends \advanced_testcase { 'objectid' => $this->forum->id)); $event->trigger(); - // Teacher access chat activity. - $event = \mod_chat\event\course_module_viewed::create(array('context' => \context_module::instance($this->chat->cmid), - 'objectid' => $this->chat->id)); + // Teacher access assignment activity. + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($this->assign->cmid), + 'objectid' => $this->assign->id]); $event->trigger(); - // Student access chat activity. + // Student access assignment activity. $this->setUser($this->student); - $event = \mod_chat\event\course_module_viewed::create(array('context' => \context_module::instance($this->chat->cmid), - 'objectid' => $this->chat->id)); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($this->assign->cmid), + 'objectid' => $this->assign->id]); $event->trigger(); // Student access forum activity. @@ -175,7 +175,7 @@ final class observer_test extends \advanced_testcase { course_delete_module($this->forum->cmid); $records = $DB->count_records($this->table, array('cmid' => $this->forum->cmid)); $this->assertEquals(0, $records); - $records = $DB->count_records($this->table, array('cmid' => $this->chat->cmid)); + $records = $DB->count_records($this->table, ['cmid' => $this->assign->cmid]); $this->assertEquals(2, $records); } } diff --git a/blocks/recentlyaccesseditems/tests/privacy/provider_test.php b/blocks/recentlyaccesseditems/tests/privacy/provider_test.php index 4d663f5bd2e..43cf4ac9ee0 100644 --- a/blocks/recentlyaccesseditems/tests/privacy/provider_test.php +++ b/blocks/recentlyaccesseditems/tests/privacy/provider_test.php @@ -57,7 +57,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $generator->enrol_user($student->id, $course->id, 'student'); $generator->enrol_user($teacher->id, $course->id, 'teacher'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Check nothing is found before block is populated. $contextlist1 = provider::get_contexts_for_userid($student->id); @@ -72,8 +72,8 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $event->trigger(); $this->setUser($teacher); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); // Ensure provider only fetches the users's own context. @@ -104,7 +104,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $generator->enrol_user($student->id, $course->id, 'student'); $generator->enrol_user($teacher->id, $course->id, 'teacher'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Check nothing is found before block is populated. $userlist1 = new \core_privacy\local\request\userlist($studentcontext, $component); @@ -119,16 +119,16 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); $this->setUser($teacher); $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); // Ensure provider only fetches the user whose user context is checked. @@ -182,15 +182,15 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $course = $generator->create_course(); $generator->enrol_user($student->id, $course->id, 'student'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Generate some recent activity. $this->setUser($student); $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); // Confirm data is present. @@ -235,15 +235,15 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $course = $generator->create_course(); $generator->enrol_user($student->id, $course->id, 'student'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Generate some recent activity. $this->setUser($student); $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); // Confirm data is present. @@ -283,7 +283,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $generator->enrol_user($student->id, $course->id, 'student'); $generator->enrol_user($teacher->id, $course->id, 'teacher'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Generate some recent activity for both users. $users = [$student, $teacher]; @@ -292,8 +292,8 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); } @@ -353,7 +353,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $generator->enrol_user($student->id, $course->id, 'student'); $generator->enrol_user($teacher->id, $course->id, 'teacher'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Generate some recent activity for both users. $users = [$student, $teacher]; @@ -362,8 +362,8 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); } @@ -433,7 +433,7 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $generator->enrol_user($student->id, $course->id, 'student'); $generator->enrol_user($teacher->id, $course->id, 'teacher'); $forum = $generator->create_module('forum', ['course' => $course]); - $chat = $generator->create_module('chat', ['course' => $course]); + $assign = $generator->create_module('assign', ['course' => $course]); // Generate some recent activity for all users. $users = [$student, $teacher]; @@ -442,8 +442,8 @@ final class provider_test extends \core_privacy\tests\provider_testcase { $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); - $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), - 'objectid' => $chat->id]); + $event = \mod_assign\event\course_module_viewed::create(['context' => \context_module::instance($assign->cmid), + 'objectid' => $assign->id]); $event->trigger(); } diff --git a/completion/tests/bulk_update_test.php b/completion/tests/bulk_update_test.php index 89d22f1204c..89840ea8ccc 100644 --- a/completion/tests/bulk_update_test.php +++ b/completion/tests/bulk_update_test.php @@ -42,8 +42,6 @@ final class bulk_update_test extends \advanced_testcase { 'assign-2' => ['assign', ['completion' => COMPLETION_TRACKING_MANUAL]], 'book-1' => ['book', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], 'book-2' => ['book', ['completion' => COMPLETION_TRACKING_MANUAL]], - 'chat-1' => ['chat', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], - 'chat-2' => ['chat', ['completion' => COMPLETION_TRACKING_MANUAL]], 'choice-1' => ['choice', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionsubmit' => 1]], 'choice-2' => ['choice', ['completion' => COMPLETION_TRACKING_MANUAL]], 'data-1' => ['data', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], @@ -94,8 +92,6 @@ final class bulk_update_test extends \advanced_testcase { ], ], 'scorm-2' => ['scorm', ['completion' => COMPLETION_TRACKING_MANUAL]], - 'survey-1' => ['survey', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionsubmit' => 1]], - 'survey-2' => ['survey', ['completion' => COMPLETION_TRACKING_MANUAL]], 'url-1' => ['url', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], 'url-2' => ['url', ['completion' => COMPLETION_TRACKING_MANUAL]], 'wiki-1' => ['wiki', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], @@ -158,11 +154,6 @@ final class bulk_update_test extends \advanced_testcase { protected function create_course_and_modules($modulenames) { global $CFG, $PAGE; - // Chat and Survey modules are disabled by default, enable them for testing. - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('chat', 1); - $manager::enable_plugin('survey', 1); - $CFG->enablecompletion = true; $course = $this->getDataGenerator()->create_course(['enablecompletion' => 1], ['createsections' => true]); $PAGE->set_course($course); @@ -215,7 +206,7 @@ final class bulk_update_test extends \advanced_testcase { ], 'If at least one module does not support completionsubmit it can\'t be set' => [ [ - 'modulenames' => ['survey', 'wiki'], + 'modulenames' => ['assign', 'wiki'], 'submitdata' => ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1, 'completionsubmit' => 1], 'validatedata' => [], 'cmdata' => ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1], diff --git a/course/tests/backup/restore_test.php b/course/tests/backup/restore_test.php index 830078243e9..09c1f7b19d8 100644 --- a/course/tests/backup/restore_test.php +++ b/course/tests/backup/restore_test.php @@ -225,13 +225,18 @@ final class restore_test extends \advanced_testcase { $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016. - // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date. + // Create two courses with different start dates, in each course create an assignment + // that is due 1 week after the course start date. $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 'startdate' => $startdate]); - $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]); + $assign1 = $dg->create_module('assign', + ['name' => 'First', 'course' => $c1->id, 'duedate' => $c1->startdate + 1 * WEEKSECS] + ); $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN, 'startdate' => $startdate + 2 * WEEKSECS]); - $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]); + $assign2 = $dg->create_module('assign', + ['name' => 'Second', 'course' => $c2->id, 'duedate' => $c2->startdate + 1 * WEEKSECS] + ); $backupid = $this->backup_course($c1->id); // The information is restored but adapted because names are already taken. @@ -242,12 +247,12 @@ final class restore_test extends \advanced_testcase { $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat); $this->assertEquals($startdate, $c2->startdate); - // Now course c2 has two chats - one ('Second') was already there and one ('First') was restored from the backup. + // Now course c2 has two assignments - one ('Second') was already there and one ('First') was restored from the backup. // Their dates are exactly the same as they were in the original modules. - $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]); - $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]); - $this->assertEquals($chat1->chattime, $restoredchat1->chattime); - $this->assertEquals($chat2->chattime, $restoredchat2->chattime); + $restoredassign1 = $DB->get_record('assign', ['name' => 'First', 'course' => $c2->id]); + $restoredassign2 = $DB->get_record('assign', ['name' => 'Second', 'course' => $c2->id]); + $this->assertEquals($assign1->duedate, $restoredassign1->duedate); + $this->assertEquals($assign2->duedate, $restoredassign2->duedate); } public function test_async_restore_course_info_in_existing_course_delete_first(): void { @@ -261,24 +266,29 @@ final class restore_test extends \advanced_testcase { $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016. - // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date. + // Create two courses with different start dates, in each course create an assignment + // that is due 1 week after the course start date. $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 'startdate' => $startdate]); - $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]); + $assign1 = $dg->create_module('assign', + ['name' => 'First', 'course' => $c1->id, 'duedate' => $c1->startdate + 1 * WEEKSECS] + ); $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN, 'startdate' => $startdate + 2 * WEEKSECS]); - $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]); + $assign2 = $dg->create_module('assign', + ['name' => 'Second', 'course' => $c2->id, 'duedate' => $c2->startdate + 1 * WEEKSECS] + ); $backupid = $this->backup_course($c1->id); // The information is restored and the existing course settings is modified. $c2 = $this->async_restore_to_existing_course($backupid, $c2->id, 2, backup::TARGET_CURRENT_DELETING); $this->assertEquals(FORMAT_MOODLE, $c2->summaryformat); - // Now course2 should have a new forum with the original forum deleted. - $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]); - $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]); - $this->assertEquals($chat1->chattime, $restoredchat1->chattime); - $this->assertEmpty($restoredchat2); + // Now course2 should have a new assignment with the original assignment deleted. + $restoredassign1 = $DB->get_record('assign', ['name' => 'First', 'course' => $c2->id]); + $restoredassign2 = $DB->get_record('assign', ['name' => 'Second', 'course' => $c2->id]); + $this->assertEquals($assign1->duedate, $restoredassign1->duedate); + $this->assertEmpty($restoredassign2); } public function test_restore_existing_idnumber_in_new_course(): void { @@ -434,13 +444,18 @@ final class restore_test extends \advanced_testcase { $startdate = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016. - // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date. + // Create two courses with different start dates,in each course create an assignment + // that opens 1 week after the course start date. $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 'startdate' => $startdate]); - $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]); + $assign1 = $dg->create_module('assign', + ['name' => 'First', 'course' => $c1->id, 'duedate' => $c1->startdate + 1 * WEEKSECS] + ); $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN, 'startdate' => $startdate + 2 * WEEKSECS]); - $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]); + $assign2 = $dg->create_module('assign', + ['name' => 'Second', 'course' => $c2->id, 'duedate' => $c2->startdate + 1 * WEEKSECS] + ); $backupid = $this->backup_course($c1->id); // The information is restored but adapted because names are already taken. @@ -453,10 +468,10 @@ final class restore_test extends \advanced_testcase { // Now course c2 has two chats - one ('Second') was already there and one ('First') was restored from the backup. // Their dates are exactly the same as they were in the original modules. - $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]); - $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]); - $this->assertEquals($chat1->chattime, $restoredchat1->chattime); - $this->assertEquals($chat2->chattime, $restoredchat2->chattime); + $restoredassign1 = $DB->get_record('assign', ['name' => 'First', 'course' => $c2->id]); + $restoredassign2 = $DB->get_record('assign', ['name' => 'Second', 'course' => $c2->id]); + $this->assertEquals($assign1->duedate, $restoredassign1->duedate); + $this->assertEquals($assign2->duedate, $restoredassign2->duedate); } public function test_restore_course_shortname_in_existing_course_without_permissions(): void { @@ -543,15 +558,20 @@ final class restore_test extends \advanced_testcase { $dg->role_assign($manager->id, $u1->id); $dg->role_assign($roleid, $u1->id); - // Create two courses with different start dates,in each course create a chat that opens 1 week after the course start date. + // Create two courses with different start dates, in each course create an assignment that + // is due 1 week after the course start date. $startdate1 = mktime(12, 0, 0, 7, 1, 2016); // 01-Jul-2016. $startdate2 = mktime(12, 0, 0, 1, 13, 2000); // 13-Jan-2000. $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 'startdate' => $startdate1]); - $chat1 = $dg->create_module('chat', ['name' => 'First', 'course' => $c1->id, 'chattime' => $c1->startdate + 1 * WEEKSECS]); + $assign1 = $dg->create_module('assign', + ['name' => 'First', 'course' => $c1->id, 'duedate' => $c1->startdate + 1 * WEEKSECS] + ); $c2 = $dg->create_course(['shortname' => 'A', 'fullname' => 'B', 'summary' => 'C', 'summaryformat' => FORMAT_PLAIN, 'startdate' => $startdate2]); - $chat2 = $dg->create_module('chat', ['name' => 'Second', 'course' => $c2->id, 'chattime' => $c2->startdate + 1 * WEEKSECS]); + $assign2 = $dg->create_module('assign', + ['name' => 'Second', 'course' => $c2->id, 'duedate' => $c2->startdate + 1 * WEEKSECS] + ); // The startdate does not change. $backupid = $this->backup_course($c1->id); @@ -562,13 +582,13 @@ final class restore_test extends \advanced_testcase { $this->assertEquals(FORMAT_MOODLE, $restored->summaryformat); $this->assertEquals($startdate2, $restored->startdate); - // Now course c2 has two chats - one ('Second') was already there and one ('First') was restored from the backup. - // Start date of the restored chat ('First') was changed to be 1 week after the c2 start date. - $restoredchat1 = $DB->get_record('chat', ['name' => 'First', 'course' => $c2->id]); - $restoredchat2 = $DB->get_record('chat', ['name' => 'Second', 'course' => $c2->id]); - $this->assertNotEquals($chat1->chattime, $restoredchat1->chattime); - $this->assertEquals($chat2->chattime, $restoredchat2->chattime); - $this->assertEquals($c2->startdate + 1 * WEEKSECS, $restoredchat2->chattime); + // Now course c2 has two assignments - one ('Second') was already there and one ('First') was restored from the backup. + // Start date of the restored assignment ('First') was changed to be 1 week after the c2 start date. + $restoredassign1 = $DB->get_record('assign', ['name' => 'First', 'course' => $c2->id]); + $restoredassign2 = $DB->get_record('assign', ['name' => 'Second', 'course' => $c2->id]); + $this->assertNotEquals($assign1->duedate, $restoredassign1->duedate); + $this->assertEquals($assign2->duedate, $restoredassign2->duedate); + $this->assertEquals($c2->startdate + 1 * WEEKSECS, $restoredassign2->duedate); } /** diff --git a/course/tests/behat/activity_navigation.feature b/course/tests/behat/activity_navigation.feature index ee8919ac662..1442a422a10 100644 --- a/course/tests/behat/activity_navigation.feature +++ b/course/tests/behat/activity_navigation.feature @@ -18,13 +18,10 @@ Feature: Activity navigation | student1 | C1 | student | | teacher1 | C1 | editingteacher | | student1 | C2 | student | - And I enable "chat" "mod" plugin - And I enable "survey" "mod" plugin And the following "activities" exist: | activity | name | intro | course | idnumber | section | | assign | Assignment 1 | Test assignment description | C1 | assign1 | 0 | | book | Book 1 | Test book description | C1 | book1 | 0 | - | chat | Chat 1 | Test chat description | C1 | chat1 | 0 | | choice | Choice 1 | Test choice description | C1 | choice1 | 1 | | data | Database 1 | Test database description | C1 | data1 | 1 | | feedback | Feedback 1 | Test feedback description | C1 | feedback1 | 1 | @@ -39,7 +36,6 @@ Feature: Activity navigation | quiz | Quiz 1 | Test quiz description | C1 | quiz1 | 4 | | resource | Resource 1 | Test resource description | C1 | resource1 | 5 | | scorm | Scorm 1 | Test scorm description | C1 | scorm1 | 5 | - | survey | Survey 1 | Test survey description | C1 | survey1 | 5 | | url | Url 1 | Test url description | C1 | url1 | 6 | | wiki | Wiki 1 | Test wiki description | C1 | wiki1 | 6 | | workshop | Workshop 1 | Test workshop description | C1 | workshop1 | 6 | @@ -74,12 +70,9 @@ Feature: Activity navigation And I should see "Book 1" in the "#next-activity-link" "css_element" And I follow "Book 1" And I should see "Assignment" in the "#prev-activity-link" "css_element" - And I should see "Chat 1" in the "#next-activity-link" "css_element" - And I follow "Chat 1" - And I should see "Book 1" in the "#prev-activity-link" "css_element" And I should see "Choice 1" in the "#next-activity-link" "css_element" And I follow "Choice 1" - And I should see "Chat 1" in the "#prev-activity-link" "css_element" + And I should see "Book 1" in the "#prev-activity-link" "css_element" And I should see "Database 1" in the "#next-activity-link" "css_element" And I follow "Database 1" And I should see "Choice 1" in the "#prev-activity-link" "css_element" @@ -117,12 +110,9 @@ Feature: Activity navigation And I should see "Scorm 1 (hidden)" in the "#next-activity-link" "css_element" And I follow "Scorm 1 (hidden)" And I should see "Resource 1 (hidden)" in the "#prev-activity-link" "css_element" - And I should see "Survey 1 (hidden)" in the "#next-activity-link" "css_element" - And I follow "Survey 1 (hidden)" - And I should see "Scorm 1 (hidden)" in the "#prev-activity-link" "css_element" And I should see "Url 1" in the "#next-activity-link" "css_element" And I follow "Url 1" - And I should see "Survey 1 (hidden)" in the "#prev-activity-link" "css_element" + And I should see "Scorm 1 (hidden)" in the "#prev-activity-link" "css_element" And I should see "Wiki 1" in the "#next-activity-link" "css_element" And I follow "Wiki 1" And I should see "Url 1" in the "#prev-activity-link" "css_element" @@ -141,12 +131,9 @@ Feature: Activity navigation And I should see "Book 1" in the "#next-activity-link" "css_element" And I follow "Book 1" And I should see "Assignment" in the "#prev-activity-link" "css_element" - And I should see "Chat 1" in the "#next-activity-link" "css_element" - And I follow "Chat 1" - And I should see "Book 1" in the "#prev-activity-link" "css_element" And I should see "Choice 1" in the "#next-activity-link" "css_element" And I follow "Choice 1" - And I should see "Chat 1" in the "#prev-activity-link" "css_element" + And I should see "Book 1" in the "#prev-activity-link" "css_element" And I should see "Database 1" in the "#next-activity-link" "css_element" And I follow "Database 1" And I should see "Choice 1" in the "#prev-activity-link" "css_element" @@ -200,7 +187,6 @@ Feature: Activity navigation And the "Jump to..." select box should not contain "Label 1" # Check drop down menu contents. And the "Jump to..." select box should contain "Book 1" - And the "Jump to..." select box should contain "Chat 1" And the "Jump to..." select box should contain "Choice 1" And the "Jump to..." select box should contain "Database 1" And the "Jump to..." select box should contain "Feedback 1" @@ -218,7 +204,6 @@ Feature: Activity navigation # Activities in hidden sections will be rendered with a '(hidden)' text. And the "Jump to..." select box should contain "Resource 1 (hidden)" And the "Jump to..." select box should contain "Scorm 1 (hidden)" - And the "Jump to..." select box should contain "Survey 1 (hidden)" # Jump to an activity somewhere in the middle. When I select "Page 1" from the "Jump to..." singleselect Then I should see "Page 1" @@ -253,10 +238,8 @@ Feature: Activity navigation # Activities in hidden sections will not be listed for students. And the "Jump to..." select box should not contain "Resource 1" And the "Jump to..." select box should not contain "Scorm 1" - And the "Jump to..." select box should not contain "Survey 1" # Only activities visible to students will be listed. And the "Jump to..." select box should contain "Book 1" - And the "Jump to..." select box should contain "Chat 1" And the "Jump to..." select box should contain "Choice 1" And the "Jump to..." select box should contain "Database 1" And the "Jump to..." select box should contain "Feedback 1" diff --git a/course/tests/behat/activity_resource_description_display.feature b/course/tests/behat/activity_resource_description_display.feature index c9280250886..761dd1fa9f1 100644 --- a/course/tests/behat/activity_resource_description_display.feature +++ b/course/tests/behat/activity_resource_description_display.feature @@ -16,10 +16,8 @@ Feature: Display activity and resource description | teacher1 | C1 | editingteacher | Scenario Outline: Display activity and resource descriptions - Given I enable "chat" "mod" plugin - And I enable "survey" "mod" plugin # Generate activity/resource with description - And the following "activities" exist: + Given the following "activities" exist: | activity | course | name | intro | showdescription | | | C1 | | intro | 1 | When I am on the "Course 1" course page logged in as teacher1 @@ -31,7 +29,6 @@ Feature: Display activity and resource description | acttype | actname | | assign | Assign 1 | | book | Book 1 | - | chat | Chat 1 | | data | Database 1 | | feedback | Feedback 1 | | forum | Forum 1 | @@ -45,7 +42,6 @@ Feature: Display activity and resource description | glossary | Glossary 1 | | scorm | Scorm 1 | | lesson | Lesson 1 | - | survey | Survey 1 | | url | URL 1 | | wiki | Wiki 1 | | workshop | Workshop 1 | diff --git a/lang/en/admin.php b/lang/en/admin.php index 943bd4d559c..8b3dd904f73 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -762,11 +762,6 @@ $string['taskh5pcleanup'] = 'Unused H5P files cleanup'; $string['iconvrequired'] = 'Installing ICONV extension is required.'; $string['igbinary322buggyversion'] = 'The php-igbinary extension installed on the site can lead to problems when running with PHP 7.2. You are recommended to either upgrade to php-igbinary 3.2.5 or later, or alternatively to upgrade to PHP 7.3 or later.'; $string['ignore'] = 'Ignore'; -$string['importantupdates_content'] = '

In the next Moodle 5.0, planned for release in April 2025, the Chat and Survey activities will -be removed from core Moodle. They will be available as plugins in the -Moodle plugins directory.

-

If you wish to continue using Chat or Survey in your site, you will be able to install them as plugins before upgrading to Moodle 5.0.

'; -$string['importantupdates_title'] = 'Important update about Chat and Survey activities'; $string['includemoduleuserdata'] = 'Include module user data'; $string['incompatibleblocks'] = 'Incompatible blocks'; $string['indexdata'] = 'Index data'; @@ -1666,3 +1661,10 @@ $string['registration_help'] = 'By registering: * You will receive security alerts * You can activate mobile app push notifications from your site * You are contributing to our Moodle statistics of the worldwide community'; + +// Deprecated since Moodle 5.0. +$string['importantupdates_content'] = '

In the next Moodle 5.0, planned for release in April 2025, the Chat and Survey activities will +be removed from core Moodle. They will be available as plugins in the +Moodle plugins directory.

+

If you wish to continue using Chat or Survey in your site, you will be able to install them as plugins before upgrading to Moodle 5.0.

'; +$string['importantupdates_title'] = 'Important update about Chat and Survey activities'; diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt index c72418d6115..078631c5185 100644 --- a/lang/en/deprecated.txt +++ b/lang/en/deprecated.txt @@ -142,3 +142,5 @@ configgeneralquestionbank,core_backup generalquestionbank,core_backup cannotdeletecategoryquestions,core_error errordeletingquestionsfromcategory,core_question +importantupdates_content,core_admin +importantupdates_title,core_admin \ No newline at end of file diff --git a/lib/classes/check/environment/publicpaths.php b/lib/classes/check/environment/publicpaths.php index c516915ddca..fc726012dfd 100644 --- a/lib/classes/check/environment/publicpaths.php +++ b/lib/classes/check/environment/publicpaths.php @@ -137,7 +137,6 @@ class publicpaths extends check { '404' => [ 'mod/README.txt', 'mod/book/README.md', - 'mod/chat/README.txt', ], ], [ diff --git a/lib/classes/event/course_module_instance_list_viewed.php b/lib/classes/event/course_module_instance_list_viewed.php index 341da811637..31e55af22d8 100644 --- a/lib/classes/event/course_module_instance_list_viewed.php +++ b/lib/classes/event/course_module_instance_list_viewed.php @@ -34,7 +34,7 @@ defined('MOODLE_INTERNAL') || die(); * * Example: * - * \mod_chat\event\course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed + * \mod_assign\event\course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed * * @package core * @since Moodle 2.7 diff --git a/lib/db/analytics.php b/lib/db/analytics.php index 7efac78d694..07919a96c7b 100644 --- a/lib/db/analytics.php +++ b/lib/db/analytics.php @@ -40,8 +40,6 @@ $models = [ '\mod_assign\analytics\indicator\social_breadth', '\mod_book\analytics\indicator\cognitive_depth', '\mod_book\analytics\indicator\social_breadth', - '\mod_chat\analytics\indicator\cognitive_depth', - '\mod_chat\analytics\indicator\social_breadth', '\mod_choice\analytics\indicator\cognitive_depth', '\mod_choice\analytics\indicator\social_breadth', '\mod_data\analytics\indicator\cognitive_depth', @@ -70,8 +68,6 @@ $models = [ '\mod_resource\analytics\indicator\social_breadth', '\mod_scorm\analytics\indicator\cognitive_depth', '\mod_scorm\analytics\indicator\social_breadth', - '\mod_survey\analytics\indicator\cognitive_depth', - '\mod_survey\analytics\indicator\social_breadth', '\mod_url\analytics\indicator\cognitive_depth', '\mod_url\analytics\indicator\social_breadth', '\mod_wiki\analytics\indicator\cognitive_depth', diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index ea4729ca06f..2b645c0ad73 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1303,5 +1303,23 @@ 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); + } + + // 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/lib/phpunit/classes/restore_date_testcase.php b/lib/phpunit/classes/restore_date_testcase.php index 7416181d28b..48d0412118d 100644 --- a/lib/phpunit/classes/restore_date_testcase.php +++ b/lib/phpunit/classes/restore_date_testcase.php @@ -115,15 +115,6 @@ abstract class restore_date_testcase extends advanced_testcase { * @return array */ protected function create_course_and_module($modulename, $record = []) { - if ($modulename == 'chat') { - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('chat', 1); - } - if ($modulename == 'survey') { - $manager = \core_plugin_manager::resolve_plugininfo_class('mod'); - $manager::enable_plugin('survey', 1); - } - // Create a course with specific start date. $record = (array)$record; $generator = $this->getDataGenerator(); diff --git a/lib/plugins.json b/lib/plugins.json index f5f616ffed3..3b8da96de0b 100644 --- a/lib/plugins.json +++ b/lib/plugins.json @@ -312,7 +312,6 @@ "assign", "bigbluebuttonbn", "book", - "chat", "choice", "data", "feedback", @@ -330,7 +329,6 @@ "resource", "scorm", "subsection", - "survey", "url", "wiki", "workshop" @@ -622,7 +620,9 @@ "jabber" ], "mod": [ - "assignment" + "assignment", + "chat", + "survey" ], "portfolio": [ "boxnet", diff --git a/lib/tests/external/moodlenet_get_share_info_activity_test.php b/lib/tests/external/moodlenet_get_share_info_activity_test.php index e2c523f9e7d..95051883219 100644 --- a/lib/tests/external/moodlenet_get_share_info_activity_test.php +++ b/lib/tests/external/moodlenet_get_share_info_activity_test.php @@ -50,7 +50,7 @@ final class moodlenet_get_share_info_activity_test extends externallib_advanced_ // Generate course and activities. $course = $this->getDataGenerator()->create_course(); - $activity1 = $this->getDataGenerator()->create_module('chat', ['course' => $course->id, 'name' => 'Chat activity']); + $activity1 = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Page activity']); $activity2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id, 'name' => 'Assign activity']); $activity3 = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id, 'name' => 'Quiz activity']); @@ -98,7 +98,7 @@ final class moodlenet_get_share_info_activity_test extends externallib_advanced_ $result = external_api::clean_returnvalue(moodlenet_get_share_info_activity::execute_returns(), $result); $this->assertTrue($result['status']); $this->assertEquals($activity1->name, $result['name']); - $this->assertEquals(get_string('modulename', 'mod_chat'), $result['type']); + $this->assertEquals(get_string('modulename', 'mod_page'), $result['type']); $this->assertEquals($issuer->get_display_name(), $result['server']); $this->assertEquals($expectedsupporturl, $result['supportpageurl']); diff --git a/lib/tests/plugininfo/mod_test.php b/lib/tests/plugininfo/mod_test.php index 711259807cc..316e851a8fe 100644 --- a/lib/tests/plugininfo/mod_test.php +++ b/lib/tests/plugininfo/mod_test.php @@ -32,12 +32,11 @@ final class mod_test extends advanced_testcase { public function test_get_enabled_plugins(): void { $this->resetAfterTest(); - // The bigbluebuttonbn and chat plugins are disabled by default. + // The bigbluebuttonbn is disabled by default. // Check all default formats. $plugins = mod::get_enabled_plugins(); $this->assertArrayHasKey('assign', $plugins); $this->assertArrayHasKey('forum', $plugins); - $this->assertArrayNotHasKey('chat', $plugins); $this->assertArrayNotHasKey('bigbluebuttonbn', $plugins); // Disable assignment. @@ -46,7 +45,6 @@ final class mod_test extends advanced_testcase { $plugins = mod::get_enabled_plugins(); $this->assertArrayHasKey('forum', $plugins); $this->assertArrayNotHasKey('assign', $plugins); - $this->assertArrayNotHasKey('chat', $plugins); $this->assertArrayNotHasKey('bigbluebuttonbn', $plugins); } } diff --git a/lib/tests/statslib_test.php b/lib/tests/statslib_test.php index a2bd2ee82ea..958f0e5e96b 100644 --- a/lib/tests/statslib_test.php +++ b/lib/tests/statslib_test.php @@ -454,72 +454,67 @@ final class statslib_test extends \advanced_testcase { * defaults for a new Moodle 2.3 install. */ public function test_statslib_get_action_names(): void { - $basepostactions = array ( - 0 => 'add', - 1 => 'delete', - 2 => 'edit', - 3 => 'add mod', - 4 => 'delete mod', - 5 => 'edit section', - 6 => 'loginas', - 7 => 'new', - 8 => 'unenrol', - 9 => 'update', - 10 => 'update mod', - 11 => 'upload', - 12 => 'submit', - 13 => 'submit for grading', - 14 => 'talk', - 15 => 'choose', - 16 => 'choose again', - 17 => 'record delete', - 18 => 'add discussion', - 19 => 'add post', - 20 => 'delete discussion', - 21 => 'delete post', - 22 => 'move discussion', - 23 => 'prune post', - 24 => 'update post', - 25 => 'add category', - 26 => 'add entry', - 27 => 'approve entry', - 28 => 'delete category', - 29 => 'delete entry', - 30 => 'edit category', - 31 => 'update entry', - 32 => 'end', - 33 => 'start', - 34 => 'attempt', - 35 => 'close attempt', - 36 => 'preview', - 37 => 'editquestions', - 38 => 'delete attempt', - 39 => 'manualgrade', - 40 => 'enrol', - ); + $basepostactions = [ + 'add', + 'delete', + 'edit', + 'add mod', + 'delete mod', + 'edit section', + 'loginas', + 'new', + 'unenrol', + 'update', + 'update mod', + 'upload', + 'submit', + 'submit for grading', + 'choose', + 'choose again', + 'record delete', + 'add discussion', + 'add post', + 'delete discussion', + 'delete post', + 'move discussion', + 'prune post', + 'update post', + 'add category', + 'add entry', + 'approve entry', + 'delete category', + 'delete entry', + 'edit category', + 'update entry', + 'end', + 'start', + 'attempt', + 'close attempt', + 'preview', + 'editquestions', + 'delete attempt', + 'manualgrade', + 'enrol', + ]; - $baseviewactions = array ( - 0 => 'view', - 1 => 'view all', - 2 => 'history', - 3 => 'view submission', - 4 => 'view feedback', - 5 => 'print', - 6 => 'report', - 7 => 'view discussion', - 8 => 'search', - 9 => 'forum', - 10 => 'forums', - 11 => 'subscribers', - 12 => 'view forum', - 13 => 'view entry', - 14 => 'review', - 15 => 'pre-view', - 16 => 'download', - 17 => 'view form', - 18 => 'view graph', - 19 => 'view report', - ); + $baseviewactions = [ + 'view', + 'view all', + 'history', + 'view submission', + 'view feedback', + 'print', + 'report', + 'view discussion', + 'search', + 'forum', + 'forums', + 'subscribers', + 'view forum', + 'view entry', + 'review', + 'pre-view', + ]; $postactions = stats_get_action_names('post'); 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 6cfa71d1ad7..00000000000 Binary files a/mod/chat/beep.mp3 and /dev/null differ 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 208dcfd86c7..00000000000 Binary files a/mod/chat/gui_ajax/theme/bubble/bubbles.png and /dev/null differ 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 = <<