diff --git a/mod/lesson/classes/external.php b/mod/lesson/classes/external.php index 7810f8810ee..1a9276d8670 100644 --- a/mod/lesson/classes/external.php +++ b/mod/lesson/classes/external.php @@ -913,4 +913,132 @@ class mod_lesson_external extends external_api { ) ); } + + /** + * Describes the parameters for get_pages. + * + * @return external_external_function_parameters + * @since Moodle 3.3 + */ + public static function get_pages_parameters() { + return new external_function_parameters ( + array( + 'lessonid' => new external_value(PARAM_INT, 'lesson instance id'), + 'password' => new external_value(PARAM_RAW, 'optional password (the lesson may be protected)', VALUE_DEFAULT, ''), + ) + ); + } + + /** + * Return the list of pages in a lesson (based on the user permissions). + * + * @param int $lessonid lesson instance id + * @param str $password optional password (the lesson may be protected) + * @return array of warnings and status result + * @since Moodle 3.3 + * @throws moodle_exception + */ + public static function get_pages($lessonid, $password = '') { + + $params = array('lessonid' => $lessonid, 'password' => $password); + $params = self::validate_parameters(self::get_pages_parameters(), $params); + $warnings = array(); + + list($lesson, $course, $cm, $context) = self::validate_lesson($params['lessonid']); + self::validate_attempt($lesson, $params); + + $lessonpages = $lesson->load_all_pages(); + $pages = array(); + + foreach ($lessonpages as $page) { + $pagedata = new stdClass; // Contains the data that will be returned by the WS + + // Return the visible data. + $visibleproperties = array('id', 'lessonid', 'prevpageid', 'nextpageid', 'qtype', 'qoption', 'layout', 'display', + 'displayinmenublock', 'type', 'typeid', 'typestring', 'timecreated', 'timemodified'); + foreach ($visibleproperties as $prop) { + $pagedata->{$prop} = $page->{$prop}; + } + + // Check if we can see title (contents required custom rendering, we won't returning it here @see get_page_data). + $canmanage = $lesson->can_manage(); + // If we are managers or the menu block is enabled and is a content page visible. + if ($canmanage || (lesson_displayleftif($lesson) && $page->displayinmenublock && $page->display)) { + $pagedata->title = external_format_string($page->title, $context->id); + } + + // Now, calculate the file area files (maybe we need to download a lesson for offline usage). + $pagedata->filescount = 0; + $pagedata->filessizetotal = 0; + $files = $page->get_files(false); // Get files excluding directories. + foreach ($files as $file) { + $pagedata->filescount++; + $pagedata->filessizetotal += $file->get_filesize(); + } + + // Now the possible answers and page jumps ids. + $pagedata->answerids = array(); + $pagedata->jumps = array(); + $answers = $page->get_answers(); + foreach ($answers as $answer) { + $pagedata->answerids[] = $answer->id; + $pagedata->jumps[] = $answer->jumpto; + $files = $answer->get_files(false); // Get files excluding directories. + foreach ($files as $file) { + $pagedata->filescount++; + $pagedata->filessizetotal += $file->get_filesize(); + } + } + $pages[] = $pagedata; + } + + $result = array(); + $result['pages'] = $pages; + $result['warnings'] = $warnings; + return $result; + } + + /** + * Describes the get_pages return value. + * + * @return external_single_structure + * @since Moodle 3.3 + */ + public static function get_pages_returns() { + return new external_single_structure( + array( + 'pages' => new external_multiple_structure( + new external_single_structure( + array( + 'id' => new external_value(PARAM_INT, 'The id of this lesson page'), + 'lessonid' => new external_value(PARAM_INT, 'The id of the lesson this page belongs to'), + 'prevpageid' => new external_value(PARAM_INT, 'The id of the page before this one'), + 'nextpageid' => new external_value(PARAM_INT, 'The id of the next page in the page sequence'), + 'qtype' => new external_value(PARAM_INT, 'Identifies the page type of this page'), + 'qoption' => new external_value(PARAM_INT, 'Used to record page type specific options'), + 'layout' => new external_value(PARAM_INT, 'Used to record page specific layout selections'), + 'display' => new external_value(PARAM_INT, 'Used to record page specific display selections'), + 'timecreated' => new external_value(PARAM_INT, 'Timestamp for when the page was created'), + 'timemodified' => new external_value(PARAM_INT, 'Timestamp for when the page was last modified'), + 'title' => new external_value(PARAM_RAW, 'The title of this page', VALUE_OPTIONAL), + 'displayinmenublock' => new external_value(PARAM_BOOL, 'Toggles display in the left menu block'), + 'type' => new external_value(PARAM_INT, 'The type of the page [question | structure]'), + 'typeid' => new external_value(PARAM_INT, 'The unique identifier for the page type'), + 'typestring' => new external_value(PARAM_RAW, 'The string that describes this page type'), + 'answerids' => new external_multiple_structure( + new external_value(PARAM_INT, 'Answer id'), 'List of answers ids (empty for content pages in Moodle 1.9)' + ), + 'jumps' => new external_multiple_structure( + new external_value(PARAM_INT, 'Page to jump id'), 'List of possible page jumps' + ), + 'filescount' => new external_value(PARAM_INT, 'The total number of files attached to the page'), + 'filessizetotal' => new external_value(PARAM_INT, 'The total size of the files'), + ), + 'The lesson pages' + ) + ), + 'warnings' => new external_warnings(), + ) + ); + } } diff --git a/mod/lesson/db/services.php b/mod/lesson/db/services.php index e9e0b7c916e..34e230357f9 100644 --- a/mod/lesson/db/services.php +++ b/mod/lesson/db/services.php @@ -92,4 +92,12 @@ $functions = array( 'capabilities' => 'mod/lesson:view', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_lesson_get_pages' => array( + 'classname' => 'mod_lesson_external', + 'methodname' => 'get_pages', + 'description' => 'Return the list of pages in a lesson (based on the user permissions).', + 'type' => 'read', + 'capabilities' => 'mod/lesson:view', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/lesson/locallib.php b/mod/lesson/locallib.php index 637c424e840..4cf21f63415 100644 --- a/mod/lesson/locallib.php +++ b/mod/lesson/locallib.php @@ -3650,6 +3650,20 @@ abstract class lesson_page extends lesson_base { $validpages[$this->properties->id] = 1; return $this->properties->nextpageid; } + + /** + * Get files from the page area file. + * + * @param bool $includedirs whether or not include directories + * @param int $updatedsince return files updated since this time + * @return array list of stored_file objects + * @since Moodle 3.2 + */ + public function get_files($includedirs = true, $updatedsince = 0) { + $fs = get_file_storage(); + return $fs->get_area_files($this->lesson->context->id, 'mod_lesson', 'page_contents', $this->properties->id, + 'itemid, filepath, filename', $includedirs, $updatedsince); + } } @@ -3698,6 +3712,25 @@ class lesson_page_answer extends lesson_base { return $page->create_answers($properties); } + /** + * Get files from the answer area file. + * + * @param bool $includedirs whether or not include directories + * @param int $updatedsince return files updated since this time + * @return array list of stored_file objects + * @since Moodle 3.2 + */ + public function get_files($includedirs = true, $updatedsince = 0) { + + $lesson = lesson::load($this->properties->lessonid); + $fs = get_file_storage(); + $answerfiles = $fs->get_area_files($lesson->context->id, 'mod_lesson', 'page_answers', $this->properties->id, + 'itemid, filepath, filename', $includedirs, $updatedsince); + $responsefiles = $fs->get_area_files($lesson->context->id, 'mod_lesson', 'page_responses', $this->properties->id, + 'itemid, filepath, filename', $includedirs, $updatedsince); + return array_merge($answerfiles, $responsefiles); + } + } /** diff --git a/mod/lesson/tests/external_test.php b/mod/lesson/tests/external_test.php index ac6d564d20f..925dd4b4698 100644 --- a/mod/lesson/tests/external_test.php +++ b/mod/lesson/tests/external_test.php @@ -666,4 +666,73 @@ class mod_lesson_external_testcase extends externallib_advanced_testcase { } } } + + /** + * Test for get_pages + */ + public function test_get_pages() { + global $DB; + + $this->setAdminUser(); + // Create another content page. + $lessongenerator = $this->getDataGenerator()->get_plugin_generator('mod_lesson'); + $page3 = $lessongenerator->create_content($this->lesson); + + $p2answers = $DB->get_records('lesson_answers', array('lessonid' => $this->lesson->id, 'pageid' => $this->page2->id), 'id'); + + // Add files everywhere. + $fs = get_file_storage(); + + $filerecord = array( + 'contextid' => $this->context->id, + 'component' => 'mod_lesson', + 'filearea' => 'page_contents', + 'itemid' => $this->page1->id, + 'filepath' => '/', + 'filename' => 'file.txt', + 'sortorder' => 1 + ); + $fs->create_file_from_string($filerecord, 'Test resource file'); + + $filerecord['itemid'] = $page3->id; + $fs->create_file_from_string($filerecord, 'Test resource file'); + + foreach ($p2answers as $answer) { + $filerecord['filearea'] = 'page_answers'; + $filerecord['itemid'] = $answer->id; + $fs->create_file_from_string($filerecord, 'Test resource file'); + + $filerecord['filearea'] = 'page_responses'; + $fs->create_file_from_string($filerecord, 'Test resource file'); + } + + $result = mod_lesson_external::get_pages($this->lesson->id); + $result = external_api::clean_returnvalue(mod_lesson_external::get_pages_returns(), $result); + $this->assertCount(0, $result['warnings']); + $this->assertCount(3, $result['pages']); + + // Check pages and values. + foreach ($result['pages'] as $page) { + if ($page['id'] == $this->page2->id) { + $this->assertEquals(2 * count($page['answerids']), $page['filescount']); + $this->assertEquals('Lesson TF question 2', $page['title']); + } else { + // Content page, no answers. + $this->assertCount(0, $page['answerids']); + $this->assertEquals(1, $page['filescount']); + } + } + + // Now, as student without pages menu. + $this->setUser($this->student); + $DB->set_field('lesson', 'displayleft', 0, array('id' => $this->lesson->id)); + $result = mod_lesson_external::get_pages($this->lesson->id); + $result = external_api::clean_returnvalue(mod_lesson_external::get_pages_returns(), $result); + $this->assertCount(0, $result['warnings']); + $this->assertCount(3, $result['pages']); + + foreach ($result['pages'] as $page) { + $this->assertArrayNotHasKey('title', $page); + } + } } diff --git a/mod/lesson/version.php b/mod/lesson/version.php index ac2a5f84474..16b2294c8ff 100644 --- a/mod/lesson/version.php +++ b/mod/lesson/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016120507; // The current module version (Date: YYYYMMDDXX) +$plugin->version = 2016120508; // 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;