first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,43 @@
<?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 mod_folder\backup;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . "/phpunit/classes/restore_date_testcase.php");
/**
* Restore date tests.
*
* @package mod_folder
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_date_test extends \restore_date_testcase {
public function test_restore_dates(): void {
global $DB;
list($course, $folder) = $this->create_course_and_module('folder');
// Do backup and restore.
$newcourseid = $this->backup_and_restore($course);
$newfolder = $DB->get_record('folder', ['course' => $newcourseid]);
$this->assertFieldsNotRolledForward($folder, $newfolder, ['timemodified']);
}
}
@@ -0,0 +1,72 @@
@mod @mod_folder @core_completion
Feature: View activity completion information in the folder activity
In order to have visibility of folder completion requirements
As a student
I need to be able to view my folder completion progress
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Vinnie | Student1 | student1@example.com |
| teacher1 | Darrell | Teacher1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | enablecompletion | showcompletionconditions |
| Course 1 | C1 | 1 | 1 |
| Course 2 | C2 | 1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
| student1 | C2 | student |
Scenario: View automatic completion items
Given the following "activity" exists:
| activity | folder |
| course | C1 |
| idnumber | mh1 |
| name | Music history |
| section | 1 |
| completion | 2 |
| completionview | 1 |
# Teacher view.
And I am on the "Music history" "folder activity" page logged in as teacher1
And "Music history" should have the "View" completion condition
And I log out
# Student view.
When I am on the "Music history" "folder activity" page logged in as student1
Then the "View" completion condition of "Music history" is displayed as "done"
@javascript
Scenario: Use manual completion
Given the following "activity" exists:
| activity | folder |
| course | C1 |
| idnumber | mh1 |
| name | Music history |
| section | 1 |
| completion | 1 |
And I am on the "Music history" "folder activity" page logged in as teacher1
# Teacher view.
And the manual completion button for "Music history" should be disabled
And I log out
# Student view.
When I am on the "Music history" "folder activity" page logged in as student1
Then the manual completion button of "Music history" is displayed as "Mark as done"
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
@javascript
Scenario: The manual completion button will be shown on the course page for Inline on a course page display mode
Given the following "activity" exists:
| activity | folder |
| course | C2 |
| idnumber | mh2 |
| name | Music history |
| section | 1 |
| completion | 1 |
| display | 1 |
When I am on the "Course 2" course page logged in as student1
Then the manual completion button for "Music history" should exist
And the manual completion button of "Music history" is displayed as "Mark as done"
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
@@ -0,0 +1,48 @@
@mod @mod_resource @_file_upload
Feature: Details of uploaded file in the resource can be changed
In order to change details of an uploaded file in a folder resource
As a teacher
I should be able to upload a file
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | t1@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "activities" exist:
| activity | course | name |
| folder | C1 | Folder1 |
@javascript
Scenario: Uploaded file details can be changed
Given I am on the "Folder1" "folder activity" page logged in as teacher1
And I click on "Edit" "button"
# Upload a file in folder resource
And I upload "lib/tests/fixtures/empty.txt" file to "Files" filemanager
And I press "Save changes"
And I click on "Edit" "button"
And I click on "empty.txt" "link"
# Initially, file details are set to default values
And the following fields match these values:
| Name | empty.txt |
| Author | Teacher 1 |
| licence | Licence not specified |
# Update the file details for testing
When I set the following fields to these values:
| Name | empty_file.txt |
| Author | Teacher 1 |
| licence | All rights reserved |
And I press "Update"
And I press "Save changes"
# Confirm that file details have been updated correctly
And I click on "Edit" "button"
And I click on "empty_file.txt" "link"
Then the following fields match these values:
| Name | empty_file.txt |
| Author | Teacher 1 |
| licence | All rights reserved |
@@ -0,0 +1,43 @@
@mod @mod_folder @block @block_recent_activity
Feature: Files added in folder activity are visible in the recent activity block
In order to view and download folder activity from recent activity block
As a teacher
I should be able to create folder activity with contents
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| recent_activity | Course | C1 | course-view-* | side-pre |
And the following "activities" exist:
| activity | course | name |
| folder | C1 | Folder 1 |
@_file_upload @javascript
Scenario: Files added in folder activity are visible in recent activity block
Given I am on the "Folder 1" "folder activity" page logged in as admin
And I click on "Edit" "button"
# Upload different file types in folder resource
And I upload "lib/tests/fixtures/empty.txt" file to "Files" filemanager
And I upload "lib/tests/fixtures/gd-logo.png" file to "Files" filemanager
And I press "Save changes"
# Confirm folder activity and files within the folder are visible in Recent activity block
When I am on the "Course 1" course page
Then I should see "Folder 1" in the "Recent activity" "block"
And I should see "empty.txt" in the "Recent activity" "block"
And I should see "gd-logo.png" in the "Recent activity" "block"
And I click on "Full report of recent activity..." "link"
# Confirm files within folder activity are visible in the full report
And "Folder 1" "link" should exist
And "empty.txt" "link" should exist
And "gd-logo.png" "link" should exist
And "//img[@alt='empty.txt']" "xpath_element" should exist
And "//img[contains(@src, 'preview=tinyicon')]" "xpath_element" should exist
# Confirm files are downloadable
And following "empty.txt" should download a file that:
| Has mimetype | text/plain |
| Contains text | empty file for testing purposes |
And following "gd-logo.png" should download a file that:
| Has mimetype | image/png |
+95
View File
@@ -0,0 +1,95 @@
<?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/>.
/**
* Events tests.
*
* @package mod_folder
* @category test
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_folder\event;
class events_test extends \advanced_testcase {
/**
* Tests set up.
*/
public function setUp(): void {
$this->resetAfterTest();
}
/**
* Test the folder updated event.
*
* There is no external API for updating a folder, so the unit test will simply create
* and trigger the event and ensure the legacy log data is returned as expected.
*/
public function test_folder_updated(): void {
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
$params = array(
'context' => \context_module::instance($folder->cmid),
'objectid' => $folder->id,
'courseid' => $course->id
);
$event = \mod_folder\event\folder_updated::create($params);
$event->add_record_snapshot('folder', $folder);
// Trigger and capturing the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_folder\event\folder_updated', $event);
$this->assertEquals(\context_module::instance($folder->cmid), $event->get_context());
$this->assertEquals($folder->id, $event->objectid);
}
/**
* Test the folder updated event.
*
* There is no external API for updating a folder, so the unit test will simply create
* and trigger the event and ensure the legacy log data is returned as expected.
*/
public function test_all_files_downloaded(): void {
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
$context = \context_module::instance($folder->cmid);
$cm = get_coursemodule_from_id('folder', $folder->cmid, $course->id, true, MUST_EXIST);
$sink = $this->redirectEvents();
folder_downloaded($folder, $course, $cm, $context);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_folder\event\all_files_downloaded', $event);
$this->assertEquals(\context_module::instance($folder->cmid), $event->get_context());
$this->assertEquals($folder->id, $event->objectid);
$expected = array($course->id, 'folder', 'edit', 'edit.php?id=' . $folder->cmid, $folder->id, $folder->cmid);
$this->assertEventContextNotUsed($event);
}
}
+233
View File
@@ -0,0 +1,233 @@
<?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 mod_folder;
use core_external\external_api;
use externallib_advanced_testcase;
use mod_folder_external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
/**
* External mod_folder functions unit tests
*
* @package mod_folder
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class externallib_test extends externallib_advanced_testcase {
/**
* Test view_folder
*/
public function test_view_folder(): void {
global $DB;
$this->resetAfterTest(true);
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
$context = \context_module::instance($folder->cmid);
$cm = get_coursemodule_from_instance('folder', $folder->id);
// Test invalid instance id.
try {
mod_folder_external::view_folder(0);
$this->fail('Exception expected due to invalid mod_folder instance id.');
} catch (\moodle_exception $e) {
$this->assertEquals('invalidrecord', $e->errorcode);
}
// Test not-enrolled user.
$user = self::getDataGenerator()->create_user();
$this->setUser($user);
try {
mod_folder_external::view_folder($folder->id);
$this->fail('Exception expected due to not enrolled user.');
} catch (\moodle_exception $e) {
$this->assertEquals('requireloginerror', $e->errorcode);
}
// Test user with full capabilities.
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$result = mod_folder_external::view_folder($folder->id);
$result = external_api::clean_returnvalue(mod_folder_external::view_folder_returns(), $result);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_folder\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$moodlefolder = new \moodle_url('/mod/folder/view.php', array('id' => $cm->id));
$this->assertEquals($moodlefolder, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Test user with no capabilities.
// We need a explicit prohibit since this capability is only defined in authenticated user and guest roles.
assign_capability('mod/folder:view', CAP_PROHIBIT, $studentrole->id, $context->id);
// Empty all the caches that may be affected by this change.
accesslib_clear_all_caches_for_unit_testing();
\course_modinfo::clear_instance_cache();
try {
mod_folder_external::view_folder($folder->id);
$this->fail('Exception expected due to missing capability.');
} catch (\moodle_exception $e) {
$this->assertEquals('requireloginerror', $e->errorcode);
}
}
/**
* Test test_mod_folder_get_folders_by_courses
*/
public function test_mod_folder_get_folders_by_courses(): void {
global $DB;
$this->resetAfterTest(true);
$course1 = self::getDataGenerator()->create_course();
$course2 = self::getDataGenerator()->create_course();
$student = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id);
self::setUser($student);
// First folder.
$record = new \stdClass();
$record->course = $course1->id;
$record->forcedownload = 1;
$folder1 = self::getDataGenerator()->create_module('folder', $record);
// Second folder.
$record = new \stdClass();
$record->course = $course2->id;
$record->forcedownload = 0;
$folder2 = self::getDataGenerator()->create_module('folder', $record);
// Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
$enrol = enrol_get_plugin('manual');
$enrolinstances = enrol_get_instances($course2->id, true);
foreach ($enrolinstances as $courseenrolinstance) {
if ($courseenrolinstance->enrol == "manual") {
$instance2 = $courseenrolinstance;
break;
}
}
$enrol->enrol_user($instance2, $student->id, $studentrole->id);
$returndescription = mod_folder_external::get_folders_by_courses_returns();
// Create what we expect to be returned when querying the two courses.
$expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'lang', 'revision',
'timemodified', 'display', 'showexpanded', 'showdownloadfolder', 'section', 'visible',
'forcedownload', 'groupmode', 'groupingid');
// Add expected coursemodule and data.
$folder1->coursemodule = $folder1->cmid;
$folder1->introformat = 1;
$folder1->section = 0;
$folder1->visible = true;
$folder1->groupmode = 0;
$folder1->groupingid = 0;
$folder1->introfiles = [];
$folder1->lang = '';
$folder2->coursemodule = $folder2->cmid;
$folder2->introformat = 1;
$folder2->section = 0;
$folder2->visible = true;
$folder2->groupmode = 0;
$folder2->groupingid = 0;
$folder2->introfiles = [];
$folder2->lang = '';
foreach ($expectedfields as $field) {
$expected1[$field] = $folder1->{$field};
$expected2[$field] = $folder2->{$field};
}
$expectedfolders = array($expected2, $expected1);
// Call the external function passing course ids.
$result = mod_folder_external::get_folders_by_courses(array($course2->id, $course1->id));
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedfolders, $result['folders']);
$this->assertCount(0, $result['warnings']);
// Call the external function without passing course id.
$result = mod_folder_external::get_folders_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedfolders, $result['folders']);
$this->assertCount(0, $result['warnings']);
// Add a file to the intro.
$fileintroname = "fileintro.txt";
$filerecordinline = array(
'contextid' => \context_module::instance($folder2->cmid)->id,
'component' => 'mod_folder',
'filearea' => 'intro',
'itemid' => 0,
'filepath' => '/',
'filename' => $fileintroname,
);
$fs = get_file_storage();
$timepost = time();
$fs->create_file_from_string($filerecordinline, 'image contents (not really)');
$result = mod_folder_external::get_folders_by_courses(array($course2->id, $course1->id));
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertCount(1, $result['folders'][0]['introfiles']);
$this->assertEquals($fileintroname, $result['folders'][0]['introfiles'][0]['filename']);
// Unenrol user from second course.
$enrol->unenrol_user($instance2, $student->id);
array_shift($expectedfolders);
// Call the external function without passing course id.
$result = mod_folder_external::get_folders_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedfolders, $result['folders']);
// Call for the second course we unenrolled the user from, expected warning.
$result = mod_folder_external::get_folders_by_courses(array($course2->id));
$this->assertCount(1, $result['warnings']);
$this->assertEquals('1', $result['warnings'][0]['warningcode']);
$this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
}
}
+49
View File
@@ -0,0 +1,49 @@
<?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/>.
/**
* mod_folder data generator.
*
* @package mod_folder
* @category test
* @copyright 2013 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* mod_folder data generator class.
*
* @package mod_folder
* @category test
* @copyright 2013 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_folder_generator extends testing_module_generator {
public function create_instance($record = null, array $options = null) {
// Add default values for folder.
$record = (array)$record + array('display' => 0);
if (!isset($record['showexpanded'])) {
$record['showexpanded'] = get_config('folder', 'showexpanded');
}
if (!isset($record['files'])) {
$record['files'] = file_get_unused_draft_itemid();
}
return parent::create_instance($record, (array)$options);
}
}
+61
View File
@@ -0,0 +1,61 @@
<?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 mod_folder;
/**
* Generator tests class for mod_folder.
*
* @package mod_folder
* @category test
* @copyright 2013 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class generator_test extends \advanced_testcase {
public function test_create_instance(): void {
global $DB, $USER;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
$this->assertFalse($DB->record_exists('folder', array('course' => $course->id)));
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course));
$records = $DB->get_records('folder', array('course' => $course->id), 'id');
$this->assertEquals(1, count($records));
$this->assertTrue(array_key_exists($folder->id, $records));
$params = array('course' => $course->id, 'name' => 'Another folder');
$folder = $this->getDataGenerator()->create_module('folder', $params);
$records = $DB->get_records('folder', array('course' => $course->id), 'id');
$this->assertEquals(2, count($records));
$this->assertEquals('Another folder', $records[$folder->id]->name);
// Examples of adding a folder with files (do not validate anything, just check for exceptions).
$params = array(
'course' => $course->id,
'files' => file_get_unused_draft_itemid()
);
$usercontext = \context_user::instance($USER->id);
$filerecord = array('component' => 'user', 'filearea' => 'draft',
'contextid' => $usercontext->id, 'itemid' => $params['files'],
'filename' => 'file1.txt', 'filepath' => '/');
$fs = get_file_storage();
$fs->create_file_from_string($filerecord, 'Test file contents');
$folder = $this->getDataGenerator()->create_module('folder', $params);
}
}
+403
View File
@@ -0,0 +1,403 @@
<?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/>.
/**
* Unit tests for mod_folder lib
*
* @package mod_folder
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
namespace mod_folder;
use context_user;
use context_module;
defined('MOODLE_INTERNAL') || die();
/**
* Unit tests for mod_folder lib
*
* @package mod_folder
* @category external
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.0
*/
class lib_test extends \advanced_testcase {
/**
* Setup.
*/
public function setUp(): void {
$this->resetAfterTest();
$this->setAdminUser();
}
/**
* Prepares things before this test case is initialised
* @return void
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/mod/folder/lib.php');
}
/**
* Test folder_view
* @return void
*/
public function test_folder_view(): void {
global $CFG;
$CFG->enablecompletion = 1;
// Setup test data.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1));
$context = \context_module::instance($folder->cmid);
$cm = get_coursemodule_from_instance('folder', $folder->id);
// Trigger and capture the event.
$sink = $this->redirectEvents();
folder_view($folder, $course, $cm, $context);
$events = $sink->get_events();
// 2 additional events thanks to completion.
$this->assertCount(3, $events);
$event = array_shift($events);
// Checking that the event contains the expected values.
$this->assertInstanceOf('\mod_folder\event\course_module_viewed', $event);
$this->assertEquals($context, $event->get_context());
$moodleurl = new \moodle_url('/mod/folder/view.php', array('id' => $cm->id));
$this->assertEquals($moodleurl, $event->get_url());
$this->assertEventContextNotUsed($event);
$this->assertNotEmpty($event->get_name());
// Check completion status.
$completion = new \completion_info($course);
$completiondata = $completion->get_data($cm);
$this->assertEquals(1, $completiondata->completionstate);
}
public function test_folder_core_calendar_provide_event_action(): void {
// Create the activity.
$course = $this->getDataGenerator()->create_course();
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $folder->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_folder_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('view'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_folder_core_calendar_provide_event_action_for_non_user(): void {
global $CFG;
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create the activity.
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $folder->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Now, log out.
$CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_folder_core_calendar_provide_event_action($event, $factory);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
public function test_folder_core_calendar_provide_event_action_in_hidden_section(): void {
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a student.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create the activity.
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $folder->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Set sections 0 as hidden.
set_section_visible($course->id, 0, 0);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_folder_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event is not shown at all.
$this->assertNull($actionevent);
}
public function test_folder_core_calendar_provide_event_action_for_user(): void {
// Create a course.
$course = $this->getDataGenerator()->create_course();
// Create a student.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create the activity.
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id));
// Create a calendar event.
$event = $this->create_action_event($course->id, $folder->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Now, log out.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_folder_core_calendar_provide_event_action($event, $factory, $student->id);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('view'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_folder_core_calendar_provide_event_action_already_completed(): void {
global $CFG;
$CFG->enablecompletion = 1;
// Create the activity.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Get some additional data.
$cm = get_coursemodule_from_instance('folder', $folder->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $folder->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event.
$actionevent = mod_folder_core_calendar_provide_event_action($event, $factory);
// Ensure result was null.
$this->assertNull($actionevent);
}
public function test_folder_core_calendar_provide_event_action_already_completed_for_user(): void {
global $CFG;
$CFG->enablecompletion = 1;
// Create a course.
$course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
// Create a student.
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create the activity.
$folder = $this->getDataGenerator()->create_module('folder', array('course' => $course->id),
array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
// Get some additional data.
$cm = get_coursemodule_from_instance('folder', $folder->id);
// Create a calendar event.
$event = $this->create_action_event($course->id, $folder->id,
\core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
// Mark the activity as completed for the student.
$completion = new \completion_info($course);
$completion->set_module_viewed($cm, $student->id);
// Now, log out.
$this->setUser();
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Decorate action event for the student.
$actionevent = mod_folder_core_calendar_provide_event_action($event, $factory, $student->id);
// Ensure result was null.
$this->assertNull($actionevent);
}
/**
* Creates an action event.
*
* @param int $courseid The course id.
* @param int $instanceid The instance id.
* @param string $eventtype The event type.
* @return bool|calendar_event
*/
private function create_action_event($courseid, $instanceid, $eventtype) {
$event = new \stdClass();
$event->name = 'Calendar event';
$event->modulename = 'folder';
$event->courseid = $courseid;
$event->instance = $instanceid;
$event->type = CALENDAR_EVENT_TYPE_ACTION;
$event->eventtype = $eventtype;
$event->timestart = time();
return \calendar_event::create($event);
}
/**
* Test Get recent mod activity method.
* @covers ::folder_get_recent_mod_activity
* @dataProvider folder_get_recent_mod_activity_provider
*
* @param int $forcedownload The forcedownload option.
* @param bool $hascapability if the user has the mod/folder:view capability
* @param int $count The expected recent activities entries.
*/
public function test_folder_get_recent_mod_activity(int $forcedownload, bool $hascapability, int $count): void {
global $USER, $DB;
$this->resetAfterTest();
$this->setAdminUser();
$course = $this->getDataGenerator()->create_course();
// Add files to draft area.
$filesitem = file_get_unused_draft_itemid();
$usercontext = context_user::instance($USER->id);
$filerecord = [
'component' => 'user',
'filearea' => 'draft',
'contextid' => $usercontext->id,
'itemid' => $filesitem,
'filename' => 'file1.txt', 'filepath' => '/',
];
$fs = get_file_storage();
$fs->create_file_from_string($filerecord, 'First test file contents');
// And a second file.
$filerecord['filename'] = 'file2.txt';
$fs->create_file_from_string($filerecord, 'Second test file contents');
// Create the activity.
$module = $this->getDataGenerator()->create_module(
'folder',
['course' => $course->id, 'forcedownload' => $forcedownload, 'files' => $filesitem]
);
// Get some additional data.
$cm = get_coursemodule_from_instance('folder', $module->id);
$context = context_module::instance($cm->id);
// Add user with the specific capability.
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id, 'editingteacher');
if (!$hascapability) {
// The recent activiy uses "folder:view" capability which is allowed by default.
$role = $DB->get_record('role', ['shortname' => 'editingteacher'], '*', MUST_EXIST);
assign_capability('mod/folder:view', CAP_PROHIBIT, $role->id, $context->id, true);
}
$this->setUser($user);
// Get the recent activity.
$index = 1;
$activities = [];
folder_get_recent_mod_activity($activities, $index, time() - HOURSECS, $course->id, $cm->id);
// Check recent activity.
$this->assertCount($count, $activities);
foreach ($activities as $index => $activity) {
$this->assertEquals('folder', $activity->type);
$content = $activity->content;
$this->assertEquals("file{$index}.txt", $content->filename);
$urlparams = $content->url->params();
if ($forcedownload) {
$this->assertEquals(1, $urlparams['forcedownload']);
} else {
$this->assertArrayNotHasKey('forcedownload', $urlparams);
}
}
}
/**
* Data provider for test_folder_get_recent_mod_activity().
*
* @return array
*/
public function folder_get_recent_mod_activity_provider(): array {
return [
'Teacher with force download' => [
'forcedownload' => 1,
'hascapability' => true,
'count' => 2,
],
'Teacher with no force download' => [
'forcedownload' => 0,
'hascapability' => true,
'count' => 2,
],
'Invalid user with force download' => [
'forcedownload' => 1,
'hascapability' => false,
'count' => 0,
],
'Invalid user with no force download' => [
'forcedownload' => 0,
'hascapability' => false,
'count' => 0,
],
];
}
}
+132
View File
@@ -0,0 +1,132 @@
<?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/>.
/**
* Folder search unit tests.
*
* @package mod_folder
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_folder\search;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
/**
* Provides the unit tests for forum search.
*
* @package mod_folder
* @category test
* @copyright 2016 Eric Merrill {@link http://www.merrilldigital.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class search_test extends \advanced_testcase {
/**
* @var string Area id
*/
protected $folderareaid = null;
public function setUp(): void {
$this->resetAfterTest(true);
set_config('enableglobalsearch', true);
$this->folderareaid = \core_search\manager::generate_areaid('mod_folder', 'activity');
// Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
$search = \testable_core_search::instance();
}
/**
* Test for folder file attachments.
*
* @return void
*/
public function test_attach_files(): void {
global $USER;
$this->setAdminUser();
// Setup test data.
$course = $this->getDataGenerator()->create_course();
$fs = get_file_storage();
$usercontext = \context_user::instance($USER->id);
$record = new \stdClass();
$record->course = $course->id;
$record->files = file_get_unused_draft_itemid();
// Attach the main file. We put them in the draft area, create_module will move them.
$filerecord = array(
'contextid' => $usercontext->id,
'component' => 'user',
'filearea' => 'draft',
'itemid' => $record->files,
'filepath' => '/'
);
// Attach 4 files.
for ($i = 1; $i <= 4; $i++) {
$filerecord['filename'] = 'myfile'.$i;
$fs->create_file_from_string($filerecord, 'Test folder file '.$i);
}
// And a fifth in a sub-folder.
$filerecord['filename'] = 'myfile5';
$filerecord['filepath'] = '/subfolder/';
$fs->create_file_from_string($filerecord, 'Test folder file 5');
$this->getDataGenerator()->create_module('folder', $record);
// Returns the instance as long as the area is supported.
$searcharea = \core_search\manager::get_search_area($this->folderareaid);
$this->assertInstanceOf('\mod_folder\search\activity', $searcharea);
$recordset = $searcharea->get_recordset_by_timestamp(0);
$nrecords = 0;
foreach ($recordset as $record) {
$doc = $searcharea->get_document($record);
$searcharea->attach_files($doc);
$files = $doc->get_files();
// Folder should return all files attached.
$this->assertCount(5, $files);
// We don't know the order, so get all the names, then sort, then check.
$filenames = array();
foreach ($files as $file) {
$filenames[] = $file->get_filename();
}
sort($filenames);
for ($i = 1; $i <= 5; $i++) {
$this->assertEquals('myfile'.$i, $filenames[($i - 1)]);
}
$nrecords++;
}
// If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
$recordset->close();
$this->assertEquals(1, $nrecords);
}
}