Файловый менеджер - Редактировать - /home/harasnat/www/mf/recentlyaccesseditems.tar
Назад
version.php 0000604 00000002320 15062123132 0006726 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Version details for the Recent activities block. * * @package block_recentlyaccesseditems * @copyright 2018 Victor Deniz <victor@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2023100900; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2023100400; // Requires this Moodle version. $plugin->component = 'block_recentlyaccesseditems'; // Full name of the plugin (used for diagnostics). tests/helper_test.php 0000604 00000005222 15062123132 0010725 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace block_recentlyaccesseditems; /** * Block Recently accessed helper class tests. * * @package block_recentlyaccesseditems * @copyright 2019 University of Nottingham * @author Neill Magill <neill.magill@nottingham.ac.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class helper_test extends \advanced_testcase { /** * Tests that the get recent items method can handle getting records when courses have been deleted. */ public function test_get_recent_items() { $this->resetAfterTest(); $course = self::getDataGenerator()->create_course(); $coursetodelete = self::getDataGenerator()->create_course(); $user = self::getDataGenerator()->create_and_enrol($course, 'student'); self::getDataGenerator()->enrol_user($user->id, $coursetodelete->id, 'student'); // Add an activity to each course. $forum = self::getDataGenerator()->create_module('forum', ['course' => $course]); $glossary = self::getDataGenerator()->create_module('glossary', ['course' => $coursetodelete]); self::setUser($user); // Get the user to visit the activities. $event1params = ['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]; $event1 = \mod_forum\event\course_module_viewed::create($event1params); $event1->trigger(); $event2params = ['context' => \context_module::instance($glossary->cmid), 'objectid' => $glossary->id]; $event2 = \mod_glossary\event\course_module_viewed::create($event2params); $event2->trigger(); $recent1 = helper::get_recent_items(); self::assertCount(2, $recent1); $recentlimited = helper::get_recent_items(1); self::assertCount(1, $recentlimited); delete_course($coursetodelete, false); // There should be no errors if a course has been deleted. $recent2 = helper::get_recent_items(); self::assertCount(1, $recent2); } } tests/privacy/provider_test.php 0000604 00000050770 15062123132 0012765 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Block recentlyaccesseditems privacy provider tests. * * @package block_recentlyaccesseditems * @copyright 2018 Michael Hawkins <michaelh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.6 */ namespace block_recentlyaccesseditems\privacy; defined('MOODLE_INTERNAL') || die(); use block_recentlyaccesseditems\privacy\provider; use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\approved_userlist; /** * Block Recently accessed items privacy provider tests. * * @package block_recentlyaccesseditems * @copyright 2018 Michael Hawkins <michaelh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.6 */ class provider_test extends \core_privacy\tests\provider_testcase { /** * Test getting the context for the user ID related to this plugin. */ public function test_get_contexts_for_userid() { $this->resetAfterTest(); $generator = $this->getDataGenerator(); $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); $teacher = $generator->create_user(); $teachercontext = \context_user::instance($teacher->id); // Enrol users in course and add course items. $course = $generator->create_course(); $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]); // Check nothing is found before block is populated. $contextlist1 = provider::get_contexts_for_userid($student->id); $this->assertCount(0, $contextlist1); $contextlist2 = provider::get_contexts_for_userid($teacher->id); $this->assertCount(0, $contextlist2); // Generate some recent activity for both users. $this->setUser($student); $event = \mod_forum\event\course_module_viewed::create(['context' => \context_module::instance($forum->cmid), 'objectid' => $forum->id]); $event->trigger(); $this->setUser($teacher); $event = \mod_chat\event\course_module_viewed::create(['context' => \context_module::instance($chat->cmid), 'objectid' => $chat->id]); $event->trigger(); // Ensure provider only fetches the users's own context. $contextlist1 = provider::get_contexts_for_userid($student->id); $this->assertCount(1, $contextlist1); $this->assertEquals($studentcontext, $contextlist1->current()); $contextlist2 = provider::get_contexts_for_userid($teacher->id); $this->assertCount(1, $contextlist2); $this->assertEquals($teachercontext, $contextlist2->current()); } /** * Test getting users in the context ID related to this plugin. */ public function test_get_users_in_context() { $this->resetAfterTest(); $generator = $this->getDataGenerator(); $component = 'block_recentlyaccesseditems'; $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); $teacher = $generator->create_user(); $teachercontext = \context_user::instance($teacher->id); // Enrol users in course and add course items. $course = $generator->create_course(); $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]); // Check nothing is found before block is populated. $userlist1 = new \core_privacy\local\request\userlist($studentcontext, $component); provider::get_users_in_context($userlist1); $this->assertCount(0, $userlist1); $userlist2 = new \core_privacy\local\request\userlist($teachercontext, $component); provider::get_users_in_context($userlist2); $this->assertCount(0, $userlist2); // Generate some recent activity for both users. $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->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->trigger(); // Ensure provider only fetches the user whose user context is checked. $userlist1 = new \core_privacy\local\request\userlist($studentcontext, $component); provider::get_users_in_context($userlist1); $this->assertCount(1, $userlist1); $this->assertEquals($student, $userlist1->current()); $userlist2 = new \core_privacy\local\request\userlist($teachercontext, $component); provider::get_users_in_context($userlist2); $this->assertCount(1, $userlist2); $this->assertEquals($teacher, $userlist2->current()); } /** * Test fetching information about user data stored. */ public function test_get_metadata() { $collection = new \core_privacy\local\metadata\collection('block_recentlyaccesseditems'); $newcollection = provider::get_metadata($collection); $itemcollection = $newcollection->get_collection(); $this->assertCount(1, $itemcollection); $table = reset($itemcollection); $this->assertEquals('block_recentlyaccesseditems', $table->get_name()); $privacyfields = $table->get_privacy_fields(); $this->assertCount(4, $privacyfields); $this->assertArrayHasKey('userid', $privacyfields); $this->assertArrayHasKey('courseid', $privacyfields); $this->assertArrayHasKey('cmid', $privacyfields); $this->assertArrayHasKey('timeaccess', $privacyfields); $this->assertEquals('privacy:metadata:block_recentlyaccesseditemstablesummary', $table->get_summary()); } /** * Test exporting data for an approved contextlist. */ public function test_export_user_data() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator(); $component = 'block_recentlyaccesseditems'; $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); // Enrol user in course and add course items. $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]); // 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->trigger(); // Confirm data is present. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); // Export data for student. $approvedlist = new approved_contextlist($student, $component, [$studentcontext->id]); provider::export_user_data($approvedlist); // Confirm student's data is exported. $writer = \core_privacy\local\request\writer::with_context($studentcontext); $this->assertTrue($writer->has_any_data()); delete_course($course, false); $sc = \context_user::instance($student->id); $approvedlist = new approved_contextlist($student, $component, [$sc->id]); provider::export_user_data($approvedlist); $writer = \core_privacy\local\request\writer::with_context($sc); $this->assertTrue($writer->has_any_data()); } /** * Test exporting data for an approved contextlist with a deleted course */ public function test_export_user_data_with_deleted_course() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator(); $component = 'block_recentlyaccesseditems'; $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); // Enrol user in course and add course items. $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]); // 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->trigger(); // Confirm data is present. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); delete_course($course, false); // Export data for student. $approvedlist = new approved_contextlist($student, $component, [$studentcontext->id]); provider::export_user_data($approvedlist); // Confirm student's data is exported. $writer = \core_privacy\local\request\writer::with_context($studentcontext); $this->assertFalse($writer->has_any_data()); } /** * Test deleting data for all users within an approved contextlist. */ public function test_delete_data_for_all_users_in_context() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator(); $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); $teacher = $generator->create_user(); // Enrol users in course and add course items. $course = $generator->create_course(); $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]); // Generate some recent activity for both users. $users = [$student, $teacher]; foreach ($users as $user) { $this->setUser($user); $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->trigger(); } // Confirm data is present for both users. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); $params['userid'] = $teacher->id; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); // Attempt system context deletion (should have no effect). $systemcontext = \context_system::instance(); provider::delete_data_for_all_users_in_context($systemcontext); $params = ['courseid' => $course->id]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(4, $result); // Delete all data in student context. provider::delete_data_for_all_users_in_context($studentcontext); // Confirm only student data is deleted. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(0, $result); $params['userid'] = $teacher->id; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); } /** * Test deleting data within an approved contextlist for a user. */ public function test_delete_data_for_user() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator(); $component = 'block_recentlyaccesseditems'; $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); $teacher = $generator->create_user(); $teachercontext = \context_user::instance($teacher->id); // Enrol users in course and add course items. $course = $generator->create_course(); $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]); // Generate some recent activity for both users. $users = [$student, $teacher]; foreach ($users as $user) { $this->setUser($user); $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->trigger(); } // Confirm data is present for both users. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); $params['userid'] = $teacher->id; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); // Attempt system context deletion (should have no effect). $systemcontext = \context_system::instance(); $approvedlist = new approved_contextlist($teacher, $component, [$systemcontext->id]); provider::delete_data_for_user($approvedlist); $params = ['courseid' => $course->id]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(4, $result); // Attempt to delete teacher data in student user context (should have no effect). $approvedlist = new approved_contextlist($teacher, $component, [$studentcontext->id]); provider::delete_data_for_user($approvedlist); $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(4, $result); // Delete teacher data in their own user context. $approvedlist = new approved_contextlist($teacher, $component, [$teachercontext->id]); provider::delete_data_for_user($approvedlist); // Confirm only teacher data is deleted. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); $params['userid'] = $teacher->id; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(0, $result); } /** * Test deleting data within a context for an approved userlist. */ public function test_delete_data_for_users() { global $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator(); $component = 'block_recentlyaccesseditems'; $student = $generator->create_user(); $studentcontext = \context_user::instance($student->id); $teacher = $generator->create_user(); $teachercontext = \context_user::instance($teacher->id); // Enrol users in course and add course items. $course = $generator->create_course(); $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]); // Generate some recent activity for all users. $users = [$student, $teacher]; foreach ($users as $user) { $this->setUser($user); $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->trigger(); } // Confirm data is present for all 3 users. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); $params['userid'] = $teacher->id; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); // Attempt system context deletion (should have no effect). $systemcontext = \context_system::instance(); $approvedlist = new approved_userlist($systemcontext, $component, [$student->id, $teacher->id]); provider::delete_data_for_users($approvedlist); $params = ['courseid' => $course->id]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(4, $result); // Attempt to delete data in another user's context (should have no effect). $approvedlist = new approved_userlist($studentcontext, $component, [$teacher->id]); provider::delete_data_for_users($approvedlist); $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(4, $result); // Delete users' data in teacher's context. $approvedlist = new approved_userlist($teachercontext, $component, [$student->id, $teacher->id]); provider::delete_data_for_users($approvedlist); // Confirm only teacher data is deleted. $params = [ 'courseid' => $course->id, 'userid' => $student->id, ]; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(2, $result); $params['userid'] = $teacher->id; $result = $DB->count_records('block_recentlyaccesseditems', $params); $this->assertEquals(0, $result); } } tests/externallib_test.php 0000604 00000010224 15062123132 0011755 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace block_recentlyaccesseditems; use externallib_advanced_testcase; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/webservice/tests/helpers.php'); /** * Test Recently accessed items block external functions * * @package block_recentlyaccesseditems * @category external * @copyright 2018 Victor Deniz <victor@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.6 */ class externallib_test extends externallib_advanced_testcase { /** * Test the get_recent_items function. */ public function test_get_recent_items() { $this->resetAfterTest(); $generator = $this->getDataGenerator(); // Add courses. $courses = array(); for ($i = 1; $i < 4; $i++) { $courses[] = $generator->create_course(); }; // Add users. $student = $generator->create_user(); $teacher = $generator->create_user(); // Enrol users and add items to courses. foreach ($courses as $course) { $generator->enrol_user($student->id, $course->id, 'student'); $forum[] = $this->getDataGenerator()->create_module('forum', array('course' => $course)); $glossary[] = $this->getDataGenerator()->create_module('glossary', array('course' => $course)); $chat[] = $this->getDataGenerator()->create_module('chat', array('course' => $course)); } $generator->enrol_user($teacher->id, $courses[0]->id, 'teacher'); $this->setUser($student); // No recent items. $result = \block_recentlyaccesseditems\external::get_recent_items(); $this->assertCount(0, $result); // Student access all forums. foreach ($forum as $module) { $event = \mod_forum\event\course_module_viewed::create(array('context' => \context_module::instance($module->cmid), 'objectid' => $module->id)); $event->trigger(); $this->waitForSecond(); } // Test that only access to forums are returned. $result = \block_recentlyaccesseditems\external::get_recent_items(); $this->assertCount(count($forum), $result); // Student access all assignments. foreach ($chat as $module) { $event = \mod_chat\event\course_module_viewed::create(array('context' => \context_module::instance($module->cmid), 'objectid' => $module->id)); $event->trigger(); $this->waitForSecond(); } // Test that results are sorted by timeaccess DESC (default). $result = \block_recentlyaccesseditems\external::get_recent_items(); $this->assertCount((count($forum) + count($chat)), $result); foreach ($result as $key => $record) { if ($key == 0) { continue; } $this->assertTrue($record->timeaccess < $result[$key - 1]->timeaccess); } // Delete a course and confirm it's activities don't get returned. delete_course($courses[0], false); $result = \block_recentlyaccesseditems\external::get_recent_items(); $this->assertCount((count($forum) + count($chat)) - 2, $result); // Delete a single course module should still return. course_delete_module($forum[1]->cmid); $result = \block_recentlyaccesseditems\external::get_recent_items(); $this->assertCount((count($forum) + count($chat)) - 3, $result); } } tests/observer_test.php 0000604 00000015611 15062123132 0011300 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. namespace block_recentlyaccesseditems; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/mod/assign/tests/generator.php'); /** * Block Recently accessed items observer tests. * * @package block_recentlyaccesseditems * @copyright 2018 Victor Deniz <victor@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.6 */ class observer_test extends \advanced_testcase { use \mod_assign_test_generator; /** @var string Table name. */ protected $table; /** @var \stdClass course data. */ protected $course; /** @var \stdClass student data. */ protected $student; /** @var \stdClass teacher data. */ protected $teacher; /** @var \stdClass student role. */ protected $studentrole; /** @var \stdClass teacher role. */ protected $teacherrole; /** @var \stdClass course forum. */ protected $forum; /** @var \stdClass course glossary. */ protected $glossary; /** @var \stdClass course chat. */ protected $chat; /** * Set up for every test */ public function setUp(): void { global $DB; $this->resetAfterTest(); $this->setAdminUser(); // Block table name. $this->table = "block_recentlyaccesseditems"; // Setup test data. $this->course = $this->getDataGenerator()->create_course(); // Create users. $this->student = self::getDataGenerator()->create_user(); $this->teacher = self::getDataGenerator()->create_user(); // Users enrolments. $this->studentrole = $DB->get_record('role', array('shortname' => 'student')); $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual'); $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual'); // 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)); } /** * Test items views are recorded * * When items events are triggered they are stored in the block_recentlyaccesseditems table. */ public function test_item_view_recorded_testcase() { global $DB; // Empty table at the beggining. $records = $DB->count_records($this->table, array()); $this->assertEquals(0, $records); // Teacher access forum activity. $this->setUser($this->teacher); $event = \mod_forum\event\course_module_viewed::create(array('context' => \context_module::instance($this->forum->cmid), 'objectid' => $this->forum->id)); $event->trigger(); // Student access chat 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->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)); $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)); $event2->trigger(); $records = $DB->get_records($this->table, array('userid' => $this->student->id, 'courseid' => $this->course->id, 'cmid' => $this->chat->cmid)); $this->assertCount(1, $records); $this->assertEquals($event2->timecreated, array_shift($records)->timeaccess); } /** * Test removed items records are deleted. * * When a course module is removed, the records associated in the block_recentlyaccesseditems table are deleted. */ public function test_item_delete_record_testcase() { global $DB; // Empty table at the beggining. $records = $DB->count_records($this->table, array()); $this->assertEquals(0, $records); // Teacher access forum activity. $this->setUser($this->teacher); $event = \mod_forum\event\course_module_viewed::create(array('context' => \context_module::instance($this->forum->cmid), '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)); $event->trigger(); // Student access chat 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->trigger(); // Student access forum activity. $event = \mod_forum\event\course_module_viewed::create(array('context' => \context_module::instance($this->forum->cmid), 'objectid' => $this->forum->id)); $event->trigger(); $records = $DB->count_records($this->table, array('cmid' => $this->forum->cmid)); $this->assertEquals(2, $records); 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)); $this->assertEquals(2, $records); } } tests/behat/block_recentlyaccesseditems_dashboard.feature 0000604 00000006022 15062123132 0020100 0 ustar 00 @block @block_recentlyaccesseditems @javascript Feature: The recently accessed items block allows users to easily access their most recently visited items In order to access the most recent items accessed As a user I can use the recently accessed items block in my dashboard Background: Given the following "users" exist: | username | firstname | lastname | email | | student1 | Student | 1 | student1@example.com | And the following "courses" exist: | fullname | shortname | | Course 1 | C1 | | Course 2 | C2 | And the following "course enrolments" exist: | user | course | role | | student1 | C1 | student | | student1 | C2 | student | And the following "activity" exists: | course | C1 | | activity | forum | | idnumber | Test forum name | | name | Test forum name | And I log in as "student1" Scenario: User has not accessed any item Then I should see "No recent items" in the "Recently accessed items" "block" Scenario: User has accessed some items Given I change window size to "large" When I am on the "Test forum name" "forum activity" page And I follow "Dashboard" Then I should see "Test forum name" in the "Recently accessed items" "block" And I should not see "Show more items" in the "Recently accessed items" "block" Scenario: User has accessed more than 3 items Given the following "activities" exist: | activity | name | intro | course | idnumber | | assign | Test assignment name | Test assignment description | C1 | assign1 | | book | Test book name | | C1 | book1 | | choice | Test choice name | Test choice description | C1 | choice1 | | data | Test database name | Test database description | C1 | data1 | And I change window size to "large" And I am on the "Test forum name" "forum activity" page And I am on the "Test database name" "data activity" page And I am on the "Test assignment name" "assign activity" page And I am on the "Test book name" "book activity" page And I am on the "Test choice name" "choice activity" page When I follow "Dashboard" Then I should see "Show more items" in the "Recently accessed items" "block" And I should not see "Test forum name" in the "Recently accessed items" "block" And I click on "Show more items" "button" in the "Recently accessed items" "block" And I should see "Test forum name" in the "Recently accessed items" "block" And I turn editing mode on And I am on homepage And I configure the "Recently accessed items" block And I set the following fields to these values: | Region | content | And I press "Save changes" And I turn editing mode off And I should not see "Show more items" in the "Recently accessed items" "block" lang/en/block_recentlyaccesseditems.php 0000604 00000003260 15062123132 0014324 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Strings for the Recently accessed items block. * * @package block_recentlyaccesseditems * @copyright 2018 Victor Deniz <victor@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['moreitems'] = 'Show more items'; $string['noitems'] = 'No recent items'; $string['pluginname'] = 'Recently accessed items'; $string['privacy:metadata:cmid'] = 'The ID of the activity or resource'; $string['privacy:metadata:courseid'] = 'Course the item belongs to'; $string['privacy:metadata:block_recentlyaccesseditemstablesummary'] = 'The Recently accessed items block stores information about items that the user accessed recently'; $string['privacy:metadata:timeaccess'] = 'The time when the user last accessed the item'; $string['privacy:metadata:userid'] = 'The ID of the user who accessed the item'; $string['privacy:recentlyaccesseditemspath'] = 'Recently accessed items'; $string['recentlyaccesseditems:myaddinstance'] = 'Add a new recently accessed items block to Dashboard'; upgrade.txt 0000604 00000000303 15062123132 0006717 0 ustar 00 This file describes API changes in the recentlyaccesseditems block code. === 3.7 === * The 'block/recentlyaccesseditems:addinstance' capability has been removed. It has never been used in code. templates/view-cards.mustache 0000604 00000005137 15062123132 0012336 0 ustar 00 {{! This file is part of Moodle - http://moodle.org/ Moodle is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Moodle is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public Licensebllsdsadfasfd along with Moodle. If not, see <http://www.gnu.org/licenses/>. }} {{! @template block_recentlyaccesseditems/view-cards This template renders the items cards of the Recently accessed items block. Example context (json): { "items": [ { "cmid": 64, "courseid": 2, "coursename": "Course", "courseviewurl": "https://moodlesite/course/view.php?id=2", "icon": "<img class=\"icon\" alt=\"Forum\" title=\"Forum\" src=\"http://moodlesite/theme/image.php/boost/forum/1539858121/icon\" />", "name": "Assignment due 1", "id": 17, "modname": "Forum", "name": "Forum", "timeaccess": 1539848498, "userid": 2, "viewurl": "http://moodlesite/mod/forum?id=64" } ] } }} <div class="card-deck dashboard-card-deck one-row" data-region="items-list" role="list"> {{#items}} <a class="card dashboard-card mb-1" href="{{{viewurl}}}" title="{{{name}}}" role="listitem"> <div class="card-body p-2 m-1"> <div class="d-flex text-truncate"> <div class="d-flex align-self-center activityiconcontainer {{purpose}}"> {{{icon}}} </div> <div class="w-100 line-height-3 text-truncate ml-2"> <h6 class="mb-0 text-truncate"><span class="clickable">{{{name}}}</span></h6> <small class="text-truncate mb-0">{{{coursename}}}</small> </div> </div> </div> </a> {{/items}} </div> {{#hasmoreitems}} <div data-region="more-items-button-container" class="mt-2 px-1"> <button type="button" class="btn btn-secondary btn-sm" data-action="more-items"> {{#str}}moreitems, block_recentlyaccesseditems {{/str}} </button> </div> {{/hasmoreitems}} templates/placeholder-item.mustache 0000604 00000002557 15062123132 0013513 0 ustar 00 {{! This file is part of Moodle - http://moodle.org/ Moodle is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Moodle is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Moodle. If not, see <http://www.gnu.org/licenses/>. }} {{! @template block_recentlyaccesseditems/placeholder-item This template renders a card item loading placeholder for the Recently accessed items block. Example context (json): {} }} <div class="card dashboard-card mb-1"> <div class="card-body p-2 m-1"> <div class="d-flex flex-row mw-100 align-items-center"> <div class="bg-pulse-grey rounded-circle" style="height: 40px; width: 40px;"></div> <div class="pl-2" style="flex: 1;"> <div class="bg-pulse-grey w-100" style="height: 1rem;"></div> <div class="bg-pulse-grey w-75 mt-1" style="height: 0.8rem;"></div> </div> </div> </div> </div>