Merge branch 'MDL-54951-master' of git://github.com/jleyva/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Tue, 5 Jul 2016 01:41:31 +0000 (09:41 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Tue, 5 Jul 2016 01:41:31 +0000 (09:41 +0800)
24 files changed:
lib/externallib.php
lib/tests/externallib_test.php
mod/assign/externallib.php
mod/book/classes/external.php
mod/book/tests/externallib_test.php
mod/chat/classes/external.php
mod/chat/tests/externallib_test.php
mod/choice/classes/external.php
mod/data/classes/external.php
mod/data/tests/externallib_test.php
mod/forum/externallib.php
mod/forum/tests/externallib_test.php
mod/glossary/classes/external.php
mod/imscp/classes/external.php
mod/lti/classes/external.php
mod/lti/tests/externallib_test.php
mod/quiz/classes/external.php
mod/quiz/tests/external_test.php
mod/scorm/classes/external.php
mod/scorm/tests/externallib_test.php
mod/survey/classes/external.php
mod/survey/tests/externallib_test.php
mod/wiki/classes/external.php
mod/wiki/tests/externallib_test.php

index befa4e6..a92d6f7 100644 (file)
@@ -1128,4 +1128,70 @@ class external_util {
         return array($courses, $warnings);
     }
 
+    /**
+     * Returns all area files (optionally limited by itemid).
+     *
+     * @param int $contextid context ID
+     * @param string $component component
+     * @param string $filearea file area
+     * @param int $itemid item ID or all files if not specified
+     * @param bool $useitemidinurl wether to use the item id in the file URL (modules intro don't use it)
+     * @return array of files, compatible with the external_files structure.
+     * @since Moodle 3.2
+     */
+    public static function get_area_files($contextid, $component, $filearea, $itemid = false, $useitemidinurl = true) {
+        $files = array();
+        $fs = get_file_storage();
+
+        if ($areafiles = $fs->get_area_files($contextid, $component, $filearea, $itemid, 'itemid, filepath, filename', false)) {
+            foreach ($areafiles as $areafile) {
+                $file = array();
+                $file['filename'] = $areafile->get_filename();
+                $file['filepath'] = $areafile->get_filepath();
+                $file['mimetype'] = $areafile->get_mimetype();
+                $file['filesize'] = $areafile->get_filesize();
+                $file['timemodified'] = $areafile->get_timemodified();
+                $fileitemid = $useitemidinurl ? $areafile->get_itemid() : null;
+                $file['fileurl'] = moodle_url::make_webservice_pluginfile_url($contextid, $component, $filearea,
+                                    $fileitemid, $areafile->get_filepath(), $areafile->get_filename())->out(false);
+                $files[] = $file;
+            }
+        }
+        return $files;
+    }
+}
+
+/**
+ * External structure representing a set of files.
+ *
+ * @package    core_webservice
+ * @copyright  2016 Juan Leyva
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since      Moodle 3.2
+ */
+class external_files extends external_multiple_structure {
+
+    /**
+     * Constructor
+     * @param string $desc Description for the multiple structure.
+     * @param int $required The type of value (VALUE_REQUIRED OR VALUE_OPTIONAL).
+     */
+    public function __construct($desc = 'List of files.', $required = VALUE_REQUIRED) {
+
+        parent::__construct(
+            new external_single_structure(
+                array(
+                    'filename' => new external_value(PARAM_FILE, 'File name.', VALUE_OPTIONAL),
+                    'filepath' => new external_value(PARAM_PATH, 'File path.', VALUE_OPTIONAL),
+                    'filesize' => new external_value(PARAM_INT, 'File size.', VALUE_OPTIONAL),
+                    'fileurl' => new external_value(PARAM_URL, 'Downloadable file url.', VALUE_OPTIONAL),
+                    'timemodified' => new external_value(PARAM_INT, 'Time modified.', VALUE_OPTIONAL),
+                    'mimetype' => new external_value(PARAM_RAW, 'File mime type.', VALUE_OPTIONAL),
+                ),
+                'File.'
+            ),
+            $desc,
+            $required
+        );
+    }
 }
