From 5319445e8789507aa174f63192ccb21e88b770fb Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 00:16:36 +0200 Subject: [PATCH 01/11] add event collection tests --- classes/moodleoverflow.php | 1 + tests/events_test.php | 313 +++++++++++++++++++++++++++++++++++++ tests/phpunit.xml | 39 +++++ 3 files changed, 353 insertions(+) create mode 100644 tests/events_test.php create mode 100644 tests/phpunit.xml diff --git a/classes/moodleoverflow.php b/classes/moodleoverflow.php index 1d82f85..c420973 100644 --- a/classes/moodleoverflow.php +++ b/classes/moodleoverflow.php @@ -99,6 +99,7 @@ public static function get_events(): array { */ private static function get_moodleoverflowposts_from_db($courses, $timestart): array { global $DB; + // Prepare params for sql statement. list($insqlcourses, $inparamscourses) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED); $params = ['courses' => $courses, 'timestart' => $timestart] + $inparamscourses; diff --git a/tests/events_test.php b/tests/events_test.php new file mode 100644 index 0000000..1c8ecb5 --- /dev/null +++ b/tests/events_test.php @@ -0,0 +1,313 @@ +. + + +/** + * Unit tests for the moodleoverflow townsquareexpansion + * + * @package townsquareexpansion_moodleoverflow + * @copyright 2025 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace townsquareexpansion_moodleoverflow; + +use coding_exception; +use dml_exception; +use Exception; +use stdClass; + +/** + * PHPUnit tests for testing the process of event collection. + * + * @package townsquareexpansion_moodleoverflow + * @copyright 2025 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \townsquareexpansion_moodleoverflow\moodleoverflow::get_events + */ +final class events_test extends \advanced_testcase { + + /** @var stdClass */ + private stdClass $testdata; + private moodleoverflow $moodleoverflowevents; + + /** + * @throws dml_exception + */ + public function setUp(): void { + parent::setUp(); + global $DB; + $this->testdata = new stdClass(); + $this->moodleoverflowevents = new moodleoverflow(); + $this->resetAfterTest(); + + // Check if moodleoverflow is available: + if (!$DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { + $this->markTestSkipped('Moodleoverflow is not installed or not activated.'); + } + $this->helper_course_set_uo(); + } + + public function tearDown(): void { + parent::tearDown(); + } + + /** + * Test, if post events are sorted correctly. + * Post should be sorted by the time they were created in descending order (newest post first). + * @return void + */ + public function test_sortorder(): void { + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // Iterate through all posts and check if the sort order is correct. + $timestamp = 9999999999; + $result = true; + foreach ($posts as $post) { + if ($timestamp < $post->timestart) { + $result = false; + break; + } + $timestamp = $post->timestart; + } + + $this->assertTrue($result); + $this->assertEquals(4 , count($posts)); + } + + /** + * Test, if the post events are processed correctly if the moodleoverflow module is not installed. + * @return void + * @throws dml_exception + */ + public function test_disabled_moodleoverflow(): void { + global $DB; + + // Test case: disable moodleoverflow. + $DB->delete_records('modules', ['name' => 'moodleoverflow']); + + // Get events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + $this->assertEquals(0, count($posts)); + } + + /** + * Test, if the post events are processed correctly if the course disappears. + * @return void + * @throws dml_exception + */ + public function test_course_deleted(): void { + global $DB; + + // Delete the course from the database. + $DB->delete_records('course', ['id' => $this->testdata->course1->id]); + + // Get events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // There should be no posts from the first course. + $result = true; + foreach ($posts as $post) { + if ($post->courseid == $this->testdata->course1->id) { + $result = false; + } + } + $this->assertTrue($result); + $this->assertEquals(2, count($posts)); + } + + /** + * Test, if the users see only posts of courses they're enrolled in. + * @return void + * @throws coding_exception + */ + public function test_user_views(): void { + // Test case 1: teacher view. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->teacher->id, true))); + $this->assertEquals(4, count($posts)); + + // Test case 2: first student views. + $this->setUser($this->testdata->student1); + $posts = $this->moodleoverflowevents->get_events(); + $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student1->id, true))); + $this->assertEquals(2, count($posts)); + + // Test case 3: second students view. + $this->setUser($this->testdata->student2); + $posts = $this->moodleoverflowevents->get_events(); + $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student2->id, true))); + $this->assertEquals(2, count($posts)); + } + + /** + * Test, if data in moodleoverflow posts is processed correctly when the moodleoverflow is anonymous. + * @return void + */ + public function test_anonymous(): void { + // Set the first moodleoverflow to partially anonymous and the second to fully anonymous. + $this->make_anonymous($this->testdata->moodleoverflow1, 1); + $this->make_anonymous($this->testdata->moodleoverflow2, 2); + + // Get the current post events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // Posts of the first moodleoverflow. + $firstteacherpost = null; + $firststudentpost = null; + + // Posts of the second moodleoverflow. + $secondteacherpost = null; + $secondstudentpost = null; + + // Iterate through all posts and save the posts from teacher and student. + foreach ($posts as $post) { + if ($post->instanceid == $this->testdata->moodleoverflow1->id) { + if ($post->postuserid == $this->testdata->teacher->id) { + $firstteacherpost = $post; + } else { + $firststudentpost = $post; + } + } else { + if ($post->postuserid == $this->testdata->teacher->id) { + $secondteacherpost = $post; + } else { + $secondstudentpost = $post; + } + } + } + + // Test case 1: The teacherpost and studentpost are in partial anonymous mode (only questions are anonymous). + $this->assertEquals(true, $firstteacherpost->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS); + $this->assertEquals(true, $firststudentpost->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS); + + // Test case 2: The teacherpost and studentpost are in full anonymous mode (all posts are anonymous). + $this->assertEquals(true, $secondteacherpost->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS); + $this->assertEquals(true, $secondstudentpost->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS); + + } + + /** + * Test, if posts are not shown in townsquare when a moodleoverflow is hidden. + * @return void + * @throws coding_exception + * @throws dml_exception + */ + public function test_hidden(): void { + global $DB; + // Hide the first moodleoverflow. + $cmid = get_coursemodule_from_instance('moodleoverflow', $this->testdata->moodleoverflow1->id)->id; + $DB->update_record('course_modules', ['id' => $cmid, 'visible' => 0]); + + // Get the current post events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // Check if the first moodleoverflow post is not in the post events. + $result = true; + foreach ($posts as $post) { + if ($post->instanceid == $this->testdata->moodleoverflow1->id) { + $result = false; + } + } + $this->assertTrue($result); + } + + // Helper functions. + + private function helper_course_set_uo(): void { + $datagenerator = $this->getDataGenerator(); + // Create two new courses. + $this->testdata->course1 = $datagenerator->create_course(); + $this->testdata->course2 = $datagenerator->create_course(); + // Create a teacher and enroll the teacher in both courses. + $this->testdata->teacher = $datagenerator->create_user(); + $datagenerator->enrol_user($this->testdata->teacher->id, $this->testdata->course1->id, 'teacher'); + $datagenerator->enrol_user($this->testdata->teacher->id, $this->testdata->course2->id, 'teacher'); + + // Create two students. + $this->testdata->student1 = $datagenerator->create_user(); + $this->getDataGenerator()->enrol_user($this->testdata->student1->id, $this->testdata->course1->id, 'student'); + $this->testdata->student2 = $datagenerator->create_user(); + $this->getDataGenerator()->enrol_user($this->testdata->student2->id, $this->testdata->course2->id, 'student'); + + $course1location = ['course' => $this->testdata->course1->id]; + $course2location = ['course' => $this->testdata->course2->id]; + $datagenerator = $this->getDataGenerator(); + $modoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); + + $this->testdata->moodleoverflow1 = $datagenerator->create_module('moodleoverflow', $course1location); + $this->testdata->mdiscussion1 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow1, + $this->testdata->teacher); + $this->testdata->answer1 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion1[1], + $this->testdata->student1); + + $this->testdata->moodleoverflow2 = $datagenerator->create_module('moodleoverflow', $course2location); + $this->testdata->mdiscussion2 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow2, + $this->testdata->teacher); + $this->testdata->answer2 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion2[1], + $this->testdata->student2); + } + + /** + * Helper function to check if all posts are in the courses of the user. + * @param array $posts + * @param array $enrolledcourses + * @return bool + */ + private function check_postcourses($posts, $enrolledcourses): bool { + foreach ($posts as $post) { + $postcourseid = $post->courseid; + + $enrolledcoursesid = []; + foreach ($enrolledcourses as $enrolledcourse) { + $enrolledcoursesid[] = $enrolledcourse->id; + } + + if (!in_array($postcourseid, $enrolledcoursesid)) { + return false; + } + } + return true; + } + + /** + * Makes the existing moodleoverflow anonymous. + * There are 2 types of anonymous moodleoverflows: + * anonymous = 1, the topic starter is anonymous + * anonymous = 2, all users are anonymous + * + * @param object $moodleoverflow The moodleoverflow that should be made anonymous. + * @param int $anonymoussetting The type of anonymous moodleoverflow. + * @throws Exception + */ + private function make_anonymous($moodleoverflow, $anonymoussetting): void { + global $DB; + if ($anonymoussetting == 1 || $anonymoussetting == 2) { + $moodleoverflow->anonymous = $anonymoussetting; + $DB->update_record('moodleoverflow', $moodleoverflow); + } else { + throw new Exception('invalid parameter, anonymoussetting should be 1 or 2'); + } + } +} \ No newline at end of file diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 0000000..0de6ece --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + local/townsquaresupport/townsquareexpansion/moodleoverflow/tests + + + + From 815af8a2e87b7177b1074e8c5f923ccedbb2dae9 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 00:35:00 +0200 Subject: [PATCH 02/11] fix coding style --- tests/events_test.php | 627 +++++++++++++++++++++--------------------- 1 file changed, 314 insertions(+), 313 deletions(-) diff --git a/tests/events_test.php b/tests/events_test.php index 1c8ecb5..1b7cd7f 100644 --- a/tests/events_test.php +++ b/tests/events_test.php @@ -1,313 +1,314 @@ -. - - -/** - * Unit tests for the moodleoverflow townsquareexpansion - * - * @package townsquareexpansion_moodleoverflow - * @copyright 2025 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace townsquareexpansion_moodleoverflow; - -use coding_exception; -use dml_exception; -use Exception; -use stdClass; - -/** - * PHPUnit tests for testing the process of event collection. - * - * @package townsquareexpansion_moodleoverflow - * @copyright 2025 Tamaro Walter - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * - * @covers \townsquareexpansion_moodleoverflow\moodleoverflow::get_events - */ -final class events_test extends \advanced_testcase { - - /** @var stdClass */ - private stdClass $testdata; - private moodleoverflow $moodleoverflowevents; - - /** - * @throws dml_exception - */ - public function setUp(): void { - parent::setUp(); - global $DB; - $this->testdata = new stdClass(); - $this->moodleoverflowevents = new moodleoverflow(); - $this->resetAfterTest(); - - // Check if moodleoverflow is available: - if (!$DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { - $this->markTestSkipped('Moodleoverflow is not installed or not activated.'); - } - $this->helper_course_set_uo(); - } - - public function tearDown(): void { - parent::tearDown(); - } - - /** - * Test, if post events are sorted correctly. - * Post should be sorted by the time they were created in descending order (newest post first). - * @return void - */ - public function test_sortorder(): void { - $this->setUser($this->testdata->teacher); - $posts = $this->moodleoverflowevents->get_events(); - - // Iterate through all posts and check if the sort order is correct. - $timestamp = 9999999999; - $result = true; - foreach ($posts as $post) { - if ($timestamp < $post->timestart) { - $result = false; - break; - } - $timestamp = $post->timestart; - } - - $this->assertTrue($result); - $this->assertEquals(4 , count($posts)); - } - - /** - * Test, if the post events are processed correctly if the moodleoverflow module is not installed. - * @return void - * @throws dml_exception - */ - public function test_disabled_moodleoverflow(): void { - global $DB; - - // Test case: disable moodleoverflow. - $DB->delete_records('modules', ['name' => 'moodleoverflow']); - - // Get events from the teacher. - $this->setUser($this->testdata->teacher); - $posts = $this->moodleoverflowevents->get_events(); - - $this->assertEquals(0, count($posts)); - } - - /** - * Test, if the post events are processed correctly if the course disappears. - * @return void - * @throws dml_exception - */ - public function test_course_deleted(): void { - global $DB; - - // Delete the course from the database. - $DB->delete_records('course', ['id' => $this->testdata->course1->id]); - - // Get events from the teacher. - $this->setUser($this->testdata->teacher); - $posts = $this->moodleoverflowevents->get_events(); - - // There should be no posts from the first course. - $result = true; - foreach ($posts as $post) { - if ($post->courseid == $this->testdata->course1->id) { - $result = false; - } - } - $this->assertTrue($result); - $this->assertEquals(2, count($posts)); - } - - /** - * Test, if the users see only posts of courses they're enrolled in. - * @return void - * @throws coding_exception - */ - public function test_user_views(): void { - // Test case 1: teacher view. - $this->setUser($this->testdata->teacher); - $posts = $this->moodleoverflowevents->get_events(); - $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->teacher->id, true))); - $this->assertEquals(4, count($posts)); - - // Test case 2: first student views. - $this->setUser($this->testdata->student1); - $posts = $this->moodleoverflowevents->get_events(); - $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student1->id, true))); - $this->assertEquals(2, count($posts)); - - // Test case 3: second students view. - $this->setUser($this->testdata->student2); - $posts = $this->moodleoverflowevents->get_events(); - $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student2->id, true))); - $this->assertEquals(2, count($posts)); - } - - /** - * Test, if data in moodleoverflow posts is processed correctly when the moodleoverflow is anonymous. - * @return void - */ - public function test_anonymous(): void { - // Set the first moodleoverflow to partially anonymous and the second to fully anonymous. - $this->make_anonymous($this->testdata->moodleoverflow1, 1); - $this->make_anonymous($this->testdata->moodleoverflow2, 2); - - // Get the current post events from the teacher. - $this->setUser($this->testdata->teacher); - $posts = $this->moodleoverflowevents->get_events(); - - // Posts of the first moodleoverflow. - $firstteacherpost = null; - $firststudentpost = null; - - // Posts of the second moodleoverflow. - $secondteacherpost = null; - $secondstudentpost = null; - - // Iterate through all posts and save the posts from teacher and student. - foreach ($posts as $post) { - if ($post->instanceid == $this->testdata->moodleoverflow1->id) { - if ($post->postuserid == $this->testdata->teacher->id) { - $firstteacherpost = $post; - } else { - $firststudentpost = $post; - } - } else { - if ($post->postuserid == $this->testdata->teacher->id) { - $secondteacherpost = $post; - } else { - $secondstudentpost = $post; - } - } - } - - // Test case 1: The teacherpost and studentpost are in partial anonymous mode (only questions are anonymous). - $this->assertEquals(true, $firstteacherpost->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS); - $this->assertEquals(true, $firststudentpost->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS); - - // Test case 2: The teacherpost and studentpost are in full anonymous mode (all posts are anonymous). - $this->assertEquals(true, $secondteacherpost->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS); - $this->assertEquals(true, $secondstudentpost->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS); - - } - - /** - * Test, if posts are not shown in townsquare when a moodleoverflow is hidden. - * @return void - * @throws coding_exception - * @throws dml_exception - */ - public function test_hidden(): void { - global $DB; - // Hide the first moodleoverflow. - $cmid = get_coursemodule_from_instance('moodleoverflow', $this->testdata->moodleoverflow1->id)->id; - $DB->update_record('course_modules', ['id' => $cmid, 'visible' => 0]); - - // Get the current post events from the teacher. - $this->setUser($this->testdata->teacher); - $posts = $this->moodleoverflowevents->get_events(); - - // Check if the first moodleoverflow post is not in the post events. - $result = true; - foreach ($posts as $post) { - if ($post->instanceid == $this->testdata->moodleoverflow1->id) { - $result = false; - } - } - $this->assertTrue($result); - } - - // Helper functions. - - private function helper_course_set_uo(): void { - $datagenerator = $this->getDataGenerator(); - // Create two new courses. - $this->testdata->course1 = $datagenerator->create_course(); - $this->testdata->course2 = $datagenerator->create_course(); - // Create a teacher and enroll the teacher in both courses. - $this->testdata->teacher = $datagenerator->create_user(); - $datagenerator->enrol_user($this->testdata->teacher->id, $this->testdata->course1->id, 'teacher'); - $datagenerator->enrol_user($this->testdata->teacher->id, $this->testdata->course2->id, 'teacher'); - - // Create two students. - $this->testdata->student1 = $datagenerator->create_user(); - $this->getDataGenerator()->enrol_user($this->testdata->student1->id, $this->testdata->course1->id, 'student'); - $this->testdata->student2 = $datagenerator->create_user(); - $this->getDataGenerator()->enrol_user($this->testdata->student2->id, $this->testdata->course2->id, 'student'); - - $course1location = ['course' => $this->testdata->course1->id]; - $course2location = ['course' => $this->testdata->course2->id]; - $datagenerator = $this->getDataGenerator(); - $modoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); - - $this->testdata->moodleoverflow1 = $datagenerator->create_module('moodleoverflow', $course1location); - $this->testdata->mdiscussion1 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow1, - $this->testdata->teacher); - $this->testdata->answer1 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion1[1], - $this->testdata->student1); - - $this->testdata->moodleoverflow2 = $datagenerator->create_module('moodleoverflow', $course2location); - $this->testdata->mdiscussion2 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow2, - $this->testdata->teacher); - $this->testdata->answer2 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion2[1], - $this->testdata->student2); - } - - /** - * Helper function to check if all posts are in the courses of the user. - * @param array $posts - * @param array $enrolledcourses - * @return bool - */ - private function check_postcourses($posts, $enrolledcourses): bool { - foreach ($posts as $post) { - $postcourseid = $post->courseid; - - $enrolledcoursesid = []; - foreach ($enrolledcourses as $enrolledcourse) { - $enrolledcoursesid[] = $enrolledcourse->id; - } - - if (!in_array($postcourseid, $enrolledcoursesid)) { - return false; - } - } - return true; - } - - /** - * Makes the existing moodleoverflow anonymous. - * There are 2 types of anonymous moodleoverflows: - * anonymous = 1, the topic starter is anonymous - * anonymous = 2, all users are anonymous - * - * @param object $moodleoverflow The moodleoverflow that should be made anonymous. - * @param int $anonymoussetting The type of anonymous moodleoverflow. - * @throws Exception - */ - private function make_anonymous($moodleoverflow, $anonymoussetting): void { - global $DB; - if ($anonymoussetting == 1 || $anonymoussetting == 2) { - $moodleoverflow->anonymous = $anonymoussetting; - $DB->update_record('moodleoverflow', $moodleoverflow); - } else { - throw new Exception('invalid parameter, anonymoussetting should be 1 or 2'); - } - } -} \ No newline at end of file +. + +/** + * Unit tests for the moodleoverflow townsquareexpansion + * + * @package townsquareexpansion_moodleoverflow + * @copyright 2025 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace townsquareexpansion_moodleoverflow; + +use coding_exception; +use dml_exception; +use Exception; +use stdClass; + +/** + * PHPUnit tests for testing the process of event collection. + * + * @package townsquareexpansion_moodleoverflow + * @copyright 2025 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @covers \townsquareexpansion_moodleoverflow\moodleoverflow::get_events + */ +final class events_test extends \advanced_testcase { + + /** @var stdClass data for testing*/ + private stdClass $testdata; + + /** @var moodleoverflow Class for moodleoverflow event collection */ + private moodleoverflow $moodleoverflowevents; + + /** + * Setup the test environment. + * @throws dml_exception + */ + public function setUp(): void { + parent::setUp(); + global $DB; + $this->testdata = new stdClass(); + $this->moodleoverflowevents = new moodleoverflow(); + $this->resetAfterTest(); + + // Check if moodleoverflow is available. + if (!$DB->get_record('modules', ['name' => 'moodleoverflow', 'visible' => 1])) { + $this->markTestSkipped('Moodleoverflow is not installed or not activated.'); + } + $this->helper_course_set_up(); + } + + /** + * Test, if post events are sorted correctly. + * Post should be sorted by the time they were created in descending order (newest post first). + * @return void + */ + public function test_sortorder(): void { + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // Iterate through all posts and check if the sort order is correct. + $timestamp = 9999999999; + $result = true; + foreach ($posts as $post) { + if ($timestamp < $post->timestart) { + $result = false; + break; + } + $timestamp = $post->timestart; + } + + $this->assertTrue($result); + $this->assertEquals(4 , count($posts)); + } + + /** + * Test, if the post events are processed correctly if the moodleoverflow module is not installed. + * @return void + * @throws dml_exception + */ + public function test_disabled_moodleoverflow(): void { + global $DB; + + // Test case: disable moodleoverflow. + $DB->delete_records('modules', ['name' => 'moodleoverflow']); + + // Get events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + $this->assertEquals(0, count($posts)); + } + + /** + * Test, if the post events are processed correctly if the course disappears. + * @return void + * @throws dml_exception + */ + public function test_course_deleted(): void { + global $DB; + + // Delete the course from the database. + $DB->delete_records('course', ['id' => $this->testdata->course1->id]); + + // Get events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // There should be no posts from the first course. + $result = true; + foreach ($posts as $post) { + if ($post->courseid == $this->testdata->course1->id) { + $result = false; + } + } + $this->assertTrue($result); + $this->assertEquals(2, count($posts)); + } + + /** + * Test, if the users see only posts of courses they're enrolled in. + * @return void + * @throws coding_exception + */ + public function test_user_views(): void { + // Test case 1: teacher view. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->teacher->id, true))); + $this->assertEquals(4, count($posts)); + + // Test case 2: first student views. + $this->setUser($this->testdata->student1); + $posts = $this->moodleoverflowevents->get_events(); + $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student1->id, true))); + $this->assertEquals(2, count($posts)); + + // Test case 3: second students view. + $this->setUser($this->testdata->student2); + $posts = $this->moodleoverflowevents->get_events(); + $this->assertTrue($this->check_postcourses($posts, enrol_get_all_users_courses($this->testdata->student2->id, true))); + $this->assertEquals(2, count($posts)); + } + + /** + * Test, if data in moodleoverflow posts is processed correctly when the moodleoverflow is anonymous. + * @return void + */ + public function test_anonymous(): void { + // Set the first moodleoverflow to partially anonymous and the second to fully anonymous. + $this->make_anonymous($this->testdata->moodleoverflow1, 1); + $this->make_anonymous($this->testdata->moodleoverflow2, 2); + + // Get the current post events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // Posts of the first moodleoverflow. + $firstteacherpost = null; + $firststudentpost = null; + + // Posts of the second moodleoverflow. + $secondteacherpost = null; + $secondstudentpost = null; + + // Iterate through all posts and save the posts from teacher and student. + foreach ($posts as $post) { + if ($post->instanceid == $this->testdata->moodleoverflow1->id) { + if ($post->postuserid == $this->testdata->teacher->id) { + $firstteacherpost = $post; + } else { + $firststudentpost = $post; + } + } else { + if ($post->postuserid == $this->testdata->teacher->id) { + $secondteacherpost = $post; + } else { + $secondstudentpost = $post; + } + } + } + + // Test case 1: The teacherpost and studentpost are in partial anonymous mode (only questions are anonymous). + $this->assertEquals(true, $firstteacherpost->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS); + $this->assertEquals(true, $firststudentpost->anonymoussetting == \mod_moodleoverflow\anonymous::QUESTION_ANONYMOUS); + + // Test case 2: The teacherpost and studentpost are in full anonymous mode (all posts are anonymous). + $this->assertEquals(true, $secondteacherpost->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS); + $this->assertEquals(true, $secondstudentpost->anonymoussetting == \mod_moodleoverflow\anonymous::EVERYTHING_ANONYMOUS); + + } + + /** + * Test, if posts are not shown in townsquare when a moodleoverflow is hidden. + * @return void + * @throws coding_exception + * @throws dml_exception + */ + public function test_hidden(): void { + global $DB; + // Hide the first moodleoverflow. + $cmid = get_coursemodule_from_instance('moodleoverflow', $this->testdata->moodleoverflow1->id)->id; + $DB->update_record('course_modules', ['id' => $cmid, 'visible' => 0]); + + // Get the current post events from the teacher. + $this->setUser($this->testdata->teacher); + $posts = $this->moodleoverflowevents->get_events(); + + // Check if the first moodleoverflow post is not in the post events. + $result = true; + foreach ($posts as $post) { + if ($post->instanceid == $this->testdata->moodleoverflow1->id) { + $result = false; + } + } + $this->assertTrue($result); + } + + // Helper functions. + + /** + * Helper function to create courses and moodleoverflows. + */ + private function helper_course_set_up(): void { + $datagenerator = $this->getDataGenerator(); + // Create two new courses. + $this->testdata->course1 = $datagenerator->create_course(); + $this->testdata->course2 = $datagenerator->create_course(); + // Create a teacher and enroll the teacher in both courses. + $this->testdata->teacher = $datagenerator->create_user(); + $datagenerator->enrol_user($this->testdata->teacher->id, $this->testdata->course1->id, 'teacher'); + $datagenerator->enrol_user($this->testdata->teacher->id, $this->testdata->course2->id, 'teacher'); + + // Create two students. + $this->testdata->student1 = $datagenerator->create_user(); + $this->getDataGenerator()->enrol_user($this->testdata->student1->id, $this->testdata->course1->id, 'student'); + $this->testdata->student2 = $datagenerator->create_user(); + $this->getDataGenerator()->enrol_user($this->testdata->student2->id, $this->testdata->course2->id, 'student'); + + $course1location = ['course' => $this->testdata->course1->id]; + $course2location = ['course' => $this->testdata->course2->id]; + $datagenerator = $this->getDataGenerator(); + $modoverflowgenerator = $datagenerator->get_plugin_generator('mod_moodleoverflow'); + + $this->testdata->moodleoverflow1 = $datagenerator->create_module('moodleoverflow', $course1location); + $this->testdata->mdiscussion1 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow1, + $this->testdata->teacher); + $this->testdata->answer1 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion1[1], + $this->testdata->student1); + + $this->testdata->moodleoverflow2 = $datagenerator->create_module('moodleoverflow', $course2location); + $this->testdata->mdiscussion2 = $modoverflowgenerator->post_to_forum($this->testdata->moodleoverflow2, + $this->testdata->teacher); + $this->testdata->answer2 = $modoverflowgenerator->reply_to_post($this->testdata->mdiscussion2[1], + $this->testdata->student2); + } + + /** + * Helper function to check if all posts are in the courses of the user. + * @param array $posts + * @param array $enrolledcourses + * @return bool + */ + private function check_postcourses($posts, $enrolledcourses): bool { + foreach ($posts as $post) { + $postcourseid = $post->courseid; + + $enrolledcoursesid = []; + foreach ($enrolledcourses as $enrolledcourse) { + $enrolledcoursesid[] = $enrolledcourse->id; + } + + if (!in_array($postcourseid, $enrolledcoursesid)) { + return false; + } + } + return true; + } + + /** + * Makes the existing moodleoverflow anonymous. + * There are 2 types of anonymous moodleoverflows: + * anonymous = 1, the topic starter is anonymous + * anonymous = 2, all users are anonymous + * + * @param object $moodleoverflow The moodleoverflow that should be made anonymous. + * @param int $anonymoussetting The type of anonymous moodleoverflow. + * @throws Exception + */ + private function make_anonymous($moodleoverflow, $anonymoussetting): void { + global $DB; + if ($anonymoussetting == 1 || $anonymoussetting == 2) { + $moodleoverflow->anonymous = $anonymoussetting; + $DB->update_record('moodleoverflow', $moodleoverflow); + } else { + throw new Exception('invalid parameter, anonymoussetting should be 1 or 2'); + } + } +} From c6d6042bb6363c390b52128740b670ea99d8f4a5 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 10:54:36 +0200 Subject: [PATCH 03/11] wip: try to fix require once access --- classes/moodleoverflow.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/classes/moodleoverflow.php b/classes/moodleoverflow.php index c420973..6f1f5b4 100644 --- a/classes/moodleoverflow.php +++ b/classes/moodleoverflow.php @@ -29,8 +29,9 @@ use mod_moodleoverflow\anonymous; use moodle_url; -global $CFG; -require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); +//global $CFG; +//require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); +require_once(__DIR__.'/../../../../../blocks/townsquare/lib.php'); /** * Class that implements the townsquaresupportinterface with the function to get the events from the plugin. From 645cf10e54b2aeb791d21f266de1c45b26a9441d Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 10:57:10 +0200 Subject: [PATCH 04/11] wip: coding style --- classes/moodleoverflow.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/classes/moodleoverflow.php b/classes/moodleoverflow.php index 6f1f5b4..118484c 100644 --- a/classes/moodleoverflow.php +++ b/classes/moodleoverflow.php @@ -29,8 +29,6 @@ use mod_moodleoverflow\anonymous; use moodle_url; -//global $CFG; -//require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); require_once(__DIR__.'/../../../../../blocks/townsquare/lib.php'); /** From ee1b6bd75bd8f545c2d6aa2b1b3548a1a7838308 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 11:36:46 +0200 Subject: [PATCH 05/11] wip: debug moodle-ci --- .github/workflows/moodle-ci.yml | 9 +++++++++ classes/moodleoverflow.php | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 7b7e2d6..142d606 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -72,6 +72,15 @@ jobs: DB: ${{ matrix.database }} MOODLE_BRANCH: ${{ matrix.moodle-branch }} + - name: Debug plugin locations + run: | + echo "Moodle dirroot:" + find ci/moodle -maxdepth 2 + echo "Blocks:" + find ci/moodle/blocks -maxdepth 2 + echo "Local:" + find ci/moodle/local -maxdepth 3 + - name: PHP Lint if: ${{ always() }} run: moodle-plugin-ci phplint diff --git a/classes/moodleoverflow.php b/classes/moodleoverflow.php index 118484c..a8a9c7e 100644 --- a/classes/moodleoverflow.php +++ b/classes/moodleoverflow.php @@ -25,12 +25,12 @@ defined('MOODLE_INTERNAL') || die; +global $CFG; +require_once($CFG->dirroot . '/blocks/townsquare/lib.php'); + use local_townsquaresupport\townsquaresupportinterface; use mod_moodleoverflow\anonymous; use moodle_url; - -require_once(__DIR__.'/../../../../../blocks/townsquare/lib.php'); - /** * Class that implements the townsquaresupportinterface with the function to get the events from the plugin. * From 4b9e74421377a6eb651a8793ab97d7a480d34c87 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 11:39:34 +0200 Subject: [PATCH 06/11] wip: debug moodle-ci --- .github/workflows/moodle-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 142d606..969e44d 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -75,11 +75,11 @@ jobs: - name: Debug plugin locations run: | echo "Moodle dirroot:" - find ci/moodle -maxdepth 2 + find moodle-plugin-ci -maxdepth 2 echo "Blocks:" - find ci/moodle/blocks -maxdepth 2 + find moodle-plugin-ci/blocks -maxdepth 2 echo "Local:" - find ci/moodle/local -maxdepth 3 + find moodle-plugin-ci/local -maxdepth 3 - name: PHP Lint if: ${{ always() }} From 37b8ab3767866d038dfac2c795fab27081fc63f0 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 11:45:07 +0200 Subject: [PATCH 07/11] wip: debug ci --- .github/workflows/moodle-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 969e44d..ade9278 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -75,11 +75,11 @@ jobs: - name: Debug plugin locations run: | echo "Moodle dirroot:" - find moodle-plugin-ci -maxdepth 2 + find /home/runner/work -maxdepth 2 echo "Blocks:" - find moodle-plugin-ci/blocks -maxdepth 2 + find /home/runner/work/blocks -maxdepth 2 echo "Local:" - find moodle-plugin-ci/local -maxdepth 3 + find /home/runner/work/local -maxdepth 3 - name: PHP Lint if: ${{ always() }} From 7a2090b3d782bf13fe35aead8a8a2f341c5f8c26 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Mon, 7 Apr 2025 11:51:32 +0200 Subject: [PATCH 08/11] wip: debug ci --- .github/workflows/moodle-ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index ade9278..e5c2f32 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -75,11 +75,7 @@ jobs: - name: Debug plugin locations run: | echo "Moodle dirroot:" - find /home/runner/work -maxdepth 2 - echo "Blocks:" - find /home/runner/work/blocks -maxdepth 2 - echo "Local:" - find /home/runner/work/local -maxdepth 3 + find /home/runner/work -maxdepth 5 - name: PHP Lint if: ${{ always() }} From 2dad4790b7a0a7039a04153e18ea1391d2b83fc8 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Sat, 12 Apr 2025 22:19:13 +0200 Subject: [PATCH 09/11] WIP: fix workflow --- .github/workflows/moodle-ci.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index e5c2f32..4a048b3 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -56,6 +56,13 @@ jobs: sudo locale-gen en_AU.UTF-8 echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + - name: Install moodle-plugin-ci + run: | + moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 --no-init + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + - name: Install mod plugin run: moodle-plugin-ci add-plugin learnweb/moodle-mod_moodleoverflow @@ -65,18 +72,6 @@ jobs: - name: Install local plugin run: moodle-plugin-ci add-plugin learnweb/moodle-local_townsquaresupport - - name: Install moodle-plugin-ci - run: | - moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 --no-init - env: - DB: ${{ matrix.database }} - MOODLE_BRANCH: ${{ matrix.moodle-branch }} - - - name: Debug plugin locations - run: | - echo "Moodle dirroot:" - find /home/runner/work -maxdepth 5 - - name: PHP Lint if: ${{ always() }} run: moodle-plugin-ci phplint From a819a67d7f8895a10026b5a839c0c09a0f7939f4 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Sat, 12 Apr 2025 22:29:28 +0200 Subject: [PATCH 10/11] WIP: fix workflows --- .github/workflows/moodle-ci.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 4a048b3..6ed259d 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -58,20 +58,14 @@ jobs: - name: Install moodle-plugin-ci run: | + moodle-plugin-ci add-plugin learnweb/moodle-mod_moodleoverflow + moodle-plugin-ci add-plugin learnweb/moodle-block_townsquare + moodle-plugin-ci add-plugin learnweb/moodle-local_townsquaresupport moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 --no-init env: DB: ${{ matrix.database }} MOODLE_BRANCH: ${{ matrix.moodle-branch }} - - name: Install mod plugin - run: moodle-plugin-ci add-plugin learnweb/moodle-mod_moodleoverflow - - - name: Install block plugin - run: moodle-plugin-ci add-plugin learnweb/moodle-block_townsquare - - - name: Install local plugin - run: moodle-plugin-ci add-plugin learnweb/moodle-local_townsquaresupport - - name: PHP Lint if: ${{ always() }} run: moodle-plugin-ci phplint From 1d6f1d7f1f8359e4c4e7be3329f9552dd62f09b2 Mon Sep 17 00:00:00 2001 From: Tamaro Walter Date: Sat, 12 Apr 2025 22:45:48 +0200 Subject: [PATCH 11/11] workflow fixed --- .github/workflows/moodle-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 6ed259d..3ac5763 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -184,6 +184,8 @@ jobs: - name: Install moodle-plugin-ci run: | + moodle-plugin-ci add-plugin learnweb/moodle-mod_moodleoverflow + moodle-plugin-ci add-plugin learnweb/moodle-block_townsquare moodle-plugin-ci add-plugin learnweb/moodle-local_townsquaresupport moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 env: