Merge branch 'MDL-57633-master' of git://github.com/jleyva/moodle

This commit is contained in:
Eloy Lafuente (stronk7)
2017-02-21 23:45:14 +01:00
7 changed files with 680 additions and 144 deletions
+212
View File
@@ -0,0 +1,212 @@
<?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/>.
/**
* Lesson external API
*
* @package mod_lesson
* @category external
* @copyright 2017 Juan Leyva <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.3
*/
defined('MOODLE_INTERNAL') || die;
require_once($CFG->libdir . '/externallib.php');
require_once($CFG->dirroot . '/mod/lesson/locallib.php');
/**
* Lesson external functions
*
* @package mod_lesson
* @category external
* @copyright 2017 Juan Leyva <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.3
*/
class mod_lesson_external extends external_api {
/**
* Describes the parameters for get_lessons_by_courses.
*
* @return external_function_parameters
* @since Moodle 3.3
*/
public static function get_lessons_by_courses_parameters() {
return new external_function_parameters (
array(
'courseids' => new external_multiple_structure(
new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array()
),
)
);
}
/**
* Returns a list of lessons in a provided list of courses,
* if no list is provided all lessons that the user can view will be returned.
*
* @param array $courseids Array of course ids
* @return array of lessons details
* @since Moodle 3.3
*/
public static function get_lessons_by_courses($courseids = array()) {
global $USER;
$warnings = array();
$returnedlessons = array();
$params = array(
'courseids' => $courseids,
);
$params = self::validate_parameters(self::get_lessons_by_courses_parameters(), $params);
$mycourses = array();
if (empty($params['courseids'])) {
$mycourses = enrol_get_my_courses();
$params['courseids'] = array_keys($mycourses);
}
// Ensure there are courseids to loop through.
if (!empty($params['courseids'])) {
list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses);
// Get the lessons in this course, this function checks users visibility permissions.
// We can avoid then additional validate_context calls.
$lessons = get_all_instances_in_courses("lesson", $courses);
foreach ($lessons as $lesson) {
$context = context_module::instance($lesson->coursemodule);
$lesson = new lesson($lesson);
$lesson->update_effective_access($USER->id);
// Entry to return.
$lessondetails = array();
// First, we return information that any user can see in the web interface.
$lessondetails['id'] = $lesson->id;
$lessondetails['coursemodule'] = $lesson->coursemodule;
$lessondetails['course'] = $lesson->course;
$lessondetails['name'] = external_format_string($lesson->name, $context->id);
$lessonavailable = $lesson->get_time_restriction_status() === false;
$lessonavailable = $lessonavailable && $lesson->get_password_restriction_status('') === false;
$lessonavailable = $lessonavailable && $lesson->get_dependencies_restriction_status() === false;
if ($lessonavailable) {
// Format intro.
list($lessondetails['intro'], $lessondetails['introformat']) = external_format_text($lesson->intro,
$lesson->introformat, $context->id, 'mod_lesson', 'intro', null);
$lessondetails['introfiles'] = external_util::get_area_files($context->id, 'mod_lesson', 'intro', false, false);
$lessondetails['mediafiles'] = external_util::get_area_files($context->id, 'mod_lesson', 'mediafile', 0);
$viewablefields = array('practice', 'modattempts', 'usepassword', 'grade', 'custom', 'ongoing', 'usemaxgrade',
'maxanswers', 'maxattempts', 'review', 'nextpagedefault', 'feedback', 'minquestions',
'maxpages', 'timelimit', 'retake', 'mediafile', 'mediaheight', 'mediawidth',
'mediaclose', 'slideshow', 'width', 'height', 'bgcolor', 'displayleft', 'displayleftif',
'progressbar');
// Fields only for managers.
if ($lesson->can_manage()) {
$additionalfields = array('password', 'dependency', 'conditions', 'activitylink', 'available', 'deadline',
'timemodified', 'completionendreached', 'completiontimespent');
$viewablefields = array_merge($viewablefields, $additionalfields);
}
foreach ($viewablefields as $field) {
$lessondetails[$field] = $lesson->{$field};
}
}
$returnedlessons[] = $lessondetails;
}
}
$result = array();
$result['lessons'] = $returnedlessons;
$result['warnings'] = $warnings;
return $result;
}
/**
* Describes the get_lessons_by_courses return value.
*
* @return external_single_structure
* @since Moodle 3.3
*/
public static function get_lessons_by_courses_returns() {
return new external_single_structure(
array(
'lessons' => new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Standard Moodle primary key.'),
'course' => new external_value(PARAM_INT, 'Foreign key reference to the course this lesson is part of.'),
'coursemodule' => new external_value(PARAM_INT, 'Course module id.'),
'name' => new external_value(PARAM_RAW, 'Lesson name.'),
'intro' => new external_value(PARAM_RAW, 'Lesson introduction text.', VALUE_OPTIONAL),
'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
'practice' => new external_value(PARAM_INT, 'Practice lesson?', VALUE_OPTIONAL),
'modattempts' => new external_value(PARAM_INT, 'Allow student review?', VALUE_OPTIONAL),
'usepassword' => new external_value(PARAM_INT, 'Password protected lesson?', VALUE_OPTIONAL),
'password' => new external_value(PARAM_RAW, 'Password', VALUE_OPTIONAL),
'dependency' => new external_value(PARAM_INT, 'Dependent on (another lesson id)', VALUE_OPTIONAL),
'conditions' => new external_value(PARAM_RAW, 'Conditions to enable the lesson', VALUE_OPTIONAL),
'grade' => new external_value(PARAM_INT, 'The total that the grade is scaled to be out of',
VALUE_OPTIONAL),
'custom' => new external_value(PARAM_INT, 'Custom scoring?', VALUE_OPTIONAL),
'ongoing' => new external_value(PARAM_INT, 'Display ongoing score?', VALUE_OPTIONAL),
'usemaxgrade' => new external_value(PARAM_INT, 'How to calculate the final grade', VALUE_OPTIONAL),
'maxanswers' => new external_value(PARAM_INT, 'Maximum answers per page', VALUE_OPTIONAL),
'maxattempts' => new external_value(PARAM_INT, 'Maximum attempts', VALUE_OPTIONAL),
'review' => new external_value(PARAM_INT, 'Provide option to try a question again', VALUE_OPTIONAL),
'nextpagedefault' => new external_value(PARAM_INT, 'Action for a correct answer', VALUE_OPTIONAL),
'feedback' => new external_value(PARAM_INT, 'Display default feedback', VALUE_OPTIONAL),
'minquestions' => new external_value(PARAM_INT, 'Minimum number of questions', VALUE_OPTIONAL),
'maxpages' => new external_value(PARAM_INT, 'Number of pages to show', VALUE_OPTIONAL),
'timelimit' => new external_value(PARAM_INT, 'Time limit', VALUE_OPTIONAL),
'retake' => new external_value(PARAM_INT, 'Re-takes allowed', VALUE_OPTIONAL),
'activitylink' => new external_value(PARAM_INT, 'Link to next activity', VALUE_OPTIONAL),
'mediafile' => new external_value(PARAM_RAW, 'Local file path or full external URL', VALUE_OPTIONAL),
'mediafiles' => new external_files('Media files', VALUE_OPTIONAL),
'mediaheight' => new external_value(PARAM_INT, 'Popup for media file height', VALUE_OPTIONAL),
'mediawidth' => new external_value(PARAM_INT, 'Popup for media with', VALUE_OPTIONAL),
'mediaclose' => new external_value(PARAM_INT, 'Display a close button in the popup?', VALUE_OPTIONAL),
'slideshow' => new external_value(PARAM_INT, 'Display lesson as slideshow', VALUE_OPTIONAL),
'width' => new external_value(PARAM_INT, 'Slideshow width', VALUE_OPTIONAL),
'height' => new external_value(PARAM_INT, 'Slideshow height', VALUE_OPTIONAL),
'bgcolor' => new external_value(PARAM_TEXT, 'Slideshow bgcolor', VALUE_OPTIONAL),
'displayleft' => new external_value(PARAM_INT, 'Display left pages menu?', VALUE_OPTIONAL),
'displayleftif' => new external_value(PARAM_INT, 'Minimum grade to display menu', VALUE_OPTIONAL),
'progressbar' => new external_value(PARAM_INT, 'Display progress bar?', VALUE_OPTIONAL),
'available' => new external_value(PARAM_INT, 'Available from', VALUE_OPTIONAL),
'deadline' => new external_value(PARAM_INT, 'Available until', VALUE_OPTIONAL),
'timemodified' => new external_value(PARAM_INT, 'Last time settings were updated', VALUE_OPTIONAL),
'completionendreached' => new external_value(PARAM_INT, 'Require end reached for completion?',
VALUE_OPTIONAL),
'completiontimespent' => new external_value(PARAM_INT, 'Student must do this activity at least for',
VALUE_OPTIONAL),
'visible' => new external_value(PARAM_INT, 'Visible?', VALUE_OPTIONAL),
'groupmode' => new external_value(PARAM_INT, 'Group mode', VALUE_OPTIONAL),
'groupingid' => new external_value(PARAM_INT, 'Grouping id', VALUE_OPTIONAL),
)
)
),
'warnings' => new external_warnings(),
)
);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?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/>.
/**
* Lesson external functions and service definitions.
*
* @package mod_lesson
* @category external
* @copyright 2017 Juan Leyva <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.3
*/
defined('MOODLE_INTERNAL') || die;
$functions = array(
'mod_lesson_get_lessons_by_courses' => array(
'classname' => 'mod_lesson_external',
'methodname' => 'get_lessons_by_courses',
'description' => 'Returns a list of lessons in a provided list of courses, if no list is provided all lessons that the user can view will be returned.',
'type' => 'read',
'capabilities' => 'mod/lesson:view',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
);
+189
View File
@@ -1010,6 +1010,32 @@ class lesson extends lesson_base {
*/
protected $loadedallpages = false;
/**
* Course module object gets set and retrieved by directly calling <code>$lesson->cm;</code>
* @see get_cm()
* @var stdClass
*/
protected $cm = null;
/**
* Context object gets set and retrieved by directly calling <code>$lesson->context;</code>
* @see get_context()
* @var stdClass
*/
protected $context = null;
/**
* Constructor method
*
* @param object $properties
* @param stdClass $cm course module object
* @since Moodle 3.3
*/
public function __construct($properties, $cm = null) {
parent::__construct($properties);
$this->cm = $cm;
}
/**
* Simply generates a lesson object given an array/object of properties
* Overrides {@see lesson_base->create()}
@@ -2066,6 +2092,169 @@ class lesson extends lesson_base {
}
}
/**
* Return the lesson context object.
*
* @return stdClass context
* @since Moodle 3.3
*/
public function get_context() {
if ($this->context == null) {
$this->context = context_module::instance($this->get_cm()->id);
}
return $this->context;
}
/**
* Set the lesson course module object.
*
* @param stdClass $cm course module objct
* @since Moodle 3.3
*/
private function set_cm($cm) {
$this->cm = $cm;
}
/**
* Return the lesson course module object.
*
* @return stdClass course module
* @since Moodle 3.3
*/
public function get_cm() {
if ($this->cm == null) {
$this->cm = get_coursemodule_from_instance('lesson', $this->properties->id);
}
return $this->cm;
}
/**
* Check if the user can manage the lesson activity.
*
* @return bool true if the user can manage the lesson
* @since Moodle 3.3
*/
public function can_manage() {
return has_capability('mod/lesson:manage', $this->get_context());
}
/**
* Check if time restriction is applied.
*
* @return mixed false if there aren't restrictions or an object with the restriction information
* @since Moodle 3.3
*/
public function get_time_restriction_status() {
if ($this->can_manage()) {
return false;
}
if (!$this->is_accessible()) {
if ($this->properties->deadline != 0 && time() > $this->properties->deadline) {
$status = ['reason' => 'lessonclosed', 'time' => $this->properties->deadline];
} else {
$status = ['reason' => 'lessonopen', 'time' => $this->properties->available];
}
return (object) $status;
}
return false;
}
/**
* Check if password restriction is applied.
*
* @param string $userpassword the user password to check (if the restriction is set)
* @return mixed false if there aren't restrictions or an object with the restriction information
* @since Moodle 3.3
*/
public function get_password_restriction_status($userpassword) {
global $USER;
if ($this->can_manage()) {
return false;
}
if ($this->properties->usepassword && empty($USER->lessonloggedin[$this->id])) {
$correctpass = false;
if (!empty($userpassword) &&
(($this->properties->password == md5(trim($userpassword))) || ($this->properties->password == trim($userpassword)))) {
// With or without md5 for backward compatibility (MDL-11090).
$correctpass = true;
$USER->lessonloggedin[$this->id] = true;
} else if (isset($this->properties->extrapasswords)) {
// Group overrides may have additional passwords.
foreach ($this->properties->extrapasswords as $password) {
if (strcmp($password, md5(trim($userpassword))) === 0 || strcmp($password, trim($userpassword)) === 0) {
$correctpass = true;
$USER->lessonloggedin[$this->id] = true;
}
}
}
return !$correctpass;
}
return false;
}
/**
* Check if dependencies restrictions are applied.
*
* @return mixed false if there aren't restrictions or an object with the restriction information
* @since Moodle 3.3
*/
public function get_dependencies_restriction_status() {
global $DB, $USER;
if ($this->can_manage()) {
return false;
}
if ($dependentlesson = $DB->get_record('lesson', array('id' => $this->properties->dependency))) {
// Lesson exists, so we can proceed.
$conditions = unserialize($this->properties->conditions);
// Assume false for all.
$errors = array();
// Check for the timespent condition.
if ($conditions->timespent) {
$timespent = false;
if ($attempttimes = $DB->get_records('lesson_timer', array("userid" => $USER->id, "lessonid" => $dependentlesson->id))) {
// Go through all the times and test to see if any of them satisfy the condition.
foreach ($attempttimes as $attempttime) {
$duration = $attempttime->lessontime - $attempttime->starttime;
if ($conditions->timespent < $duration / 60) {
$timespent = true;
}
}
}
if (!$timespent) {
$errors[] = get_string('timespenterror', 'lesson', $conditions->timespent);
}
}
// Check for the gradebetterthan condition.
if ($conditions->gradebetterthan) {
$gradebetterthan = false;
if ($studentgrades = $DB->get_records('lesson_grades', array("userid" => $USER->id, "lessonid" => $dependentlesson->id))) {
// Go through all the grades and test to see if any of them satisfy the condition.
foreach ($studentgrades as $studentgrade) {
if ($studentgrade->grade >= $conditions->gradebetterthan) {
$gradebetterthan = true;
}
}
}
if (!$gradebetterthan) {
$errors[] = get_string('gradebetterthanerror', 'lesson', $conditions->gradebetterthan);
}
}
// Check for the completed condition.
if ($conditions->completed) {
if (!$DB->count_records('lesson_grades', array('userid' => $USER->id, 'lessonid' => $dependentlesson->id))) {
$errors[] = get_string('completederror', 'lesson');
}
}
if (!empty($errors)) {
return (object) ['errors' => $errors, 'dependentlesson' => $dependentlesson];
}
}
return false;
}
}
+21 -45
View File
@@ -34,16 +34,15 @@ $printclose = optional_param('printclose', 0, PARAM_INT);
$cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST));
$lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST), $cm);
require_login($course, false, $cm);
// Apply overrides.
$lesson->update_effective_access($USER->id);
$context = context_module::instance($cm->id);
$canmanage = has_capability('mod/lesson:manage', $context);
$context = $lesson->context;
$canmanage = $lesson->can_manage();
$url = new moodle_url('/mod/lesson/mediafile.php', array('id'=>$id));
if ($printclose !== '') {
@@ -67,49 +66,26 @@ if ($printclose) { // this is for framesets
exit();
}
echo $lessonoutput->header($lesson, $cm);
//TODO: this is copied from view.php - the access should be the same!
/// Check these for students only TODO: Find a better method for doing this!
/// Check lesson availability
/// Check for password
/// Check dependencies
if (!$canmanage) {
if (!$lesson->is_accessible()) { // Deadline restrictions
echo $lessonoutput->header($lesson, $cm);
if ($lesson->deadline != 0 && time() > $lesson->deadline) {
echo $lessonoutput->lesson_inaccessible(get_string('lessonclosed', 'lesson', userdate($lesson->deadline)));
} else {
echo $lessonoutput->lesson_inaccessible(get_string('lessonopen', 'lesson', userdate($lesson->available)));
}
echo $lessonoutput->footer();
exit();
} else if ($lesson->usepassword && empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code
$correctpass = false;
if (!empty($userpassword) && (($lesson->password == md5(trim($userpassword))) || ($lesson->password == trim($userpassword)))) {
require_sesskey();
// with or without md5 for backward compatibility (MDL-11090)
$USER->lessonloggedin[$lesson->id] = true;
$correctpass = true;
} else if (isset($lesson->extrapasswords)) {
// Group overrides may have additional passwords.
foreach ($lesson->extrapasswords as $password) {
if (strcmp($password, md5(trim($userpassword))) === 0 || strcmp($password, trim($userpassword)) === 0) {
require_sesskey();
$correctpass = true;
$USER->lessonloggedin[$lesson->id] = true;
}
}
}
if (!$correctpass) {
echo $lessonoutput->header($lesson, $cm);
echo $lessonoutput->login_prompt($lesson, $userpassword !== '');
echo $lessonoutput->footer();
exit();
}
}
// Check access restrictions.
if ($timerestriction = $lesson->get_time_restriction_status()) { // Deadline restrictions.
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('notavailable'));
echo $lessonoutput->lesson_inaccessible(get_string($timerestriction->reason, 'lesson', userdate($timerestriction->time)));
echo $lessonoutput->footer();
exit();
} else if ($passwordrestriction = $lesson->get_password_restriction_status(null)) { // Password protected lesson code.
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name)));
echo $lessonoutput->login_prompt($lesson, $userpassword !== '');
echo $lessonoutput->footer();
exit();
} else if ($dependenciesrestriction = $lesson->get_dependencies_restriction_status()) { // Check for dependencies.
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('completethefollowingconditions', 'lesson', format_string($lesson->name)));
echo $lessonoutput->dependancy_errors($dependenciesrestriction->dependentlesson, $dependenciesrestriction->errors);
echo $lessonoutput->footer();
exit();
}
echo $lessonoutput->header($lesson, $cm);
// print the embedded media html code
echo $OUTPUT->box(lesson_get_media_html($lesson, $context));
+195
View File
@@ -0,0 +1,195 @@
<?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/>.
/**
* Lesson module external functions tests
*
* @package mod_lesson
* @category external
* @copyright 2017 Juan Leyva <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.3
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/mod/lesson/locallib.php');
/**
* Lesson module external functions tests
*
* @package mod_lesson
* @category external
* @copyright 2017 Juan Leyva <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.3
*/
class mod_lesson_external_testcase extends externallib_advanced_testcase {
/**
* Set up for every test
*/
public function setUp() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$this->course = $this->getDataGenerator()->create_course();
$this->lesson = $this->getDataGenerator()->create_module('lesson', array('course' => $this->course->id));
$this->context = context_module::instance($this->lesson->cmid);
$this->cm = get_coursemodule_from_instance('lesson', $this->lesson->id);
// Create users.
$this->student = self::getDataGenerator()->create_user();
$this->teacher = self::getDataGenerator()->create_user();
// Users enrolments.
$this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
}
/**
* Test test_mod_lesson_get_lessons_by_courses
*/
public function test_mod_lesson_get_lessons_by_courses() {
global $DB;
// Create additional course.
$course2 = self::getDataGenerator()->create_course();
// Second lesson.
$record = new stdClass();
$record->course = $course2->id;
$lesson2 = self::getDataGenerator()->create_module('lesson', $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, $this->student->id, $this->studentrole->id);
self::setUser($this->student);
$returndescription = mod_lesson_external::get_lessons_by_courses_returns();
// Create what we expect to be returned when querying the two courses.
// First for the student user.
$expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'practice',
'modattempts', 'usepassword', 'grade', 'custom', 'ongoing', 'usemaxgrade',
'maxanswers', 'maxattempts', 'review', 'nextpagedefault', 'feedback', 'minquestions',
'maxpages', 'timelimit', 'retake', 'mediafile', 'mediafiles', 'mediaheight', 'mediawidth',
'mediaclose', 'slideshow', 'width', 'height', 'bgcolor', 'displayleft', 'displayleftif',
'progressbar');
// Add expected coursemodule and data.
$lesson1 = $this->lesson;
$lesson1->coursemodule = $lesson1->cmid;
$lesson1->introformat = 1;
$lesson1->section = 0;
$lesson1->visible = true;
$lesson1->groupmode = 0;
$lesson1->groupingid = 0;
$lesson1->introfiles = [];
$lesson1->mediafiles = [];
$lesson2->coursemodule = $lesson2->cmid;
$lesson2->introformat = 1;
$lesson2->section = 0;
$lesson2->visible = true;
$lesson2->groupmode = 0;
$lesson2->groupingid = 0;
$lesson2->introfiles = [];
$lesson2->mediafiles = [];
foreach ($expectedfields as $field) {
$expected1[$field] = $lesson1->{$field};
$expected2[$field] = $lesson2->{$field};
}
$expectedlessons = array($expected2, $expected1);
// Call the external function passing course ids.
$result = mod_lesson_external::get_lessons_by_courses(array($course2->id, $this->course->id));
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedlessons, $result['lessons']);
$this->assertCount(0, $result['warnings']);
// Call the external function without passing course id.
$result = mod_lesson_external::get_lessons_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedlessons, $result['lessons']);
$this->assertCount(0, $result['warnings']);
// Unenrol user from second course and alter expected lessons.
$enrol->unenrol_user($instance2, $this->student->id);
array_shift($expectedlessons);
// Call the external function without passing course id.
$result = mod_lesson_external::get_lessons_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedlessons, $result['lessons']);
// Call for the second course we unenrolled the user from, expected warning.
$result = mod_lesson_external::get_lessons_by_courses(array($course2->id));
$this->assertCount(1, $result['warnings']);
$this->assertEquals('1', $result['warnings'][0]['warningcode']);
$this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
// Now, try as a teacher for getting all the additional fields.
self::setUser($this->teacher);
$additionalfields = array('password', 'dependency', 'conditions', 'activitylink', 'available', 'deadline',
'timemodified', 'completionendreached', 'completiontimespent');
foreach ($additionalfields as $field) {
$expectedlessons[0][$field] = $lesson1->{$field};
}
$result = mod_lesson_external::get_lessons_by_courses();
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedlessons, $result['lessons']);
// Admin also should get all the information.
self::setAdminUser();
$result = mod_lesson_external::get_lessons_by_courses(array($this->course->id));
$result = external_api::clean_returnvalue($returndescription, $result);
$this->assertEquals($expectedlessons, $result['lessons']);
// Now, add a restriction.
$this->setUser($this->student);
$DB->set_field('lesson', 'usepassword', 1, array('id' => $lesson1->id));
$DB->set_field('lesson', 'password', 'abc', array('id' => $lesson1->id));
$lessons = mod_lesson_external::get_lessons_by_courses(array($this->course->id));
$lessons = external_api::clean_returnvalue(mod_lesson_external::get_lessons_by_courses_returns(), $lessons);
$this->assertFalse(isset($lessons['lessons'][0]['intro']));
}
}
+1 -1
View File
@@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2016120500; // The current module version (Date: YYYYMMDDXX)
$plugin->version = 2016120501; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2016112900; // Requires this Moodle version
$plugin->component = 'mod_lesson'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 0;
+24 -98
View File
@@ -37,7 +37,7 @@ $backtocourse = optional_param('backtocourse', false, PARAM_RAW);
$cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST));
$lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST), $cm);
require_login($course, false, $cm);
@@ -59,8 +59,8 @@ if ($pageid !== null) {
$PAGE->set_url($url);
$PAGE->force_settings_menu();
$context = context_module::instance($cm->id);
$canmanage = has_capability('mod/lesson:manage', $context);
$context = $lesson->context;
$canmanage = $lesson->can_manage();
$lessonoutput = $PAGE->get_renderer('mod_lesson');
@@ -70,103 +70,29 @@ if ($userhasgrade && !$lesson->retake) {
$reviewmode = true;
}
/// Check these for students only TODO: Find a better method for doing this!
/// Check lesson availability
/// Check for password
/// Check dependencies
if (!$canmanage) {
if (!$lesson->is_accessible()) { // Deadline restrictions
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('notavailable'));
if ($lesson->deadline != 0 && time() > $lesson->deadline) {
echo $lessonoutput->lesson_inaccessible(get_string('lessonclosed', 'lesson', userdate($lesson->deadline)));
} else {
echo $lessonoutput->lesson_inaccessible(get_string('lessonopen', 'lesson', userdate($lesson->available)));
}
echo $lessonoutput->footer();
exit();
} else if ($lesson->usepassword && empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code
$correctpass = false;
if (!empty($userpassword) && (($lesson->password == md5(trim($userpassword))) || ($lesson->password == trim($userpassword)))) {
require_sesskey();
// with or without md5 for backward compatibility (MDL-11090)
$correctpass = true;
$USER->lessonloggedin[$lesson->id] = true;
} else if (isset($lesson->extrapasswords)) {
// Group overrides may have additional passwords.
foreach ($lesson->extrapasswords as $password) {
if (strcmp($password, md5(trim($userpassword))) === 0 || strcmp($password, trim($userpassword)) === 0) {
require_sesskey();
$correctpass = true;
$USER->lessonloggedin[$lesson->id] = true;
}
}
}
if (!$correctpass) {
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name)));
echo $lessonoutput->login_prompt($lesson, $userpassword !== '');
echo $lessonoutput->footer();
exit();
}
} else if ($lesson->dependency) { // check for dependencies
if ($dependentlesson = $DB->get_record('lesson', array('id' => $lesson->dependency))) {
// lesson exists, so we can proceed
$conditions = unserialize($lesson->conditions);
// assume false for all
$errors = array();
// check for the timespent condition
if ($conditions->timespent) {
$timespent = false;
if ($attempttimes = $DB->get_records('lesson_timer', array("userid"=>$USER->id, "lessonid"=>$dependentlesson->id))) {
// go through all the times and test to see if any of them satisfy the condition
foreach($attempttimes as $attempttime) {
$duration = $attempttime->lessontime - $attempttime->starttime;
if ($conditions->timespent < $duration/60) {
$timespent = true;
}
}
}
if (!$timespent) {
$errors[] = get_string('timespenterror', 'lesson', $conditions->timespent);
}
}
// check for the gradebetterthan condition
if($conditions->gradebetterthan) {
$gradebetterthan = false;
if ($studentgrades = $DB->get_records('lesson_grades', array("userid"=>$USER->id, "lessonid"=>$dependentlesson->id))) {
// go through all the grades and test to see if any of them satisfy the condition
foreach($studentgrades as $studentgrade) {
if ($studentgrade->grade >= $conditions->gradebetterthan) {
$gradebetterthan = true;
}
}
}
if (!$gradebetterthan) {
$errors[] = get_string('gradebetterthanerror', 'lesson', $conditions->gradebetterthan);
}
}
// check for the completed condition
if ($conditions->completed) {
if (!$DB->count_records('lesson_grades', array('userid'=>$USER->id, 'lessonid'=>$dependentlesson->id))) {
$errors[] = get_string('completederror', 'lesson');
}
}
if (!empty($errors)) { // print out the errors if any
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('completethefollowingconditions', 'lesson', format_string($lesson->name)));
echo $lessonoutput->dependancy_errors($dependentlesson, $errors);
echo $lessonoutput->footer();
exit();
}
}
}
if ($lesson->usepassword && !empty($userpassword)) {
require_sesskey();
}
// this is called if a student leaves during a lesson
// Check these for students only TODO: Find a better method for doing this!
if ($timerestriction = $lesson->get_time_restriction_status()) { // Deadline restrictions.
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('notavailable'));
echo $lessonoutput->lesson_inaccessible(get_string($timerestriction->reason, 'lesson', userdate($timerestriction->time)));
echo $lessonoutput->footer();
exit();
} else if ($passwordrestriction = $lesson->get_password_restriction_status($userpassword)) { // Password protected lesson code.
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name)));
echo $lessonoutput->login_prompt($lesson, $userpassword !== '');
echo $lessonoutput->footer();
exit();
} else if ($dependenciesrestriction = $lesson->get_dependencies_restriction_status()) { // Check for dependencies.
echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('completethefollowingconditions', 'lesson', format_string($lesson->name)));
echo $lessonoutput->dependancy_errors($dependenciesrestriction->dependentlesson, $dependenciesrestriction->errors);
echo $lessonoutput->footer();
exit();
}
// This is called if a student leaves during a lesson.
if ($pageid == LESSON_UNSEENBRANCHPAGE) {
$pageid = lesson_unseen_question_jump($lesson, $USER->id, $pageid);
}