index 39796cc..cda9bd3 100644 (file)
@@ -30,6 +30,19 @@ require_once($CFG->libdir . '/externallib.php');
 
 
 class core_externallib_testcase extends advanced_testcase {
+    protected $DB;
+
+    public function setUp() {
+        $this->DB = null;
+    }
+
+    public function tearDown() {
+        global $DB;
+        if ($this->DB !== null) {
+            $DB = $this->DB;
+        }
+    }
+
     public function test_validate_params() {
         $params = array('text'=>'aaa', 'someid'=>'6');
         $description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value'),
@@ -459,6 +472,73 @@ class core_externallib_testcase extends advanced_testcase {
         $this->assertSame($beforecourse, $COURSE);
     }
 
+    /**
+     * Text external_util::get_area_files
+     */
+    public function test_external_util_get_area_files() {
+        global $CFG, $DB;
+
+        $this->DB = $DB;
+        $DB = $this->getMockBuilder('moodle_database')->getMock();
+
+        $content = base64_encode("Let us create a nice simple file.");
+        $timemodified = 102030405;
+        $itemid = 42;
+        $filesize = strlen($content);
+
+        $DB->method('get_records_sql')->willReturn([
+            (object) [
+                'filename'      => 'example.txt',
+                'filepath'      => '/',
+                'mimetype'      => 'text/plain',
+                'filesize'      => $filesize,
+                'timemodified'  => $timemodified,
+                'itemid'        => $itemid,
+                'pathnamehash'  => sha1('/example.txt'),
+            ],
+        ]);
+
+        $component = 'mod_foo';
+        $filearea = 'area';
+        $context = 12345;
+
+        $expectedfiles[] = array(
+            'filename' => 'example.txt',
+            'filepath' => '/',
+            'fileurl' => "{$CFG->wwwroot}/webservice/pluginfile.php/{$context}/{$component}/{$filearea}/{$itemid}/example.txt",
+            'timemodified' => $timemodified,
+            'filesize' => $filesize,
+            'mimetype' => 'text/plain',
+        );
+        // Get all the files for the area.
+        $files = external_util::get_area_files($context, $component, $filearea, false);
+        $this->assertEquals($expectedfiles, $files);
+
+        // Get just the file indicated by $itemid.
+        $files = external_util::get_area_files($context, $component, $filearea, $itemid);
+        $this->assertEquals($expectedfiles, $files);
+
+    }
+
+    /**
+     * Text external files structure.
+     */
+    public function test_external_files() {
+
+        $description = new external_files();
+
+        // First check that the expected default values and keys are returned.
+        $expectedkeys = array_flip(array('filename', 'filepath', 'filesize', 'fileurl', 'timemodified', 'mimetype'));
+        $returnedkeys = array_flip(array_keys($description->content->keys));
+        $this->assertEquals($expectedkeys, $returnedkeys);
+        $this->assertEquals('List of files.', $description->desc);
+        $this->assertEquals(VALUE_REQUIRED, $description->required);
+        foreach ($description->content->keys as $key) {
+            $this->assertEquals(VALUE_OPTIONAL, $key->required);
+        }
+
+    }
+
 }
 
 /*
index f2eb881..5c71156 100644 (file)
@@ -451,6 +451,8 @@ class mod_assign_external extends external_api {
 
                         list($assignment['intro'], $assignment['introformat']) = external_format_text($module->intro,
                             $module->introformat, $context->id, 'mod_assign', 'intro', null);
+                        $assignment['introfiles'] = external_util::get_area_files($context->id, 'mod_assign', 'intro', false,
+                                                                                    false);
 
                         $fs = get_file_storage();
                         if ($files = $fs->get_area_files($context->id, 'mod_assign', ASSIGN_INTROATTACHMENT_FILEAREA,
@@ -528,6 +530,7 @@ class mod_assign_external extends external_api {
                 'intro' => new external_value(PARAM_RAW,
                     'assignment intro, not allways returned because it deppends on the activity configuration', VALUE_OPTIONAL),
                 'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
+                'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                 'introattachments' => new external_multiple_structure(
                     new external_single_structure(
                         array (
index 34d1493..3fde48d 100644 (file)
@@ -207,6 +207,7 @@ class mod_book_external extends external_api {
                 // Format intro.
                 list($bookdetails['intro'], $bookdetails['introformat']) =
                     external_format_text($book->intro, $book->introformat, $context->id, 'mod_book', 'intro', null);
+                $bookdetails['introfiles'] = external_util::get_area_files($context->id, 'mod_book', 'intro', false, false);
                 $bookdetails['numbering']         = $book->numbering;
                 $bookdetails['navstyle']          = $book->navstyle;
                 $bookdetails['customtitles']      = $book->customtitles;
@@ -247,6 +248,7 @@ class mod_book_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Book name'),
                             'intro' => new external_value(PARAM_RAW, 'The Book intro'),
                             'introformat' => new external_format_value('intro'),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'numbering' => new external_value(PARAM_INT, 'Book numbering configuration'),
                             'navstyle' => new external_value(PARAM_INT, 'Book navigation style configuration'),
                             'customtitles' => new external_value(PARAM_INT, 'Book custom titles type'),
index 74dfec8..e363ec7 100644 (file)
@@ -164,8 +164,8 @@ class mod_book_external_testcase extends externallib_advanced_testcase {
         $books = external_api::clean_returnvalue(mod_book_external::get_books_by_courses_returns(), $books);
         $this->assertCount(1, $books['books']);
         $this->assertEquals('First Book', $books['books'][0]['name']);
-        // We see 9 fields.
-        $this->assertCount(9, $books['books'][0]);
+        // We see 10 fields.
+        $this->assertCount(10, $books['books'][0]);
 
         // As Student you cannot see some book properties like 'section'.
         $this->assertFalse(isset($books['books'][0]['section']));
@@ -186,8 +186,8 @@ class mod_book_external_testcase extends externallib_advanced_testcase {
 
         $this->assertCount(1, $books['books']);
         $this->assertEquals('Second Book', $books['books'][0]['name']);
-        // We see 16 fields.
-        $this->assertCount(16, $books['books'][0]);
+        // We see 17 fields.
+        $this->assertCount(17, $books['books'][0]);
         // As an Admin you can see some book properties like 'section'.
         $this->assertEquals(0, $books['books'][0]['section']);
 
index 8405efb..cd08786 100644 (file)
@@ -549,6 +549,7 @@ class mod_chat_external extends external_api {
                 // Format intro.
                 list($chatdetails['intro'], $chatdetails['introformat']) =
                     external_format_text($chat->intro, $chat->introformat, $chatcontext->id, 'mod_chat', 'intro', null);
+                $chatdetails['introfiles'] = external_util::get_area_files($chatcontext->id, 'mod_chat', 'intro', false, false);
 
                 if (has_capability('mod/chat:chat', $chatcontext)) {
                     $chatdetails['chatmethod']    = $CFG->chat_method;
@@ -592,6 +593,7 @@ class mod_chat_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Chat name'),
                             'intro' => new external_value(PARAM_RAW, 'The Chat intro'),
                             'introformat' => new external_format_value('intro'),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'chatmethod' => new external_value(PARAM_ALPHA, 'chat method (sockets, daemon)', VALUE_OPTIONAL),
                             'keepdays' => new external_value(PARAM_INT, 'keep days', VALUE_OPTIONAL),
                             'studentlogs' => new external_value(PARAM_INT, 'student logs visible to everyone', VALUE_OPTIONAL),
index cbd335f..e9698d2 100644 (file)
@@ -250,8 +250,8 @@ class mod_chat_external_testcase extends externallib_advanced_testcase {
         $chats = external_api::clean_returnvalue(mod_chat_external::get_chats_by_courses_returns(), $chats);
         $this->assertCount(1, $chats['chats']);
         $this->assertEquals('First Chat', $chats['chats'][0]['name']);
-        // We see 11 fields.
-        $this->assertCount(11, $chats['chats'][0]);
+        // We see 12 fields.
+        $this->assertCount(12, $chats['chats'][0]);
 
         // As Student you cannot see some chat properties like 'section'.
         $this->assertFalse(isset($chats['chats'][0]['section']));
@@ -272,8 +272,8 @@ class mod_chat_external_testcase extends externallib_advanced_testcase {
 
         $this->assertCount(1, $chats['chats']);
         $this->assertEquals('Second Chat', $chats['chats'][0]['name']);
-        // We see 16 fields.
-        $this->assertCount(16, $chats['chats'][0]);
+        // We see 17 fields.
+        $this->assertCount(17, $chats['chats'][0]);
         // As an Admin you can see some chat properties like 'section'.
         $this->assertEquals(0, $chats['chats'][0]['section']);
 
index 7eb5a16..6732b94 100644 (file)
@@ -507,6 +507,8 @@ class mod_choice_external extends external_api {
                 list($choicedetails['intro'], $choicedetails['introformat']) =
                     external_format_text($choice->intro, $choice->introformat,
                                             $context->id, 'mod_choice', 'intro', null);
+                    $choicedetails['introfiles'] = external_util::get_area_files($context->id, 'mod_choice', 'intro', false,
+                                                                                    false);
 
                 if (has_capability('mod/choice:choose', $context)) {
                     $choicedetails['publish']  = $choice->publish;
@@ -557,6 +559,7 @@ class mod_choice_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Choice name'),
                             'intro' => new external_value(PARAM_RAW, 'The choice intro'),
                             'introformat' => new external_format_value('intro'),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'publish' => new external_value(PARAM_BOOL, 'If choice is published', VALUE_OPTIONAL),
                             'showresults' => new external_value(PARAM_INT, '0 never, 1 after answer, 2 after close, 3 always',
                                                                 VALUE_OPTIONAL),
index 3ac5e82..8a53280 100644 (file)
@@ -104,6 +104,7 @@ class mod_data_external extends external_api {
                 list($newdb['intro'], $newdb['introformat']) =
                     external_format_text($database->intro, $database->introformat,
                                             $datacontext->id, 'mod_data', 'intro', null);
+                $newdb['introfiles'] = external_util::get_area_files($datacontext->id, 'mod_data', 'intro', false, false);
 
                 // This information should be only available if the user can see the database entries.
                 if (has_capability('mod/data:viewentry', $datacontext)) {
@@ -167,6 +168,7 @@ class mod_data_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Database name'),
                             'intro' => new external_value(PARAM_RAW, 'The Database intro'),
                             'introformat' => new external_format_value('intro'),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'comments' => new external_value(PARAM_BOOL, 'comments enabled', VALUE_OPTIONAL),
                             'timeavailablefrom' => new external_value(PARAM_INT, 'timeavailablefrom field', VALUE_OPTIONAL),
                             'timeavailableto' => new external_value(PARAM_INT, 'timeavailableto field', VALUE_OPTIONAL),
index 831f0c9..b569105 100644 (file)
@@ -94,11 +94,13 @@ class mod_data_external_testcase extends externallib_advanced_testcase {
         // First for the student user.
         $expectedfields = array('id', 'coursemodule', 'course', 'name', 'comments', 'timeavailablefrom',
                             'timeavailableto', 'timeviewfrom', 'timeviewto', 'requiredentries', 'requiredentriestoview',
-                            'intro', 'introformat');
+                            'intro', 'introformat', 'introfiles');
 
         // Add expected coursemodule.
         $database1->coursemodule = $database1->cmid;
+        $database1->introfiles = [];
         $database2->coursemodule = $database2->cmid;
+        $database2->introfiles = [];
 
         $expected1 = array();
         $expected2 = array();
index 1b393ec..8df9913 100644 (file)
@@ -92,6 +92,7 @@ class mod_forum_external extends external_api {
                 // Format the intro before being returning using the format setting.
                 list($forum->intro, $forum->introformat) = external_format_text($forum->intro, $forum->introformat,
                                                                                 $context->id, 'mod_forum', 'intro', 0);
+                $forum->introfiles = external_util::get_area_files($context->id, 'mod_forum', 'intro', false, false);
                 // Discussions count. This function does static request cache.
                 $forum->numdiscussions = forum_count_discussions($forum, $cm, $course);
                 $forum->cmid = $forum->coursemodule;
@@ -121,6 +122,7 @@ class mod_forum_external extends external_api {
                     'name' => new external_value(PARAM_RAW, 'Forum name'),
                     'intro' => new external_value(PARAM_RAW, 'The forum intro'),
                     'introformat' => new external_format_value('intro'),
+                    'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                     'assessed' => new external_value(PARAM_INT, 'Aggregate type'),
                     'assesstimestart' => new external_value(PARAM_INT, 'Assess start time'),
                     'assesstimefinish' => new external_value(PARAM_INT, 'Assess finish time'),
index 455abca..f9f08ca 100644 (file)
@@ -79,6 +79,7 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
         $record->introformat = FORMAT_HTML;
         $record->course = $course2->id;
         $forum2 = self::getDataGenerator()->create_module('forum', $record);
+        $forum2->introfiles = [];
 
         // Add discussions to the forums.
         $record = new stdClass();
@@ -89,6 +90,7 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
         // Expect one discussion.
         $forum1->numdiscussions = 1;
         $forum1->cancreatediscussions = true;
+        $forum1->introfiles = [];
 
         $record = new stdClass();
         $record->course = $course2->id;
index ee61c3f..a8b7fc6 100644 (file)
@@ -232,6 +232,7 @@ class mod_glossary_external extends external_api {
                 $glossary->name = external_format_string($glossary->name, $context->id);
                 list($glossary->intro, $glossary->introformat) = external_format_text($glossary->intro, $glossary->introformat,
                     $context->id, 'mod_glossary', 'intro', null);
+                $glossary->introfiles = external_util::get_area_files($context->id, 'mod_glossary', 'intro', false, false);
 
                 // Make sure we have a number of entries per page.
                 if (!$glossary->entbypage) {
@@ -268,6 +269,7 @@ class mod_glossary_external extends external_api {
                     'name' => new external_value(PARAM_RAW, 'Glossary name'),
                     'intro' => new external_value(PARAM_RAW, 'The Glossary intro'),
                     'introformat' => new external_format_value('intro'),
+                    'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                     'allowduplicatedentries' => new external_value(PARAM_INT, 'If enabled, multiple entries can have the' .
                         ' same concept name'),
                     'displayformat' => new external_value(PARAM_TEXT, 'Display format type'),
index 4ae2fdd..a5f0b37 100644 (file)
@@ -165,6 +165,7 @@ class mod_imscp_external extends external_api {
                     // Format intro.
                     list($imscpdetails['intro'], $imscpdetails['introformat']) =
                         external_format_text($imscp->intro, $imscp->introformat, $context->id, 'mod_imscp', 'intro', null);
+                    $imscpdetails['introfiles'] = external_util::get_area_files($context->id, 'mod_imscp', 'intro', false, false);
                 }
 
                 if (has_capability('moodle/course:manageactivities', $context)) {
@@ -204,6 +205,7 @@ class mod_imscp_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Activity name'),
                             'intro' => new external_value(PARAM_RAW, 'The IMSCP intro', VALUE_OPTIONAL),
                             'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'revision' => new external_value(PARAM_INT, 'Revision', VALUE_OPTIONAL),
                             'keepold' => new external_value(PARAM_INT, 'Number of old IMSCP to keep', VALUE_OPTIONAL),
                             'structure' => new external_value(PARAM_RAW, 'IMSCP structure', VALUE_OPTIONAL),
index e45c0f3..460340d 100644 (file)
@@ -309,6 +309,7 @@ class mod_lti_external extends external_api {
                     list($module['intro'], $module['introformat']) =
                         external_format_text($lti->intro, $lti->introformat, $context->id, 'mod_lti', 'intro', $lti->id);
 
+                    $module['introfiles'] = external_util::get_area_files($context->id, 'mod_lti', 'intro', false, false);
                     $viewablefields = array('launchcontainer', 'showtitlelaunch', 'showdescriptionlaunch', 'icon', 'secureicon');
                 }
 
@@ -356,6 +357,7 @@ class mod_lti_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'LTI name'),
                             'intro' => new external_value(PARAM_RAW, 'The LTI intro', VALUE_OPTIONAL),
                             'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'timecreated' => new external_value(PARAM_INT, 'Time of creation', VALUE_OPTIONAL),
                             'timemodified' => new external_value(PARAM_INT, 'Time of last modification', VALUE_OPTIONAL),
                             'typeid' => new external_value(PARAM_INT, 'Type id', VALUE_OPTIONAL),
index a7f0323..07fc5b4 100644 (file)
@@ -129,7 +129,7 @@ class mod_lti_external_testcase extends externallib_advanced_testcase {
 
         // 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', 'launchcontainer',
+        $expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'launchcontainer',
                                 'showtitlelaunch', 'showdescriptionlaunch', 'icon', 'secureicon');
 
         // Add expected coursemodule and data.
@@ -140,6 +140,7 @@ class mod_lti_external_testcase extends externallib_advanced_testcase {
         $lti1->visible = true;
         $lti1->groupmode = 0;
         $lti1->groupingid = 0;
+        $lti1->introfiles = [];
 
         $lti2->coursemodule = $lti2->cmid;
         $lti2->introformat = 1;
@@ -147,6 +148,7 @@ class mod_lti_external_testcase extends externallib_advanced_testcase {
         $lti2->visible = true;
         $lti2->groupmode = 0;
         $lti2->groupingid = 0;
+        $lti2->introfiles = [];
 
         foreach ($expectedfields as $field) {
                 $expected1[$field] = $lti1->{$field};
index d38a907..2359578 100644 (file)
@@ -108,6 +108,7 @@ class mod_quiz_external extends external_api {
                     list($quizdetails['intro'], $quizdetails['introformat']) = external_format_text($quiz->intro,
                                                                     $quiz->introformat, $context->id, 'mod_quiz', 'intro', null);
 
+                    $quizdetails['introfiles'] = external_util::get_area_files($context->id, 'mod_quiz', 'intro', false, false);
                     $viewablefields = array('timeopen', 'timeclose', 'grademethod', 'section', 'visible', 'groupmode',
                                             'groupingid');
 
@@ -171,6 +172,7 @@ class mod_quiz_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Quiz name.'),
                             'intro' => new external_value(PARAM_RAW, 'Quiz introduction text.', VALUE_OPTIONAL),
                             'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'timeopen' => new external_value(PARAM_INT, 'The time when this quiz opens. (0 = no restriction.)',
                                                                 VALUE_OPTIONAL),
                             'timeclose' => new external_value(PARAM_INT, 'The time when this quiz closes. (0 = no restriction.)',
index a62bb95..c106aca 100644 (file)
@@ -189,8 +189,8 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
 
         // Create what we expect to be returned when querying the two courses.
         // First for the student user.
-        $allusersfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'timeopen', 'timeclose',
-                                'grademethod', 'section', 'visible', 'groupmode', 'groupingid');
+        $allusersfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'timeopen',
+                                'timeclose', 'grademethod', 'section', 'visible', 'groupmode', 'groupingid');
         $userswithaccessfields = array('timelimit', 'attempts', 'attemptonlast', 'grademethod', 'decimalpoints',
                                         'questiondecimalpoints', 'reviewattempt', 'reviewcorrectness', 'reviewmarks',
                                         'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer',
@@ -211,6 +211,7 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
         $quiz1->hasquestions = 0;
         $quiz1->hasfeedback = 0;
         $quiz1->autosaveperiod = get_config('quiz', 'autosaveperiod');
+        $quiz1->introfiles = [];
 
         $quiz2->coursemodule = $quiz2->cmid;
         $quiz2->introformat = 1;
@@ -221,6 +222,7 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
         $quiz2->hasquestions = 0;
         $quiz2->hasfeedback = 0;
         $quiz2->autosaveperiod = get_config('quiz', 'autosaveperiod');
+        $quiz2->introfiles = [];
 
         foreach (array_merge($allusersfields, $userswithaccessfields) as $field) {
             $expected1[$field] = $quiz1->{$field};
index ab8e166..d41122f 100644 (file)
@@ -693,6 +693,7 @@ class mod_scorm_external extends external_api {
                 $module['name']  = external_format_string($scorm->name, $context->id);
                 list($module['intro'], $module['introformat']) =
                     external_format_text($scorm->intro, $scorm->introformat, $context->id, 'mod_scorm', 'intro', $scorm->id);
+                $module['introfiles'] = external_util::get_area_files($context->id, 'mod_scorm', 'intro', false, false);
 
                 // Check if the SCORM open and return warnings if so.
                 list($open, $openwarnings) = scorm_get_availability_status($scorm, true, $context);
@@ -769,6 +770,7 @@ class mod_scorm_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'SCORM name'),
                             'intro' => new external_value(PARAM_RAW, 'The SCORM intro'),
                             'introformat' => new external_format_value('intro'),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'packagesize' => new external_value(PARAM_INT, 'SCORM zip package size', VALUE_OPTIONAL),
                             'packageurl' => new external_value(PARAM_URL, 'SCORM zip package URL', VALUE_OPTIONAL),
                             'version' => new external_value(PARAM_NOTAGS, 'SCORM version (SCORM_12, SCORM_13, SCORM_AICC)',
index 5a71a6a..53aaeea 100644 (file)
@@ -649,8 +649,8 @@ class mod_scorm_external_testcase extends externallib_advanced_testcase {
         $result = mod_scorm_external::get_scorms_by_courses(array($course1->id));
         $result = external_api::clean_returnvalue($returndescription, $result);
         $this->assertCount(1, $result['warnings']);
-        // Only 'id', 'coursemodule', 'course', 'name', 'intro', 'introformat'.
-        $this->assertCount(6, $result['scorms'][0]);
+        // Only 'id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles'.
+        $this->assertCount(7, $result['scorms'][0]);
         $this->assertEquals('expired', $result['warnings'][0]['warningcode']);
 
         $scorm1->timeopen = $timenow + DAYSECS;
@@ -660,8 +660,8 @@ class mod_scorm_external_testcase extends externallib_advanced_testcase {
         $result = mod_scorm_external::get_scorms_by_courses(array($course1->id));
         $result = external_api::clean_returnvalue($returndescription, $result);
         $this->assertCount(1, $result['warnings']);
-        // Only 'id', 'coursemodule', 'course', 'name', 'intro', 'introformat'.
-        $this->assertCount(6, $result['scorms'][0]);
+        // Only 'id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles'.
+        $this->assertCount(7, $result['scorms'][0]);
         $this->assertEquals('notopenyet', $result['warnings'][0]['warningcode']);
 
         // Reset times.
@@ -716,6 +716,9 @@ class mod_scorm_external_testcase extends externallib_advanced_testcase {
 
             // Since we return the fields used as boolean as PARAM_BOOL instead PARAM_INT we need to force casting here.
             // From the returned fields definition we obtain the type expected for the field.
+            if (empty($returndescription->keys['scorms']->content->keys[$field]->type)) {
+                continue;
+            }
             $fieldtype = $returndescription->keys['scorms']->content->keys[$field]->type;
             if ($fieldtype == PARAM_BOOL) {
                 $expected1[$field] = (bool) $scorm1->{$field};
@@ -725,6 +728,8 @@ class mod_scorm_external_testcase extends externallib_advanced_testcase {
                 $expected2[$field] = $scorm2->{$field};
             }
         }
+        $expected1['introfiles'] = [];
+        $expected2['introfiles'] = [];
 
         $expectedscorms = array();
         $expectedscorms[] = $expected2;
index 762f4d5..d232b90 100644 (file)
@@ -106,6 +106,8 @@ class mod_survey_external extends external_api {
                     // Format intro.
                     list($surveydetails['intro'], $surveydetails['introformat']) =
                         external_format_text($survey->intro, $survey->introformat, $context->id, 'mod_survey', 'intro', null);
+                    $surveydetails['introfiles'] = external_util::get_area_files($context->id, 'mod_survey', 'intro', false,
+                                                                                    false);
 
                     $surveydetails['template']  = $survey->template;
                     $surveydetails['days']      = $survey->days;
@@ -149,6 +151,7 @@ class mod_survey_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Survey name'),
                             'intro' => new external_value(PARAM_RAW, 'The Survey intro', VALUE_OPTIONAL),
                             'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'template' => new external_value(PARAM_INT, 'Survey type', VALUE_OPTIONAL),
                             'days' => new external_value(PARAM_INT, 'Days', VALUE_OPTIONAL),
                             'questions' => new external_value(PARAM_RAW, 'Question ids', VALUE_OPTIONAL),
index 5b9976d..30de66b 100644 (file)
@@ -101,8 +101,8 @@ class mod_survey_external_testcase extends externallib_advanced_testcase {
 
         // 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', 'template', 'days', 'questions',
-                                    'surveydone');
+        $expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'template', 'days',
+                                'questions', 'surveydone');
 
         // Add expected coursemodule and data.
         $survey1 = $this->survey;
@@ -113,6 +113,7 @@ class mod_survey_external_testcase extends externallib_advanced_testcase {
         $survey1->visible = true;
         $survey1->groupmode = 0;
         $survey1->groupingid = 0;
+        $survey1->introfiles = [];
 
         $survey2->coursemodule = $survey2->cmid;
         $survey2->introformat = 1;
@@ -123,6 +124,7 @@ class mod_survey_external_testcase extends externallib_advanced_testcase {
         $survey2->groupingid = 0;
         $tempo = $DB->get_field("survey", "intro", array("id" => $survey2->template));
         $survey2->intro = nl2br(get_string($tempo, "survey"));
+        $survey2->introfiles = [];
 
         foreach ($expectedfields as $field) {
             $expected1[$field] = $survey1->{$field};
index 4d8f00b..c79f544 100644 (file)
@@ -104,6 +104,7 @@ class mod_wiki_external extends external_api {
                 if (has_capability('mod/wiki:viewpage', $context)) {
                     list($module['intro'], $module['introformat']) =
                         external_format_text($wiki->intro, $wiki->introformat, $context->id, 'mod_wiki', 'intro', $wiki->id);
+                    $module['introfiles'] = external_util::get_area_files($context->id, 'mod_wiki', 'intro', false, false);
 
                     $viewablefields = array('firstpagetitle', 'wikimode', 'defaultformat', 'forceformat', 'editbegin', 'editend',
                                             'section', 'visible', 'groupmode', 'groupingid');
@@ -151,6 +152,7 @@ class mod_wiki_external extends external_api {
                             'name' => new external_value(PARAM_RAW, 'Wiki name.'),
                             'intro' => new external_value(PARAM_RAW, 'Wiki intro.', VALUE_OPTIONAL),
                             'introformat' => new external_format_value('Wiki intro format.', VALUE_OPTIONAL),
+                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                             'timecreated' => new external_value(PARAM_INT, 'Time of creation.', VALUE_OPTIONAL),
                             'timemodified' => new external_value(PARAM_INT, 'Time of last modification.', VALUE_OPTIONAL),
                             'firstpagetitle' => new external_value(PARAM_RAW, 'First page title.', VALUE_OPTIONAL),
index 3cb4e83..f1ff9e8 100644 (file)
@@ -172,9 +172,9 @@ class mod_wiki_external_testcase extends externallib_advanced_testcase {
 
         // 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', 'firstpagetitle', 'wikimode',
-                                'defaultformat', 'forceformat', 'editbegin', 'editend', 'section', 'visible', 'groupmode',
-                                'groupingid');
+        $expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'firstpagetitle',
+                                'wikimode', 'defaultformat', 'forceformat', 'editbegin', 'editend', 'section', 'visible',
+                                'groupmode', 'groupingid');
 
         // Add expected coursemodule and data.
         $wiki1 = $this->wiki;
@@ -184,6 +184,7 @@ class mod_wiki_external_testcase extends externallib_advanced_testcase {
         $wiki1->visible = true;
         $wiki1->groupmode = 0;
         $wiki1->groupingid = 0;
+        $wiki1->introfiles = [];
 
         $wiki2->coursemodule = $wiki2->cmid;
         $wiki2->introformat = 1;
@@ -191,6 +192,7 @@ class mod_wiki_external_testcase extends externallib_advanced_testcase {
         $wiki2->visible = true;
         $wiki2->groupmode = 0;
         $wiki2->groupingid = 0;
+        $wiki2->introfiles = [];
 
         foreach ($expectedfields as $field) {
             $expected1[$field] = $wiki1->{$field};